forked from such-gitea/wownero
Compare commits
415 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b303931b23 | ||
|
|
7b4e1b0859 | ||
|
|
8fb16a3280 | ||
|
|
4e097c26a2 | ||
|
|
2aabc5863e | ||
|
|
2a6d817ea1 | ||
|
|
f6533856df | ||
|
|
32497a641c | ||
|
|
aaa015b3e7 | ||
|
|
9c35901592 | ||
|
|
f9c0871877 | ||
|
|
96d1d08f48 | ||
|
|
2e8fae1b4c | ||
|
|
d99c27e24d | ||
|
|
48eeca2077 | ||
|
|
96ae690083 | ||
|
|
b9974f7bff | ||
|
|
389a02d93f | ||
|
|
a3c9befbb5 | ||
|
|
08a0e737f9 | ||
|
|
1396426d59 | ||
|
|
93cc82423e | ||
|
|
572d7ea5ef | ||
|
|
d27d4526fe | ||
|
|
5b3614e6a9 | ||
|
|
2b1488ef6f | ||
|
|
ea587de300 | ||
|
|
80e535c95a | ||
|
|
4971219c2c | ||
|
|
c3f354e6c1 | ||
|
|
9bba1a24ea | ||
|
|
2993d2004a | ||
|
|
244ae22795 | ||
|
|
f240b1dd88 | ||
|
|
929ea98662 | ||
|
|
ef4325fd41 | ||
|
|
a3844e257e | ||
|
|
836067b68b | ||
|
|
9c9c689db4 | ||
|
|
df0dcea061 | ||
|
|
3a761e10d2 | ||
|
|
fd657c7706 | ||
|
|
fc2cb224a9 | ||
|
|
5498142e8f | ||
|
|
1b9fe0761c | ||
|
|
aefa7740c3 | ||
|
|
2a7086caa8 | ||
|
|
541a7c81a1 | ||
|
|
036da6d45b | ||
|
|
4e4430603f | ||
|
|
9fb2243db0 | ||
|
|
ee0b02d0db | ||
|
|
b09cc3d03d | ||
|
|
de9a9fb340 | ||
|
|
6a37da837e | ||
|
|
2d8a197b91 | ||
|
|
77ffea0825 | ||
|
|
94b056c06e | ||
|
|
54d5f098f2 | ||
|
|
a70374d3e6 | ||
|
|
a51ccc036f | ||
|
|
61dd04b681 | ||
|
|
bdcf587c79 | ||
|
|
fa06c39d97 | ||
|
|
743608ec16 | ||
|
|
5946002105 | ||
|
|
51bf6b5842 | ||
|
|
5245ba132b | ||
|
|
e6c81c5ea7 | ||
|
|
975ae22211 | ||
|
|
333ae55fef | ||
|
|
0a3c5a605b | ||
|
|
1dc427def9 | ||
|
|
4a9bd8f70f | ||
|
|
44cd8a13ec | ||
|
|
39a087406d | ||
|
|
d20ff4f648 | ||
|
|
6a0b3b1f8a | ||
|
|
9d42649d58 | ||
|
|
1660fe8a25 | ||
|
|
703944c4d4 | ||
|
|
aff87b5f6a | ||
|
|
f964a92c57 | ||
|
|
5aa1575e91 | ||
|
|
641b08c920 | ||
|
|
82ee01699c | ||
|
|
8cd1d6df8f | ||
|
|
4b328c6616 | ||
|
|
30c1cf83fc | ||
|
|
c695470cff | ||
|
|
0c101f1236 | ||
|
|
8aaeff46ee | ||
|
|
27b49033fd | ||
|
|
05390fd2d4 | ||
|
|
aa56bf66a6 | ||
|
|
b04da25e4d | ||
|
|
4fe2858b4d | ||
|
|
dd7fd2ef80 | ||
|
|
a06c83db73 | ||
|
|
42519b48a7 | ||
|
|
bad5d8d6f0 | ||
|
|
3f392341e7 | ||
|
|
38914fe6fa | ||
|
|
c3f991332f | ||
|
|
839e1f4bab | ||
|
|
aadd72202f | ||
|
|
a6f1fa0194 | ||
|
|
844fb4e940 | ||
|
|
7c7ccbd2a5 | ||
|
|
bdc6b10d62 | ||
|
|
b641e0a2c0 | ||
|
|
765db1ae7a | ||
|
|
7175dcb107 | ||
|
|
55363c5941 | ||
|
|
43a4fd9e16 | ||
|
|
43f5369bec | ||
|
|
d73b1b6560 | ||
|
|
569d07d60b | ||
|
|
7db379cc82 | ||
|
|
10ad0d7eb2 | ||
|
|
01b512f3a9 | ||
|
|
f40b9e34e0 | ||
|
|
65d7d8312d | ||
|
|
43f91ee12e | ||
|
|
d3e611fda2 | ||
|
|
79e93a8af8 | ||
|
|
0b0da2aa81 | ||
|
|
236256f114 | ||
|
|
eba2189925 | ||
|
|
6b2d3deb20 | ||
|
|
bc48494731 | ||
|
|
adcadd9ed0 | ||
|
|
8f02e7a7fc | ||
|
|
976a9e0c72 | ||
|
|
c6c4ead44e | ||
|
|
a08df6eb1b | ||
|
|
009ca6fcd3 | ||
|
|
9eebe01c58 | ||
|
|
0f5eb0e70c | ||
|
|
461651fce5 | ||
|
|
b61a9afa5d | ||
|
|
6d29ee6c52 | ||
|
|
e2e09d00c2 | ||
|
|
3614f78d5f | ||
|
|
13549d590e | ||
|
|
728ba38b11 | ||
|
|
07442a6059 | ||
|
|
12ffc79b27 | ||
|
|
9f05df1996 | ||
|
|
4e2377995d | ||
|
|
98c151ecb8 | ||
|
|
60627c9f24 | ||
|
|
fe96e66ebe | ||
|
|
85899230d1 | ||
|
|
4ff2074c74 | ||
|
|
921dd8dde5 | ||
|
|
6bfcd31015 | ||
|
|
c108c5e2f0 | ||
|
|
e916201f12 | ||
|
|
20f603c6be | ||
|
|
9414194b1e | ||
|
|
d9deb2c2fe | ||
|
|
4f01cf4b46 | ||
|
|
05ad4fa397 | ||
|
|
429d495121 | ||
|
|
d745d24333 | ||
|
|
db5d6e4602 | ||
|
|
13eee1d6ab | ||
|
|
92e6b7df2c | ||
|
|
6dd95d5308 | ||
|
|
90016ad744 | ||
|
|
c1b03fb1a6 | ||
|
|
8baa7bb238 | ||
|
|
fb31167b12 | ||
|
|
85efc88c1e | ||
|
|
86abf558cb | ||
|
|
76c16822d0 | ||
|
|
3d6bc0a680 | ||
|
|
01cd3d9342 | ||
|
|
5d850dde99 | ||
|
|
2a82258dff | ||
|
|
3434cc24a2 | ||
|
|
9871fefbf9 | ||
|
|
c0a6e1aab9 | ||
|
|
bb0241da6e | ||
|
|
61e5208181 | ||
|
|
6d6c691a0f | ||
|
|
36d50d93f2 | ||
|
|
912cbad6db | ||
|
|
814e617117 | ||
|
|
3ba6c7fd30 | ||
|
|
a0d179e528 | ||
|
|
616558d512 | ||
|
|
7cd0d7f324 | ||
|
|
65938d26f6 | ||
|
|
2fa20016a7 | ||
|
|
5041de8a3b | ||
|
|
66235c7f02 | ||
|
|
17823be66d | ||
|
|
cb882dfc55 | ||
|
|
332d60719a | ||
|
|
9f93a1b632 | ||
|
|
0fd6ccef21 | ||
|
|
803f58553b | ||
|
|
99b14ccd6a | ||
|
|
18bb011afe | ||
|
|
e8d87fccc2 | ||
|
|
0376195015 | ||
|
|
3057f52f89 | ||
|
|
228101a72e | ||
|
|
81c2586358 | ||
|
|
340e1943ac | ||
|
|
be170c485c | ||
|
|
8b3fa2d373 | ||
|
|
634262f3f5 | ||
|
|
f1334ebf64 | ||
|
|
35e2520115 | ||
|
|
ee817e00bb | ||
|
|
ed903578d7 | ||
|
|
7d903bc992 | ||
|
|
ed901798d9 | ||
|
|
a3933a2a5e | ||
|
|
6111689cfa | ||
|
|
afd002c31f | ||
|
|
ec7bba0793 | ||
|
|
2f1ad3b3d2 | ||
|
|
f9e3fcdf3e | ||
|
|
3721d5688f | ||
|
|
99684e3ec3 | ||
|
|
93257997bd | ||
|
|
e334280127 | ||
|
|
b3d6382d40 | ||
|
|
267ce5b718 | ||
|
|
bde7f1c5cc | ||
|
|
c4b74208c7 | ||
|
|
c4df8b1390 | ||
|
|
38ca1bb389 | ||
|
|
4d8d121462 | ||
|
|
58e1c8b031 | ||
|
|
7bd66b01bf | ||
|
|
ff4d470629 | ||
|
|
c4f4091dd4 | ||
|
|
445f74c71a | ||
|
|
28745b1b63 | ||
|
|
e17c864ba2 | ||
|
|
e27604ff10 | ||
|
|
3a577f1ce7 | ||
|
|
967285a9fa | ||
|
|
09667700e8 | ||
|
|
37c359e765 | ||
|
|
01c384c5de | ||
|
|
ef694d028f | ||
|
|
795e18632c | ||
|
|
4df8f9c414 | ||
|
|
2d5d74ff5c | ||
|
|
b6e904e547 | ||
|
|
992b7ce30f | ||
|
|
7aeb503547 | ||
|
|
dc1a053081 | ||
|
|
eb1b321fe2 | ||
|
|
7e78da7772 | ||
|
|
9b86e14c5a | ||
|
|
6e4a55ba7e | ||
|
|
d6d4a03b85 | ||
|
|
463d044f5e | ||
|
|
ec46069248 | ||
|
|
6f5411d305 | ||
|
|
c6dc2850c2 | ||
|
|
bcef52d430 | ||
|
|
94befecb05 | ||
|
|
40b73d2a6c | ||
|
|
7d0b7e83ef | ||
|
|
82d21f5b3c | ||
|
|
78d435a5fa | ||
|
|
2314dae8c8 | ||
|
|
a6803231e6 | ||
|
|
4d3c2d0b7b | ||
|
|
15538f7e3f | ||
|
|
1d31e6c000 | ||
|
|
7ebb351c2d | ||
|
|
f0371210e9 | ||
|
|
567402c508 | ||
|
|
72cdfa4a20 | ||
|
|
c17fe815a2 | ||
|
|
f1d0457523 | ||
|
|
bb5c5dff15 | ||
|
|
ca60d60fea | ||
|
|
bd69e3b37a | ||
|
|
5ed37ba83c | ||
|
|
5741b4d74d | ||
|
|
eda1675858 | ||
|
|
35665df206 | ||
|
|
85164a8daf | ||
|
|
7178bb5c84 | ||
|
|
a11ec4ac1d | ||
|
|
5e0ea6e95c | ||
|
|
bd96536637 | ||
|
|
cb4edc1f45 | ||
|
|
81773f55a4 | ||
|
|
67ade80055 | ||
|
|
f35ced6d7f | ||
|
|
86cf811a39 | ||
|
|
153977aed4 | ||
|
|
b73f4e78d0 | ||
|
|
4baee200a7 | ||
|
|
5d882f4f14 | ||
|
|
ab4429346d | ||
|
|
29e563bb1e | ||
|
|
8656a8c9ff | ||
|
|
77a008f714 | ||
|
|
4c2f78aeeb | ||
|
|
5ef0607da6 | ||
|
|
70609d7681 | ||
|
|
dbba6004f5 | ||
|
|
71693f06a1 | ||
|
|
f80ab3edde | ||
|
|
f2c78f6a5b | ||
|
|
3de804f1e9 | ||
|
|
98e3802b26 | ||
|
|
de025281dc | ||
|
|
9e3f72c375 | ||
|
|
0f233c6ad8 | ||
|
|
9f3e8e3ff0 | ||
|
|
483e5cab5c | ||
|
|
8d0f1696df | ||
|
|
1f505a5eac | ||
|
|
6d1f3c9acd | ||
|
|
b4023dcfc5 | ||
|
|
a7334faf63 | ||
|
|
42e14840fb | ||
|
|
3843a6aba5 | ||
|
|
e5214a2ca2 | ||
|
|
a07c8abcc1 | ||
|
|
db8563cb46 | ||
|
|
8185054db7 | ||
|
|
a5cc613a68 | ||
|
|
ae18ec080c | ||
|
|
ec90f9a54b | ||
|
|
d68497a3e3 | ||
|
|
ac9f7c9bec | ||
|
|
c9b800a787 | ||
|
|
f020b24b02 | ||
|
|
6e7b883212 | ||
|
|
6b7e88e16c | ||
|
|
443f5c6bda | ||
|
|
69320cd913 | ||
|
|
3e21e591b8 | ||
|
|
7765da6eb2 | ||
|
|
26bfd70459 | ||
|
|
dd807b8410 | ||
|
|
feee455c9f | ||
|
|
7a8c1eece9 | ||
|
|
e509ede2aa | ||
|
|
e7d01056f4 | ||
|
|
119f706921 | ||
|
|
647c069db6 | ||
|
|
4f489fa6a2 | ||
|
|
ee58362b1f | ||
|
|
afe5a55e96 | ||
|
|
6d41d9e8f9 | ||
|
|
91182330d7 | ||
|
|
2efbd5f0cc | ||
|
|
d3e77ccb59 | ||
|
|
c6a1294b5e | ||
|
|
8b655de8ed | ||
|
|
9faf3d1a72 | ||
|
|
145be6dbdb | ||
|
|
378cdeaeae | ||
|
|
c846c8650e | ||
|
|
4540afc51b | ||
|
|
cc91c0221d | ||
|
|
f389ce1a0f | ||
|
|
665736d323 | ||
|
|
cb8f4280bb | ||
|
|
06c81b6527 | ||
|
|
79a1653a07 | ||
|
|
2d729fbdf7 | ||
|
|
9c660e159e | ||
|
|
a813c46a1b | ||
|
|
f8b1480f95 | ||
|
|
57854a3e21 | ||
|
|
5eb7f63df8 | ||
|
|
d2d3a81d0e | ||
|
|
87d75584e8 | ||
|
|
613071f4fa | ||
|
|
4ed60b626a | ||
|
|
27d551d12f | ||
|
|
c26c93019a | ||
|
|
7c74e1919e | ||
|
|
228af683a7 | ||
|
|
4badcf3781 | ||
|
|
bce050ee78 | ||
|
|
7954f8cb18 | ||
|
|
53800b3b63 | ||
|
|
b367630ee8 | ||
|
|
7c4a4003a3 | ||
|
|
688a3e87e7 | ||
|
|
69b5992296 | ||
|
|
7326b691d3 | ||
|
|
082dd2c373 | ||
|
|
da99157462 | ||
|
|
09abca76ae | ||
|
|
14e803565f | ||
|
|
9c95437167 | ||
|
|
571546067f | ||
|
|
babf25d2ec | ||
|
|
f9441c5759 | ||
|
|
5ef7138d86 | ||
|
|
8d230473ef | ||
|
|
02d887c2e5 | ||
|
|
387fd668d1 | ||
|
|
8688b467ce | ||
|
|
5de2295f3c | ||
|
|
8958b4e7aa | ||
|
|
927fd47934 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
||||
custom: https://dev-funding.webui.wowkira.co
|
||||
custom: https://dev-funding.webui.wowkira.com
|
||||
|
||||
38
.github/workflows/build.yml
vendored
38
.github/workflows/build.yml
vendored
@@ -38,10 +38,15 @@ jobs:
|
||||
submodules: recursive
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
- name: set apt conf
|
||||
run: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
|
||||
- name: build
|
||||
run: make -j3
|
||||
|
||||
@@ -53,10 +58,39 @@ jobs:
|
||||
submodules: recursive
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
- name: set apt conf
|
||||
run: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
|
||||
- name: build
|
||||
run: cmake -DBUILD_GUI_DEPS=ON && make -j3
|
||||
|
||||
test-ubuntu:
|
||||
needs: build-ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
- name: set apt conf
|
||||
run: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler
|
||||
- name: install requests
|
||||
run: pip install requests
|
||||
- name: tests
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: ON
|
||||
run: make release-test -j3
|
||||
|
||||
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -13,3 +13,7 @@
|
||||
path = external/RandomWOW
|
||||
url = https://git.wownero.com/wownero/RandomWOW
|
||||
branch = 1.1.8-wow
|
||||
[submodule "external/supercop"]
|
||||
path = external/supercop
|
||||
url = https://git.wownero.com/wownero/supercop
|
||||
branch = monero
|
||||
|
||||
@@ -25,7 +25,7 @@ env:
|
||||
# ARM v8
|
||||
- HOST=aarch64-linux-gnu PACKAGES="python3 gperf g++-aarch64-linux-gnu"
|
||||
# i686 Win
|
||||
- HOST=i686-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 g++-mingw-w64-i686 qttools5-dev-tools"
|
||||
- HOST=i686-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 g++-mingw-w64-i686 qttools5-dev-tools" MAKEJOBS=-j2
|
||||
# i686 Linux
|
||||
- HOST=i686-pc-linux-gnu PACKAGES="gperf cmake g++-multilib python3-zmq"
|
||||
# Win64
|
||||
|
||||
@@ -55,6 +55,21 @@ else()
|
||||
message(STATUS "ccache deselected")
|
||||
endif()
|
||||
|
||||
# Job pool feature requires Ninja.
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.0.0")
|
||||
set(WOWNERO_PARALLEL_COMPILE_JOBS "" CACHE STRING "The maximum number of concurrent compilation jobs.")
|
||||
if (WOWNERO_PARALLEL_COMPILE_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${WOWNERO_PARALLEL_COMPILE_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_job_pool)
|
||||
endif ()
|
||||
|
||||
set(WOWNERO_PARALLEL_LINK_JOBS "" CACHE STRING "The maximum number of concurrent link jobs.")
|
||||
if (WOWNERO_PARALLEL_LINK_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${WOWNERO_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
enable_language(C ASM)
|
||||
|
||||
function (die msg)
|
||||
@@ -218,6 +233,7 @@ if(NOT MANUAL_SUBMODULES)
|
||||
check_submodule(external/unbound)
|
||||
check_submodule(external/rapidjson)
|
||||
check_submodule(external/RandomWOW)
|
||||
check_submodule(external/supercop)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -275,6 +291,12 @@ else()
|
||||
endif()
|
||||
option(BUILD_DEBUG_UTILITIES "Build debug utilities." DEFAULT_BUILD_DEBUG_UTILITIES)
|
||||
|
||||
if(OSSFUZZ)
|
||||
message(STATUS "Using OSS-Fuzz fuzzing system")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DOSSFUZZ")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOSSFUZZ")
|
||||
endif()
|
||||
|
||||
# Check whether we're on a 32-bit or 64-bit system
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL "8")
|
||||
set(DEFAULT_BUILD_64 ON)
|
||||
@@ -313,7 +335,7 @@ endif()
|
||||
# elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
|
||||
# set(BSDI TRUE)
|
||||
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external)
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include)
|
||||
|
||||
if(APPLE)
|
||||
include_directories(SYSTEM /usr/include/malloc)
|
||||
@@ -433,7 +455,7 @@ endif ()
|
||||
|
||||
if (APPLE AND NOT IOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
|
||||
if (NOT OpenSSL_DIR)
|
||||
if (NOT OPENSSL_ROOT_DIR)
|
||||
EXECUTE_PROCESS(COMMAND brew --prefix openssl
|
||||
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
@@ -458,6 +480,9 @@ add_definition_if_function_found(strptime HAVE_STRPTIME)
|
||||
|
||||
add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP)
|
||||
|
||||
set(MONERO_GENERATED_HEADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include")
|
||||
include_directories(${MONERO_GENERATED_HEADERS_DIR})
|
||||
|
||||
# Generate header for embedded translations
|
||||
# Generate header for embedded translations, use target toolchain if depends, otherwise use the
|
||||
# lrelease and lupdate binaries from the host
|
||||
@@ -471,14 +496,6 @@ ExternalProject_Add(generate_translations_header
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/translations")
|
||||
add_subdirectory(external)
|
||||
|
||||
# Final setup for miniupnpc
|
||||
if(UPNP_STATIC OR IOS)
|
||||
add_definitions("-DUPNP_STATIC")
|
||||
else()
|
||||
add_definitions("-DUPNP_DYNAMIC")
|
||||
include_directories(${UPNP_INCLUDE})
|
||||
endif()
|
||||
|
||||
# Final setup for libunbound
|
||||
include_directories(${UNBOUND_INCLUDE})
|
||||
link_directories(${UNBOUND_LIBRARY_DIRS})
|
||||
@@ -667,7 +684,8 @@ else()
|
||||
endif()
|
||||
|
||||
# linker
|
||||
if (NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1)))
|
||||
if (NOT SANITIZE AND NOT OSSFUZZ AND NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1)))
|
||||
# PIE executables randomly crash at startup with ASAN
|
||||
# Windows binaries die on startup with PIE when compiled with GCC <9.x
|
||||
add_linker_flag_if_supported(-pie LD_SECURITY_FLAGS)
|
||||
endif()
|
||||
@@ -789,7 +807,8 @@ else()
|
||||
|
||||
endif(ARM)
|
||||
|
||||
if(ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS)
|
||||
# random crash on startup when asan is on if pie is enabled
|
||||
if(NOT SANITIZE AND ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS)
|
||||
#From Android 5: "only position independent executables (PIE) are supported"
|
||||
message(STATUS "Enabling PIE executable")
|
||||
set(PIC_FLAG "")
|
||||
@@ -976,9 +995,6 @@ find_library(NORM_LIBRARY norm)
|
||||
find_library(PROTOLIB_LIBRARY protolib)
|
||||
find_library(SODIUM_LIBRARY sodium)
|
||||
|
||||
set(ZMQ_INCLUDE_PATH zmq_dummy_include_path)
|
||||
set(ZMQ_LIB zmq_dummy_lib_2)
|
||||
|
||||
if(NOT ZMQ_INCLUDE_PATH)
|
||||
message(FATAL_ERROR "Could not find required header zmq.h")
|
||||
endif()
|
||||
@@ -998,6 +1014,7 @@ if(SODIUM_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
|
||||
endif()
|
||||
|
||||
include(external/supercop/functions.cmake) # place after setting flags and before src directory inclusion
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
18
README.md
18
README.md
@@ -41,12 +41,11 @@ Blockchain Explorers
|
||||
- https://wownero.xmrauctions.com
|
||||
|
||||
Free Public Nodes
|
||||
- wow7dhbgiljnkspkzpjyy66auegbrye2ptfv4gucgbhireg5rrjza5ad.onion:34568
|
||||
- so.wow.candy.surf:34568 (US)
|
||||
- such.wow.candy.surf:34568 (CAN)
|
||||
- very.wow.candy.surf:34568 (IN)
|
||||
- much.wow.candy.surf:34568 (UK)
|
||||
- node.suchwow.xyz:34568 (US)
|
||||
- global.wownodes.com:34568 (Global)
|
||||
- node.suchwow.xyz:34568 (US)
|
||||
- wow.pwned.systems:34568 (NL)
|
||||
- wowbux.org:34568 (CA)
|
||||
- wowbuxx535x4exuexja2xfezpwcyznxkofui4ndjiectj4yuh2xheiid.onion:34568
|
||||
|
||||
Tor Peers
|
||||
- wowp2p5gelm6vhl2d5tvfqills63jilgy6hkvlrqljooov5ktaxgqdad.onion
|
||||
@@ -103,7 +102,7 @@ Dates are provided in the format YYYY-MM-DD.
|
||||
| 114,969 | 2019-06-14 | F For Fappening | v0.6.1.0 | v0.6.1.2 | RandomWOW, new block weight algorithm, slightly more efficient RingCT format
|
||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||
| XXXX | 2020-09-XX | XXXXX | v0.9.0.0 | v0.9.0.0 | RandomWOW v2 (WOWv2), increase coinbase unlock to 8,640 (1 mo.), CLSAG
|
||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.0.0 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||
|
||||
X's indicate that these details have not been determined as of commit date.
|
||||
|
||||
@@ -155,7 +154,6 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
git clone https://git.wownero.com/wownero/wownero && cd wownero
|
||||
make -j2
|
||||
|
||||
|
||||
* Debian/Ubuntu
|
||||
|
||||
sudo apt update && sudo apt install build-essential cmake pkg-config 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
|
||||
@@ -166,7 +164,7 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||
## Running Binaries
|
||||
|
||||
The build places the binary in `bin/` sub-directory within the build directory
|
||||
from which cmake was invoked (repository root by default). To run in
|
||||
from which cmake was invoked (repository root by default). To run in the
|
||||
foreground:
|
||||
|
||||
./bin/wownerod
|
||||
@@ -175,7 +173,7 @@ To list all available options, run `./bin/wownerod --help`. Options can be
|
||||
specified either on the command line or in a configuration file passed by the
|
||||
`--config-file` argument. To specify an option in the configuration file, add
|
||||
a line with the syntax `argumentname=value`, where `argumentname` is the name
|
||||
of the argument without the leading dashes, for example `log-level=1`.
|
||||
of the argument without the leading dashes, for example, `log-level=1`.
|
||||
|
||||
To run in background:
|
||||
|
||||
|
||||
61
ZMQ.md
Normal file
61
ZMQ.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# The Current/Future Status of ZMQ in Monero
|
||||
|
||||
## ZMQ Pub/Sub
|
||||
Client `ZMQ_SUB` sockets must "subscribe" to topics before it receives any data.
|
||||
This allows filtering on the server side, so network traffic is reduced. Monero
|
||||
allows for filtering on: (1) format, (2) context, and (3) event.
|
||||
|
||||
* **format** refers to the _wire_ format (i.e. JSON) used to send event
|
||||
information.
|
||||
* **context** allows for a reduction in fields for the event, so the
|
||||
daemon doesn't waste cycles serializing fields that get ignored.
|
||||
* **event** refers to status changes occurring within the daemon (i.e. new
|
||||
block to main chain).
|
||||
|
||||
* Formats:
|
||||
* `json`
|
||||
* Contexts:
|
||||
* `full` - the entire block or transaction is transmitted (the hash can be
|
||||
computed remotely).
|
||||
* `minimal` - the bare minimum for a remote client to react to an event is
|
||||
sent.
|
||||
* Events:
|
||||
* `chain_main` - changes to the primary/main blockchain.
|
||||
* `txpool_add` - new _publicly visible_ transactions in the mempool.
|
||||
Includes previously unseen transactions in a block but _not_ the
|
||||
`miner_tx`. Does not "re-publish" after a reorg. Includes `do_not_relay`
|
||||
transactions.
|
||||
|
||||
The subscription topics are formatted as `format-context-event`, with prefix
|
||||
matching supported by both Monero and ZMQ. The `format`, `context` and `event`
|
||||
will _never_ have hyphens or colons in their name. For example, subscribing to
|
||||
`json-minimal-chain_main` will send minimal information in JSON when changes
|
||||
to the main/primary blockchain occur. Whereas, subscribing to `json-minimal`
|
||||
will send minimal information in JSON on all available events supported by the
|
||||
daemon.
|
||||
|
||||
The Monero daemon will ensure that events prefixed by `chain` will be sent in
|
||||
"chain-order" - the `prev_id` (hash) field will _always_ refer to a previous
|
||||
block. On rollbacks/reorgs, the event will reference an earlier block in the
|
||||
chain instead of the last block. The Monero daemon also ensures that
|
||||
`txpool_add` events are sent before `chain_*` events - the `chain_*` messages
|
||||
will only serialize miner transactions since the other transactions were
|
||||
previously published via `txpool_add`. This prevents transactions from being
|
||||
serialized twice, even when the transaction was first observed in a block.
|
||||
|
||||
ZMQ Pub/Sub will drop messages if the network is congested, so the above rules
|
||||
for send order are used for detecting lost messages. A missing gap in `height`
|
||||
or `prev_id` for `chain_*` events indicates a lost pub message. Missing
|
||||
`txpool_add` messages can only be detected at the next `chain_` message.
|
||||
|
||||
Since blockchain events can be dropped, clients will likely want to have a
|
||||
timeout against `chain_main` events. The `GetLastBlockHeader` RPC is useful
|
||||
for checking the current chain state. Dropped messages should be rare in most
|
||||
conditions.
|
||||
|
||||
The Monero daemon will send a `txpool_add` pub exactly once for each
|
||||
transaction, even after a reorg or restarts. Clients should use the
|
||||
`GetTransactionPool` after a reorg to get all transactions that have been put
|
||||
back into the tx pool or been invalidated due to a double-spend.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package=expat
|
||||
$(package)_version=2.2.4
|
||||
$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
|
||||
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_2_4
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=03ad85db965f8ab2d27328abcf0bc5571af6ec0a414874b2066ee3fdd372019e
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package=native_ds_store
|
||||
$(package)_version=1.1.0
|
||||
$(package)_download_path=https://bitbucket.org/al45tair/ds_store/get
|
||||
$(package)_download_file=v$($(package)_version).tar.bz2
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=921596764d71d1bbd3297a90ef6d286f718794d667e4f81d91d14053525d64c1
|
||||
$(package)_download_path=https://github.com/al45tair/ds_store/archive/
|
||||
$(package)_download_file=v$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=a9f4c0755c6be7224ff7029e188dd262e830bb81e801424841db9eb0780ec8ed
|
||||
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
|
||||
$(package)_dependencies=native_biplist
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package=native_mac_alias
|
||||
$(package)_version=1.1.0
|
||||
$(package)_download_path=https://bitbucket.org/al45tair/mac_alias/get
|
||||
$(package)_download_file=v$($(package)_version).tar.bz2
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=87ad827e66790028361e43fc754f68ed041a9bdb214cca03c853f079b04fb120
|
||||
$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
|
||||
$(package)_download_file=v$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=b10cb44ecb64fc25283fae7a9cf365d2829377d84e37b9c21100aca8757509be
|
||||
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
|
||||
$(package)_patches=python3.patch
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Set the system name to one of Android, Darwin, FreeBSD, Linux, or Windows
|
||||
SET(CMAKE_SYSTEM_NAME @depends@)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR @arch@)
|
||||
SET(CMAKE_BUILD_TYPE @release_type@)
|
||||
|
||||
OPTION(STATIC "Link libraries statically" ON)
|
||||
@@ -55,7 +56,7 @@ SET(Boost_NO_SYSTEM_PATHS ON)
|
||||
SET(Boost_USE_STATIC_LIBS ON)
|
||||
SET(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
SET(OpenSSL_DIR @prefix@/lib)
|
||||
SET(OPENSSL_ROOT_DIR @prefix@)
|
||||
SET(ARCHITECTURE @arch@)
|
||||
|
||||
# for libraries and headers in the target directories
|
||||
@@ -63,14 +64,14 @@ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Find programs on host
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Find libs in target
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Find includes in target
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR} CACHE STRING "" FORCE)
|
||||
|
||||
# specify the cross compiler to be used. Darwin uses clang provided by the SDK.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
SET(CMAKE_C_COMPILER @prefix@/native/bin/clang)
|
||||
SET(CMAKE_C_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_CXX_COMPILER @prefix@/native/bin/clang++ -stdlib=libc++)
|
||||
SET(CMAKE_CXX_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_ASM_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_ASM-ATT_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(_CMAKE_TOOLCHAIN_PREFIX x86_64-apple-darwin11-)
|
||||
SET(APPLE True)
|
||||
SET(BUILD_TAG "mac-x64")
|
||||
|
||||
@@ -117,6 +117,9 @@ namespace epee
|
||||
check(more);
|
||||
}
|
||||
|
||||
//! Reset write position, but do not release internal memory. \post `size() == 0`.
|
||||
void clear() noexcept { next_write_ = buffer_.get(); }
|
||||
|
||||
/*! Copy `length` bytes starting at `ptr` to end of stream.
|
||||
\throw std::range_error If exceeding max size_t value.
|
||||
\throw std::bad_alloc If allocation fails. */
|
||||
|
||||
@@ -543,6 +543,31 @@ eof:
|
||||
return it->second.second;
|
||||
}
|
||||
|
||||
std::vector<std::string> get_command_list(const std::vector<std::string>& keywords = std::vector<std::string>())
|
||||
{
|
||||
std::vector<std::string> list;
|
||||
list.reserve(m_command_handlers.size());
|
||||
for(auto const& x:m_command_handlers)
|
||||
{
|
||||
bool take = true;
|
||||
for(auto const& y:keywords)
|
||||
{
|
||||
bool in_usage = x.second.second.first.find(y) != std::string::npos;
|
||||
bool in_description = x.second.second.second.find(y) != std::string::npos;
|
||||
if (!(in_usage || in_description))
|
||||
{
|
||||
take = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (take)
|
||||
{
|
||||
list.push_back(x.first);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void set_handler(const std::string& cmd, const callback& hndlr, const std::string& usage = "", const std::string& description = "")
|
||||
{
|
||||
lookup::mapped_type & vt = m_command_handlers[cmd];
|
||||
|
||||
@@ -106,6 +106,14 @@ namespace misc_utils
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get_mid(const T &a, const T &b)
|
||||
{
|
||||
//returns the average of two numbers; overflow safe and works with at least all integral and floating point types
|
||||
//(a+b)/2 = (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2
|
||||
return (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2;
|
||||
}
|
||||
|
||||
template<class type_vec_type>
|
||||
type_vec_type median(std::vector<type_vec_type> &v)
|
||||
{
|
||||
@@ -122,7 +130,7 @@ namespace misc_utils
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
return get_mid<type_vec_type>(v[n-1],v[n]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace http
|
||||
abstract_http_client() {}
|
||||
virtual ~abstract_http_client() {}
|
||||
bool set_server(const std::string& address, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
|
||||
virtual bool set_proxy(const std::string& address);
|
||||
virtual void set_server(std::string host, std::string port, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect) = 0;
|
||||
virtual void set_auto_connect(bool auto_connect) = 0;
|
||||
virtual bool connect(std::chrono::milliseconds timeout) = 0;
|
||||
|
||||
@@ -885,14 +885,6 @@ namespace net_utils
|
||||
}
|
||||
};
|
||||
typedef http_simple_client_template<blocked_mode_client> http_simple_client;
|
||||
|
||||
class http_simple_client_factory : public http_client_factory
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<abstract_http_client> create() override {
|
||||
return std::unique_ptr<epee::net_utils::http::abstract_http_client>(new epee::net_utils::http::http_simple_client());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,17 @@
|
||||
MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \
|
||||
response.m_response_code = 200; \
|
||||
response.m_response_comment = "Ok"; \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context)) \
|
||||
{response.m_response_code = 404;response.m_response_comment = "Not found";} \
|
||||
try \
|
||||
{ \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context)) \
|
||||
{response.m_response_code = 404;response.m_response_comment = "Not found";} \
|
||||
} \
|
||||
catch (const std::exception &e) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Exception in handle_http_request_map: " << e.what()); \
|
||||
response.m_response_code = 500; \
|
||||
response.m_response_comment = "Internal Server Error"; \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
@@ -69,9 +78,11 @@
|
||||
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
MINFO(m_conn_context << "calling " << s_pattern); \
|
||||
if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \
|
||||
response_info.m_response_code = 500; \
|
||||
response_info.m_response_comment = "Internal Server Error"; \
|
||||
return true; \
|
||||
@@ -97,9 +108,11 @@
|
||||
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
MINFO(m_conn_context << "calling " << s_pattern); \
|
||||
if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "()"); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \
|
||||
response_info.m_response_code = 500; \
|
||||
response_info.m_response_comment = "Internal Server Error"; \
|
||||
return true; \
|
||||
@@ -184,7 +197,10 @@
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
fail_resp.id = req.id; \
|
||||
MINFO(m_conn_context << "Calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, fail_resp.error, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, fail_resp.error, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
|
||||
return true; \
|
||||
@@ -203,7 +219,10 @@
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
fail_resp.id = req.id; \
|
||||
MINFO(m_conn_context << "calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
|
||||
return true; \
|
||||
@@ -217,7 +236,10 @@
|
||||
{ \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
MINFO(m_conn_context << "calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include "int-util.h"
|
||||
|
||||
// IP addresses are kept in network byte order
|
||||
@@ -40,30 +38,6 @@ namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
inline
|
||||
bool is_ipv6_local(const std::string& ip)
|
||||
{
|
||||
auto addr = boost::asio::ip::address_v6::from_string(ip);
|
||||
|
||||
// ipv6 link-local unicast addresses are fe80::/10
|
||||
bool is_link_local = addr.is_link_local();
|
||||
|
||||
auto addr_bytes = addr.to_bytes();
|
||||
|
||||
// ipv6 unique local unicast addresses start with fc00::/7 -- (fcXX or fdXX)
|
||||
bool is_unique_local_unicast = (addr_bytes[0] == 0xfc || addr_bytes[0] == 0xfd);
|
||||
|
||||
return is_link_local || is_unique_local_unicast;
|
||||
}
|
||||
|
||||
inline
|
||||
bool is_ipv6_loopback(const std::string& ip)
|
||||
{
|
||||
// ipv6 loopback is ::1
|
||||
return boost::asio::ip::address_v6::from_string(ip).is_loopback();
|
||||
}
|
||||
|
||||
inline
|
||||
bool is_ip_local(uint32_t ip)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -226,7 +228,7 @@ public:
|
||||
Item v = data[heap[0]];
|
||||
if (minCt < maxCt)
|
||||
{
|
||||
v = (v + data[heap[-1]]) / 2;
|
||||
v = get_mid<Item>(v, data[heap[-1]]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ namespace epee
|
||||
#define BEGIN_INVOKE_MAP2(owner_type) \
|
||||
template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_context& context, bool& handled) \
|
||||
{ \
|
||||
try { \
|
||||
typedef owner_type internal_owner_type_name;
|
||||
|
||||
#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \
|
||||
@@ -336,7 +337,13 @@ namespace epee
|
||||
LOG_ERROR("Unknown command:" << command); \
|
||||
on_levin_traffic(context, false, false, true, in_buff.size(), "invalid-command"); \
|
||||
return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \
|
||||
} \
|
||||
catch (const std::exception &e) { \
|
||||
MERROR("Error in handle_invoke_map: " << e.what()); \
|
||||
return LEVIN_ERROR_CONNECTION_TIMEDOUT; /* seems kinda appropriate */ \
|
||||
} \
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +137,11 @@ namespace http
|
||||
set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool epee::net_utils::http::abstract_http_client::set_proxy(const std::string& address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ Setup for LXC:
|
||||
|
||||
```bash
|
||||
GH_USER=fluffypony
|
||||
VERSION=v0.15.0.0
|
||||
VERSION=v0.17.0.0
|
||||
|
||||
./gitian-build.py --setup $GH_USER $VERSION
|
||||
```
|
||||
@@ -182,7 +182,7 @@ If you chose to do detached signing using `--detach-sign` above (recommended), y
|
||||
|
||||
```bash
|
||||
GH_USER=fluffypony
|
||||
VERSION=v0.15.0.0
|
||||
VERSION=v0.17.0.0
|
||||
|
||||
gpg --detach-sign ${VERSION}-linux/${GH_USER}/monero-linux-*-build.assert
|
||||
gpg --detach-sign ${VERSION}-win/${GH_USER}/monero-win-*-build.assert
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "wownero-android-0.8"
|
||||
name: "monero-android-0.17"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "bionic"
|
||||
@@ -32,8 +32,8 @@ packages:
|
||||
- "python3-zmq"
|
||||
- "unzip"
|
||||
remotes:
|
||||
- "url": "https://github.com/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
- "url": "https://github.com/monero-project/monero.git"
|
||||
"dir": "monero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -75,7 +75,7 @@ script: |
|
||||
then
|
||||
ABI=$i"eabi"
|
||||
fi
|
||||
NDKDIR="${BUILD_DIR}/wownero/contrib/depends/$i/native/bin"
|
||||
NDKDIR="${BUILD_DIR}/monero/contrib/depends/$i/native/bin"
|
||||
for prog in ${FAKETIME_HOST_PROGS}; do
|
||||
WRAPPER=${WRAP_DIR}/${ABI}-${prog}
|
||||
echo '#!/usr/bin/env bash' > ${WRAPPER}
|
||||
@@ -97,7 +97,7 @@ script: |
|
||||
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
|
||||
|
||||
git config --global core.abbrev 9
|
||||
cd wownero
|
||||
cd monero
|
||||
# Set the version string that gets added to the tar archive name
|
||||
version="`git describe`"
|
||||
if [[ $version == *"-"*"-"* ]]; then
|
||||
@@ -127,7 +127,7 @@ script: |
|
||||
chmod 755 bin/*
|
||||
cp ../LICENSE bin
|
||||
chmod 644 bin/LICENSE
|
||||
DISTNAME=wownero-${i}-${version}
|
||||
DISTNAME=monero-${i}-${version}
|
||||
mv bin ${DISTNAME}
|
||||
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
|
||||
cd ..
|
||||
|
||||
@@ -5,8 +5,8 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
gsigs = 'https://github.com/wownero/gitian.sigs.git'
|
||||
gbrepo = 'https://github.com/wownero/gitian-builder.git'
|
||||
gsigs = 'https://github.com/monero-project/gitian.sigs.git'
|
||||
gbrepo = 'https://github.com/devrandom/gitian-builder.git'
|
||||
|
||||
platforms = {'l': ['Linux', 'linux', 'tar.bz2'],
|
||||
'a': ['Android', 'android', 'tar.bz2'],
|
||||
@@ -31,8 +31,8 @@ def setup():
|
||||
subprocess.check_call(['git', 'checkout', 'c0f77ca018cb5332bfd595e0aff0468f77542c23'])
|
||||
os.makedirs('inputs', exist_ok=True)
|
||||
os.chdir('inputs')
|
||||
if not os.path.isdir('wownero'):
|
||||
subprocess.check_call(['git', 'clone', args.url, 'wownero'])
|
||||
if not os.path.isdir('monero'):
|
||||
subprocess.check_call(['git', 'clone', args.url, 'monero'])
|
||||
os.chdir('..')
|
||||
make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
|
||||
if args.docker:
|
||||
@@ -67,10 +67,10 @@ def rebuild():
|
||||
suffix = platforms[i][2]
|
||||
|
||||
print('\nCompiling ' + args.version + ' ' + os_name)
|
||||
infile = 'inputs/wownero/contrib/gitian/gitian-' + tag_name + '.yml'
|
||||
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'wownero='+args.commit, '--url', 'wownero='+args.url, infile])
|
||||
infile = 'inputs/monero/contrib/gitian/gitian-' + tag_name + '.yml'
|
||||
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'monero='+args.commit, '--url', 'monero='+args.url, infile])
|
||||
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-'+tag_name, '--destination', '../sigs/', infile])
|
||||
subprocess.check_call('mv build/out/wownero-*.' + suffix + ' ../out/'+args.version, shell=True)
|
||||
subprocess.check_call('mv build/out/monero-*.' + suffix + ' ../out/'+args.version, shell=True)
|
||||
print('Moving var/install.log to var/install-' + tag_name + '.log')
|
||||
subprocess.check_call('mv var/install.log var/install-' + tag_name + '.log', shell=True)
|
||||
print('Moving var/build.log to var/build-' + tag_name + '.log')
|
||||
@@ -98,7 +98,7 @@ def build():
|
||||
subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch'])
|
||||
subprocess.check_output(["echo 'a8c4e9cafba922f89de0df1f2152e7be286aba73f78505169bc351a7938dd911 inputs/osslsigncode-Backports-to-1.7.1.patch' | sha256sum -c"], shell=True)
|
||||
subprocess.check_output(["echo 'f9a8cdb38b9c309326764ebc937cba1523a3a751a7ab05df3ecc99d18ae466c9 inputs/osslsigncode-1.7.1.tar.gz' | sha256sum -c"], shell=True)
|
||||
subprocess.check_call(['make', '-C', 'inputs/wownero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common'])
|
||||
subprocess.check_call(['make', '-C', 'inputs/monero/contrib/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common'])
|
||||
|
||||
rebuild()
|
||||
|
||||
@@ -109,7 +109,7 @@ def verify():
|
||||
|
||||
for i, v in platforms:
|
||||
print('\nVerifying v'+args.version+' '+v[0]+'\n')
|
||||
subprocess.check_call(['bin/gverify', '-v', '-d', '../sigs/', '-r', args.version+'-'+v[1], 'inputs/wownero/contrib/gitian/gitian-'+v[1]+'.yml'])
|
||||
subprocess.check_call(['bin/gverify', '-v', '-d', '../sigs/', '-r', args.version+'-'+v[1], 'inputs/monero/contrib/gitian/gitian-'+v[1]+'.yml'])
|
||||
os.chdir(workdir)
|
||||
|
||||
def main():
|
||||
@@ -118,7 +118,7 @@ def main():
|
||||
parser = argparse.ArgumentParser(description='Script for running full Gitian builds.', usage='%(prog)s [options] signer version')
|
||||
parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch')
|
||||
parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request')
|
||||
parser.add_argument('-u', '--url', dest='url', default='https://github.com/wownero/wownero', help='Specify the URL of the repository. Default is %(default)s')
|
||||
parser.add_argument('-u', '--url', dest='url', default='https://github.com/monero-project/monero', help='Specify the URL of the repository. Default is %(default)s')
|
||||
parser.add_argument('-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')
|
||||
@@ -190,8 +190,8 @@ def main():
|
||||
if args.setup:
|
||||
setup()
|
||||
|
||||
os.makedirs('builder/inputs/wownero', exist_ok=True)
|
||||
os.chdir('builder/inputs/wownero')
|
||||
os.makedirs('builder/inputs/monero', exist_ok=True)
|
||||
os.chdir('builder/inputs/monero')
|
||||
if args.pull:
|
||||
subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge'])
|
||||
args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True).strip()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "wownero-freebsd-0.8"
|
||||
name: "monero-freebsd-0.17"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "bionic"
|
||||
@@ -32,8 +32,8 @@ packages:
|
||||
- "libprotobuf-dev"
|
||||
- "python3-zmq"
|
||||
remotes:
|
||||
- "url": "https://github.com/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
- "url": "https://github.com/monero-project/monero.git"
|
||||
"dir": "monero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -92,7 +92,7 @@ script: |
|
||||
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
|
||||
|
||||
git config --global core.abbrev 9
|
||||
cd wownero
|
||||
cd monero
|
||||
# Set the version string that gets added to the tar archive name
|
||||
version="`git describe`"
|
||||
if [[ $version == *"-"*"-"* ]]; then
|
||||
@@ -124,7 +124,7 @@ script: |
|
||||
chmod 755 bin/*
|
||||
cp ../LICENSE bin
|
||||
chmod 644 bin/LICENSE
|
||||
DISTNAME=wownero-${i}-${version}
|
||||
DISTNAME=monero-${i}-${version}
|
||||
mv bin ${DISTNAME}
|
||||
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
|
||||
cd ..
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "wownero-linux-0.8"
|
||||
name: "monero-linux-0.17"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "bionic"
|
||||
@@ -43,8 +43,8 @@ packages:
|
||||
- "libprotobuf-dev"
|
||||
- "python3-zmq"
|
||||
remotes:
|
||||
- "url": "https://github.com/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
- "url": "https://github.com/monero-project/monero.git"
|
||||
"dir": "monero"
|
||||
files: []
|
||||
script: |
|
||||
|
||||
@@ -115,7 +115,7 @@ script: |
|
||||
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
|
||||
|
||||
git config --global core.abbrev 9
|
||||
cd wownero
|
||||
cd monero
|
||||
# Set the version string that gets added to the tar archive name
|
||||
version="`git describe`"
|
||||
if [[ $version == *"-"*"-"* ]]; then
|
||||
@@ -164,7 +164,7 @@ script: |
|
||||
chmod 755 bin/*
|
||||
cp ../LICENSE bin
|
||||
chmod 644 bin/LICENSE
|
||||
DISTNAME=wownero-${i}-${version}
|
||||
DISTNAME=monero-${i}-${version}
|
||||
mv bin ${DISTNAME}
|
||||
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
|
||||
cd ..
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "wownero-osx-0.8"
|
||||
name: "monero-osx-0.17"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "bionic"
|
||||
@@ -24,8 +24,8 @@ packages:
|
||||
- "python-dev"
|
||||
- "python-setuptools"
|
||||
remotes:
|
||||
- "url": "https://github.com/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
- "url": "https://github.com/monero-project/monero.git"
|
||||
"dir": "monero"
|
||||
files:
|
||||
- "MacOSX10.11.sdk.tar.gz"
|
||||
script: |
|
||||
@@ -77,7 +77,7 @@ script: |
|
||||
export PATH=${WRAP_DIR}:${PATH}
|
||||
|
||||
git config --global core.abbrev 9
|
||||
cd wownero
|
||||
cd monero
|
||||
# Set the version string that gets added to the tar archive name
|
||||
version="`git describe`"
|
||||
if [[ $version == *"-"*"-"* ]]; then
|
||||
@@ -113,7 +113,7 @@ script: |
|
||||
chmod 755 bin/*
|
||||
cp ../LICENSE bin
|
||||
chmod 644 bin/LICENSE
|
||||
DISTNAME=wownero-${i}-${version}
|
||||
DISTNAME=monero-${i}-${version}
|
||||
mv bin ${DISTNAME}
|
||||
find ${DISTNAME}/ | sort | tar --no-recursion --owner=0 --group=0 -c -T - | bzip2 -9 > ${OUTDIR}/${DISTNAME}.tar.bz2
|
||||
cd ..
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: "wownero-win-0.8"
|
||||
name: "monero-win-0.17"
|
||||
enable_cache: true
|
||||
suites:
|
||||
- "bionic"
|
||||
@@ -36,8 +36,8 @@ alternatives:
|
||||
package: "x86_64-w64-mingw32-gcc"
|
||||
path: "/usr/bin/x86_64-w64-mingw32-gcc-posix"
|
||||
remotes:
|
||||
- "url": "https://github.com/wownero/wownero.git"
|
||||
"dir": "wownero"
|
||||
- "url": "https://github.com/monero-project/monero.git"
|
||||
"dir": "monero"
|
||||
files: []
|
||||
script: |
|
||||
WRAP_DIR=$HOME/wrapped
|
||||
@@ -91,7 +91,7 @@ script: |
|
||||
export SOURCE_DATE_EPOCH=`date -d 2000-01-01T12:00:00 +%s`
|
||||
|
||||
git config --global core.abbrev 9
|
||||
cd wownero
|
||||
cd monero
|
||||
# Set the version string that gets added to the tar archive name
|
||||
version="`git describe`"
|
||||
if [[ $version == *"-"*"-"* ]]; then
|
||||
@@ -128,7 +128,7 @@ script: |
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=${BASEPREFIX}/${i}/share/toolchain.cmake
|
||||
make ${MAKEOPTS}
|
||||
cp ../LICENSE bin
|
||||
DISTNAME=wownero-${i}-${version}
|
||||
DISTNAME=monero-${i}-${version}
|
||||
mv bin ${DISTNAME}
|
||||
find ${DISTNAME}/ | sort | zip -X@ ${OUTDIR}/${DISTNAME}.zip
|
||||
cd .. && rm -rf build
|
||||
|
||||
48
external/CMakeLists.txt
vendored
48
external/CMakeLists.txt
vendored
@@ -34,42 +34,22 @@
|
||||
# We always compile if we are building statically to reduce static dependency issues...
|
||||
# ...except for FreeBSD, because FreeBSD is a special case that doesn't play well with
|
||||
# others.
|
||||
if(NOT IOS)
|
||||
find_package(Miniupnpc QUIET)
|
||||
|
||||
find_package(Miniupnpc REQUIRED)
|
||||
|
||||
message(STATUS "Using in-tree miniupnpc")
|
||||
add_subdirectory(miniupnp/miniupnpc)
|
||||
set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
|
||||
if(MSVC)
|
||||
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
||||
elseif(NOT MSVC)
|
||||
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value")
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -D_NETBSD_SOURCE")
|
||||
endif()
|
||||
|
||||
# If we have the correct shared version and we're not building static, use it
|
||||
if(STATIC OR IOS)
|
||||
set(USE_SHARED_MINIUPNPC false)
|
||||
elseif(MINIUPNP_FOUND AND MINIUPNPC_VERSION_1_7_OR_HIGHER)
|
||||
set(USE_SHARED_MINIUPNPC true)
|
||||
endif()
|
||||
|
||||
if(USE_SHARED_MINIUPNPC)
|
||||
message(STATUS "Using shared miniupnpc found at ${MINIUPNP_INCLUDE_DIR}")
|
||||
|
||||
set(UPNP_STATIC false PARENT_SCOPE)
|
||||
set(UPNP_INCLUDE ${MINIUPNP_INCLUDE_DIR} PARENT_SCOPE)
|
||||
set(UPNP_LIBRARIES ${MINIUPNP_LIBRARY} PARENT_SCOPE)
|
||||
else()
|
||||
if(STATIC)
|
||||
message(STATUS "Using miniupnpc from local source tree for static build")
|
||||
else()
|
||||
message(STATUS "Using miniupnpc from local source tree (/external/miniupnp/miniupnpc)")
|
||||
endif()
|
||||
|
||||
add_subdirectory(miniupnp/miniupnpc)
|
||||
|
||||
set_property(TARGET libminiupnpc-static PROPERTY FOLDER "external")
|
||||
if(MSVC)
|
||||
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -wd4244 -wd4267")
|
||||
elseif(NOT MSVC)
|
||||
set_property(TARGET libminiupnpc-static APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-unused-result -Wno-unused-value")
|
||||
endif()
|
||||
|
||||
set(UPNP_STATIC true PARENT_SCOPE)
|
||||
set(UPNP_LIBRARIES "libminiupnpc-static" PARENT_SCOPE)
|
||||
endif()
|
||||
set(UPNP_LIBRARIES "libminiupnpc-static" PARENT_SCOPE)
|
||||
|
||||
find_package(Unbound)
|
||||
|
||||
|
||||
2
external/easylogging++/ea_config.h
vendored
2
external/easylogging++/ea_config.h
vendored
@@ -11,7 +11,7 @@
|
||||
#define ELPP_UTC_DATETIME
|
||||
|
||||
#ifdef EASYLOGGING_CC
|
||||
#if !(!defined __GLIBC__ || !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__)
|
||||
#if !(!defined __GLIBC__ || !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__ || defined __NetBSD__)
|
||||
#define ELPP_FEATURE_CRASH_LOG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
11
external/easylogging++/easylogging++.cc
vendored
11
external/easylogging++/easylogging++.cc
vendored
@@ -2968,6 +2968,16 @@ void Writer::initializeLogger(Logger *logger, bool needLock) {
|
||||
}
|
||||
|
||||
void Writer::processDispatch() {
|
||||
static std::atomic_flag in_dispatch;
|
||||
if (in_dispatch.test_and_set())
|
||||
{
|
||||
if (m_proceed && m_logger != NULL)
|
||||
{
|
||||
m_logger->stream().str(ELPP_LITERAL(""));
|
||||
m_logger->releaseLock();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if ELPP_LOGGING_ENABLED
|
||||
if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) {
|
||||
bool firstDispatched = false;
|
||||
@@ -3006,6 +3016,7 @@ void Writer::processDispatch() {
|
||||
m_logger->releaseLock();
|
||||
}
|
||||
#endif // ELPP_LOGGING_ENABLED
|
||||
in_dispatch.clear();
|
||||
}
|
||||
|
||||
void Writer::triggerDispatch(void) {
|
||||
|
||||
3
external/qrcodegen/CMakeLists.txt
vendored
3
external/qrcodegen/CMakeLists.txt
vendored
@@ -1,7 +1,8 @@
|
||||
project(libqrcodegen)
|
||||
|
||||
add_library(qrcodegen STATIC QrCode.cpp)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set_target_properties(qrcodegen PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
set_target_properties(qrcodegen PROPERTIES CXX_STANDARD 11)
|
||||
|
||||
target_include_directories(qrcodegen PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
1
external/supercop
vendored
Submodule
1
external/supercop
vendored
Submodule
Submodule external/supercop added at 633500ad8c
@@ -63,6 +63,7 @@ bool matches_category(relay_method method, relay_category category) noexcept
|
||||
{
|
||||
default:
|
||||
case relay_method::local:
|
||||
case relay_method::forward:
|
||||
case relay_method::stem:
|
||||
return false;
|
||||
case relay_method::block:
|
||||
@@ -79,6 +80,7 @@ void txpool_tx_meta_t::set_relay_method(relay_method method) noexcept
|
||||
kept_by_block = 0;
|
||||
do_not_relay = 0;
|
||||
is_local = 0;
|
||||
is_forwarding = 0;
|
||||
dandelionpp_stem = 0;
|
||||
|
||||
switch (method)
|
||||
@@ -89,8 +91,8 @@ void txpool_tx_meta_t::set_relay_method(relay_method method) noexcept
|
||||
case relay_method::local:
|
||||
is_local = 1;
|
||||
break;
|
||||
default:
|
||||
case relay_method::fluff:
|
||||
case relay_method::forward:
|
||||
is_forwarding = 1;
|
||||
break;
|
||||
case relay_method::stem:
|
||||
dandelionpp_stem = 1;
|
||||
@@ -98,26 +100,45 @@ void txpool_tx_meta_t::set_relay_method(relay_method method) noexcept
|
||||
case relay_method::block:
|
||||
kept_by_block = 1;
|
||||
break;
|
||||
default:
|
||||
case relay_method::fluff:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
relay_method txpool_tx_meta_t::get_relay_method() const noexcept
|
||||
{
|
||||
if (kept_by_block)
|
||||
return relay_method::block;
|
||||
if (do_not_relay)
|
||||
return relay_method::none;
|
||||
if (is_local)
|
||||
return relay_method::local;
|
||||
if (dandelionpp_stem)
|
||||
return relay_method::stem;
|
||||
const uint8_t state =
|
||||
uint8_t(kept_by_block) +
|
||||
(uint8_t(do_not_relay) << 1) +
|
||||
(uint8_t(is_local) << 2) +
|
||||
(uint8_t(is_forwarding) << 3) +
|
||||
(uint8_t(dandelionpp_stem) << 4);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
default: // error case
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return relay_method::block;
|
||||
case 2:
|
||||
return relay_method::none;
|
||||
case 4:
|
||||
return relay_method::local;
|
||||
case 8:
|
||||
return relay_method::forward;
|
||||
case 16:
|
||||
return relay_method::stem;
|
||||
};
|
||||
return relay_method::fluff;
|
||||
}
|
||||
|
||||
bool txpool_tx_meta_t::upgrade_relay_method(relay_method method) noexcept
|
||||
{
|
||||
static_assert(relay_method::none < relay_method::local, "bad relay_method value");
|
||||
static_assert(relay_method::local < relay_method::stem, "bad relay_method value");
|
||||
static_assert(relay_method::local < relay_method::forward, "bad relay_method value");
|
||||
static_assert(relay_method::forward < relay_method::stem, "bad relay_method value");
|
||||
static_assert(relay_method::stem < relay_method::fluff, "bad relay_method value");
|
||||
static_assert(relay_method::fluff < relay_method::block, "bad relay_method value");
|
||||
|
||||
@@ -158,7 +179,7 @@ void BlockchainDB::pop_block()
|
||||
pop_block(blk, txs);
|
||||
}
|
||||
|
||||
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr)
|
||||
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr)
|
||||
{
|
||||
const transaction &tx = txp.first;
|
||||
|
||||
@@ -260,12 +281,13 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
time1 = epee::misc_utils::get_tick_count();
|
||||
|
||||
uint64_t num_rct_outs = 0;
|
||||
add_transaction(blk_hash, std::make_pair(blk.miner_tx, tx_to_blob(blk.miner_tx)));
|
||||
blobdata miner_bd = tx_to_blob(blk.miner_tx);
|
||||
add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd)));
|
||||
if (blk.miner_tx.version == 2)
|
||||
num_rct_outs += blk.miner_tx.vout.size();
|
||||
int tx_i = 0;
|
||||
crypto::hash tx_hash = crypto::null_hash;
|
||||
for (const std::pair<transaction, blobdata>& tx : txs)
|
||||
for (const std::pair<transaction, blobdata_ref>& tx : txs)
|
||||
{
|
||||
tx_hash = blk.tx_hashes[tx_i];
|
||||
add_transaction(blk_hash, tx, &tx_hash);
|
||||
|
||||
@@ -160,7 +160,7 @@ struct txpool_tx_meta_t
|
||||
uint64_t max_used_block_height;
|
||||
uint64_t last_failed_height;
|
||||
uint64_t receive_time;
|
||||
uint64_t last_relayed_time; //!< If Dandelion++ stem, randomized embargo timestamp. Otherwise, last relayed timestmap.
|
||||
uint64_t last_relayed_time; //!< If received over i2p/tor, randomized forward time. If Dandelion++stem, randomized embargo time. Otherwise, last relayed timestamp
|
||||
// 112 bytes
|
||||
uint8_t kept_by_block;
|
||||
uint8_t relayed;
|
||||
@@ -169,7 +169,8 @@ struct txpool_tx_meta_t
|
||||
uint8_t pruned: 1;
|
||||
uint8_t is_local: 1;
|
||||
uint8_t dandelionpp_stem : 1;
|
||||
uint8_t bf_padding: 4;
|
||||
uint8_t is_forwarding: 1;
|
||||
uint8_t bf_padding: 3;
|
||||
|
||||
uint8_t padding[76]; // till 192 bytes
|
||||
|
||||
@@ -439,7 +440,7 @@ private:
|
||||
* @param tx_prunable_hash the hash of the prunable part of the transaction
|
||||
* @return the transaction ID
|
||||
*/
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0;
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) = 0;
|
||||
|
||||
/**
|
||||
* @brief remove data about a transaction
|
||||
@@ -567,7 +568,7 @@ protected:
|
||||
* @param tx_hash_ptr the hash of the transaction, if already calculated
|
||||
* @param tx_prunable_hash_ptr the hash of the prunable part of the transaction, if already calculated
|
||||
*/
|
||||
void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL);
|
||||
void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL);
|
||||
|
||||
mutable uint64_t time_tx_exists = 0; //!< a performance metric
|
||||
uint64_t time_commit1 = 0; //!< a performance metric
|
||||
@@ -1523,7 +1524,7 @@ public:
|
||||
*
|
||||
* @param details the details of the transaction to add
|
||||
*/
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& details) = 0;
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t& details) = 0;
|
||||
|
||||
/**
|
||||
* @brief update a txpool transaction's metadata
|
||||
@@ -1643,7 +1644,7 @@ public:
|
||||
* @param: data: the metadata for the block
|
||||
* @param: blob: the block's blob
|
||||
*/
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob) = 0;
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob) = 0;
|
||||
|
||||
/**
|
||||
* @brief get an alternative block by hash
|
||||
@@ -1686,7 +1687,7 @@ public:
|
||||
*
|
||||
* @return false if the function returns false for any transaction, otherwise true
|
||||
*/
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const = 0;
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const = 0;
|
||||
|
||||
/**
|
||||
* @brief runs a function over all key images stored
|
||||
@@ -1778,7 +1779,7 @@ public:
|
||||
*
|
||||
* @return false if the function returns false for any output, otherwise true
|
||||
*/
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const = 0;
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const = 0;
|
||||
|
||||
|
||||
//
|
||||
|
||||
@@ -856,7 +856,7 @@ void BlockchainLMDB::remove_block()
|
||||
throw1(DB_ERROR(lmdb_error("Failed to add removal of block info to db transaction: ", result).c_str()));
|
||||
}
|
||||
|
||||
uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash)
|
||||
uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -896,7 +896,7 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add tx data to db transaction: ", result).c_str()));
|
||||
|
||||
const cryptonote::blobdata &blob = txp.second;
|
||||
const cryptonote::blobdata_ref &blob = txp.second;
|
||||
MDB_val_sized(blobval, blob);
|
||||
|
||||
unsigned int unprunable_size = tx.unprunable_size;
|
||||
@@ -1756,7 +1756,7 @@ void BlockchainLMDB::unlock()
|
||||
auto_txn.commit(); \
|
||||
} while(0)
|
||||
|
||||
void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
|
||||
void BlockchainLMDB::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t &meta)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -2308,7 +2308,7 @@ bool BlockchainLMDB::check_pruning()
|
||||
return prune_worker(prune_mode_check, 0);
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category category) const
|
||||
bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob, relay_category category) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -2334,8 +2334,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&,
|
||||
const txpool_tx_meta_t &meta = *(const txpool_tx_meta_t*)v.mv_data;
|
||||
if (!meta.matches(category))
|
||||
continue;
|
||||
const cryptonote::blobdata *passed_bd = NULL;
|
||||
cryptonote::blobdata bd;
|
||||
cryptonote::blobdata_ref bd;
|
||||
if (include_blob)
|
||||
{
|
||||
MDB_val b;
|
||||
@@ -2344,11 +2343,10 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&,
|
||||
throw0(DB_ERROR("Failed to find txpool tx blob to match metadata"));
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate txpool tx blob: ", result).c_str()));
|
||||
bd.assign(reinterpret_cast<const char*>(b.mv_data), b.mv_size);
|
||||
passed_bd = &bd;
|
||||
bd = {reinterpret_cast<const char*>(b.mv_data), b.mv_size};
|
||||
}
|
||||
|
||||
if (!f(txid, meta, passed_bd)) {
|
||||
if (!f(txid, meta, &bd)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -2359,7 +2357,7 @@ bool BlockchainLMDB::for_all_txpool_txes(std::function<bool(const crypto::hash&,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const cryptonote::blobdata*)> f, bool include_blob) const
|
||||
bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&, const alt_block_data_t&, const cryptonote::blobdata_ref*)> f, bool include_blob) const
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -2384,15 +2382,13 @@ bool BlockchainLMDB::for_all_alt_blocks(std::function<bool(const crypto::hash&,
|
||||
if (v.mv_size < sizeof(alt_block_data_t))
|
||||
throw0(DB_ERROR("alt_blocks record is too small"));
|
||||
const alt_block_data_t *data = (const alt_block_data_t*)v.mv_data;
|
||||
const cryptonote::blobdata *passed_bd = NULL;
|
||||
cryptonote::blobdata bd;
|
||||
cryptonote::blobdata_ref bd;
|
||||
if (include_blob)
|
||||
{
|
||||
bd.assign(reinterpret_cast<const char*>(v.mv_data) + sizeof(alt_block_data_t), v.mv_size - sizeof(alt_block_data_t));
|
||||
passed_bd = &bd;
|
||||
bd = {reinterpret_cast<const char*>(v.mv_data) + sizeof(alt_block_data_t), v.mv_size - sizeof(alt_block_data_t)};
|
||||
}
|
||||
|
||||
if (!f(blkid, *data, passed_bd)) {
|
||||
if (!f(blkid, *data, &bd)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
@@ -3604,8 +3600,7 @@ bool BlockchainLMDB::for_blocks_range(const uint64_t& h1, const uint64_t& h2, st
|
||||
if (ret)
|
||||
throw0(DB_ERROR("Failed to enumerate blocks"));
|
||||
uint64_t height = *(const uint64_t*)k.mv_data;
|
||||
blobdata bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
blobdata_ref bd{reinterpret_cast<char*>(v.mv_data), v.mv_size};
|
||||
block b;
|
||||
if (!parse_and_validate_block_from_blob(bd, b))
|
||||
throw0(DB_ERROR("Failed to parse block from blob retrieved from the db"));
|
||||
@@ -3660,15 +3655,16 @@ bool BlockchainLMDB::for_all_transactions(std::function<bool(const crypto::hash&
|
||||
if (ret)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to enumerate transactions: ", ret).c_str()));
|
||||
transaction tx;
|
||||
blobdata bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
if (pruned)
|
||||
{
|
||||
blobdata_ref bd{reinterpret_cast<char*>(v.mv_data), v.mv_size};
|
||||
if (!parse_and_validate_tx_base_from_blob(bd, tx))
|
||||
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
|
||||
}
|
||||
else
|
||||
{
|
||||
blobdata bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
ret = mdb_cursor_get(m_cur_txs_prunable, &k, &v, MDB_SET);
|
||||
if (ret)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get prunable tx data the db: ", ret).c_str()));
|
||||
@@ -4402,7 +4398,7 @@ uint8_t BlockchainLMDB::get_hard_fork_version(uint64_t height) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob)
|
||||
void BlockchainLMDB::add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@@ -4969,7 +4965,7 @@ void BlockchainLMDB::migrate_0_1()
|
||||
}
|
||||
|
||||
MDB_dbi o_txs;
|
||||
blobdata bd;
|
||||
blobdata_ref bd;
|
||||
block b;
|
||||
MDB_val hk;
|
||||
|
||||
@@ -5051,7 +5047,7 @@ void BlockchainLMDB::migrate_0_1()
|
||||
} else if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get a record from blocks: ", result).c_str()));
|
||||
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
bd = {reinterpret_cast<char*>(v.mv_data), v.mv_size};
|
||||
if (!parse_and_validate_block_from_blob(bd, b))
|
||||
throw0(DB_ERROR("Failed to parse block from blob retrieved from the db"));
|
||||
|
||||
@@ -5062,7 +5058,7 @@ void BlockchainLMDB::migrate_0_1()
|
||||
result = mdb_cursor_get(c_txs, &hk, &v, MDB_SET);
|
||||
if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get record from txs: ", result).c_str()));
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
bd = {reinterpret_cast<char*>(v.mv_data), v.mv_size};
|
||||
if (!parse_and_validate_tx_from_blob(bd, tx))
|
||||
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
|
||||
add_transaction(null_hash, std::make_pair(std::move(tx), bd), &b.tx_hashes[j]);
|
||||
@@ -5184,8 +5180,7 @@ void BlockchainLMDB::migrate_1_2()
|
||||
else if (result)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get a record from txs: ", result).c_str()));
|
||||
|
||||
cryptonote::blobdata bd;
|
||||
bd.assign(reinterpret_cast<char*>(v.mv_data), v.mv_size);
|
||||
cryptonote::blobdata bd{reinterpret_cast<char*>(v.mv_data), v.mv_size};
|
||||
transaction tx;
|
||||
if (!parse_and_validate_tx_from_blob(bd, tx))
|
||||
throw0(DB_ERROR("Failed to parse tx from blob retrieved from the db"));
|
||||
|
||||
@@ -283,7 +283,7 @@ public:
|
||||
|
||||
virtual bool has_key_image(const crypto::key_image& img) const;
|
||||
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t& meta);
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const txpool_tx_meta_t& meta);
|
||||
virtual void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t& meta);
|
||||
virtual uint64_t get_txpool_tx_count(relay_category category = relay_category::broadcasted) const;
|
||||
virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const;
|
||||
@@ -296,20 +296,20 @@ public:
|
||||
virtual bool update_pruning();
|
||||
virtual bool check_pruning();
|
||||
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob);
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob);
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob);
|
||||
virtual void remove_alt_block(const crypto::hash &blkid);
|
||||
virtual uint64_t get_alt_block_count();
|
||||
virtual void drop_alt_blocks();
|
||||
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob = false, relay_category category = relay_category::broadcasted) const;
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob = false, relay_category category = relay_category::broadcasted) const;
|
||||
|
||||
virtual bool for_all_key_images(std::function<bool(const crypto::key_image&)>) const;
|
||||
virtual bool for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const;
|
||||
virtual bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>, bool pruned) const;
|
||||
virtual bool for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const;
|
||||
virtual bool for_all_outputs(uint64_t amount, const std::function<bool(uint64_t height)> &f) const;
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const;
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const;
|
||||
|
||||
virtual uint64_t add_block( const std::pair<block, blobdata>& blk
|
||||
, size_t block_weight
|
||||
@@ -376,7 +376,7 @@ private:
|
||||
|
||||
virtual void remove_block();
|
||||
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash);
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash);
|
||||
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx);
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
virtual std::vector<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<uint64_t>>(); }
|
||||
virtual bool has_key_image(const crypto::key_image& img) const override { return false; }
|
||||
virtual void remove_block() override { }
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {}
|
||||
virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {}
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
virtual std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>> get_output_histogram(const std::vector<uint64_t> &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count) const override { return std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t>>(); }
|
||||
virtual bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, std::vector<uint64_t> &distribution, uint64_t &base) const override { return false; }
|
||||
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata_ref &blob, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual void update_txpool_tx(const crypto::hash &txid, const cryptonote::txpool_tx_meta_t& details) override {}
|
||||
virtual uint64_t get_txpool_tx_count(relay_category tx_relay = relay_category::broadcasted) const override { return 0; }
|
||||
virtual bool txpool_has_tx(const crypto::hash &txid, relay_category tx_category) const override { return false; }
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const override { return false; }
|
||||
virtual uint64_t get_database_size() const override { return 0; }
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
|
||||
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
@@ -160,12 +160,12 @@ public:
|
||||
virtual uint64_t get_max_block_size() override { return 100000000; }
|
||||
virtual void add_max_block_size(uint64_t sz) override { }
|
||||
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata &blob) override {}
|
||||
virtual void add_alt_block(const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref &blob) override {}
|
||||
virtual bool get_alt_block(const crypto::hash &blkid, alt_block_data_t *data, cryptonote::blobdata *blob) override { return false; }
|
||||
virtual void remove_alt_block(const crypto::hash &blkid) override {}
|
||||
virtual uint64_t get_alt_block_count() override { return 0; }
|
||||
virtual void drop_alt_blocks() override {}
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata *blob)> f, bool include_blob = false) const override { return true; }
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const override { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/archive/portable_binary_iarchive.hpp>
|
||||
#include <boost/archive/portable_binary_oarchive.hpp>
|
||||
#include "common/unordered_containers_boost_serialization.h"
|
||||
#include "common/command_line.h"
|
||||
#include "common/varint.h"
|
||||
|
||||
@@ -68,6 +68,9 @@ int main(int argc, char* argv[])
|
||||
const command_line::arg_descriptor<bool> arg_outputs = {"with-outputs", "with output stats", false};
|
||||
const command_line::arg_descriptor<bool> arg_ringsize = {"with-ringsize", "with ringsize stats", false};
|
||||
const command_line::arg_descriptor<bool> arg_hours = {"with-hours", "with txns per hour", false};
|
||||
const command_line::arg_descriptor<bool> arg_emission = {"with-emission", "with coin emission", false};
|
||||
const command_line::arg_descriptor<bool> arg_fees = {"with-fees", "with txn fees", false};
|
||||
const command_line::arg_descriptor<bool> arg_diff = {"with-diff", "with difficulty", false};
|
||||
|
||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
|
||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
|
||||
@@ -79,6 +82,9 @@ int main(int argc, char* argv[])
|
||||
command_line::add_arg(desc_cmd_sett, arg_outputs);
|
||||
command_line::add_arg(desc_cmd_sett, arg_ringsize);
|
||||
command_line::add_arg(desc_cmd_sett, arg_hours);
|
||||
command_line::add_arg(desc_cmd_sett, arg_emission);
|
||||
command_line::add_arg(desc_cmd_sett, arg_fees);
|
||||
command_line::add_arg(desc_cmd_sett, arg_diff);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_help);
|
||||
|
||||
po::options_description desc_options("Allowed options");
|
||||
@@ -120,6 +126,9 @@ int main(int argc, char* argv[])
|
||||
bool do_outputs = command_line::get_arg(vm, arg_outputs);
|
||||
bool do_ringsize = command_line::get_arg(vm, arg_ringsize);
|
||||
bool do_hours = command_line::get_arg(vm, arg_hours);
|
||||
bool do_emission = command_line::get_arg(vm, arg_emission);
|
||||
bool do_fees = command_line::get_arg(vm, arg_fees);
|
||||
bool do_diff = command_line::get_arg(vm, arg_diff);
|
||||
|
||||
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
|
||||
std::unique_ptr<Blockchain> core_storage;
|
||||
@@ -177,12 +186,20 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
|
||||
// spit out a comment that GnuPlot can use as an index
|
||||
std::cout << ENDL << "# DATA" << ENDL;
|
||||
std::cout << "Date\tBlocks/day\tBlocks\tTxs/Day\tTxs\tBytes/Day\tBytes";
|
||||
if (do_emission)
|
||||
std::cout << "\tEmission/day\tEmission";
|
||||
if (do_fees)
|
||||
std::cout << "\tFees/day\tFees";
|
||||
if (do_diff)
|
||||
std::cout << "\tDiffMin\tDiffMax\tDiffAvg";
|
||||
if (do_inputs)
|
||||
std::cout << "\tInMin\tInMax\tInAvg";
|
||||
if (do_outputs)
|
||||
std::cout << "\tOutMin\tOutMax\tOutAvg";
|
||||
if (do_ringsize)
|
||||
std::cout << "\tRingMin\tRingMax\tRingAvg";
|
||||
if (do_inputs || do_outputs || do_ringsize)
|
||||
std::cout << std::setprecision(2) << std::fixed;
|
||||
if (do_hours) {
|
||||
char buf[8];
|
||||
unsigned int i;
|
||||
@@ -193,14 +210,20 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
|
||||
}
|
||||
std::cout << ENDL;
|
||||
|
||||
#define MAX_INOUT 0xffffffff
|
||||
#define MAX_RINGS 0xffffffff
|
||||
|
||||
struct tm prevtm = {0}, currtm;
|
||||
uint64_t prevsz = 0, currsz = 0;
|
||||
uint64_t prevtxs = 0, currtxs = 0;
|
||||
uint64_t currblks = 0;
|
||||
uint64_t totins = 0, totouts = 0, totrings = 0;
|
||||
uint32_t minins = 10, maxins = 0;
|
||||
uint32_t minouts = 10, maxouts = 0;
|
||||
uint32_t minrings = 50, maxrings = 0;
|
||||
boost::multiprecision::uint128_t prevemission = 0, prevfees = 0;
|
||||
boost::multiprecision::uint128_t emission = 0, fees = 0;
|
||||
boost::multiprecision::uint128_t totdiff = 0, mindiff = 0, maxdiff = 0;
|
||||
uint32_t minins = MAX_INOUT, maxins = 0;
|
||||
uint32_t minouts = MAX_INOUT, maxouts = 0;
|
||||
uint32_t minrings = MAX_RINGS, maxrings = 0;
|
||||
uint32_t io, tottxs = 0;
|
||||
uint32_t txhr[24] = {0};
|
||||
unsigned int i;
|
||||
@@ -230,34 +253,50 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
|
||||
std::cout << timebuf << "\t" << currblks << "\t" << h << "\t" << currtxs << "\t" << prevtxs + currtxs << "\t" << currsz << "\t" << prevsz + currsz;
|
||||
prevsz += currsz;
|
||||
currsz = 0;
|
||||
currblks = 0;
|
||||
prevtxs += currtxs;
|
||||
currtxs = 0;
|
||||
if (!tottxs)
|
||||
tottxs = 1;
|
||||
if (do_emission) {
|
||||
std::cout << "\t" << print_money(emission) << "\t" << print_money(prevemission + emission);
|
||||
prevemission += emission;
|
||||
emission = 0;
|
||||
}
|
||||
if (do_fees) {
|
||||
std::cout << "\t" << print_money(fees) << "\t" << print_money(prevfees + fees);
|
||||
prevfees += fees;
|
||||
fees = 0;
|
||||
}
|
||||
if (do_diff) {
|
||||
std::cout << "\t" << (maxdiff ? mindiff : 0) << "\t" << maxdiff << "\t" << totdiff / currblks;
|
||||
mindiff = 0; maxdiff = 0; totdiff = 0;
|
||||
}
|
||||
if (do_inputs) {
|
||||
std::cout << "\t" << (maxins ? minins : 0) << "\t" << maxins << "\t" << totins / tottxs;
|
||||
minins = 10; maxins = 0; totins = 0;
|
||||
std::cout << "\t" << (maxins ? minins : 0) << "\t" << maxins << "\t" << totins * 1.0 / tottxs;
|
||||
minins = MAX_INOUT; maxins = 0; totins = 0;
|
||||
}
|
||||
if (do_outputs) {
|
||||
std::cout << "\t" << (maxouts ? minouts : 0) << "\t" << maxouts << "\t" << totouts / tottxs;
|
||||
minouts = 10; maxouts = 0; totouts = 0;
|
||||
std::cout << "\t" << (maxouts ? minouts : 0) << "\t" << maxouts << "\t" << totouts * 1.0 / tottxs;
|
||||
minouts = MAX_INOUT; maxouts = 0; totouts = 0;
|
||||
}
|
||||
if (do_ringsize) {
|
||||
std::cout << "\t" << (maxrings ? minrings : 0) << "\t" << maxrings << "\t" << totrings / tottxs;
|
||||
minrings = 50; maxrings = 0; totrings = 0;
|
||||
std::cout << "\t" << (maxrings ? minrings : 0) << "\t" << maxrings << "\t" << totrings * 1.0 / tottxs;
|
||||
minrings = MAX_RINGS; maxrings = 0; totrings = 0;
|
||||
}
|
||||
tottxs = 0;
|
||||
if (do_hours) {
|
||||
for (i=0; i<24; i++) {
|
||||
std::cout << "\t" << txhr[i];
|
||||
txhr[i] = 0;
|
||||
}
|
||||
}
|
||||
currblks = 0;
|
||||
tottxs = 0;
|
||||
std::cout << ENDL;
|
||||
}
|
||||
skip:
|
||||
currsz += bd.size();
|
||||
uint64_t coinbase_amount;
|
||||
uint64_t tx_fee_amount = 0;
|
||||
for (const auto& tx_id : blk.tx_hashes)
|
||||
{
|
||||
if (tx_id == crypto::null_hash)
|
||||
@@ -275,7 +314,12 @@ skip:
|
||||
return 1;
|
||||
}
|
||||
currsz += bd.size();
|
||||
if (db->get_prunable_tx_blob(tx_id, bd))
|
||||
currsz += bd.size();
|
||||
currtxs++;
|
||||
if (do_fees || do_emission) {
|
||||
tx_fee_amount += get_tx_fee(tx);
|
||||
}
|
||||
if (do_hours)
|
||||
txhr[currtm.tm_hour]++;
|
||||
if (do_inputs) {
|
||||
@@ -306,6 +350,21 @@ skip:
|
||||
}
|
||||
tottxs++;
|
||||
}
|
||||
if (do_diff) {
|
||||
difficulty_type diff = db->get_block_difficulty(h);
|
||||
if (!mindiff || diff < mindiff)
|
||||
mindiff = diff;
|
||||
if (diff > maxdiff)
|
||||
maxdiff = diff;
|
||||
totdiff += diff;
|
||||
}
|
||||
if (do_emission) {
|
||||
coinbase_amount = get_outs_money_amount(blk.miner_tx);
|
||||
emission += coinbase_amount - tx_fee_amount;
|
||||
}
|
||||
if (do_fees) {
|
||||
fees += tx_fee_amount;
|
||||
}
|
||||
currblks++;
|
||||
|
||||
if (stop_requested)
|
||||
|
||||
Binary file not shown.
@@ -182,12 +182,26 @@ namespace cryptonote
|
||||
{
|
||||
if (nettype == TESTNET)
|
||||
{
|
||||
ADD_CHECKPOINT2(1, "c47b8effcc84e22ddd1b876d059c8fbd3e26e4bdffb6bed8b8f4fe283104a7af", "0x2");
|
||||
ADD_CHECKPOINT2(5, "292add330f6cf5f3845dc4cd2f28ce8d211dd487ddcfe1b5d1d545d7b90ff7d1", "0x5df"); //Hard fork to v8
|
||||
ADD_CHECKPOINT2(10, "fbdf7d812aa6dd4c5915aadcbf023e722eab1d8ad47c24a230634e688d314798", "0xfa3"); //Hard fork to v9
|
||||
ADD_CHECKPOINT2(15, "9b86e40b959d7cfe75366686dfd2657699e85b8c658aa8c20b23f7bc01b38af0", "0x1967"); //Hard fork to v10
|
||||
ADD_CHECKPOINT2(20, "8f65c309ba3ed2bf25df2b7d91e1db40c864230aa3caaf823db81bc19e0bd6a3", "0x232b"); //Hard fork to v11
|
||||
ADD_CHECKPOINT2(25, "35f2957fdba45d5421561ba2f126a61ec0101b5c2eb79b9e296310acbbdbbe58", "0x2cef"); //Hard fork to v12
|
||||
ADD_CHECKPOINT2(30, "32cc5aacce8bea10ae869313e194ba51a30720810f3665433ffeea2818938429", "0x36b3"); //Hard fork to v13
|
||||
ADD_CHECKPOINT2(35, "7f1cdd2c4a6002772343ad9de6c5dba743a0be1d326a6f63924511f08b15863a", "0x4077"); //Hard fork to v14
|
||||
ADD_CHECKPOINT2(40, "63cf4f703489a881baf63bacd6a3af2b5bde79b558ce123e97313890be6f747f", "0x4a3b"); //Hard fork to v15
|
||||
ADD_CHECKPOINT2(45, "65da4c966ae02983c6c8b7ab9b959df612863c379c5e48669061cbbb1e02a3ab", "0x53ff"); //Hard fork to v16
|
||||
ADD_CHECKPOINT2(50, "8c68a444b6743a14152f130357be9751e42e82a84f69f25320eda532a830c7b0", "0x5dc3"); //Hard fork to v17
|
||||
return true;
|
||||
}
|
||||
if (nettype == STAGENET)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// make RPC call to daemon
|
||||
// curl http://127.0.0.1:34568/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"get_block","params":{"height":247600}}' -H 'Content-Type: application/json'
|
||||
// "wide_cumulative_difficulty": "0x14eb4d0131fe8",
|
||||
ADD_CHECKPOINT2(1, "97f4ce4d7879b3bea54dcec738cd2ebb7952b4e9bb9743262310cd5fec749340", "0x2");
|
||||
ADD_CHECKPOINT2(6969, "aa7b66e8c461065139b55c29538a39c33ceda93e587f84d490ed573d80511c87", "0x118eef693fd"); //Hard fork to v8
|
||||
ADD_CHECKPOINT2(53666, "3f43f56f66ef0c43cf2fd14d0d28fa2aae0ef8f40716773511345750770f1255", "0xb677d6405ae"); //Hard fork to v9
|
||||
@@ -197,7 +211,8 @@ namespace cryptonote
|
||||
ADD_CHECKPOINT2(114969, "b48245956b87f243048fd61021f4b3e5443e57eee7ff8ba4762d18926e80b80c", "0x1ca552b3ec68"); //Hard fork to v13
|
||||
ADD_CHECKPOINT2(115257, "338e056551087fe23d6c4b4280244bc5362b004716d85ec799a775f190f9fea9", "0x1cb25f5d4628"); //Hard fork to v14
|
||||
ADD_CHECKPOINT2(160777, "9496690579af21f38f00e67e11c2e85a15912fe4f412aad33d1162be1579e755", "0x5376eaa196a8"); //Hard fork to v15
|
||||
ADD_CHECKPOINT2(230200, "0ebb018c452fa84997f573937db67ef3946a857ee57cd40fa51ffe368896c666", "0xbcc1409c7268");
|
||||
ADD_CHECKPOINT2(247600, "f5ecf7b9d2376d7b1d4ca7843c7d39c5854b8f94c968bf9bc2072fa2e0c92ef7", "0x14eb4d0131fe8");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -519,14 +519,14 @@ bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std
|
||||
// send all requests in parallel
|
||||
std::deque<bool> avail(dns_urls.size(), false), valid(dns_urls.size(), false);
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
tools::threadpool::waiter waiter;
|
||||
tools::threadpool::waiter waiter(tpool);
|
||||
for (size_t n = 0; n < dns_urls.size(); ++n)
|
||||
{
|
||||
tpool.submit(&waiter,[n, dns_urls, &records, &avail, &valid](){
|
||||
records[n] = tools::DNSResolver::instance().get_txt_record(dns_urls[n], avail[n], valid[n]);
|
||||
});
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
waiter.wait();
|
||||
|
||||
size_t cur_index = first_index;
|
||||
do
|
||||
|
||||
@@ -62,7 +62,7 @@ static void replace(std::vector<std::string> &v, const char *tag, const char *s)
|
||||
boost::replace_all(str, tag, s);
|
||||
}
|
||||
|
||||
int Notify::notify(const char *tag, const char *s, ...)
|
||||
int Notify::notify(const char *tag, const char *s, ...) const
|
||||
{
|
||||
std::vector<std::string> margs = args;
|
||||
|
||||
|
||||
@@ -38,8 +38,12 @@ class Notify
|
||||
{
|
||||
public:
|
||||
Notify(const char *spec);
|
||||
Notify(const Notify&) = default;
|
||||
Notify(Notify&&) = default;
|
||||
Notify& operator=(const Notify&) = default;
|
||||
Notify& operator=(Notify&&) = default;
|
||||
|
||||
int notify(const char *tag, const char *s, ...);
|
||||
int notify(const char *tag, const char *s, ...) const;
|
||||
|
||||
private:
|
||||
std::string filename;
|
||||
@@ -47,3 +51,4 @@ private:
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ threadpool::waiter::~waiter()
|
||||
catch (...) { /* ignore */ }
|
||||
try
|
||||
{
|
||||
wait(NULL);
|
||||
wait();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -128,12 +128,12 @@ threadpool::waiter::~waiter()
|
||||
}
|
||||
}
|
||||
|
||||
void threadpool::waiter::wait(threadpool *tpool) {
|
||||
if (tpool)
|
||||
tpool->run(true);
|
||||
bool threadpool::waiter::wait() {
|
||||
pool.run(true);
|
||||
boost::unique_lock<boost::mutex> lock(mt);
|
||||
while(num)
|
||||
cv.wait(lock);
|
||||
return !error();
|
||||
}
|
||||
|
||||
void threadpool::waiter::inc() {
|
||||
@@ -166,7 +166,8 @@ void threadpool::run(bool flush) {
|
||||
lock.unlock();
|
||||
++depth;
|
||||
is_leaf = e.leaf;
|
||||
e.f();
|
||||
try { e.f(); }
|
||||
catch (const std::exception &ex) { e.wo->set_error(); try { MERROR("Exception in threadpool job: " << ex.what()); } catch (...) {} }
|
||||
--depth;
|
||||
is_leaf = false;
|
||||
|
||||
|
||||
@@ -55,12 +55,16 @@ public:
|
||||
class waiter {
|
||||
boost::mutex mt;
|
||||
boost::condition_variable cv;
|
||||
threadpool &pool;
|
||||
int num;
|
||||
bool error_flag;
|
||||
public:
|
||||
void inc();
|
||||
void dec();
|
||||
void wait(threadpool *tpool); //! Wait for a set of tasks to finish.
|
||||
waiter() : num(0){}
|
||||
bool wait(); //! Wait for a set of tasks to finish, returns false iff any error
|
||||
void set_error() noexcept { error_flag = true; }
|
||||
bool error() const noexcept { return error_flag; }
|
||||
waiter(threadpool &pool) : pool(pool), num(0), error_flag(false) {}
|
||||
~waiter();
|
||||
};
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ namespace tools
|
||||
const char *base = user ? "" : "";
|
||||
#ifdef _WIN32
|
||||
static const char *extension = strncmp(buildtag.c_str(), "source", 6) ? (strncmp(buildtag.c_str(), "install-", 8) ? ".zip" : ".exe") : ".tar.bz2";
|
||||
#elif defined(__APPLE__)
|
||||
static const char *extension = strncmp(software.c_str(), "monero-gui", 10) ? ".tar.bz2" : ".dmg";
|
||||
#else
|
||||
static const char extension[] = ".tar.bz2";
|
||||
#endif
|
||||
|
||||
@@ -1116,7 +1116,7 @@ std::string get_nix_version_display_string()
|
||||
static constexpr const byte_map sizes[] =
|
||||
{
|
||||
{"%.0f B", 1024},
|
||||
{"%.2f KB", 1024 * 1024},
|
||||
{"%.2f kB", 1024 * 1024},
|
||||
{"%.2f MB", std::uint64_t(1024) * 1024 * 1024},
|
||||
{"%.2f GB", std::uint64_t(1024) * 1024 * 1024 * 1024},
|
||||
{"%.2f TB", std::uint64_t(1024) * 1024 * 1024 * 1024 * 1024}
|
||||
|
||||
@@ -116,3 +116,6 @@ endif()
|
||||
|
||||
# cheat because cmake and ccache hate each other
|
||||
set_property(SOURCE CryptonightR_template.S PROPERTY LANGUAGE C)
|
||||
|
||||
# Must be done last, because it references libraries in this directory
|
||||
add_subdirectory(wallet)
|
||||
|
||||
@@ -1234,6 +1234,56 @@ void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const g
|
||||
}
|
||||
}
|
||||
|
||||
// Computes aG + bB + cC (G is the fixed basepoint)
|
||||
void ge_triple_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const unsigned char *b, const ge_dsmp Bi, const unsigned char *c, const ge_dsmp Ci) {
|
||||
signed char aslide[256];
|
||||
signed char bslide[256];
|
||||
signed char cslide[256];
|
||||
ge_p1p1 t;
|
||||
ge_p3 u;
|
||||
int i;
|
||||
|
||||
slide(aslide, a);
|
||||
slide(bslide, b);
|
||||
slide(cslide, c);
|
||||
|
||||
ge_p2_0(r);
|
||||
|
||||
for (i = 255; i >= 0; --i) {
|
||||
if (aslide[i] || bslide[i] || cslide[i]) break;
|
||||
}
|
||||
|
||||
for (; i >= 0; --i) {
|
||||
ge_p2_dbl(&t, r);
|
||||
|
||||
if (aslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_madd(&t, &u, &ge_Bi[aslide[i]/2]);
|
||||
} else if (aslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_msub(&t, &u, &ge_Bi[(-aslide[i])/2]);
|
||||
}
|
||||
|
||||
if (bslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Bi[bslide[i]/2]);
|
||||
} else if (bslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Bi[(-bslide[i])/2]);
|
||||
}
|
||||
|
||||
if (cslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ci[cslide[i]/2]);
|
||||
} else if (cslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ci[(-cslide[i])/2]);
|
||||
}
|
||||
|
||||
ge_p1p1_to_p2(r, &t);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r3, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
|
||||
signed char aslide[256];
|
||||
signed char bslide[256];
|
||||
@@ -2148,6 +2198,56 @@ void ge_double_scalarmult_precomp_vartime2(ge_p2 *r, const unsigned char *a, con
|
||||
}
|
||||
}
|
||||
|
||||
// Computes aA + bB + cC (all points require precomputation)
|
||||
void ge_triple_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi, const unsigned char *c, const ge_dsmp Ci) {
|
||||
signed char aslide[256];
|
||||
signed char bslide[256];
|
||||
signed char cslide[256];
|
||||
ge_p1p1 t;
|
||||
ge_p3 u;
|
||||
int i;
|
||||
|
||||
slide(aslide, a);
|
||||
slide(bslide, b);
|
||||
slide(cslide, c);
|
||||
|
||||
ge_p2_0(r);
|
||||
|
||||
for (i = 255; i >= 0; --i) {
|
||||
if (aslide[i] || bslide[i] || cslide[i]) break;
|
||||
}
|
||||
|
||||
for (; i >= 0; --i) {
|
||||
ge_p2_dbl(&t, r);
|
||||
|
||||
if (aslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ai[aslide[i]/2]);
|
||||
} else if (aslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ai[(-aslide[i])/2]);
|
||||
}
|
||||
|
||||
if (bslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Bi[bslide[i]/2]);
|
||||
} else if (bslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Bi[(-bslide[i])/2]);
|
||||
}
|
||||
|
||||
if (cslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ci[cslide[i]/2]);
|
||||
} else if (cslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ci[(-cslide[i])/2]);
|
||||
}
|
||||
|
||||
ge_p1p1_to_p2(r, &t);
|
||||
}
|
||||
}
|
||||
|
||||
void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *r3, const unsigned char *a, const ge_dsmp Ai, const unsigned char *b, const ge_dsmp Bi) {
|
||||
signed char aslide[256];
|
||||
signed char bslide[256];
|
||||
|
||||
@@ -79,6 +79,7 @@ typedef ge_cached ge_dsmp[8];
|
||||
extern const ge_precomp ge_Bi[8];
|
||||
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s);
|
||||
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *);
|
||||
void ge_triple_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
|
||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *, const unsigned char *, const ge_p3 *, const unsigned char *);
|
||||
|
||||
/* From ge_frombytes.c, modified */
|
||||
@@ -130,6 +131,7 @@ void sc_reduce(unsigned char *);
|
||||
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
|
||||
void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *);
|
||||
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
|
||||
void ge_triple_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
|
||||
void ge_double_scalarmult_precomp_vartime2(ge_p2 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
|
||||
void ge_double_scalarmult_precomp_vartime2_p3(ge_p3 *, const unsigned char *, const ge_dsmp, const unsigned char *, const ge_dsmp);
|
||||
void ge_mul8(ge_p1p1 *, const ge_p2 *);
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
#include "crypto.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include "cryptonote_config.h"
|
||||
|
||||
namespace {
|
||||
static void local_abort(const char *msg)
|
||||
{
|
||||
@@ -261,11 +263,24 @@ namespace crypto {
|
||||
ec_point comm;
|
||||
};
|
||||
|
||||
// Used in v1 tx proofs
|
||||
struct s_comm_2_v1 {
|
||||
hash msg;
|
||||
ec_point D;
|
||||
ec_point X;
|
||||
ec_point Y;
|
||||
};
|
||||
|
||||
// Used in v1/v2 tx proofs
|
||||
struct s_comm_2 {
|
||||
hash msg;
|
||||
ec_point D;
|
||||
ec_point X;
|
||||
ec_point Y;
|
||||
hash sep; // domain separation
|
||||
ec_point R;
|
||||
ec_point A;
|
||||
ec_point B;
|
||||
};
|
||||
|
||||
void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
|
||||
@@ -321,6 +336,86 @@ namespace crypto {
|
||||
return sc_isnonzero(&c) == 0;
|
||||
}
|
||||
|
||||
// Generate a proof of knowledge of `r` such that (`R = rG` and `D = rA`) or (`R = rB` and `D = rA`) via a Schnorr proof
|
||||
// This handles use cases for both standard addresses and subaddresses
|
||||
//
|
||||
// NOTE: This generates old v1 proofs, and is for TESTING ONLY
|
||||
void crypto_ops::generate_tx_proof_v1(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
|
||||
// sanity check
|
||||
ge_p3 R_p3;
|
||||
ge_p3 A_p3;
|
||||
ge_p3 B_p3;
|
||||
ge_p3 D_p3;
|
||||
if (ge_frombytes_vartime(&R_p3, &R) != 0) throw std::runtime_error("tx pubkey is invalid");
|
||||
if (ge_frombytes_vartime(&A_p3, &A) != 0) throw std::runtime_error("recipient view pubkey is invalid");
|
||||
if (B && ge_frombytes_vartime(&B_p3, &*B) != 0) throw std::runtime_error("recipient spend pubkey is invalid");
|
||||
if (ge_frombytes_vartime(&D_p3, &D) != 0) throw std::runtime_error("key derivation is invalid");
|
||||
#if !defined(NDEBUG)
|
||||
{
|
||||
assert(sc_check(&r) == 0);
|
||||
// check R == r*G or R == r*B
|
||||
public_key dbg_R;
|
||||
if (B)
|
||||
{
|
||||
ge_p2 dbg_R_p2;
|
||||
ge_scalarmult(&dbg_R_p2, &r, &B_p3);
|
||||
ge_tobytes(&dbg_R, &dbg_R_p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
ge_p3 dbg_R_p3;
|
||||
ge_scalarmult_base(&dbg_R_p3, &r);
|
||||
ge_p3_tobytes(&dbg_R, &dbg_R_p3);
|
||||
}
|
||||
assert(R == dbg_R);
|
||||
// check D == r*A
|
||||
ge_p2 dbg_D_p2;
|
||||
ge_scalarmult(&dbg_D_p2, &r, &A_p3);
|
||||
public_key dbg_D;
|
||||
ge_tobytes(&dbg_D, &dbg_D_p2);
|
||||
assert(D == dbg_D);
|
||||
}
|
||||
#endif
|
||||
|
||||
// pick random k
|
||||
ec_scalar k;
|
||||
random_scalar(k);
|
||||
|
||||
s_comm_2_v1 buf;
|
||||
buf.msg = prefix_hash;
|
||||
buf.D = D;
|
||||
|
||||
if (B)
|
||||
{
|
||||
// compute X = k*B
|
||||
ge_p2 X_p2;
|
||||
ge_scalarmult(&X_p2, &k, &B_p3);
|
||||
ge_tobytes(&buf.X, &X_p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compute X = k*G
|
||||
ge_p3 X_p3;
|
||||
ge_scalarmult_base(&X_p3, &k);
|
||||
ge_p3_tobytes(&buf.X, &X_p3);
|
||||
}
|
||||
|
||||
// compute Y = k*A
|
||||
ge_p2 Y_p2;
|
||||
ge_scalarmult(&Y_p2, &k, &A_p3);
|
||||
ge_tobytes(&buf.Y, &Y_p2);
|
||||
|
||||
// sig.c = Hs(Msg || D || X || Y)
|
||||
hash_to_scalar(&buf, sizeof(buf), sig.c);
|
||||
|
||||
// sig.r = k - sig.c*r
|
||||
sc_mulsub(&sig.r, &sig.c, &unwrap(r), &k);
|
||||
}
|
||||
|
||||
// Generate a proof of knowledge of `r` such that (`R = rG` and `D = rA`) or (`R = rB` and `D = rA`) via a Schnorr proof
|
||||
// This handles use cases for both standard addresses and subaddresses
|
||||
//
|
||||
// Generates only proofs for InProofV2 and OutProofV2
|
||||
void crypto_ops::generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
|
||||
// sanity check
|
||||
ge_p3 R_p3;
|
||||
@@ -362,10 +457,20 @@ namespace crypto {
|
||||
ec_scalar k;
|
||||
random_scalar(k);
|
||||
|
||||
// if B is not present
|
||||
static const ec_point zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
|
||||
|
||||
s_comm_2 buf;
|
||||
buf.msg = prefix_hash;
|
||||
buf.D = D;
|
||||
|
||||
buf.R = R;
|
||||
buf.A = A;
|
||||
if (B)
|
||||
buf.B = *B;
|
||||
else
|
||||
buf.B = zero;
|
||||
cn_fast_hash(config::HASH_KEY_TXPROOF_V2, sizeof(config::HASH_KEY_TXPROOF_V2)-1, buf.sep);
|
||||
|
||||
if (B)
|
||||
{
|
||||
// compute X = k*B
|
||||
@@ -386,7 +491,7 @@ namespace crypto {
|
||||
ge_scalarmult(&Y_p2, &k, &A_p3);
|
||||
ge_tobytes(&buf.Y, &Y_p2);
|
||||
|
||||
// sig.c = Hs(Msg || D || X || Y)
|
||||
// sig.c = Hs(Msg || D || X || Y || sep || R || A || B)
|
||||
hash_to_scalar(&buf, sizeof(buf), sig.c);
|
||||
|
||||
// sig.r = k - sig.c*r
|
||||
@@ -395,7 +500,8 @@ namespace crypto {
|
||||
memwipe(&k, sizeof(k));
|
||||
}
|
||||
|
||||
bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
|
||||
// Verify a proof: either v1 (version == 1) or v2 (version == 2)
|
||||
bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig, const int version) {
|
||||
// sanity check
|
||||
ge_p3 R_p3;
|
||||
ge_p3 A_p3;
|
||||
@@ -467,14 +573,31 @@ namespace crypto {
|
||||
ge_p2 Y_p2;
|
||||
ge_p1p1_to_p2(&Y_p2, &Y_p1p1);
|
||||
|
||||
// compute c2 = Hs(Msg || D || X || Y)
|
||||
// Compute hash challenge
|
||||
// for v1, c2 = Hs(Msg || D || X || Y)
|
||||
// for v2, c2 = Hs(Msg || D || X || Y || sep || R || A || B)
|
||||
|
||||
// if B is not present
|
||||
static const ec_point zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
|
||||
|
||||
s_comm_2 buf;
|
||||
buf.msg = prefix_hash;
|
||||
buf.D = D;
|
||||
buf.R = R;
|
||||
buf.A = A;
|
||||
if (B)
|
||||
buf.B = *B;
|
||||
else
|
||||
buf.B = zero;
|
||||
cn_fast_hash(config::HASH_KEY_TXPROOF_V2, sizeof(config::HASH_KEY_TXPROOF_V2)-1, buf.sep);
|
||||
ge_tobytes(&buf.X, &X_p2);
|
||||
ge_tobytes(&buf.Y, &Y_p2);
|
||||
ec_scalar c2;
|
||||
hash_to_scalar(&buf, sizeof(s_comm_2), c2);
|
||||
|
||||
// Hash depends on version
|
||||
if (version == 1) hash_to_scalar(&buf, sizeof(s_comm_2) - 3*sizeof(ec_point) - sizeof(hash), c2);
|
||||
else if (version == 2) hash_to_scalar(&buf, sizeof(s_comm_2), c2);
|
||||
else return false;
|
||||
|
||||
// test if c2 == sig.c
|
||||
sc_sub(&c2, &c2, &sig.c);
|
||||
|
||||
@@ -132,8 +132,10 @@ namespace crypto {
|
||||
friend bool check_signature(const hash &, const public_key &, const signature &);
|
||||
static void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
|
||||
friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
|
||||
static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
|
||||
friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
|
||||
static void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
|
||||
friend void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
|
||||
static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
|
||||
friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
|
||||
static void generate_key_image(const public_key &, const secret_key &, key_image &);
|
||||
friend void generate_key_image(const public_key &, const secret_key &, key_image &);
|
||||
static void generate_ring_signature(const hash &, const key_image &,
|
||||
@@ -248,8 +250,11 @@ namespace crypto {
|
||||
inline void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
|
||||
crypto_ops::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
|
||||
}
|
||||
inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
|
||||
return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig);
|
||||
inline void generate_tx_proof_v1(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
|
||||
crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
|
||||
}
|
||||
inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig, const int version) {
|
||||
return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
|
||||
}
|
||||
|
||||
/* To send money to a key:
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace crypto {
|
||||
inline void cn_slow_hash(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) {
|
||||
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 0/*prehashed*/, height);
|
||||
}
|
||||
|
||||
|
||||
inline void cn_slow_hash_prehashed(const void *data, std::size_t length, hash &hash, int variant = 0, uint64_t height = 0) {
|
||||
cn_slow_hash(data, length, reinterpret_cast<char *>(&hash), variant, 1/*prehashed*/, height);
|
||||
}
|
||||
|
||||
@@ -116,6 +116,46 @@ static inline int enabled_flags(void) {
|
||||
#define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */
|
||||
#define SEEDHASH_EPOCH_LAG 64
|
||||
|
||||
static inline int is_power_of_2(uint64_t n) { return n && (n & (n-1)) == 0; }
|
||||
|
||||
static int get_seedhash_epoch_lag(void)
|
||||
{
|
||||
static unsigned int lag = (unsigned int)-1;
|
||||
if (lag != (unsigned int)-1)
|
||||
return lag;
|
||||
const char *e = getenv("SEEDHASH_EPOCH_LAG");
|
||||
if (e)
|
||||
{
|
||||
lag = atoi(e);
|
||||
if (lag > SEEDHASH_EPOCH_LAG || !is_power_of_2(lag))
|
||||
lag = SEEDHASH_EPOCH_LAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
lag = SEEDHASH_EPOCH_LAG;
|
||||
}
|
||||
return lag;
|
||||
}
|
||||
|
||||
static unsigned int get_seedhash_epoch_blocks(void)
|
||||
{
|
||||
static unsigned int blocks = (unsigned int)-1;
|
||||
if (blocks != (unsigned int)-1)
|
||||
return blocks;
|
||||
const char *e = getenv("SEEDHASH_EPOCH_BLOCKS");
|
||||
if (e)
|
||||
{
|
||||
blocks = atoi(e);
|
||||
if (blocks < 2 || blocks > SEEDHASH_EPOCH_BLOCKS || !is_power_of_2(blocks))
|
||||
blocks = SEEDHASH_EPOCH_BLOCKS;
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks = SEEDHASH_EPOCH_BLOCKS;
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
void rx_reorg(const uint64_t split_height) {
|
||||
int i;
|
||||
CTHR_MUTEX_LOCK(rx_mutex);
|
||||
@@ -130,14 +170,16 @@ void rx_reorg(const uint64_t split_height) {
|
||||
}
|
||||
|
||||
uint64_t rx_seedheight(const uint64_t height) {
|
||||
uint64_t s_height = (height <= SEEDHASH_EPOCH_BLOCKS+SEEDHASH_EPOCH_LAG) ? 0 :
|
||||
(height - SEEDHASH_EPOCH_LAG - 1) & ~(SEEDHASH_EPOCH_BLOCKS-1);
|
||||
const uint64_t seedhash_epoch_lag = get_seedhash_epoch_lag();
|
||||
const uint64_t seedhash_epoch_blocks = get_seedhash_epoch_blocks();
|
||||
uint64_t s_height = (height <= seedhash_epoch_blocks+seedhash_epoch_lag) ? 0 :
|
||||
(height - seedhash_epoch_lag - 1) & ~(seedhash_epoch_blocks-1);
|
||||
return s_height;
|
||||
}
|
||||
|
||||
void rx_seedheights(const uint64_t height, uint64_t *seedheight, uint64_t *nextheight) {
|
||||
*seedheight = rx_seedheight(height);
|
||||
*nextheight = rx_seedheight(height + SEEDHASH_EPOCH_LAG);
|
||||
*nextheight = rx_seedheight(height + get_seedhash_epoch_lag());
|
||||
}
|
||||
|
||||
typedef struct seedinfo {
|
||||
@@ -161,11 +203,11 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_
|
||||
CTHR_THREAD_TYPE *st;
|
||||
si = malloc(miners * sizeof(seedinfo));
|
||||
if (si == NULL)
|
||||
local_abort("Couldn't allocate RandomWOW mining threadinfo");
|
||||
local_abort("Couldn't allocate RandomX mining threadinfo");
|
||||
st = malloc(miners * sizeof(CTHR_THREAD_TYPE));
|
||||
if (st == NULL) {
|
||||
free(si);
|
||||
local_abort("Couldn't allocate RandomWOW mining threadlist");
|
||||
local_abort("Couldn't allocate RandomX mining threadlist");
|
||||
}
|
||||
for (i=0; i<miners-1; i++) {
|
||||
si[i].si_cache = rs_cache;
|
||||
@@ -194,7 +236,7 @@ static void rx_initdata(randomx_cache *rs_cache, const int miners, const uint64_
|
||||
void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const char *seedhash, const void *data, size_t length,
|
||||
char *hash, int miners, int is_alt) {
|
||||
uint64_t s_height = rx_seedheight(mainheight);
|
||||
int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0;
|
||||
int toggle = (s_height & get_seedhash_epoch_blocks()) != 0;
|
||||
randomx_flags flags = enabled_flags() & ~disabled_flags();
|
||||
rx_state *rx_sp;
|
||||
randomx_cache *cache;
|
||||
@@ -225,11 +267,11 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
|
||||
if (cache == NULL) {
|
||||
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (cache == NULL) {
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomWOW cache");
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
|
||||
cache = randomx_alloc_cache(flags);
|
||||
}
|
||||
if (cache == NULL)
|
||||
local_abort("Couldn't allocate RandomWOW cache");
|
||||
local_abort("Couldn't allocate RandomX cache");
|
||||
}
|
||||
}
|
||||
if (rx_sp->rs_height != seedheight || rx_sp->rs_cache == NULL || memcmp(seedhash, rx_sp->rs_hash, HASH_SIZE)) {
|
||||
@@ -251,7 +293,7 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
|
||||
if (rx_dataset == NULL) {
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
|
||||
if (rx_dataset == NULL) {
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomWOW dataset");
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
|
||||
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
|
||||
}
|
||||
if (rx_dataset != NULL)
|
||||
@@ -264,14 +306,14 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
|
||||
miners = 0;
|
||||
if (!rx_dataset_nomem) {
|
||||
rx_dataset_nomem = 1;
|
||||
mwarning(RX_LOGCAT, "Couldn't allocate RandomWOW dataset for miner");
|
||||
mwarning(RX_LOGCAT, "Couldn't allocate RandomX dataset for miner");
|
||||
}
|
||||
}
|
||||
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
|
||||
}
|
||||
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
|
||||
if(rx_vm == NULL) { //large pages failed
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomWOW VM");
|
||||
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
|
||||
}
|
||||
if(rx_vm == NULL) {//fallback if everything fails
|
||||
@@ -279,7 +321,7 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
|
||||
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
|
||||
}
|
||||
if (rx_vm == NULL)
|
||||
local_abort("Couldn't allocate RandomWOW VM");
|
||||
local_abort("Couldn't allocate RandomX VM");
|
||||
} else if (miners) {
|
||||
CTHR_MUTEX_LOCK(rx_dataset_mutex);
|
||||
if (rx_dataset != NULL && rx_dataset_height != seedheight)
|
||||
|
||||
62
src/crypto/wallet/CMakeLists.txt
Normal file
62
src/crypto/wallet/CMakeLists.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
# Copyright (c) 2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# Possibly user defined values.
|
||||
#
|
||||
set(MONERO_WALLET_CRYPTO_LIBRARY "auto" CACHE STRING "Select a wallet crypto library")
|
||||
|
||||
#
|
||||
# If the user specified "auto", detect best library defaulting to internal.
|
||||
#
|
||||
if (${MONERO_WALLET_CRYPTO_LIBRARY} STREQUAL "auto")
|
||||
monero_crypto_autodetect(AVAILABLE BEST)
|
||||
if (DEFINED BEST)
|
||||
message("Wallet crypto is using ${BEST} backend")
|
||||
set(MONERO_WALLET_CRYPTO_LIBRARY ${BEST})
|
||||
else ()
|
||||
message("Defaulting to internal crypto library for wallet")
|
||||
set(MONERO_WALLET_CRYPTO_LIBRARY "cn")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
#
|
||||
# Configure library target "wallet-crypto" - clients will use this as a
|
||||
# library dependency which in turn will depend on the crypto library selected.
|
||||
#
|
||||
if (${MONERO_WALLET_CRYPTO_LIBRARY} STREQUAL "cn")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/empty.h.in ${MONERO_GENERATED_HEADERS_DIR}/crypto/wallet/ops.h)
|
||||
add_library(wallet-crypto ALIAS cncrypto)
|
||||
else ()
|
||||
monero_crypto_generate_header(${MONERO_WALLET_CRYPTO_LIBRARY} "${MONERO_GENERATED_HEADERS_DIR}/crypto/wallet/ops.h")
|
||||
monero_crypto_get_target(${MONERO_WALLET_CRYPTO_LIBRARY} CRYPTO_TARGET)
|
||||
add_library(wallet-crypto $<TARGET_OBJECTS:${CRYPTO_TARGET}>)
|
||||
target_link_libraries(wallet-crypto cncrypto)
|
||||
endif ()
|
||||
|
||||
|
||||
56
src/crypto/wallet/crypto.h
Normal file
56
src/crypto/wallet/crypto.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include "crypto/wallet/ops.h"
|
||||
|
||||
namespace crypto {
|
||||
namespace wallet {
|
||||
// if C functions defined from external/supercop - cmake generates crypto/wallet/ops.h
|
||||
#if defined(monero_crypto_generate_key_derivation)
|
||||
inline
|
||||
bool generate_key_derivation(const public_key &tx_pub, const secret_key &view_sec, key_derivation &out)
|
||||
{
|
||||
return monero_crypto_generate_key_derivation(out.data, tx_pub.data, view_sec.data) == 0;
|
||||
}
|
||||
|
||||
inline
|
||||
bool derive_subaddress_public_key(const public_key &output_pub, const key_derivation &d, std::size_t index, public_key &out)
|
||||
{
|
||||
ec_scalar scalar;
|
||||
derivation_to_scalar(d, index, scalar);
|
||||
return monero_crypto_generate_subaddress_public_key(out.data, output_pub.data, scalar.data) == 0;
|
||||
}
|
||||
#else
|
||||
using ::crypto::generate_key_derivation;
|
||||
using ::crypto::derive_subaddress_public_key;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
31
src/crypto/wallet/empty.h.in
Normal file
31
src/crypto/wallet/empty.h.in
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
// Left empty so internal cryptonote crypto library is used.
|
||||
@@ -31,10 +31,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/utility/string_ref_fwd.hpp>
|
||||
#include "span.h"
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
typedef std::string blobdata;
|
||||
typedef epee::span<const char> blobdata_ref;
|
||||
typedef boost::string_ref blobdata_ref;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <sstream>
|
||||
#include <atomic>
|
||||
#include "serialization/variant.h"
|
||||
#include "serialization/vector.h"
|
||||
#include "serialization/containers.h"
|
||||
#include "serialization/binary_archive.h"
|
||||
#include "serialization/json_archive.h"
|
||||
#include "serialization/debug_archive.h"
|
||||
|
||||
@@ -34,7 +34,6 @@ using namespace epee;
|
||||
#include "cryptonote_basic_impl.h"
|
||||
#include "string_tools.h"
|
||||
#include "serialization/binary_utils.h"
|
||||
#include "serialization/container.h"
|
||||
#include "cryptonote_format_utils.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "misc_language.h"
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include <boost/serialization/set.hpp>
|
||||
#include <boost/serialization/map.hpp>
|
||||
#include <boost/serialization/is_bitwise_serializable.hpp>
|
||||
#include <boost/archive/binary_iarchive.hpp>
|
||||
#include <boost/archive/portable_binary_iarchive.hpp>
|
||||
#include <boost/archive/portable_binary_oarchive.hpp>
|
||||
#include "cryptonote_basic.h"
|
||||
@@ -46,7 +45,6 @@
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
||||
//namespace cryptonote {
|
||||
namespace boost
|
||||
{
|
||||
namespace serialization
|
||||
@@ -245,6 +243,15 @@ namespace boost
|
||||
// a & x.II; // not serialized, we can recover it from the tx vin
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::clsag &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.s;
|
||||
a & x.c1;
|
||||
// a & x.I; // not serialized, we can recover it from the tx vin
|
||||
a & x.D;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, rct::ecdhTuple &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
@@ -265,6 +272,9 @@ namespace boost
|
||||
inline void serialize(Archive &a, rct::multisig_out &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.c;
|
||||
if (ver < 1)
|
||||
return;
|
||||
a & x.mu_p;
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
@@ -295,7 +305,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -313,6 +323,8 @@ namespace boost
|
||||
if (x.rangeSigs.empty())
|
||||
a & x.bulletproofs;
|
||||
a & x.MGs;
|
||||
if (ver >= 1u)
|
||||
a & x.CLSAGs;
|
||||
if (x.rangeSigs.empty())
|
||||
a & x.pseudoOuts;
|
||||
}
|
||||
@@ -323,7 +335,7 @@ namespace boost
|
||||
a & x.type;
|
||||
if (x.type == rct::RCTTypeNull)
|
||||
return;
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof)
|
||||
if (x.type != rct::RCTTypeFull && x.type != rct::RCTTypeSimple && x.type != rct::RCTTypeBulletproof && x.type != rct::RCTTypeBulletproof2 && x.type != rct::RCTTypeFullBulletproof && x.type != rct::RCTTypeSimpleBulletproof && x.type != rct::RCTTypeCLSAG)
|
||||
throw boost::archive::archive_exception(boost::archive::archive_exception::other_exception, "Unsupported rct type");
|
||||
// a & x.message; message is not serialized, as it can be reconstructed from the tx data
|
||||
// a & x.mixRing; mixRing is not serialized, as it can be reconstructed from the offsets
|
||||
@@ -337,7 +349,9 @@ namespace boost
|
||||
if (x.p.rangeSigs.empty())
|
||||
a & x.p.bulletproofs;
|
||||
a & x.p.MGs;
|
||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof)
|
||||
if (ver >= 1u)
|
||||
a & x.p.CLSAGs;
|
||||
if (x.type == rct::RCTTypeBulletproof || x.type == rct::RCTTypeBulletproof2 || x.type == rct::RCTTypeSimpleBulletproof || x.type == rct::RCTTypeCLSAG)
|
||||
a & x.p.pseudoOuts;
|
||||
}
|
||||
|
||||
@@ -378,4 +392,6 @@ namespace boost
|
||||
}
|
||||
}
|
||||
|
||||
//}
|
||||
BOOST_CLASS_VERSION(rct::rctSigPrunable, 1)
|
||||
BOOST_CLASS_VERSION(rct::rctSig, 1)
|
||||
BOOST_CLASS_VERSION(rct::multisig_out, 1)
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx)
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
@@ -242,7 +242,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx)
|
||||
bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
@@ -254,7 +254,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx)
|
||||
bool parse_and_validate_tx_prefix_from_blob(const blobdata_ref& tx_blob, transaction_prefix& tx)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
@@ -264,7 +264,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash)
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << tx_blob;
|
||||
@@ -278,7 +278,7 @@ namespace cryptonote
|
||||
return get_transaction_hash(tx, tx_hash);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
|
||||
{
|
||||
if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
|
||||
return false;
|
||||
@@ -462,7 +462,7 @@ namespace cryptonote
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
|
||||
CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
|
||||
CHECK_AND_ASSERT_MES(tx.rct_signatures.type >= rct::RCTTypeBulletproof2,
|
||||
CHECK_AND_ASSERT_MES(tx.rct_signatures.type >= rct::RCTTypeBulletproof2 || tx.rct_signatures.type == rct::RCTTypeCLSAG,
|
||||
std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support older range proof types");
|
||||
CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||
CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
|
||||
@@ -484,9 +484,12 @@ namespace cryptonote
|
||||
extra = 32 * (9 + 2 * nrl) + 2;
|
||||
weight += extra;
|
||||
|
||||
// calculate deterministic MLSAG data size
|
||||
// calculate deterministic CLSAG/MLSAG data size
|
||||
const size_t ring_size = boost::get<cryptonote::txin_to_key>(tx.vin[0]).key_offsets.size();
|
||||
extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */);
|
||||
if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
|
||||
extra = tx.vin.size() * (ring_size + 2) * 32;
|
||||
else
|
||||
extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */);
|
||||
weight += extra;
|
||||
|
||||
// calculate deterministic pseudoOuts size
|
||||
@@ -984,7 +987,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res)
|
||||
void get_blob_hash(const blobdata_ref& blob, crypto::hash& res)
|
||||
{
|
||||
cn_fast_hash(blob.data(), blob.size(), res);
|
||||
}
|
||||
@@ -1071,7 +1074,7 @@ namespace cryptonote
|
||||
return h;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_blob_hash(const epee::span<const char>& blob)
|
||||
crypto::hash get_blob_hash(const blobdata_ref& blob)
|
||||
{
|
||||
crypto::hash h = null_hash;
|
||||
get_blob_hash(blob, h);
|
||||
@@ -1091,7 +1094,7 @@ namespace cryptonote
|
||||
return get_transaction_hash(t, res, NULL);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res)
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob, crypto::hash& res)
|
||||
{
|
||||
if (t.version == 1)
|
||||
return false;
|
||||
@@ -1099,7 +1102,7 @@ namespace cryptonote
|
||||
if (blob && unprunable_size)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(unprunable_size <= blob->size(), false, "Inconsistent transaction unprunable and blob sizes");
|
||||
cryptonote::get_blob_hash(epee::span<const char>(blob->data() + unprunable_size, blob->size() - unprunable_size), res);
|
||||
cryptonote::get_blob_hash(blobdata_ref(blob->data() + unprunable_size, blob->size() - unprunable_size), res);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1116,7 +1119,7 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blobdata)
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blobdata)
|
||||
{
|
||||
crypto::hash res;
|
||||
if (t.is_prunable_hash_valid())
|
||||
@@ -1194,7 +1197,7 @@ namespace cryptonote
|
||||
|
||||
// base rct
|
||||
CHECK_AND_ASSERT_MES(prefix_size <= unprunable_size && unprunable_size <= blob.size(), false, "Inconsistent transaction prefix, unprunable and blob sizes");
|
||||
cryptonote::get_blob_hash(epee::span<const char>(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]);
|
||||
cryptonote::get_blob_hash(blobdata_ref(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]);
|
||||
|
||||
// prunable rct
|
||||
if (t.rct_signatures.type == rct::RCTTypeNull)
|
||||
@@ -1203,7 +1206,8 @@ namespace cryptonote
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blob, hashes[2]), false, "Failed to get tx prunable hash");
|
||||
cryptonote::blobdata_ref blobref(blob);
|
||||
CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blobref, hashes[2]), false, "Failed to get tx prunable hash");
|
||||
}
|
||||
|
||||
// the tx hash is the hash of the 3 hashes
|
||||
@@ -1267,7 +1271,7 @@ namespace cryptonote
|
||||
return blob;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob)
|
||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob)
|
||||
{
|
||||
return get_object_hash(get_block_hashing_blob(b), res);
|
||||
}
|
||||
@@ -1318,7 +1322,7 @@ namespace cryptonote
|
||||
return res;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash)
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << b_blob;
|
||||
@@ -1336,12 +1340,12 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b)
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b)
|
||||
{
|
||||
return parse_and_validate_block_from_blob(b_blob, b, NULL);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash)
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash)
|
||||
{
|
||||
return parse_and_validate_block_from_blob(b_blob, b, &block_hash);
|
||||
}
|
||||
|
||||
@@ -52,11 +52,11 @@ namespace cryptonote
|
||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx, hw::device &hwdev);
|
||||
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
|
||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool parse_and_validate_tx_prefix_from_blob(const blobdata_ref& tx_blob, transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx);
|
||||
bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx);
|
||||
bool is_v1_tx(const blobdata_ref& tx_blob);
|
||||
bool is_v1_tx(const blobdata& tx_blob);
|
||||
|
||||
@@ -102,27 +102,27 @@ namespace cryptonote
|
||||
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
|
||||
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
|
||||
void get_blob_hash(const blobdata& blob, crypto::hash& res);
|
||||
void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res);
|
||||
void get_blob_hash(const blobdata_ref& blob, crypto::hash& res);
|
||||
crypto::hash get_blob_hash(const blobdata& blob);
|
||||
crypto::hash get_blob_hash(const epee::span<const char>& blob);
|
||||
crypto::hash get_blob_hash(const blobdata_ref& blob);
|
||||
std::string short_hash_str(const crypto::hash& h);
|
||||
|
||||
crypto::hash get_transaction_hash(const transaction& t);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res);
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob = NULL);
|
||||
bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob, crypto::hash& res);
|
||||
crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata_ref *blob = NULL);
|
||||
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
|
||||
crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash);
|
||||
|
||||
blobdata get_block_hashing_blob(const block& b);
|
||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob = NULL);
|
||||
bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata_ref *blob = NULL);
|
||||
bool get_block_hash(const block& b, crypto::hash& res);
|
||||
crypto::hash get_block_hash(const block& b);
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash);
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
|
||||
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash);
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash *block_hash);
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b);
|
||||
bool parse_and_validate_block_from_blob(const blobdata_ref& b_blob, block& b, crypto::hash &block_hash);
|
||||
bool get_inputs_money_amount(const transaction& tx, uint64_t& money);
|
||||
uint64_t get_outs_money_amount(const transaction& tx);
|
||||
bool check_inputs_types_supported(const transaction& tx);
|
||||
|
||||
@@ -201,20 +201,19 @@ namespace cryptonote {
|
||||
return check_hash_128(hash, difficulty);
|
||||
}
|
||||
|
||||
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
||||
difficulty_type next_difficulty(std::vector<uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
|
||||
//cutoff DIFFICULTY_LAG
|
||||
if(timestamps.size() > DIFFICULTY_WINDOW)
|
||||
{
|
||||
timestamps.resize(DIFFICULTY_WINDOW);
|
||||
cumulative_difficulties.resize(DIFFICULTY_WINDOW);
|
||||
}
|
||||
|
||||
|
||||
size_t length = timestamps.size();
|
||||
assert(length == cumulative_difficulties.size());
|
||||
if (length <= 1) {
|
||||
return 1;
|
||||
}
|
||||
if (HEIGHT < 200 && HEIGHT > 2 && m_nettype == TESTNET) { return 500; }
|
||||
static_assert(DIFFICULTY_WINDOW >= 2, "Window is too small");
|
||||
assert(length <= DIFFICULTY_WINDOW);
|
||||
sort(timestamps.begin(), timestamps.end());
|
||||
@@ -258,18 +257,21 @@ namespace cryptonote {
|
||||
// LWMA difficulty algorithm
|
||||
// Background: https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||
// Copyright (c) 2017-2018 Zawy
|
||||
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds) {
|
||||
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT) {
|
||||
|
||||
const int64_t T = static_cast<int64_t>(target_seconds);
|
||||
size_t N = DIFFICULTY_WINDOW_V2;
|
||||
if (timestamps.size() < 4) {
|
||||
return 1;
|
||||
} else if ( timestamps.size() < N+1 ) {
|
||||
N = timestamps.size() - 1;
|
||||
} else {
|
||||
timestamps.resize(N+1);
|
||||
cumulative_difficulties.resize(N+1);
|
||||
if (m_nettype == MAINNET) {
|
||||
if (timestamps.size() < 4) {
|
||||
return 1;
|
||||
} else if ( timestamps.size() < N+1 ) {
|
||||
N = timestamps.size() - 1;
|
||||
} else {
|
||||
timestamps.resize(N+1);
|
||||
cumulative_difficulties.resize(N+1);
|
||||
}
|
||||
}
|
||||
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
|
||||
const double adjust = 0.998;
|
||||
const double k = N * (N + 1) / 2;
|
||||
double LWMA(0), sum_inverse_D(0), harmonic_mean_D(0), nextDifficulty(0);
|
||||
@@ -292,12 +294,13 @@ namespace cryptonote {
|
||||
}
|
||||
|
||||
// LWMA-2
|
||||
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties) {
|
||||
difficulty_type next_difficulty_v3(std::vector<uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
|
||||
|
||||
int64_t T = DIFFICULTY_TARGET_V2;
|
||||
int64_t N = DIFFICULTY_WINDOW_V2;
|
||||
int64_t L(0), ST, sum_3_ST(0), next_D, prev_D;
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
|
||||
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
|
||||
for ( int64_t i = 1; i <= N; i++ ) {
|
||||
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
|
||||
ST = std::max(-4*T, std::min(ST, 6*T));
|
||||
@@ -316,13 +319,14 @@ namespace cryptonote {
|
||||
}
|
||||
|
||||
// LWMA-4
|
||||
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height) {
|
||||
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT) {
|
||||
|
||||
uint64_t T = DIFFICULTY_TARGET_V2;
|
||||
uint64_t N = DIFFICULTY_WINDOW_V2;
|
||||
uint64_t L(0), ST(0), next_D, prev_D, avg_D, i;
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
|
||||
if ( height <= 63469 + 1 ) { return 100000069; }
|
||||
if (HEIGHT <= 63469 + 1 && m_nettype == MAINNET) { return 100000069; }
|
||||
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
|
||||
std::vector<uint64_t>TS(N+1);
|
||||
TS[0] = timestamps[0];
|
||||
for ( i = 1; i <= N; i++) {
|
||||
@@ -364,44 +368,11 @@ namespace cryptonote {
|
||||
// LWMA-1 difficulty algorithm
|
||||
// Copyright (c) 2017-2019 Zawy, MIT License
|
||||
// https://github.com/zawy12/difficulty-algorithms/issues/3
|
||||
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) {
|
||||
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) {
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
|
||||
|
||||
if (HEIGHT >= 81769 && HEIGHT < 81769 + N) { return 10000000; }
|
||||
assert(timestamps.size() == N+1);
|
||||
|
||||
uint64_t L(0), next_D, i, this_timestamp(0), previous_timestamp(0), avg_D;
|
||||
|
||||
previous_timestamp = timestamps[0]-T;
|
||||
for ( i = 1; i <= N; i++) {
|
||||
// Safely prevent out-of-sequence timestamps
|
||||
if ( timestamps[i] > previous_timestamp ) { this_timestamp = timestamps[i]; }
|
||||
else { this_timestamp = previous_timestamp+1; }
|
||||
L += i*std::min(6*T ,this_timestamp - previous_timestamp);
|
||||
previous_timestamp = this_timestamp;
|
||||
}
|
||||
if (L < N*N*T/20 ) { L = N*N*T/20; }
|
||||
avg_D = static_cast<uint64_t>(( cumulative_difficulties[N] - cumulative_difficulties[0] )/ N);
|
||||
|
||||
// Prevent round off error for small D and overflow for large D.
|
||||
if (avg_D > 2000000*N*N*T) {
|
||||
next_D = (avg_D/(200*L))*(N*(N+1)*T*99);
|
||||
}
|
||||
else { next_D = (avg_D*N*(N+1)*T*99)/(200*L); }
|
||||
|
||||
// Make all insignificant digits zero for easy reading.
|
||||
i = 1000000000;
|
||||
while (i > 1) {
|
||||
if ( next_D > i*100 ) { next_D = ((next_D+i/2)/i)*i; break; }
|
||||
else { i /= 10; }
|
||||
}
|
||||
return next_D;
|
||||
}
|
||||
|
||||
difficulty_type next_difficulty_test(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT) {
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
|
||||
|
||||
if (HEIGHT < N) { return 1337; }
|
||||
if (HEIGHT >= 81769 && HEIGHT < 81769 + N && m_nettype == MAINNET) { return 10000000; }
|
||||
if (HEIGHT < 200 && m_nettype == TESTNET) { return 500; }
|
||||
assert(timestamps.size() == N+1);
|
||||
|
||||
uint64_t L(0), next_D, i, this_timestamp(0), previous_timestamp(0), avg_D;
|
||||
|
||||
@@ -57,12 +57,11 @@ namespace cryptonote
|
||||
|
||||
bool check_hash_128(const crypto::hash &hash, difficulty_type difficulty);
|
||||
bool check_hash(const crypto::hash &hash, difficulty_type difficulty);
|
||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties);
|
||||
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height);
|
||||
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty_test(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t HEIGHT);
|
||||
difficulty_type next_difficulty_v5(std::vector<std::uint64_t> timestamps, network_type m_nettype, std::vector<difficulty_type> cumulative_difficulties, uint64_t T, uint64_t N, uint64_t HEIGHT);
|
||||
|
||||
std::string hex(difficulty_type v);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
@@ -25,41 +25,22 @@
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "serialization.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "cryptonote_basic/cryptonote_basic.h"
|
||||
|
||||
template <template <bool> class Archive, class T>
|
||||
bool do_serialize(Archive<false> &ar, std::vector<T> &v);
|
||||
template <template <bool> class Archive, class T>
|
||||
bool do_serialize(Archive<true> &ar, std::vector<T> &v);
|
||||
|
||||
namespace serialization
|
||||
namespace cryptonote
|
||||
{
|
||||
namespace detail
|
||||
/*! Transactions are expensive to move or copy (lots of 32-byte internal
|
||||
buffers). This allows `cryptonote::core` to do a single notification for
|
||||
a vector of transactions, without having to move/copy duplicate or invalid
|
||||
transactions. */
|
||||
struct txpool_event
|
||||
{
|
||||
template <typename T>
|
||||
void do_reserve(std::vector<T> &c, size_t N)
|
||||
{
|
||||
c.reserve(N);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void do_add(std::vector<T> &c, T &&e)
|
||||
{
|
||||
c.emplace_back(std::move(e));
|
||||
}
|
||||
}
|
||||
cryptonote::transaction tx;
|
||||
crypto::hash hash;
|
||||
bool res; //!< Listeners must ignore `tx` when this is false.
|
||||
};
|
||||
}
|
||||
|
||||
#include "container.h"
|
||||
|
||||
template <template <bool> class Archive, class T>
|
||||
bool do_serialize(Archive<false> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
|
||||
template <template <bool> class Archive, class T>
|
||||
bool do_serialize(Archive<true> &ar, std::vector<T> &v) { return do_serialize_container(ar, v); }
|
||||
|
||||
36
src/cryptonote_basic/fwd.h
Normal file
36
src/cryptonote_basic/fwd.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
struct block;
|
||||
class transaction;
|
||||
struct txpool_event;
|
||||
}
|
||||
@@ -169,7 +169,9 @@ namespace cryptonote
|
||||
extra_nonce = m_extra_messages[m_config.current_extra_message_index];
|
||||
}
|
||||
|
||||
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce))
|
||||
uint64_t seed_height;
|
||||
crypto::hash seed_hash;
|
||||
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce, seed_height, seed_hash))
|
||||
{
|
||||
LOG_ERROR("Failed to get_block_template(), stopping mining");
|
||||
return false;
|
||||
@@ -471,12 +473,12 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
bool miner::find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height)
|
||||
bool miner::find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height, const crypto::hash *seed_hash)
|
||||
{
|
||||
for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
|
||||
{
|
||||
crypto::hash h;
|
||||
gbh(bl, height, diffic <= 100 ? 0 : tools::get_max_concurrency(), h);
|
||||
gbh(bl, height, seed_hash, diffic <= 100 ? 0 : tools::get_max_concurrency(), h);
|
||||
|
||||
if(check_hash(h, diffic))
|
||||
{
|
||||
@@ -572,7 +574,7 @@ namespace cryptonote
|
||||
|
||||
b.nonce = nonce;
|
||||
crypto::hash h;
|
||||
m_gbh(b, height, tools::get_max_concurrency(), h);
|
||||
m_gbh(b, height, NULL, tools::get_max_concurrency(), h);
|
||||
|
||||
if(check_hash(h, local_diff))
|
||||
{
|
||||
|
||||
@@ -47,12 +47,12 @@ namespace cryptonote
|
||||
struct i_miner_handler
|
||||
{
|
||||
virtual bool handle_block_found(block& b, block_verification_context &bvc) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash) = 0;
|
||||
protected:
|
||||
~i_miner_handler(){};
|
||||
};
|
||||
|
||||
typedef std::function<bool(const cryptonote::block&, uint64_t, unsigned int, crypto::hash&)> get_block_hash_t;
|
||||
typedef std::function<bool(const cryptonote::block&, uint64_t, const crypto::hash*, unsigned int, crypto::hash&)> get_block_hash_t;
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
@@ -76,7 +76,7 @@ namespace cryptonote
|
||||
bool on_idle();
|
||||
void on_synchronized();
|
||||
//synchronous analog (for fast calls)
|
||||
static bool find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height);
|
||||
static bool find_nonce_for_given_block(const get_block_hash_t &gbh, block& bl, const difficulty_type& diffic, uint64_t height, const crypto::hash *seed_hash = NULL);
|
||||
void pause();
|
||||
void resume();
|
||||
void do_print_hashrate(bool do_hr);
|
||||
@@ -91,17 +91,16 @@ namespace cryptonote
|
||||
uint64_t get_block_reward() const { return m_block_reward; }
|
||||
|
||||
static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 0;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE = 99;
|
||||
static constexpr uint16_t BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS = 10;
|
||||
static constexpr uint16_t BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS = 10;
|
||||
static constexpr uint16_t BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS = 3600;
|
||||
static constexpr uint8_t BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE = 40;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 5;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 50;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 1;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 100;
|
||||
static constexpr uint8_t BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS = 10;
|
||||
static constexpr uint64_t BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS = 400; // ramp up
|
||||
static constexpr uint64_t BACKGROUND_MINING_MIN_MINER_EXTRA_SLEEP_MILLIS = 5;
|
||||
|
||||
private:
|
||||
bool worker_thread();
|
||||
|
||||
@@ -37,11 +37,9 @@
|
||||
#define CRYPTONOTE_DNS_TIMEOUT_MS 20000
|
||||
|
||||
#define CRYPTONOTE_MAX_BLOCK_NUMBER 500000000
|
||||
#define CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE 196608 //size of block (bytes) that is the maximum that miners will produce
|
||||
#define CRYPTONOTE_MAX_TX_SIZE 1000000
|
||||
#define CRYPTONOTE_MAX_TX_PER_BLOCK 0x10000000
|
||||
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
|
||||
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
|
||||
#define CURRENT_TRANSACTION_VERSION 2
|
||||
#define CURRENT_BLOCK_MAJOR_VERSION 7
|
||||
#define CURRENT_BLOCK_MINOR_VERSION 7
|
||||
@@ -122,6 +120,11 @@
|
||||
#define CRYPTONOTE_NOISE_BYTES 3*1024 // 3 KiB
|
||||
#define CRYPTONOTE_NOISE_CHANNELS 2 // Max outgoing connections per zone used for noise/covert sending
|
||||
|
||||
// Both below are in seconds. The idea is to delay forwarding from i2p/tor
|
||||
// to ipv4/6, such that 2+ incoming connections _could_ have sent the tx
|
||||
#define CRYPTONOTE_FORWARD_DELAY_BASE (CRYPTONOTE_NOISE_MIN_DELAY + CRYPTONOTE_NOISE_DELAY_RANGE)
|
||||
#define CRYPTONOTE_FORWARD_DELAY_AVERAGE (CRYPTONOTE_FORWARD_DELAY_BASE + (CRYPTONOTE_FORWARD_DELAY_BASE / 2))
|
||||
|
||||
#define CRYPTONOTE_MAX_FRAGMENTS 20 // ~20 * NOISE_BYTES max payload size for covert/noise send
|
||||
|
||||
#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT 1000
|
||||
@@ -178,6 +181,10 @@
|
||||
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 15
|
||||
#define HF_VERSION_ENFORCE_MIN_AGE 15
|
||||
#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 15
|
||||
#define HF_VERSION_EXACT_COINBASE 16
|
||||
#define HF_VERSION_CLSAG 16
|
||||
#define HF_VERSION_DETERMINISTIC_UNLOCK_TIME 16
|
||||
#define HF_VERSION_DYNAMIC_UNLOCK 16
|
||||
|
||||
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
||||
|
||||
@@ -224,6 +231,11 @@ namespace config
|
||||
const unsigned char HASH_KEY_RPC_PAYMENT_NONCE = 0x58;
|
||||
const unsigned char HASH_KEY_MEMORY = 'k';
|
||||
const unsigned char HASH_KEY_MULTISIG[] = {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
const unsigned char HASH_KEY_TXPROOF_V2[] = "TXPROOF_V2";
|
||||
const unsigned char HASH_KEY_CLSAG_ROUND[] = "CLSAG_round";
|
||||
const unsigned char HASH_KEY_CLSAG_AGG_0[] = "CLSAG_agg_0";
|
||||
const unsigned char HASH_KEY_CLSAG_AGG_1[] = "CLSAG_agg_1";
|
||||
const char HASH_KEY_MESSAGE_SIGNING[] = "MoneroMessageSignature";
|
||||
|
||||
namespace testnet
|
||||
{
|
||||
|
||||
@@ -861,11 +861,11 @@ start:
|
||||
uint64_t height;
|
||||
auto new_top_hash = get_tail_id(height); // get it again now that we have the lock
|
||||
++height;
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t difficulty_blocks_count = version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
|
||||
if (!(new_top_hash == top_hash)) D=0;
|
||||
ss << "Re-locked, height " << height << ", tail id " << new_top_hash << (new_top_hash == top_hash ? "" : " (different)") << std::endl;
|
||||
top_hash = new_top_hash;
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t difficulty_blocks_count = version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
|
||||
|
||||
// ND: Speedup
|
||||
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
|
||||
@@ -946,37 +946,31 @@ start:
|
||||
uint64_t N = DIFFICULTY_WINDOW_V3;
|
||||
uint64_t HEIGHT = m_db->height();
|
||||
|
||||
difficulty_type diff = next_difficulty(timestamps, difficulties, target);
|
||||
difficulty_type diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
|
||||
if (m_nettype == MAINNET) {
|
||||
if (version >= 11) {
|
||||
diff = next_difficulty_v5(timestamps, difficulties, T, N, HEIGHT);
|
||||
} else if (version == 10) {
|
||||
diff = next_difficulty_v4(timestamps, difficulties, height);
|
||||
} else if (version == 9) {
|
||||
diff = next_difficulty_v3(timestamps, difficulties);
|
||||
} else if (version == 8) {
|
||||
diff = next_difficulty_v2(timestamps, difficulties, target);
|
||||
} else {
|
||||
diff = next_difficulty(timestamps, difficulties, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nettype == TESTNET) {
|
||||
diff = next_difficulty_test(timestamps, difficulties, T, N, HEIGHT);
|
||||
if (version >= 11) {
|
||||
diff = next_difficulty_v5(timestamps, m_nettype, difficulties, T, N, HEIGHT);
|
||||
} else if (version == 10) {
|
||||
diff = next_difficulty_v4(timestamps, m_nettype, difficulties, HEIGHT);
|
||||
} else if (version == 9) {
|
||||
diff = next_difficulty_v3(timestamps, m_nettype, difficulties, HEIGHT);
|
||||
} else if (version == 8) {
|
||||
diff = next_difficulty_v2(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
} else {
|
||||
diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
}
|
||||
|
||||
CRITICAL_REGION_LOCAL1(m_difficulty_lock);
|
||||
m_difficulty_for_next_block_top_hash = top_hash;
|
||||
m_difficulty_for_next_block = diff;
|
||||
if (D && D != diff)
|
||||
if (D && D != diff && m_nettype == MAINNET)
|
||||
{
|
||||
ss << "XXX Mismatch at " << height << "/" << top_hash << "/" << get_tail_id() << ": cached " << D << ", real " << diff << std::endl;
|
||||
print = true;
|
||||
}
|
||||
|
||||
++done;
|
||||
if (done == 1 && D && D != diff)
|
||||
if (done == 1 && D && D != diff && m_nettype == MAINNET)
|
||||
{
|
||||
print = true;
|
||||
ss << "Might be a race. Let's see what happens if we try again..." << std::endl;
|
||||
@@ -984,12 +978,12 @@ start:
|
||||
goto start;
|
||||
}
|
||||
ss << "Diff for " << top_hash << ": " << diff << std::endl;
|
||||
if (print)
|
||||
if (print && m_nettype == MAINNET)
|
||||
{
|
||||
MGINFO("START DUMP");
|
||||
MGINFO(ss.str());
|
||||
MGINFO("END DUMP");
|
||||
MGINFO("Please send moneromooo on Freenode the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
|
||||
MGINFO("Please send wowario on Freenode #wownero-dev the contents of this log, from a couple dozen lines before START DUMP to END DUMP");
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
@@ -1020,14 +1014,15 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||
const uint64_t start_height = start_height_opt ? *start_height_opt : check_difficulty_checkpoints().second;
|
||||
const uint64_t top_height = m_db->height() - 1;
|
||||
MGINFO("Recalculating difficulties from height " << start_height << " to height " << top_height);
|
||||
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t difficulty_blocks_count = version >= 11 ? DIFFICULTY_BLOCKS_COUNT_V3 : version <= 10 && version >= 8 ? DIFFICULTY_BLOCKS_COUNT_V2 : DIFFICULTY_BLOCKS_COUNT;
|
||||
std::vector<uint64_t> timestamps;
|
||||
std::vector<difficulty_type> difficulties;
|
||||
timestamps.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
|
||||
difficulties.reserve(DIFFICULTY_BLOCKS_COUNT + 1);
|
||||
timestamps.reserve(difficulty_blocks_count + 1);
|
||||
difficulties.reserve(difficulty_blocks_count + 1);
|
||||
if (start_height > 1)
|
||||
{
|
||||
for (uint64_t i = 0; i < DIFFICULTY_BLOCKS_COUNT; ++i)
|
||||
for (uint64_t i = 0; i < difficulty_blocks_count; ++i)
|
||||
{
|
||||
uint64_t height = start_height - 1 - i;
|
||||
if (height == 0)
|
||||
@@ -1041,8 +1036,24 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||
std::vector<difficulty_type> new_cumulative_difficulties;
|
||||
for (uint64_t height = start_height; height <= top_height; ++height)
|
||||
{
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t T = DIFFICULTY_TARGET_V2;
|
||||
uint64_t N = DIFFICULTY_WINDOW_V3;
|
||||
uint64_t HEIGHT = m_db->height();
|
||||
size_t target = get_ideal_hard_fork_version(height) < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
||||
difficulty_type recalculated_diff = next_difficulty(timestamps, difficulties, target);
|
||||
difficulty_type recalculated_diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
|
||||
if (version >= 11) {
|
||||
recalculated_diff = next_difficulty_v5(timestamps, m_nettype, difficulties, T, N, HEIGHT);
|
||||
} else if (version == 10) {
|
||||
recalculated_diff = next_difficulty_v4(timestamps, m_nettype, difficulties, HEIGHT);
|
||||
} else if (version == 9) {
|
||||
recalculated_diff = next_difficulty_v3(timestamps, m_nettype, difficulties, HEIGHT);
|
||||
} else if (version == 8) {
|
||||
recalculated_diff = next_difficulty_v2(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
} else {
|
||||
recalculated_diff = next_difficulty(timestamps, m_nettype, difficulties, target, HEIGHT);
|
||||
}
|
||||
|
||||
boost::multiprecision::uint256_t recalculated_cum_diff_256 = boost::multiprecision::uint256_t(recalculated_diff) + last_cum_diff;
|
||||
CHECK_AND_ASSERT_THROW_MES(recalculated_cum_diff_256 <= std::numeric_limits<difficulty_type>::max(), "Difficulty overflow!");
|
||||
@@ -1070,9 +1081,9 @@ size_t Blockchain::recalculate_difficulties(boost::optional<uint64_t> start_heig
|
||||
timestamps.push_back(m_db->get_block_timestamp(height));
|
||||
difficulties.push_back(recalculated_cum_diff);
|
||||
}
|
||||
if (timestamps.size() > DIFFICULTY_BLOCKS_COUNT)
|
||||
if (timestamps.size() > difficulty_blocks_count)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(timestamps.size() == DIFFICULTY_BLOCKS_COUNT + 1, "Wrong timestamps size: " << timestamps.size());
|
||||
CHECK_AND_ASSERT_THROW_MES(timestamps.size() == difficulty_blocks_count + 1, "Wrong timestamps size: " << timestamps.size());
|
||||
timestamps.erase(timestamps.begin());
|
||||
difficulties.erase(difficulties.begin());
|
||||
}
|
||||
@@ -1258,10 +1269,15 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
|
||||
reorg_notify->notify("%s", std::to_string(split_height).c_str(), "%h", std::to_string(m_db->height()).c_str(),
|
||||
"%n", std::to_string(m_db->height() - split_height).c_str(), "%d", std::to_string(discarded_blocks).c_str(), NULL);
|
||||
|
||||
std::shared_ptr<tools::Notify> block_notify = m_block_notify;
|
||||
if (block_notify)
|
||||
for (const auto &bei: alt_chain)
|
||||
block_notify->notify("%s", epee::string_tools::pod_to_hex(get_block_hash(bei.bl)).c_str(), NULL);
|
||||
for (const auto& notifier : m_block_notifiers)
|
||||
{
|
||||
std::size_t notify_height = split_height;
|
||||
for (const auto& bei: alt_chain)
|
||||
{
|
||||
notifier(notify_height, {std::addressof(bei.bl), 1});
|
||||
++notify_height;
|
||||
}
|
||||
}
|
||||
|
||||
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
|
||||
return true;
|
||||
@@ -1324,7 +1340,7 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||
size_t count = 0;
|
||||
size_t max_i = timestamps.size()-1;
|
||||
// get difficulties and timestamps from most recent blocks in alt chain
|
||||
for (const auto bei: boost::adaptors::reverse(alt_chain))
|
||||
for (const auto &bei: boost::adaptors::reverse(alt_chain))
|
||||
{
|
||||
timestamps[max_i - count] = bei.bl.timestamp;
|
||||
cumulative_difficulties[max_i - count] = bei.cumulative_difficulty;
|
||||
@@ -1341,23 +1357,18 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||
uint64_t HEIGHT = m_db->height();
|
||||
|
||||
// calculate the difficulty target for the block and return it
|
||||
if (m_nettype == MAINNET) {
|
||||
if (version >= 11) {
|
||||
return next_difficulty_v5(timestamps, cumulative_difficulties, T, N, HEIGHT);
|
||||
} else if (version == 10) {
|
||||
return next_difficulty_v4(timestamps, cumulative_difficulties, height);
|
||||
} else if (version == 9) {
|
||||
return next_difficulty_v3(timestamps, cumulative_difficulties);
|
||||
} else if (version == 8) {
|
||||
return next_difficulty_v2(timestamps, cumulative_difficulties, target);
|
||||
} else {
|
||||
return next_difficulty(timestamps, cumulative_difficulties, target);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_nettype == TESTNET) {
|
||||
return next_difficulty_test(timestamps, cumulative_difficulties, T, N, HEIGHT);
|
||||
if (version >= 11) {
|
||||
return next_difficulty_v5(timestamps, m_nettype, cumulative_difficulties, T, N, HEIGHT);
|
||||
} else if (version == 10) {
|
||||
return next_difficulty_v4(timestamps, m_nettype, cumulative_difficulties, HEIGHT);
|
||||
} else if (version == 9) {
|
||||
return next_difficulty_v3(timestamps, m_nettype, cumulative_difficulties, HEIGHT);
|
||||
} else if (version == 8) {
|
||||
return next_difficulty_v2(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
|
||||
} else {
|
||||
return next_difficulty(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
|
||||
}
|
||||
return next_difficulty(timestamps, m_nettype, cumulative_difficulties, target, HEIGHT);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// This function does a sanity check on basic things that all miner
|
||||
@@ -1384,7 +1395,32 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
|
||||
return false;
|
||||
}
|
||||
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// Dynamic unlock time from HF 16
|
||||
// To calculate unlock window, get the block hash at height-1337, convert the
|
||||
// first 3 characters from hexadecimal to decimal, multiply by 2, and then add 288.
|
||||
// Unlock minimum 1 day (288 blocks), maximum is ~29 days ((4095*2)+288 = 8478 blocks)
|
||||
// unlock time = unlock_window + height
|
||||
if (hf_version >= HF_VERSION_DYNAMIC_UNLOCK)
|
||||
{
|
||||
uint64_t N = m_nettype == MAINNET ? 1337 : 5;
|
||||
crypto::hash blk_id = get_block_id_by_height(height-N);
|
||||
std::string hex_str = epee::string_tools::pod_to_hex(blk_id).substr(0, 3);
|
||||
uint64_t blk_num = std::stol(hex_str,nullptr,16)*2;
|
||||
uint64_t unlock_window = blk_num + 288;
|
||||
|
||||
if (b.miner_tx.unlock_time != height + unlock_window) {
|
||||
MWARNING("Coinbase transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + unlock_window);
|
||||
return false;
|
||||
}
|
||||
LOG_PRINT_L1("+++++ MINER TX UNLOCK TIME INFO" <<
|
||||
"\nHeight: " << height << ", Unlock window: " << unlock_window << ", Unlock time: " << b.miner_tx.unlock_time <<
|
||||
"\nblk_height: " << height-N << ", blk_id: " << blk_id <<
|
||||
"\nhex_str: " << hex_str << ", blk_num: " << blk_num);
|
||||
} else {
|
||||
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + 60, false, "coinbase transaction transaction has the wrong unlock time="
|
||||
<< b.miner_tx.unlock_time << ", expected " << height + 60);
|
||||
}
|
||||
|
||||
//check outs overflow
|
||||
//NOTE: not entirely sure this is necessary, given that this function is
|
||||
@@ -1439,8 +1475,8 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
||||
MERROR_VER("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << "), cumulative_block_weight " << cumulative_block_weight);
|
||||
return false;
|
||||
}
|
||||
// From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
|
||||
if (version < 2)
|
||||
// From hard fork 2 till 12, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
|
||||
if (version < 2 || version >= HF_VERSION_EXACT_COINBASE)
|
||||
{
|
||||
if(base_reward + fee != money_in_use)
|
||||
{
|
||||
@@ -1548,13 +1584,15 @@ uint64_t Blockchain::get_current_cumulative_block_weight_median() const
|
||||
// in a lot of places. That flag is not referenced in any of the code
|
||||
// nor any of the makefiles, howeve. Need to look into whether or not it's
|
||||
// necessary at all.
|
||||
bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool Blockchain::create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
size_t median_weight;
|
||||
uint64_t already_generated_coins;
|
||||
uint64_t pool_cookie;
|
||||
|
||||
seed_hash = crypto::null_hash;
|
||||
|
||||
m_tx_pool.lock();
|
||||
const auto unlock_guard = epee::misc_utils::create_scope_leave_handler([&]() { m_tx_pool.unlock(); });
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
@@ -1573,6 +1611,8 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
diffic = m_btc_difficulty;
|
||||
height = m_btc_height;
|
||||
expected_reward = m_btc_expected_reward;
|
||||
seed_height = m_btc_seed_height;
|
||||
seed_hash = m_btc_seed_hash;
|
||||
return true;
|
||||
}
|
||||
MDEBUG("Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address))) << ", nonce " << (m_btc_nonce == ex_nonce) << ", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()) << ", from_block " << (!!from_block));
|
||||
@@ -1606,10 +1646,34 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
|
||||
uint64_t from_block_height = cryptonote::get_block_height(prev_block);
|
||||
height = from_block_height + 1;
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
height = alt_chain.back().height + 1;
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
|
||||
if (alt_chain.size() && alt_chain.front().height <= seed_height)
|
||||
{
|
||||
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
|
||||
{
|
||||
if (it->height == seed_height+1)
|
||||
{
|
||||
seed_hash = it->bl.prev_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
b.major_version = m_hardfork->get_ideal_version(height);
|
||||
b.minor_version = m_hardfork->get_ideal_version();
|
||||
@@ -1644,6 +1708,12 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
median_weight = m_current_block_cumul_weight_limit / 2;
|
||||
diffic = get_difficulty_for_next_block();
|
||||
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
}
|
||||
b.timestamp = time(NULL);
|
||||
|
||||
@@ -1722,7 +1792,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob weight
|
||||
uint8_t hf_version = b.major_version;
|
||||
size_t max_outs = hf_version >= 4 ? 1 : 11;
|
||||
bool r = construct_miner_tx(height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||
bool r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, txs_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
|
||||
size_t cumulative_weight = txs_weight + get_transaction_weight(b.miner_tx);
|
||||
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
||||
@@ -1731,7 +1801,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
#endif
|
||||
for (size_t try_count = 0; try_count != 10; ++try_count)
|
||||
{
|
||||
r = construct_miner_tx(height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||
r = construct_miner_tx(this, m_nettype, height, median_weight, already_generated_coins, cumulative_weight, fee, miner_address, b.miner_tx, ex_nonce, max_outs, hf_version);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, second chance");
|
||||
size_t coinbase_weight = get_transaction_weight(b.miner_tx);
|
||||
@@ -1776,16 +1846,16 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
#endif
|
||||
|
||||
if (!from_block)
|
||||
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, pool_cookie);
|
||||
cache_block_template(b, miner_address, ex_nonce, diffic, height, expected_reward, seed_height, seed_hash, pool_cookie);
|
||||
return true;
|
||||
}
|
||||
LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool Blockchain::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce);
|
||||
return create_block_template(b, NULL, miner_address, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// for an alternate chain, get the timestamps from the main chain to complete
|
||||
@@ -2201,7 +2271,7 @@ bool Blockchain::get_alternative_blocks(std::vector<block>& blocks) const
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
||||
blocks.reserve(m_db->get_alt_block_count());
|
||||
m_db->for_all_alt_blocks([&blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata *blob) {
|
||||
m_db->for_all_alt_blocks([&blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref *blob) {
|
||||
if (!blob)
|
||||
{
|
||||
MERROR("No blob, but blobs were requested");
|
||||
@@ -2276,8 +2346,9 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
|
||||
MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size());
|
||||
return false;
|
||||
}
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
for (const auto &t: data)
|
||||
res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
|
||||
res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time, hf_version), t.height, crypto::null_hash});
|
||||
|
||||
if (req.get_txid)
|
||||
{
|
||||
@@ -2301,7 +2372,8 @@ void Blockchain::get_output_key_mask_unlocked(const uint64_t& amount, const uint
|
||||
key = o_data.pubkey;
|
||||
mask = o_data.commitment;
|
||||
tx_out_index toi = m_db->get_output_tx_and_index(amount, index);
|
||||
unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first), hf_version);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector<uint64_t> &distribution, uint64_t &base) const
|
||||
@@ -3014,7 +3086,7 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
const bool bulletproof = rct::is_rct_bulletproof(tx.rct_signatures.type);
|
||||
if (bulletproof || !tx.rct_signatures.p.bulletproofs.empty())
|
||||
{
|
||||
MERROR_VER("New Bulletproofs are not allowed before v8");
|
||||
MERROR_VER("Bulletproofs are not allowed before v8");
|
||||
tvc.m_invalid_output = true;
|
||||
return false;
|
||||
}
|
||||
@@ -3058,6 +3130,30 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
|
||||
}
|
||||
}
|
||||
|
||||
// from v16, allow CLSAGs
|
||||
if (hf_version < HF_VERSION_CLSAG) {
|
||||
if (tx.version >= 2) {
|
||||
if (tx.rct_signatures.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
MERROR_VER("Ringct type " << (unsigned)rct::RCTTypeCLSAG << " is not allowed before v" << HF_VERSION_CLSAG);
|
||||
tvc.m_invalid_output = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from v17, allow only CLSAGs
|
||||
if (hf_version > HF_VERSION_CLSAG) {
|
||||
if (tx.version >= 2) {
|
||||
if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2)
|
||||
{
|
||||
MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1));
|
||||
tvc.m_invalid_output = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from v12, forbid old bulletproofs
|
||||
if (hf_version > 11) {
|
||||
if (tx.version >= 2) {
|
||||
@@ -3111,7 +3207,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof)
|
||||
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeBulletproof || rv.type == rct::RCTTypeBulletproof2 || rv.type == rct::RCTTypeSimpleBulletproof || rv.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
|
||||
rv.mixRing.resize(pubkeys.size());
|
||||
@@ -3124,6 +3220,14 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(rv.p.CLSAGs.size() == tx.vin.size(), false, "Bad CLSAGs size");
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
rv.p.CLSAGs[n].I = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast<std::string>(rv.type));
|
||||
@@ -3152,6 +3256,17 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rv.type == rct::RCTTypeCLSAG)
|
||||
{
|
||||
if (!tx.pruned)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(rv.p.CLSAGs.size() == tx.vin.size(), false, "Bad CLSAGs size");
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
rv.p.CLSAGs[n].I = rct::ki2rct(boost::get<txin_to_key>(tx.vin[n]).k_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(false, false, "Unsupported rct tx type: " + boost::lexical_cast<std::string>(rv.type));
|
||||
@@ -3311,8 +3426,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
results.resize(tx.vin.size(), 0);
|
||||
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
tools::threadpool::waiter waiter;
|
||||
const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(&tpool); });
|
||||
tools::threadpool::waiter waiter(tpool);
|
||||
int threads = tpool.get_max_concurrency();
|
||||
|
||||
uint64_t max_used_block_height = 0;
|
||||
@@ -3343,7 +3457,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
|
||||
// make sure that output being spent matches up correctly with the
|
||||
// signature spending it.
|
||||
if (!check_tx_input(tx.version, in_to_key, tx_prefix_hash, tx.version == 1 ? tx.signatures[sig_index] : std::vector<crypto::signature>(), tx.rct_signatures, pubkeys[sig_index], pmax_used_block_height))
|
||||
if (!check_tx_input(tx.version, in_to_key, tx_prefix_hash, tx.version == 1 ? tx.signatures[sig_index] : std::vector<crypto::signature>(), tx.rct_signatures, pubkeys[sig_index], pmax_used_block_height, hf_version))
|
||||
{
|
||||
MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
||||
if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
|
||||
@@ -3382,7 +3496,8 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
sig_index++;
|
||||
}
|
||||
if (tx.version == 1 && threads > 1)
|
||||
waiter.wait(&tpool);
|
||||
if (!waiter.wait())
|
||||
return false;
|
||||
|
||||
// enforce min output age
|
||||
if (hf_version >= HF_VERSION_ENFORCE_MIN_AGE)
|
||||
@@ -3434,6 +3549,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
case rct::RCTTypeSimpleBulletproof:
|
||||
case rct::RCTTypeBulletproof:
|
||||
case rct::RCTTypeBulletproof2:
|
||||
case rct::RCTTypeCLSAG:
|
||||
{
|
||||
// check all this, either reconstructed (so should really pass), or not
|
||||
{
|
||||
@@ -3469,14 +3585,20 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
}
|
||||
}
|
||||
|
||||
if (rv.p.MGs.size() != tx.vin.size())
|
||||
const size_t n_sigs = rv.type == rct::RCTTypeCLSAG ? rv.p.CLSAGs.size() : rv.p.MGs.size();
|
||||
if (n_sigs != tx.vin.size())
|
||||
{
|
||||
MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes");
|
||||
return false;
|
||||
}
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
if (rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
|
||||
bool error;
|
||||
if (rv.type == rct::RCTTypeCLSAG)
|
||||
error = memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.CLSAGs[n].I, 32);
|
||||
else
|
||||
error = rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32);
|
||||
if (error)
|
||||
{
|
||||
MERROR_VER("Failed to check ringct signatures: mismatched key image");
|
||||
return false;
|
||||
@@ -3730,7 +3852,7 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
|
||||
//------------------------------------------------------------------
|
||||
// This function checks to see if a tx is unlocked. unlock_time is either
|
||||
// a block index or a unix time.
|
||||
bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
|
||||
bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time, uint8_t hf_version) const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
if(unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
|
||||
@@ -3745,7 +3867,7 @@ bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
|
||||
else
|
||||
{
|
||||
//interpret as time
|
||||
uint64_t current_time = static_cast<uint64_t>(time(NULL));
|
||||
const uint64_t current_time = hf_version >= HF_VERSION_DETERMINISTIC_UNLOCK_TIME ? get_adjusted_time(m_db->height()) : static_cast<uint64_t>(time(NULL));
|
||||
if(current_time + (get_current_hard_fork_version() < 2 ? CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 : CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2) >= unlock_time)
|
||||
return true;
|
||||
else
|
||||
@@ -3757,7 +3879,7 @@ bool Blockchain::is_tx_spendtime_unlocked(uint64_t unlock_time) const
|
||||
// This function locates all outputs associated with a given input (mixins)
|
||||
// and validates that they exist and are usable. It also checks the ring
|
||||
// signature for each input.
|
||||
bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const rct::rctSig &rct_signatures, std::vector<rct::ctkey> &output_keys, uint64_t* pmax_related_block_height) const
|
||||
bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const rct::rctSig &rct_signatures, std::vector<rct::ctkey> &output_keys, uint64_t* pmax_related_block_height, uint8_t hf_version) const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
@@ -3769,14 +3891,15 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons
|
||||
{
|
||||
std::vector<rct::ctkey >& m_output_keys;
|
||||
const Blockchain& m_bch;
|
||||
outputs_visitor(std::vector<rct::ctkey>& output_keys, const Blockchain& bch) :
|
||||
m_output_keys(output_keys), m_bch(bch)
|
||||
const uint8_t hf_version;
|
||||
outputs_visitor(std::vector<rct::ctkey>& output_keys, const Blockchain& bch, uint8_t hf_version) :
|
||||
m_output_keys(output_keys), m_bch(bch), hf_version(hf_version)
|
||||
{
|
||||
}
|
||||
bool handle_output(uint64_t unlock_time, const crypto::public_key &pubkey, const rct::key &commitment)
|
||||
{
|
||||
//check tx unlock time
|
||||
if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
|
||||
if (!m_bch.is_tx_spendtime_unlocked(unlock_time, hf_version))
|
||||
{
|
||||
MERROR_VER("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
|
||||
return false;
|
||||
@@ -3795,7 +3918,7 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons
|
||||
output_keys.clear();
|
||||
|
||||
// collect output keys
|
||||
outputs_visitor vi(output_keys, *this);
|
||||
outputs_visitor vi(output_keys, *this, hf_version);
|
||||
if (!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height))
|
||||
{
|
||||
MERROR_VER("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size());
|
||||
@@ -3814,12 +3937,41 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
//TODO: Is this intended to do something else? Need to look into the todo there.
|
||||
uint64_t Blockchain::get_adjusted_time() const
|
||||
// only works on the main chain
|
||||
uint64_t Blockchain::get_adjusted_time(uint64_t height) const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
//TODO: add collecting median time
|
||||
return time(NULL);
|
||||
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
|
||||
// if not enough blocks, no proper median yet, return current time
|
||||
if(height < blockchain_timestamp_check_window)
|
||||
{
|
||||
return static_cast<uint64_t>(time(NULL));
|
||||
}
|
||||
std::vector<uint64_t> timestamps;
|
||||
|
||||
// need most recent 60 blocks, get index of first of those
|
||||
size_t offset = height - blockchain_timestamp_check_window;
|
||||
timestamps.reserve(height - offset);
|
||||
for(;offset < height; ++offset)
|
||||
{
|
||||
timestamps.push_back(m_db->get_block_timestamp(offset));
|
||||
}
|
||||
uint64_t median_ts = epee::misc_utils::median(timestamps);
|
||||
|
||||
// project the median to match approximately when the block being validated will appear
|
||||
// the median is calculated from a chunk of past blocks, so we use +1 to offset onto the current block
|
||||
median_ts += (blockchain_timestamp_check_window + 1) * DIFFICULTY_TARGET_V2 / 2;
|
||||
|
||||
// project the current block's time based on the previous block's time
|
||||
// we don't use the current block's time directly to mitigate timestamp manipulation
|
||||
uint64_t adjusted_current_block_ts = timestamps.back() + DIFFICULTY_TARGET_V2;
|
||||
|
||||
// return minimum of ~current block time and adjusted median time
|
||||
// we do this since it's better to report a time in the past than a time in the future
|
||||
return (adjusted_current_block_ts < median_ts ? adjusted_current_block_ts : median_ts);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
//TODO: revisit, has changed a bit on upstream
|
||||
@@ -3848,13 +4000,14 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
|
||||
bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
uint8_t version = get_current_hard_fork_version();
|
||||
uint64_t cryptonote_block_future_time_limit = version >= 8 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT;
|
||||
size_t blockchain_timestamp_check_window = version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
|
||||
if(b.timestamp > get_adjusted_time() + cryptonote_block_future_time_limit)
|
||||
|
||||
if(b.timestamp > (uint64_t)time(NULL) + cryptonote_block_future_time_limit)
|
||||
{
|
||||
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 10 minutes");
|
||||
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than local time + 10 minutes");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4028,8 +4181,8 @@ leave:
|
||||
MCINFO("verify", "No pre-validated hash at height " << blockchain_height << ", verifying fully");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (!fast_check)
|
||||
{
|
||||
auto it = m_blocks_longhash_table.find(id);
|
||||
if (it != m_blocks_longhash_table.end())
|
||||
@@ -4304,12 +4457,9 @@ leave:
|
||||
get_difficulty_for_next_block(); // just to cache it
|
||||
invalidate_block_template_cache();
|
||||
|
||||
if (notify)
|
||||
{
|
||||
std::shared_ptr<tools::Notify> block_notify = m_block_notify;
|
||||
if (block_notify)
|
||||
block_notify->notify("%s", epee::string_tools::pod_to_hex(id).c_str(), NULL);
|
||||
}
|
||||
|
||||
for (const auto& notifier: m_block_notifiers)
|
||||
notifier(new_height - 1, {std::addressof(bl), 1});
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -4437,6 +4587,9 @@ bool Blockchain::update_next_cumulative_weight_limit(uint64_t *long_term_effecti
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
crypto::hash id = get_block_hash(bl);
|
||||
CRITICAL_REGION_LOCAL(m_tx_pool);//to avoid deadlock lets lock tx_pool for whole add/reorganize process
|
||||
@@ -4464,6 +4617,14 @@ bool Blockchain::add_new_block(const block& bl, block_verification_context& bvc)
|
||||
|
||||
rtxn_guard.stop();
|
||||
return handle_block_to_main_chain(bl, id, bvc);
|
||||
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
LOG_ERROR("Exception at [add_new_block], what=" << e.what());
|
||||
bvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
//TODO: Refactor, consider returning a failure height and letting
|
||||
@@ -4913,7 +5074,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
|
||||
{
|
||||
m_blocks_longhash_table.clear();
|
||||
uint64_t thread_height = height;
|
||||
tools::threadpool::waiter waiter;
|
||||
tools::threadpool::waiter waiter(tpool);
|
||||
m_prepare_height = height;
|
||||
m_prepare_nblocks = blocks_entry.size();
|
||||
m_prepare_blocks = &blocks;
|
||||
@@ -4926,7 +5087,8 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
|
||||
thread_height += nblocks;
|
||||
}
|
||||
|
||||
waiter.wait(&tpool);
|
||||
if (!waiter.wait())
|
||||
return false;
|
||||
m_prepare_height = 0;
|
||||
|
||||
if (m_cancel)
|
||||
@@ -5060,14 +5222,15 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
|
||||
|
||||
if (threads > 1 && amounts.size() > 1)
|
||||
{
|
||||
tools::threadpool::waiter waiter;
|
||||
tools::threadpool::waiter waiter(tpool);
|
||||
|
||||
for (size_t i = 0; i < amounts.size(); i++)
|
||||
{
|
||||
uint64_t amount = amounts[i];
|
||||
tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount])), true);
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
if (!waiter.wait())
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5176,7 +5339,7 @@ cryptonote::blobdata Blockchain::get_txpool_tx_blob(const crypto::hash& txid, re
|
||||
return m_db->get_txpool_tx_blob(txid, tx_category);
|
||||
}
|
||||
|
||||
bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)> f, bool include_blob, relay_category tx_category) const
|
||||
bool Blockchain::for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)> f, bool include_blob, relay_category tx_category) const
|
||||
{
|
||||
return m_db->for_all_txpool_txes(f, include_blob, tx_category);
|
||||
}
|
||||
@@ -5200,6 +5363,15 @@ void Blockchain::set_user_options(uint64_t maxthreads, bool sync_on_blocks, uint
|
||||
m_max_prepare_blocks_threads = maxthreads;
|
||||
}
|
||||
|
||||
void Blockchain::add_block_notify(boost::function<void(std::uint64_t, epee::span<const block>)>&& notify)
|
||||
{
|
||||
if (notify)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
m_block_notifiers.push_back(std::move(notify));
|
||||
}
|
||||
}
|
||||
|
||||
void Blockchain::safesyncmode(const bool onoff)
|
||||
{
|
||||
/* all of this is no-op'd if the user set a specific
|
||||
@@ -5238,7 +5410,7 @@ std::vector<std::pair<Blockchain::block_extended_info,std::vector<crypto::hash>>
|
||||
|
||||
blocks_ext_by_hash alt_blocks;
|
||||
alt_blocks.reserve(m_db->get_alt_block_count());
|
||||
m_db->for_all_alt_blocks([&alt_blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata *blob) {
|
||||
m_db->for_all_alt_blocks([&alt_blocks](const crypto::hash &blkid, const cryptonote::alt_block_data_t &data, const cryptonote::blobdata_ref *blob) {
|
||||
if (!blob)
|
||||
{
|
||||
MERROR("No blob, but blobs were requested");
|
||||
@@ -5295,7 +5467,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "c8d6e428606b22f77d2df05d880cac01dc59d485b356bc469e78b7c79ad1ed1f";
|
||||
static const char expected_block_hashes_hash[] = "5489781213b29d0227fd79b3ac854c42793bc5d11b554b89f822035e117df586";
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
@@ -5437,7 +5609,7 @@ void Blockchain::invalidate_block_template_cache()
|
||||
m_btc_valid = false;
|
||||
}
|
||||
|
||||
void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t pool_cookie)
|
||||
void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie)
|
||||
{
|
||||
MDEBUG("Setting block template cache");
|
||||
m_btc = b;
|
||||
@@ -5446,6 +5618,8 @@ void Blockchain::cache_block_template(const block &b, const cryptonote::account_
|
||||
m_btc_difficulty = diff;
|
||||
m_btc_height = height;
|
||||
m_btc_expected_reward = expected_reward;
|
||||
m_btc_seed_hash = seed_hash;
|
||||
m_btc_seed_height = seed_height;
|
||||
m_btc_pool_cookie = pool_cookie;
|
||||
m_btc_valid = true;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
|
||||
#pragma once
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/function/function_fwd.hpp>
|
||||
#if BOOST_VERSION >= 107400
|
||||
#include <boost/serialization/library_version_type.hpp>
|
||||
#endif
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <boost/serialization/list.hpp>
|
||||
@@ -362,8 +366,8 @@ namespace cryptonote
|
||||
*
|
||||
* @return true if block template filled in successfully, else false
|
||||
*/
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
|
||||
/**
|
||||
* @brief checks if a block is known about with a given hash
|
||||
@@ -764,7 +768,7 @@ namespace cryptonote
|
||||
*
|
||||
* @param notify the notify object to call at every new block
|
||||
*/
|
||||
void set_block_notify(const std::shared_ptr<tools::Notify> ¬ify) { m_block_notify = notify; }
|
||||
void add_block_notify(boost::function<void(std::uint64_t, epee::span<const block>)> &¬ify);
|
||||
|
||||
/**
|
||||
* @brief sets a reorg notify object to call for every reorg
|
||||
@@ -984,7 +988,7 @@ namespace cryptonote
|
||||
bool get_txpool_tx_meta(const crypto::hash& txid, txpool_tx_meta_t &meta) const;
|
||||
bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const;
|
||||
cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const;
|
||||
bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata*)>, bool include_blob = false, relay_category tx_category = relay_category::broadcasted) const;
|
||||
bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category tx_category = relay_category::broadcasted) const;
|
||||
bool txpool_tx_matches_category(const crypto::hash& tx_hash, relay_category category);
|
||||
|
||||
bool is_within_compiled_block_hash_area() const { return is_within_compiled_block_hash_area(m_db->height()); }
|
||||
@@ -1038,6 +1042,21 @@ namespace cryptonote
|
||||
*/
|
||||
void flush_invalid_blocks();
|
||||
|
||||
/**
|
||||
* @brief get the "adjusted time"
|
||||
*
|
||||
* Computes the median timestamp of the previous 60 blocks, projects it
|
||||
* onto the current block to get an 'adjusted median time' which approximates
|
||||
* what the current block's timestamp should be. Also projects the previous
|
||||
* block's timestamp to estimate the current block's timestamp.
|
||||
*
|
||||
* Returns the minimum of the two projections, or the current local time on
|
||||
* the machine if less than 60 blocks are available.
|
||||
*
|
||||
* @return current time approximated from chain data
|
||||
*/
|
||||
uint64_t get_adjusted_time(uint64_t height) const;
|
||||
|
||||
#ifndef IN_UNIT_TESTS
|
||||
private:
|
||||
#endif
|
||||
@@ -1120,12 +1139,18 @@ namespace cryptonote
|
||||
uint64_t m_btc_height;
|
||||
uint64_t m_btc_pool_cookie;
|
||||
uint64_t m_btc_expected_reward;
|
||||
crypto::hash m_btc_seed_hash;
|
||||
uint64_t m_btc_seed_height;
|
||||
bool m_btc_valid;
|
||||
|
||||
|
||||
bool m_batch_success;
|
||||
|
||||
std::shared_ptr<tools::Notify> m_block_notify;
|
||||
/* `boost::function` is used because the implementation never allocates if
|
||||
the callable object has a single `std::shared_ptr` or `std::weap_ptr`
|
||||
internally. Whereas, the libstdc++ `std::function` will allocate. */
|
||||
|
||||
std::vector<boost::function<void(std::uint64_t, epee::span<const block>)>> m_block_notifiers;
|
||||
std::shared_ptr<tools::Notify> m_reorg_notify;
|
||||
|
||||
// for prepare_handle_incoming_blocks
|
||||
@@ -1172,10 +1197,11 @@ namespace cryptonote
|
||||
* @param output_keys return-by-reference the public keys of the outputs in the input set
|
||||
* @param rct_signatures the ringCT signatures, which are only valid if tx version > 1
|
||||
* @param pmax_related_block_height return-by-pointer the height of the most recent block in the input set
|
||||
* @param hf_version the consensus rules version to use
|
||||
*
|
||||
* @return false if any output is not yet unlocked, or is missing, otherwise true
|
||||
*/
|
||||
bool check_tx_input(size_t tx_version,const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const rct::rctSig &rct_signatures, std::vector<rct::ctkey> &output_keys, uint64_t* pmax_related_block_height) const;
|
||||
bool check_tx_input(size_t tx_version,const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const rct::rctSig &rct_signatures, std::vector<rct::ctkey> &output_keys, uint64_t* pmax_related_block_height, uint8_t hf_version) const;
|
||||
|
||||
/**
|
||||
* @brief validate a transaction's inputs and their keys
|
||||
@@ -1363,10 +1389,11 @@ namespace cryptonote
|
||||
* unlock_time is either a block index or a unix time.
|
||||
*
|
||||
* @param unlock_time the unlock parameter (height or time)
|
||||
* @param hf_version the consensus rules version to use
|
||||
*
|
||||
* @return true if spendable, otherwise false
|
||||
*/
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time) const;
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time, uint8_t hf_version) const;
|
||||
|
||||
/**
|
||||
* @brief stores an invalid block in a separate container
|
||||
@@ -1427,16 +1454,6 @@ namespace cryptonote
|
||||
bool check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const;
|
||||
bool check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b) const { uint64_t median_ts; return check_block_timestamp(timestamps, b, median_ts); }
|
||||
|
||||
/**
|
||||
* @brief get the "adjusted time"
|
||||
*
|
||||
* Currently this simply returns the current time according to the
|
||||
* user's machine.
|
||||
*
|
||||
* @return the current time
|
||||
*/
|
||||
uint64_t get_adjusted_time() const;
|
||||
|
||||
/**
|
||||
* @brief finish an alternate chain's timestamp window from the main chain
|
||||
*
|
||||
@@ -1512,6 +1529,6 @@ namespace cryptonote
|
||||
*
|
||||
* At some point, may be used to push an update to miners
|
||||
*/
|
||||
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t pool_cookie);
|
||||
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie);
|
||||
};
|
||||
} // namespace cryptonote
|
||||
|
||||
@@ -41,6 +41,7 @@ using namespace epee;
|
||||
#include "common/download.h"
|
||||
#include "common/threadpool.h"
|
||||
#include "common/command_line.h"
|
||||
#include "cryptonote_basic/events.h"
|
||||
#include "warnings.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "cryptonote_config.h"
|
||||
@@ -51,6 +52,7 @@ using namespace epee;
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "ringct/rctSigs.h"
|
||||
#include "rpc/zmq_pub.h"
|
||||
#include "common/notify.h"
|
||||
#include "hardforks/hardforks.h"
|
||||
#include "version.h"
|
||||
@@ -224,8 +226,8 @@ namespace cryptonote
|
||||
core::core(i_cryptonote_protocol* pprotocol):
|
||||
m_mempool(m_blockchain_storage),
|
||||
m_blockchain_storage(m_mempool),
|
||||
m_miner(this, [this](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, threads);
|
||||
m_miner(this, [this](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash) {
|
||||
return cryptonote::get_block_longhash(&m_blockchain_storage, b, hash, height, seed_hash, threads);
|
||||
}),
|
||||
m_starter_message_showed(false),
|
||||
m_target_blockchain_height(0),
|
||||
@@ -262,6 +264,13 @@ namespace cryptonote
|
||||
{
|
||||
m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
void core::set_txpool_listener(boost::function<void(std::vector<txpool_event>)> zmq_pub)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
||||
m_zmq_pub = std::move(zmq_pub);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::update_checkpoints(const bool skip_dns /* = false */)
|
||||
{
|
||||
@@ -614,7 +623,20 @@ namespace cryptonote
|
||||
try
|
||||
{
|
||||
if (!command_line::is_arg_defaulted(vm, arg_block_notify))
|
||||
m_blockchain_storage.set_block_notify(std::shared_ptr<tools::Notify>(new tools::Notify(command_line::get_arg(vm, arg_block_notify).c_str())));
|
||||
{
|
||||
struct hash_notify
|
||||
{
|
||||
tools::Notify cmdline;
|
||||
|
||||
void operator()(std::uint64_t, epee::span<const block> blocks) const
|
||||
{
|
||||
for (const block bl : blocks)
|
||||
cmdline.notify("%s", epee::string_tools::pod_to_hex(get_block_hash(bl)).c_str(), NULL);
|
||||
}
|
||||
};
|
||||
|
||||
m_blockchain_storage.add_block_notify(hash_notify{{command_line::get_arg(vm, arg_block_notify).c_str()}});
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -946,6 +968,7 @@ namespace cryptonote
|
||||
break;
|
||||
case rct::RCTTypeBulletproof:
|
||||
case rct::RCTTypeBulletproof2:
|
||||
case rct::RCTTypeCLSAG:
|
||||
if (!is_canonical_bulletproof_layout(rv.p.bulletproofs))
|
||||
{
|
||||
MERROR_VER("Bulletproof does not have canonical form");
|
||||
@@ -973,7 +996,7 @@ namespace cryptonote
|
||||
{
|
||||
if (!tx_info[n].result)
|
||||
continue;
|
||||
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2)
|
||||
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG)
|
||||
continue;
|
||||
if (assumed_bad || !rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures))
|
||||
{
|
||||
@@ -997,13 +1020,12 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
|
||||
struct result { bool res; cryptonote::transaction tx; crypto::hash hash; };
|
||||
std::vector<result> results(tx_blobs.size());
|
||||
std::vector<txpool_event> results(tx_blobs.size());
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
||||
|
||||
tools::threadpool& tpool = tools::threadpool::getInstance();
|
||||
tools::threadpool::waiter waiter;
|
||||
tools::threadpool::waiter waiter(tpool);
|
||||
epee::span<tx_blob_entry>::const_iterator it = tx_blobs.begin();
|
||||
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
|
||||
tpool.submit(&waiter, [&, i, it] {
|
||||
@@ -1019,7 +1041,8 @@ namespace cryptonote
|
||||
}
|
||||
});
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
if (!waiter.wait())
|
||||
return false;
|
||||
it = tx_blobs.begin();
|
||||
std::vector<bool> already_have(tx_blobs.size(), false);
|
||||
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
|
||||
@@ -1051,7 +1074,8 @@ namespace cryptonote
|
||||
});
|
||||
}
|
||||
}
|
||||
waiter.wait(&tpool);
|
||||
if (!waiter.wait())
|
||||
return false;
|
||||
|
||||
std::vector<tx_verification_batch_info> tx_info;
|
||||
tx_info.reserve(tx_blobs.size());
|
||||
@@ -1063,6 +1087,7 @@ namespace cryptonote
|
||||
if (!tx_info.empty())
|
||||
handle_incoming_tx_accumulated_batch(tx_info, tx_relay == relay_method::block);
|
||||
|
||||
bool valid_events = false;
|
||||
bool ok = true;
|
||||
it = tx_blobs.begin();
|
||||
for (size_t i = 0; i < tx_blobs.size(); i++, ++it) {
|
||||
@@ -1085,10 +1110,18 @@ namespace cryptonote
|
||||
{MERROR_VER("Transaction verification impossible: " << results[i].hash);}
|
||||
|
||||
if(tvc[i].m_added_to_pool)
|
||||
{
|
||||
MDEBUG("tx added: " << results[i].hash);
|
||||
valid_events = true;
|
||||
}
|
||||
else
|
||||
results[i].res = false;
|
||||
}
|
||||
return ok;
|
||||
|
||||
if (valid_events && m_zmq_pub && matches_category(tx_relay, relay_category::legacy))
|
||||
m_zmq_pub(std::move(results));
|
||||
|
||||
return ok;
|
||||
CATCH_ENTRY_L0("core::handle_incoming_txs()", false);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
@@ -1191,11 +1224,42 @@ namespace cryptonote
|
||||
size_t core::get_block_sync_size(uint64_t height) const
|
||||
{
|
||||
static const uint64_t quick_height = m_nettype == TESTNET ? 801219 : m_nettype == MAINNET ? 53666 : 0;
|
||||
size_t res = 0;
|
||||
if (block_sync_size > 0)
|
||||
return block_sync_size;
|
||||
if (height >= quick_height)
|
||||
return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
|
||||
return BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4;
|
||||
res = block_sync_size;
|
||||
else if (height >= quick_height)
|
||||
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT;
|
||||
else
|
||||
res = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT_PRE_V4;
|
||||
|
||||
static size_t max_block_size = 0;
|
||||
if (max_block_size == 0)
|
||||
{
|
||||
const char *env = getenv("SEEDHASH_EPOCH_BLOCKS");
|
||||
if (env)
|
||||
{
|
||||
int n = atoi(env);
|
||||
if (n <= 0)
|
||||
n = BLOCKS_SYNCHRONIZING_MAX_COUNT;
|
||||
size_t p = 1;
|
||||
while (p < (size_t)n)
|
||||
p <<= 1;
|
||||
max_block_size = p;
|
||||
}
|
||||
else
|
||||
max_block_size = BLOCKS_SYNCHRONIZING_MAX_COUNT;
|
||||
}
|
||||
if (res > max_block_size)
|
||||
{
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
{
|
||||
MWARNING("Clamping block sync size to " << max_block_size);
|
||||
warned = true;
|
||||
}
|
||||
res = max_block_size;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::are_key_images_spent_in_pool(const std::vector<crypto::key_image>& key_im, std::vector<bool> &spent) const
|
||||
@@ -1313,6 +1377,7 @@ namespace cryptonote
|
||||
{
|
||||
NOTIFY_NEW_TRANSACTIONS::request public_req{};
|
||||
NOTIFY_NEW_TRANSACTIONS::request private_req{};
|
||||
NOTIFY_NEW_TRANSACTIONS::request stem_req{};
|
||||
for (auto& tx : txs)
|
||||
{
|
||||
switch (std::get<2>(tx))
|
||||
@@ -1323,6 +1388,9 @@ namespace cryptonote
|
||||
case relay_method::local:
|
||||
private_req.txs.push_back(std::move(std::get<1>(tx)));
|
||||
break;
|
||||
case relay_method::forward:
|
||||
stem_req.txs.push_back(std::move(std::get<1>(tx)));
|
||||
break;
|
||||
case relay_method::block:
|
||||
case relay_method::fluff:
|
||||
case relay_method::stem:
|
||||
@@ -1340,6 +1408,8 @@ namespace cryptonote
|
||||
get_protocol()->relay_transactions(public_req, source, epee::net_utils::zone::public_, relay_method::fluff);
|
||||
if (!private_req.txs.empty())
|
||||
get_protocol()->relay_transactions(private_req, source, epee::net_utils::zone::invalid, relay_method::local);
|
||||
if (!stem_req.txs.empty())
|
||||
get_protocol()->relay_transactions(stem_req, source, epee::net_utils::zone::public_, relay_method::stem);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1361,14 +1431,14 @@ namespace cryptonote
|
||||
m_mempool.set_relayed(epee::to_span(tx_hashes), tx_relay);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce);
|
||||
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce)
|
||||
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce);
|
||||
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, bool clip_pruned, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
|
||||
@@ -1683,27 +1753,36 @@ namespace cryptonote
|
||||
main_message = "The daemon is running offline and will not attempt to sync to the Monero network.";
|
||||
else
|
||||
main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
|
||||
MGINFO_GREEN(ENDL <<
|
||||
MGINFO_MAGENTA(ENDL <<
|
||||
"\n \n"
|
||||
" ,'``.._ ,'``. \n"
|
||||
" :,--._:)|,:,._,.: All Glory to \n"
|
||||
" :`--,'' :`...';| the HYPNO TOAD! \n"
|
||||
" `,' `---' `. \n"
|
||||
" / : \n"
|
||||
" / | \n"
|
||||
" ,' :|.___,-. \n"
|
||||
" `...,---'``````-..._ |: | \n"
|
||||
" ( ) ;: ) | _,-. \n"
|
||||
" `. ( // `' | \n"
|
||||
" : `.// ) ) , ; \n"
|
||||
" ,-|`. _,'/ ) ) ,' ,' \n"
|
||||
" ( :`.`-..____..=:.-': . _,' ,' \n"
|
||||
" `,'| ``--....-)=' `._, | ,') _ '``._ \n"
|
||||
" _.-/ _ `. (WOW) / )' ; / | |`-.' \n"
|
||||
"`--( `-:`. `' ___..' _,-' |/ `.) \n"
|
||||
" `-. `.`.``-----``--, .' \n"
|
||||
" |/`.|`' ,','); \n"
|
||||
" ` (/ (/ \n"
|
||||
" ... . -..- \n"
|
||||
" `-. .-'. \n"
|
||||
" `-. -./\\.- .-' \n"
|
||||
" -. /__\\ .- \n"
|
||||
" `-. `/__|_\\' .-'. \n"
|
||||
" `-. -./ .-- \\.- ' \n"
|
||||
" `-. / <(O)> \\ .-' \n"
|
||||
" - .`/__ .-- ___\\ .- Magnus \n"
|
||||
" ,...`-./___|__|__|__\\.-'.,. Frater \n"
|
||||
" -.. .-. ..- --. ... Spectat Te \n"
|
||||
" .-. --- -.-. -.- -. .-. --- .-.. .-.. \n"
|
||||
" ,-' ________________ `-, \n"
|
||||
" /'/____|_____|_____\\ \n"
|
||||
" / /__|___|___|___|___\\ \n"
|
||||
" / /|_____|_____|____|__\\ \n"
|
||||
" ' /_____|____|_____|_____\\ \n"
|
||||
" ' /__|_____|______|_____|__\\ \n"
|
||||
" /' /_|_____|_____|_____|____|_\\ \n"
|
||||
" .. - . .-. .- - .. ...- ./ /____|_____|_____|_____|_____\\-.. .. ... -.-. --- ..- .-. ... .\n"
|
||||
" / /__|_____|_____|_____|_____|___\\ \n"
|
||||
" / /|_____|_____|_____|_____|_____|_\\ \n"
|
||||
" / /____|_____|_____|_____|_____|_____\\ \n"
|
||||
" / /__|_____|_____|_____|_____|_____|___\\ \n"
|
||||
" / /|_____|_____|_____|_____|_____|_____|_\\ \n"
|
||||
" / /____|_____|_____|_____|_____|_____|_____\\ \n"
|
||||
" \\ /___________.-- --- .-- -. . .-. ---_______\\ \n"
|
||||
" IV.I.MMXVIII \n"
|
||||
" .- / -... .-.. .- -.-. -.- .... .- - / -.-. ..- .-.. - ..- .-. . \n"
|
||||
"\n \n" << ENDL);
|
||||
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
|
||||
<< main_message << ENDL
|
||||
@@ -1714,9 +1793,8 @@ namespace cryptonote
|
||||
<< "You can set the level of process detailization through \"set_log <level|categories>\" command," << ENDL
|
||||
<< "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING)." << ENDL
|
||||
<< ENDL
|
||||
<< "Use the \"help\" command to see a simplified list of available commands." << ENDL
|
||||
<< "Use the \"help_advanced\" command to see an advanced list of available commands." << ENDL
|
||||
<< "Use \"help_advanced <command>\" to see a command's documentation." << ENDL
|
||||
<< "Use the \"help\" command to see the list of available commands." << ENDL
|
||||
<< "Use \"help <command>\" to see a command's documentation." << ENDL
|
||||
<< "**********************************************************************" << ENDL);
|
||||
m_starter_message_showed = true;
|
||||
}
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
|
||||
#include <ctime>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
#include "cryptonote_basic/fwd.h"
|
||||
#include "cryptonote_core/i_core_events.h"
|
||||
#include "cryptonote_protocol/cryptonote_protocol_handler_common.h"
|
||||
#include "cryptonote_protocol/enums.h"
|
||||
@@ -48,6 +50,7 @@
|
||||
#include "warnings.h"
|
||||
#include "crypto/hash.h"
|
||||
#include "span.h"
|
||||
#include "rpc/fwd.h"
|
||||
|
||||
PUSH_WARNINGS
|
||||
DISABLE_VS_WARNINGS(4355)
|
||||
@@ -228,8 +231,8 @@ namespace cryptonote
|
||||
*
|
||||
* @note see Blockchain::create_block_template
|
||||
*/
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce);
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
|
||||
|
||||
/**
|
||||
* @brief called when a transaction is relayed.
|
||||
@@ -445,6 +448,13 @@ namespace cryptonote
|
||||
*/
|
||||
void set_enforce_dns_checkpoints(bool enforce_dns);
|
||||
|
||||
/**
|
||||
* @brief set a listener for txes being added to the txpool
|
||||
*
|
||||
* @param callable to notify, or empty function to disable.
|
||||
*/
|
||||
void set_txpool_listener(boost::function<void(std::vector<txpool_event>)> zmq_pub);
|
||||
|
||||
/**
|
||||
* @brief set whether or not to enable or disable DNS checkpoints
|
||||
*
|
||||
@@ -1098,7 +1108,12 @@ namespace cryptonote
|
||||
bool m_fluffy_blocks_enabled;
|
||||
bool m_offline;
|
||||
|
||||
/* `boost::function` is used because the implementation never allocates if
|
||||
the callable object has a single `std::shared_ptr` or `std::weap_ptr`
|
||||
internally. Whereas, the libstdc++ `std::function` will allocate. */
|
||||
|
||||
std::shared_ptr<tools::Notify> m_block_rate_notify;
|
||||
boost::function<void(std::vector<txpool_event>)> m_zmq_pub;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace cryptonote
|
||||
LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses");
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
|
||||
bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
|
||||
tx.vin.clear();
|
||||
tx.vout.clear();
|
||||
tx.extra.clear();
|
||||
@@ -167,7 +167,17 @@ namespace cryptonote
|
||||
tx.version = 1;
|
||||
|
||||
//lock
|
||||
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||
if (hard_fork_version >= HF_VERSION_DYNAMIC_UNLOCK)
|
||||
{
|
||||
uint64_t N = m_nettype == MAINNET ? 1337 : 5;
|
||||
crypto::hash blk_id = pb->get_block_id_by_height(height-N);
|
||||
std::string hex_str = epee::string_tools::pod_to_hex(blk_id).substr(0, 3);
|
||||
uint64_t blk_num = std::stol(hex_str,nullptr,16)*2;
|
||||
uint64_t unlock_window = blk_num + 288;
|
||||
tx.unlock_time = height + unlock_window;
|
||||
} else {
|
||||
tx.unlock_time = height + 60;
|
||||
}
|
||||
tx.vin.push_back(in);
|
||||
|
||||
tx.invalidate_hashes();
|
||||
@@ -665,9 +675,9 @@ namespace cryptonote
|
||||
bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
|
||||
bl.timestamp = 0;
|
||||
bl.nonce = nonce;
|
||||
miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, threads);
|
||||
}, bl, 1, 0);
|
||||
miner::find_nonce_for_given_block([](const cryptonote::block &b, uint64_t height, const crypto::hash *seed_hash, unsigned int threads, crypto::hash &hash){
|
||||
return cryptonote::get_block_longhash(NULL, b, hash, height, seed_hash, threads);
|
||||
}, bl, 1, 0, NULL);
|
||||
bl.invalidate_hashes();
|
||||
return true;
|
||||
}
|
||||
@@ -678,8 +688,15 @@ namespace cryptonote
|
||||
rx_slow_hash(main_height, seed_height, seed_hash.data, bd.data(), bd.size(), res.data, 0, 1);
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners)
|
||||
{
|
||||
// block 202612 bug workaround
|
||||
if (height == 202612)
|
||||
{
|
||||
static const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000";
|
||||
epee::string_tools::hex_to_pod(longhash_202612, res);
|
||||
return true;
|
||||
}
|
||||
blobdata bd = get_block_hashing_blob(b);
|
||||
if (b.major_version >= RX_BLOCK_VERSION)
|
||||
{
|
||||
@@ -688,7 +705,7 @@ namespace cryptonote
|
||||
if (pbc != NULL)
|
||||
{
|
||||
seed_height = rx_seedheight(height);
|
||||
hash = pbc->get_pending_block_id_by_height(seed_height);
|
||||
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
|
||||
main_height = pbc->get_current_blockchain_height();
|
||||
} else
|
||||
{
|
||||
@@ -696,7 +713,7 @@ namespace cryptonote
|
||||
seed_height = 0;
|
||||
main_height = 0;
|
||||
}
|
||||
rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, miners, 0);
|
||||
rx_slow_hash(main_height, seed_height, hash.data, bd.data(), bd.size(), res.data, seed_hash ? 0 : miners, !!seed_hash);
|
||||
} else {
|
||||
const int pow_variant = b.major_version >= 11 ? 4 : b.major_version >= 9 ? 2 : 1;
|
||||
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
|
||||
@@ -704,6 +721,11 @@ namespace cryptonote
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_block_longhash(const Blockchain *pbc, const block& b, crypto::hash& res, const uint64_t height, const int miners)
|
||||
{
|
||||
return get_block_longhash(pbc, b, res, height, NULL, miners);
|
||||
}
|
||||
|
||||
crypto::hash get_block_longhash(const Blockchain *pbc, const block& b, const uint64_t height, const int miners)
|
||||
{
|
||||
crypto::hash p = crypto::null_hash;
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
namespace cryptonote
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
|
||||
class Blockchain;
|
||||
bool construct_miner_tx(const Blockchain *pb, network_type m_nettype, size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
|
||||
|
||||
struct tx_source_entry
|
||||
{
|
||||
@@ -134,6 +135,7 @@ namespace cryptonote
|
||||
|
||||
class Blockchain;
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const int miners);
|
||||
bool get_block_longhash(const Blockchain *pb, const block& b, crypto::hash& res, const uint64_t height, const crypto::hash *seed_hash, const int miners);
|
||||
void get_altblock_longhash(const block& b, crypto::hash& res, const uint64_t main_height, const uint64_t height,
|
||||
const uint64_t seed_height, const crypto::hash& seed_hash);
|
||||
crypto::hash get_block_longhash(const Blockchain *pb, const block& b, const uint64_t height, const int miners);
|
||||
|
||||
@@ -91,6 +91,8 @@ namespace cryptonote
|
||||
time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
|
||||
float const ACCEPT_THRESHOLD = 1.0f;
|
||||
|
||||
constexpr const std::chrono::seconds forward_delay_average{CRYPTONOTE_FORWARD_DELAY_AVERAGE};
|
||||
|
||||
// a kind of increasing backoff within min/max bounds
|
||||
uint64_t get_relay_delay(time_t now, time_t received)
|
||||
{
|
||||
@@ -309,8 +311,14 @@ namespace cryptonote
|
||||
|
||||
if (meta.upgrade_relay_method(tx_relay) || !existing_tx) // synchronize with embargo timer or stem/fluff out-of-order messages
|
||||
{
|
||||
using clock = std::chrono::system_clock;
|
||||
auto last_relayed_time = std::numeric_limits<decltype(meta.last_relayed_time)>::max();
|
||||
if (tx_relay == relay_method::forward)
|
||||
last_relayed_time = clock::to_time_t(clock::now() + crypto::random_poisson_seconds{forward_delay_average}());
|
||||
// else the `set_relayed` function will adjust the time accordingly later
|
||||
|
||||
//update transactions container
|
||||
meta.last_relayed_time = std::numeric_limits<decltype(meta.last_relayed_time)>::max();
|
||||
meta.last_relayed_time = last_relayed_time;
|
||||
meta.receive_time = receive_time;
|
||||
meta.weight = tx_weight;
|
||||
meta.fee = fee;
|
||||
@@ -341,7 +349,7 @@ namespace cryptonote
|
||||
tvc.m_added_to_pool = true;
|
||||
|
||||
static_assert(unsigned(relay_method::none) == 0, "expected relay_method::none value to be zero");
|
||||
if(meta.fee > 0)
|
||||
if(meta.fee > 0 && tx_relay != relay_method::forward)
|
||||
tvc.m_relay = tx_relay;
|
||||
}
|
||||
|
||||
@@ -614,7 +622,7 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
|
||||
m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
|
||||
m_blockchain.for_all_txpool_txes([this, &hashes, &txes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) {
|
||||
const auto tx_relay_method = meta.get_relay_method();
|
||||
if (tx_relay_method != relay_method::block && tx_relay_method != relay_method::fluff)
|
||||
return true;
|
||||
@@ -662,7 +670,7 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
std::list<std::pair<crypto::hash, uint64_t>> remove;
|
||||
m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
|
||||
m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) {
|
||||
uint64_t tx_age = time(nullptr) - meta.receive_time;
|
||||
|
||||
if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !meta.kept_by_block) ||
|
||||
@@ -722,28 +730,46 @@ namespace cryptonote
|
||||
//TODO: investigate whether boolean return is appropriate
|
||||
bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs) const
|
||||
{
|
||||
std::vector<std::pair<crypto::hash, txpool_tx_meta_t>> change_timestamps;
|
||||
const uint64_t now = time(NULL);
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const uint64_t now = time(NULL);
|
||||
LockedTXN lock(m_blockchain.get_db());
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count());
|
||||
m_blockchain.for_all_txpool_txes([this, now, &txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *){
|
||||
m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){
|
||||
// 0 fee transactions are never relayed
|
||||
if(!meta.pruned && meta.fee > 0 && !meta.do_not_relay)
|
||||
{
|
||||
if (!meta.dandelionpp_stem && now - meta.last_relayed_time <= get_relay_delay(now, meta.receive_time))
|
||||
return true;
|
||||
if (meta.dandelionpp_stem && meta.last_relayed_time < now) // for dandelion++ stem, this value is the embargo timeout
|
||||
return true;
|
||||
const relay_method tx_relay = meta.get_relay_method();
|
||||
switch (tx_relay)
|
||||
{
|
||||
case relay_method::stem:
|
||||
case relay_method::forward:
|
||||
if (meta.last_relayed_time > now)
|
||||
return true; // continue to next tx
|
||||
change_timestamps.emplace_back(txid, meta);
|
||||
break;
|
||||
default:
|
||||
case relay_method::none:
|
||||
return true;
|
||||
case relay_method::local:
|
||||
case relay_method::fluff:
|
||||
case relay_method::block:
|
||||
if (now - meta.last_relayed_time <= get_relay_delay(now, meta.receive_time))
|
||||
return true; // continue to next tx
|
||||
break;
|
||||
}
|
||||
|
||||
// if the tx is older than half the max lifetime, we don't re-relay it, to avoid a problem
|
||||
// mentioned by smooth where nodes would flush txes at slightly different times, causing
|
||||
// flushed txes to be re-added when received from a node which was just about to flush it
|
||||
uint64_t max_age = meta.kept_by_block ? CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME : CRYPTONOTE_MEMPOOL_TX_LIVETIME;
|
||||
uint64_t max_age = (tx_relay == relay_method::block) ? CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME : CRYPTONOTE_MEMPOOL_TX_LIVETIME;
|
||||
if (now - meta.receive_time <= max_age / 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
txs.emplace_back(txid, m_blockchain.get_txpool_tx_blob(txid, relay_category::all), meta.get_relay_method());
|
||||
txs.emplace_back(txid, m_blockchain.get_txpool_tx_blob(txid, relay_category::all), tx_relay);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -754,6 +780,18 @@ namespace cryptonote
|
||||
}
|
||||
return true;
|
||||
}, false, relay_category::relayable);
|
||||
|
||||
for (auto& elem : change_timestamps)
|
||||
{
|
||||
/* These transactions are still in forward or stem state, so the field
|
||||
represents the next time a relay should be attempted. Will be
|
||||
overwritten when the state is upgraded to stem, fluff or block. This
|
||||
function is only called every ~2 minutes, so this resetting should be
|
||||
unnecessary, but is primarily a precaution against potential changes
|
||||
to the callback routines. */
|
||||
elem.second.last_relayed_time = now + get_relay_delay(now, elem.second.receive_time);
|
||||
m_blockchain.update_txpool_tx(elem.first, elem.second);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
@@ -806,7 +844,7 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
transaction tx;
|
||||
if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, tx) : parse_and_validate_tx_from_blob(*bd, tx)))
|
||||
{
|
||||
@@ -826,7 +864,7 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
txs.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&txs](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
txs.push_back(txid);
|
||||
return true;
|
||||
}, false, category);
|
||||
@@ -839,7 +877,7 @@ namespace cryptonote
|
||||
const uint64_t now = time(NULL);
|
||||
const relay_category category = include_sensitive ? relay_category::all : relay_category::broadcasted;
|
||||
backlog.reserve(m_blockchain.get_txpool_tx_count(include_sensitive));
|
||||
m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&backlog, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
backlog.push_back({meta.weight, meta.fee, meta.receive_time - now});
|
||||
return true;
|
||||
}, false, category);
|
||||
@@ -855,7 +893,7 @@ namespace cryptonote
|
||||
stats.txs_total = m_blockchain.get_txpool_tx_count(include_sensitive);
|
||||
std::vector<uint32_t> weights;
|
||||
weights.reserve(stats.txs_total);
|
||||
m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&stats, &weights, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
weights.push_back(meta.weight);
|
||||
stats.bytes_total += meta.weight;
|
||||
if (!stats.bytes_min || meta.weight < stats.bytes_min)
|
||||
@@ -940,10 +978,10 @@ namespace cryptonote
|
||||
const size_t count = m_blockchain.get_txpool_tx_count(include_sensitive_data);
|
||||
tx_infos.reserve(count);
|
||||
key_image_infos.reserve(count);
|
||||
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos, include_sensitive_data](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
tx_info txi;
|
||||
txi.id_hash = epee::string_tools::pod_to_hex(txid);
|
||||
txi.tx_blob = *bd;
|
||||
txi.tx_blob = blobdata(bd->data(), bd->size());
|
||||
transaction tx;
|
||||
if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, tx) : parse_and_validate_tx_from_blob(*bd, tx)))
|
||||
{
|
||||
@@ -997,7 +1035,7 @@ namespace cryptonote
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
tx_infos.reserve(m_blockchain.get_txpool_tx_count());
|
||||
key_image_infos.reserve(m_blockchain.get_txpool_tx_count());
|
||||
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){
|
||||
m_blockchain.for_all_txpool_txes([&tx_infos, key_image_infos](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd){
|
||||
cryptonote::rpc::tx_in_pool txi;
|
||||
txi.tx_hash = txid;
|
||||
if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(*bd, txi.tx) : parse_and_validate_tx_from_blob(*bd, txi.tx)))
|
||||
@@ -1293,7 +1331,7 @@ namespace cryptonote
|
||||
std::stringstream ss;
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
CRITICAL_REGION_LOCAL1(m_blockchain);
|
||||
m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *txblob) {
|
||||
m_blockchain.for_all_txpool_txes([&ss, short_format](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *txblob) {
|
||||
ss << "id: " << txid << std::endl;
|
||||
if (!short_format) {
|
||||
cryptonote::transaction tx;
|
||||
@@ -1471,7 +1509,7 @@ namespace cryptonote
|
||||
std::unordered_set<crypto::hash> remove;
|
||||
|
||||
m_txpool_weight = 0;
|
||||
m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata*) {
|
||||
m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref*) {
|
||||
m_txpool_weight += meta.weight;
|
||||
if (meta.weight > tx_weight_limit) {
|
||||
LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool");
|
||||
@@ -1543,7 +1581,7 @@ namespace cryptonote
|
||||
for (int pass = 0; pass < 2; ++pass)
|
||||
{
|
||||
const bool kept = pass == 1;
|
||||
bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) {
|
||||
bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *bd) {
|
||||
if (!!kept != !!meta.kept_by_block)
|
||||
return true;
|
||||
cryptonote::transaction_prefix tx;
|
||||
|
||||
@@ -935,7 +935,19 @@ namespace cryptonote
|
||||
return 1;
|
||||
}
|
||||
|
||||
relay_method tx_relay;
|
||||
/* If the txes were received over i2p/tor, the default is to "forward"
|
||||
with a randomized delay to further enhance the "white noise" behavior,
|
||||
potentially making it harder for ISP-level spies to determine which
|
||||
inbound link sent the tx. If the sender disabled "white noise" over
|
||||
i2p/tor, then the sender is "fluffing" (to only outbound) i2p/tor
|
||||
connections with the `dandelionpp_fluff` flag set. The receiver (hidden
|
||||
service) will immediately fluff in that scenario (i.e. this assumes that a
|
||||
sybil spy will be unable to link an IP to an i2p/tor connection). */
|
||||
|
||||
const epee::net_utils::zone zone = context.m_remote_address.get_zone();
|
||||
relay_method tx_relay = zone == epee::net_utils::zone::public_ ?
|
||||
relay_method::stem : relay_method::forward;
|
||||
|
||||
std::vector<blobdata> stem_txs{};
|
||||
std::vector<blobdata> fluff_txs{};
|
||||
if (arg.dandelionpp_fluff)
|
||||
@@ -944,10 +956,7 @@ namespace cryptonote
|
||||
fluff_txs.reserve(arg.txs.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
tx_relay = relay_method::stem;
|
||||
stem_txs.reserve(arg.txs.size());
|
||||
}
|
||||
|
||||
for (auto& tx : arg.txs)
|
||||
{
|
||||
@@ -970,6 +979,7 @@ namespace cryptonote
|
||||
fluff_txs.push_back(std::move(tx));
|
||||
break;
|
||||
default:
|
||||
case relay_method::forward: // not supposed to happen here
|
||||
case relay_method::none:
|
||||
break;
|
||||
}
|
||||
@@ -1927,8 +1937,8 @@ skip:
|
||||
if (local_stripe == 0)
|
||||
return false;
|
||||
// don't request pre-bulletprooof pruned blocks, we can't reconstruct their weight (yet)
|
||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(8);
|
||||
if (first_block_height + nblocks - 1 < bp_fork_height)
|
||||
static const uint64_t bp_fork_height = m_core.get_earliest_ideal_height_for_version(HF_VERSION_SMALLER_BP);
|
||||
if (first_block_height < bp_fork_height)
|
||||
return false;
|
||||
// assumes the span size is less or equal to the stripe size
|
||||
bool full_data_needed = tools::get_pruning_stripe(first_block_height, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES) == local_stripe
|
||||
@@ -2337,8 +2347,7 @@ skip:
|
||||
MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL
|
||||
<< "You are now synchronized with the network. You may now start wownero-wallet-cli." << ENDL
|
||||
<< ENDL
|
||||
<< "Use the \"help\" command to see a simplified list of available commands." << ENDL
|
||||
<< "Use the \"help_advanced\" command to see an advanced list of available commands." << ENDL
|
||||
<< "Use the \"help\" command to see the list of available commands." << ENDL
|
||||
<< "**********************************************************************");
|
||||
m_sync_timer.pause();
|
||||
if (ELPP->vRegistry()->allowed(el::Level::Info, "sync-info"))
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace cryptonote
|
||||
{
|
||||
none = 0, //!< Received via RPC with `do_not_relay` set
|
||||
local, //!< Received via RPC; trying to send over i2p/tor, etc.
|
||||
forward, //!< Received over i2p/tor; timer delayed before ipv4/6 public broadcast
|
||||
stem, //!< Received/send over network using Dandelion++ stem
|
||||
fluff, //!< Received/sent over network using Dandelion++ fluff
|
||||
block //!< Received in block, takes precedence over others
|
||||
|
||||
@@ -357,11 +357,15 @@ namespace levin
|
||||
return true;
|
||||
});
|
||||
|
||||
// Always send txs in stem mode over i2p/tor, see comments in `send_txs` below.
|
||||
/* Always send with `fluff` flag, even over i2p/tor. The hidden service
|
||||
will disable the forwarding delay and immediately fluff. The i2p/tor
|
||||
network is therefore replacing the sybil protection of Dandelion++.
|
||||
Dandelion++ stem phase over i2p/tor is also worth investigating
|
||||
(with/without "noise"?). */
|
||||
for (auto& connection : connections)
|
||||
{
|
||||
std::sort(connection.first.begin(), connection.first.end()); // don't leak receive order
|
||||
make_payload_send_txs(*zone_->p2p, std::move(connection.first), connection.second, zone_->pad_txs, zone_->is_public);
|
||||
make_payload_send_txs(*zone_->p2p, std::move(connection.first), connection.second, zone_->pad_txs, true);
|
||||
}
|
||||
|
||||
if (next_flush != std::chrono::steady_clock::time_point::max())
|
||||
@@ -811,12 +815,11 @@ namespace levin
|
||||
case relay_method::block:
|
||||
return false;
|
||||
case relay_method::stem:
|
||||
tx_relay = relay_method::fluff; // don't set stempool embargo when skipping to fluff
|
||||
/* fallthrough */
|
||||
case relay_method::forward:
|
||||
case relay_method::local:
|
||||
if (zone_->is_public)
|
||||
{
|
||||
// this will change a local tx to stem or fluff ...
|
||||
// this will change a local/forward tx to stem or fluff ...
|
||||
zone_->strand.dispatch(
|
||||
dandelionpp_notify{zone_, std::addressof(core), std::move(txs), source}
|
||||
);
|
||||
@@ -824,6 +827,11 @@ namespace levin
|
||||
}
|
||||
/* fallthrough */
|
||||
case relay_method::fluff:
|
||||
/* If sending stem/forward/local txes over non public networks,
|
||||
continue to claim that relay mode even though it used the "fluff"
|
||||
routine. A "fluff" over i2p/tor is not the same as a "fluff" over
|
||||
ipv4/6. Marking it as "fluff" here will make the tx immediately
|
||||
visible externally from this node, which is not desired. */
|
||||
core.on_transactions_relayed(epee::to_span(txs), tx_relay);
|
||||
zone_->strand.dispatch(fluff_notify{zone_, std::move(txs), source});
|
||||
break;
|
||||
|
||||
@@ -88,6 +88,7 @@ target_link_libraries(daemon
|
||||
${Boost_REGEX_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${ZMQ_LIB}
|
||||
${GNU_READLINE_LIBRARY}
|
||||
${EXTRA_LIBRARIES}
|
||||
${Blocks})
|
||||
|
||||
@@ -121,6 +121,10 @@ namespace daemon_args
|
||||
return val;
|
||||
}
|
||||
};
|
||||
const command_line::arg_descriptor<std::vector<std::string>> arg_zmq_pub = {
|
||||
"zmq-pub"
|
||||
, "Address for ZMQ pub - tcp://ip:port or ipc://path"
|
||||
};
|
||||
|
||||
const command_line::arg_descriptor<bool> arg_zmq_rpc_disabled = {
|
||||
"no-zmq"
|
||||
|
||||
@@ -57,6 +57,12 @@ t_command_server::t_command_server(
|
||||
, "help [<command>]"
|
||||
, "Show the help section or the documentation about a <command>."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
"apropos"
|
||||
, std::bind(&t_command_server::apropos, this, p::_1)
|
||||
, "apropos <keyword> [<keyword> ...]"
|
||||
, "Search all command descriptions for keyword(s)."
|
||||
);
|
||||
m_command_lookup.set_handler(
|
||||
"print_height"
|
||||
, std::bind(&t_command_parser_executor::print_height, &m_parser, p::_1)
|
||||
@@ -349,7 +355,7 @@ bool t_command_server::start_handling(std::function<void(void)> exit_handler)
|
||||
{
|
||||
if (m_is_rpc) return false;
|
||||
|
||||
m_command_lookup.start_handling("", get_commands_str(), exit_handler);
|
||||
m_command_lookup.start_handling("", "Use \"help\" to list all commands and their usage\n", exit_handler);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -374,6 +380,33 @@ bool t_command_server::help(const std::vector<std::string>& args)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool t_command_server::apropos(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "Missing keyword" << std::endl;
|
||||
return true;
|
||||
}
|
||||
const std::vector<std::string>& command_list = m_command_lookup.get_command_list(args);
|
||||
if (command_list.empty())
|
||||
{
|
||||
std::cout << "Nothing found" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
for(auto const& command:command_list)
|
||||
{
|
||||
std::vector<std::string> cmd;
|
||||
cmd.push_back(command);
|
||||
std::pair<std::string, std::string> documentation = m_command_lookup.get_documentation(cmd);
|
||||
std::cout << " " << documentation.first << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string t_command_server::get_commands_str()
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -382,7 +415,7 @@ std::string t_command_server::get_commands_str()
|
||||
std::string usage = m_command_lookup.get_usage();
|
||||
boost::replace_all(usage, "\n", "\n ");
|
||||
usage.insert(0, " ");
|
||||
ss << usage << std::endl;
|
||||
ss << usage;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
|
||||
private:
|
||||
bool help(const std::vector<std::string>& args);
|
||||
bool apropos(const std::vector<std::string>& args);
|
||||
|
||||
std::string get_commands_str();
|
||||
std::string get_command_usage(const std::vector<std::string> &args);
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
#include "misc_log_ex.h"
|
||||
#include "daemon/daemon.h"
|
||||
#include "rpc/daemon_handler.h"
|
||||
#include "rpc/zmq_pub.h"
|
||||
#include "rpc/zmq_server.h"
|
||||
|
||||
#include "common/password.h"
|
||||
#include "common/util.h"
|
||||
#include "cryptonote_basic/events.h"
|
||||
#include "daemon/core.h"
|
||||
#include "daemon/p2p.h"
|
||||
#include "daemon/protocol.h"
|
||||
@@ -55,6 +58,17 @@ using namespace epee;
|
||||
|
||||
namespace daemonize {
|
||||
|
||||
struct zmq_internals
|
||||
{
|
||||
explicit zmq_internals(t_core& core, t_p2p& p2p)
|
||||
: rpc_handler{core.get(), p2p.get()}
|
||||
, server{rpc_handler}
|
||||
{}
|
||||
|
||||
cryptonote::rpc::DaemonHandler rpc_handler;
|
||||
cryptonote::rpc::ZmqServer server;
|
||||
};
|
||||
|
||||
struct t_internals {
|
||||
private:
|
||||
t_protocol protocol;
|
||||
@@ -62,6 +76,7 @@ public:
|
||||
t_core core;
|
||||
t_p2p p2p;
|
||||
std::vector<std::unique_ptr<t_rpc>> rpcs;
|
||||
std::unique_ptr<zmq_internals> zmq;
|
||||
|
||||
t_internals(
|
||||
boost::program_options::variables_map const & vm
|
||||
@@ -69,6 +84,7 @@ public:
|
||||
: core{vm}
|
||||
, protocol{vm, core, command_line::get_arg(vm, cryptonote::arg_offline)}
|
||||
, p2p{vm, protocol}
|
||||
, zmq{nullptr}
|
||||
{
|
||||
// Handle circular dependencies
|
||||
protocol.set_p2p_endpoint(p2p.get());
|
||||
@@ -85,6 +101,28 @@ public:
|
||||
auto restricted_rpc_port = command_line::get_arg(vm, restricted_rpc_port_arg);
|
||||
rpcs.emplace_back(new t_rpc{vm, core, p2p, true, restricted_rpc_port, "restricted", true});
|
||||
}
|
||||
|
||||
if (!command_line::get_arg(vm, daemon_args::arg_zmq_rpc_disabled))
|
||||
{
|
||||
zmq.reset(new zmq_internals{core, p2p});
|
||||
|
||||
const std::string zmq_port = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_port);
|
||||
const std::string zmq_address = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip);
|
||||
|
||||
if (!zmq->server.init_rpc(zmq_address, zmq_port))
|
||||
throw std::runtime_error{"Failed to add TCP socket(" + zmq_address + ":" + zmq_port + ") to ZMQ RPC Server"};
|
||||
|
||||
std::shared_ptr<cryptonote::listener::zmq_pub> shared;
|
||||
const std::vector<std::string> zmq_pub = command_line::get_arg(vm, daemon_args::arg_zmq_pub);
|
||||
if (!zmq_pub.empty() && !(shared = zmq->server.init_pub(epee::to_span(zmq_pub))))
|
||||
throw std::runtime_error{"Failed to initialize zmq_pub"};
|
||||
|
||||
if (shared)
|
||||
{
|
||||
core.get().get_blockchain_storage().add_block_notify(cryptonote::listener::zmq_pub::chain_main{shared});
|
||||
core.get().set_txpool_listener(cryptonote::listener::zmq_pub::txpool_add{shared});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,9 +140,6 @@ t_daemon::t_daemon(
|
||||
: mp_internals{new t_internals{vm}},
|
||||
public_rpc_port(public_rpc_port)
|
||||
{
|
||||
zmq_rpc_bind_port = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_port);
|
||||
zmq_rpc_bind_address = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_bind_ip);
|
||||
zmq_rpc_disabled = command_line::get_arg(vm, daemon_args::arg_zmq_rpc_disabled);
|
||||
}
|
||||
|
||||
t_daemon::~t_daemon() = default;
|
||||
@@ -168,29 +203,8 @@ bool t_daemon::run(bool interactive)
|
||||
rpc_commands->start_handling(std::bind(&daemonize::t_daemon::stop_p2p, this));
|
||||
}
|
||||
|
||||
cryptonote::rpc::DaemonHandler rpc_daemon_handler(mp_internals->core.get(), mp_internals->p2p.get());
|
||||
|
||||
if (false)
|
||||
{
|
||||
if (false)
|
||||
{
|
||||
LOG_ERROR(std::string("Failed to add TCP Socket (") + zmq_rpc_bind_address
|
||||
+ ":" + zmq_rpc_bind_port + ") to ZMQ RPC Server");
|
||||
|
||||
if (rpc_commands)
|
||||
rpc_commands->stop_handling();
|
||||
|
||||
for(auto& rpc : mp_internals->rpcs)
|
||||
rpc->stop();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MINFO("Starting ZMQ server...");
|
||||
|
||||
MINFO(std::string("ZMQ server started at ") + zmq_rpc_bind_address
|
||||
+ ":" + zmq_rpc_bind_port + ".");
|
||||
}
|
||||
if (mp_internals->zmq)
|
||||
mp_internals->zmq->server.run();
|
||||
else
|
||||
MINFO("ZMQ server disabled");
|
||||
|
||||
@@ -205,6 +219,9 @@ bool t_daemon::run(bool interactive)
|
||||
if (rpc_commands)
|
||||
rpc_commands->stop_handling();
|
||||
|
||||
if (mp_internals->zmq)
|
||||
mp_internals->zmq->server.stop();
|
||||
|
||||
for(auto& rpc : mp_internals->rpcs)
|
||||
rpc->stop();
|
||||
MGINFO("Node stopped.");
|
||||
|
||||
@@ -44,9 +44,6 @@ private:
|
||||
private:
|
||||
std::unique_ptr<t_internals> mp_internals;
|
||||
uint16_t public_rpc_port;
|
||||
std::string zmq_rpc_bind_address;
|
||||
std::string zmq_rpc_bind_port;
|
||||
bool zmq_rpc_disabled;
|
||||
public:
|
||||
t_daemon(
|
||||
boost::program_options::variables_map const & vm,
|
||||
|
||||
@@ -154,6 +154,7 @@ int main(int argc, char const * argv[])
|
||||
command_line::add_arg(core_settings, daemon_args::arg_public_node);
|
||||
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_ip);
|
||||
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_bind_port);
|
||||
command_line::add_arg(core_settings, daemon_args::arg_zmq_pub);
|
||||
command_line::add_arg(core_settings, daemon_args::arg_zmq_rpc_disabled);
|
||||
|
||||
daemonizer::init_options(hidden_options, visible_options);
|
||||
|
||||
@@ -721,10 +721,11 @@ bool t_rpc_command_executor::print_net_stats()
|
||||
uint64_t average = seconds > 0 ? net_stats_res.total_bytes_in / seconds : 0;
|
||||
uint64_t limit = limit_res.limit_down * 1024; // convert to bytes, as limits are always kB/s
|
||||
double percent = (double)average / (double)limit * 100.0;
|
||||
tools::success_msg_writer() << boost::format("Received %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s")
|
||||
tools::success_msg_writer() << boost::format("Received %u bytes (%s) in %u packets in %s, average %s/s = %.2f%% of the limit of %s/s")
|
||||
% net_stats_res.total_bytes_in
|
||||
% tools::get_human_readable_bytes(net_stats_res.total_bytes_in)
|
||||
% net_stats_res.total_packets_in
|
||||
% tools::get_human_readable_timespan(seconds)
|
||||
% tools::get_human_readable_bytes(average)
|
||||
% percent
|
||||
% tools::get_human_readable_bytes(limit);
|
||||
@@ -732,10 +733,11 @@ bool t_rpc_command_executor::print_net_stats()
|
||||
average = seconds > 0 ? net_stats_res.total_bytes_out / seconds : 0;
|
||||
limit = limit_res.limit_up * 1024;
|
||||
percent = (double)average / (double)limit * 100.0;
|
||||
tools::success_msg_writer() << boost::format("Sent %u bytes (%s) in %u packets, average %s/s = %.2f%% of the limit of %s/s")
|
||||
tools::success_msg_writer() << boost::format("Sent %u bytes (%s) in %u packets in %s, average %s/s = %.2f%% of the limit of %s/s")
|
||||
% net_stats_res.total_bytes_out
|
||||
% tools::get_human_readable_bytes(net_stats_res.total_bytes_out)
|
||||
% net_stats_res.total_packets_out
|
||||
% tools::get_human_readable_timespan(seconds)
|
||||
% tools::get_human_readable_bytes(average)
|
||||
% percent
|
||||
% tools::get_human_readable_bytes(limit);
|
||||
@@ -1001,7 +1003,9 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash,
|
||||
if (1 == res.txs.size())
|
||||
{
|
||||
// only available for new style answers
|
||||
bool pruned = res.txs.front().prunable_as_hex.empty() && res.txs.front().prunable_hash != epee::string_tools::pod_to_hex(crypto::null_hash);
|
||||
static const std::string empty_hash = epee::string_tools::pod_to_hex(crypto::cn_fast_hash("", 0));
|
||||
// prunable_hash will equal empty_hash when nothing is prunable (mostly when the transaction is coinbase)
|
||||
bool pruned = res.txs.front().prunable_as_hex.empty() && res.txs.front().prunable_hash != epee::string_tools::pod_to_hex(crypto::null_hash) && res.txs.front().prunable_hash != empty_hash;
|
||||
if (res.txs.front().in_pool)
|
||||
tools::success_msg_writer() << "Found in pool";
|
||||
else
|
||||
|
||||
@@ -72,6 +72,7 @@ target_link_libraries(device
|
||||
${HIDAPI_LIBRARIES}
|
||||
cncrypto
|
||||
ringct_basic
|
||||
wallet-crypto
|
||||
${OPENSSL_CRYPTO_LIBRARIES}
|
||||
${Boost_SERIALIZATION_LIBRARY}
|
||||
PRIVATE
|
||||
|
||||
@@ -231,6 +231,10 @@ namespace hw {
|
||||
virtual bool mlsag_hash(const rct::keyV &long_message, rct::key &c) = 0;
|
||||
virtual bool mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) = 0;
|
||||
|
||||
virtual bool clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) = 0;
|
||||
virtual bool clsag_hash(const rct::keyV &data, rct::key &hash) = 0;
|
||||
virtual bool clsag_sign(const rct::key &c, const rct::key &a, const rct::key &p, const rct::key &z, const rct::key &mu_P, const rct::key &mu_C, rct::key &s) = 0;
|
||||
|
||||
virtual bool close_tx(void) = 0;
|
||||
|
||||
virtual bool has_ki_cold_sync(void) const { return false; }
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "device_default.hpp"
|
||||
#include "int-util.h"
|
||||
#include "crypto/wallet/crypto.h"
|
||||
#include "cryptonote_basic/account.h"
|
||||
#include "cryptonote_basic/subaddress_index.h"
|
||||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
@@ -120,7 +121,7 @@ namespace hw {
|
||||
/* ======================================================================= */
|
||||
|
||||
bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_key) {
|
||||
return crypto::derive_subaddress_public_key(out_key, derivation, output_index,derived_key);
|
||||
return crypto::wallet::derive_subaddress_public_key(out_key, derivation, output_index,derived_key);
|
||||
}
|
||||
|
||||
crypto::public_key device_default::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
|
||||
@@ -236,7 +237,7 @@ namespace hw {
|
||||
}
|
||||
|
||||
bool device_default::generate_key_derivation(const crypto::public_key &key1, const crypto::secret_key &key2, crypto::key_derivation &derivation) {
|
||||
return crypto::generate_key_derivation(key1, key2, derivation);
|
||||
return crypto::wallet::generate_key_derivation(key1, key2, derivation);
|
||||
}
|
||||
|
||||
bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res){
|
||||
@@ -401,6 +402,29 @@ namespace hw {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) {
|
||||
rct::skpkGen(a,aG); // aG = a*G
|
||||
rct::scalarmultKey(aH,H,a); // aH = a*H
|
||||
rct::scalarmultKey(I,H,p); // I = p*H
|
||||
rct::scalarmultKey(D,H,z); // D = z*H
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::clsag_hash(const rct::keyV &data, rct::key &hash) {
|
||||
hash = rct::hash_to_scalar(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::clsag_sign(const rct::key &c, const rct::key &a, const rct::key &p, const rct::key &z, const rct::key &mu_P, const rct::key &mu_C, rct::key &s) {
|
||||
rct::key s0_p_mu_P;
|
||||
sc_mul(s0_p_mu_P.bytes,mu_P.bytes,p.bytes);
|
||||
rct::key s0_add_z_mu_C;
|
||||
sc_muladd(s0_add_z_mu_C.bytes,mu_C.bytes,z.bytes,s0_p_mu_P.bytes);
|
||||
sc_mulsub(s.bytes,c.bytes,s0_add_z_mu_C.bytes,a.bytes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_default::close_tx() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,10 @@ namespace hw {
|
||||
bool mlsag_hash(const rct::keyV &long_message, rct::key &c) override;
|
||||
bool mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) override;
|
||||
|
||||
bool clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) override;
|
||||
bool clsag_hash(const rct::keyV &data, rct::key &hash) override;
|
||||
bool clsag_sign(const rct::key &c, const rct::key &a, const rct::key &p, const rct::key &z, const rct::key &mu_P, const rct::key &mu_C, rct::key &s) override;
|
||||
|
||||
bool close_tx(void) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ namespace hw {
|
||||
|
||||
static int device_id = 0;
|
||||
|
||||
#define PROTOCOL_VERSION 3
|
||||
#define PROTOCOL_VERSION 4
|
||||
|
||||
#define INS_NONE 0x00
|
||||
#define INS_RESET 0x02
|
||||
@@ -299,6 +299,7 @@ namespace hw {
|
||||
#define INS_PREFIX_HASH 0x7D
|
||||
#define INS_VALIDATE 0x7C
|
||||
#define INS_MLSAG 0x7E
|
||||
#define INS_CLSAG 0x7F
|
||||
#define INS_CLOSE_TX 0x80
|
||||
|
||||
#define INS_GET_TX_PROOF 0xA0
|
||||
@@ -1548,7 +1549,7 @@ namespace hw {
|
||||
const bool need_additional_txkeys_x = need_additional_txkeys;
|
||||
|
||||
std::vector<crypto::secret_key> additional_tx_keys_x;
|
||||
for (const auto k: additional_tx_keys) {
|
||||
for (const auto &k: additional_tx_keys) {
|
||||
additional_tx_keys_x.push_back(hw::ledger::decrypt(k));
|
||||
}
|
||||
|
||||
@@ -1857,7 +1858,7 @@ namespace hw {
|
||||
|
||||
// ====== Aout, Bout, AKout, C, v, k ======
|
||||
kv_offset = data_offset;
|
||||
if (type==rct::RCTTypeBulletproof2) {
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
|
||||
C_offset = kv_offset+ (8)*outputs_size;
|
||||
} else {
|
||||
C_offset = kv_offset+ (32+32)*outputs_size;
|
||||
@@ -1874,7 +1875,7 @@ namespace hw {
|
||||
offset = set_command_header(INS_VALIDATE, 0x02, i+1);
|
||||
//options
|
||||
this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
|
||||
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2)?0x02:0x00;
|
||||
this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG)?0x02:0x00;
|
||||
offset += 1;
|
||||
//is_subaddress
|
||||
this->buffer_send[offset] = outKeys.is_subaddress;
|
||||
@@ -1895,7 +1896,7 @@ namespace hw {
|
||||
memmove(this->buffer_send+offset, data+C_offset,32);
|
||||
offset += 32;
|
||||
C_offset += 32;
|
||||
if (type==rct::RCTTypeBulletproof2) {
|
||||
if (type==rct::RCTTypeBulletproof2 || type==rct::RCTTypeCLSAG) {
|
||||
//k
|
||||
memset(this->buffer_send+offset, 0, 32);
|
||||
offset += 32;
|
||||
@@ -2121,6 +2122,159 @@ namespace hw {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) {
|
||||
AUTO_LOCK_CMD();
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const rct::key p_x = hw::ledger::decrypt(p);
|
||||
const rct::key z_x = z;
|
||||
rct::key I_x;
|
||||
rct::key D_x;
|
||||
const rct::key H_x = H;
|
||||
rct::key a_x;
|
||||
rct::key aG_x;
|
||||
rct::key aH_x;
|
||||
this->controle_device->clsag_prepare(p_x, z_x, I_x, D_x, H_x, a_x, aG_x, aH_x);
|
||||
#endif
|
||||
|
||||
/*
|
||||
rct::skpkGen(a,aG); // aG = a*G
|
||||
rct::scalarmultKey(aH,H,a); // aH = a*H
|
||||
rct::scalarmultKey(I,H,p); // I = p*H
|
||||
rct::scalarmultKey(D,H,z); // D = z*H
|
||||
*/
|
||||
int offset = set_command_header_noopt(INS_CLSAG, 0x01);
|
||||
//p
|
||||
this->send_secret(p.bytes, offset);
|
||||
//z
|
||||
memmove(this->buffer_send+offset, z.bytes, 32);
|
||||
offset += 32;
|
||||
//H
|
||||
memmove(this->buffer_send+offset, H.bytes, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
offset = 0;
|
||||
//a
|
||||
this->receive_secret(a.bytes, offset);
|
||||
//aG
|
||||
memmove(aG.bytes, this->buffer_recv+offset, 32);
|
||||
offset +=32;
|
||||
//aH
|
||||
memmove(aH.bytes, this->buffer_recv+offset, 32);
|
||||
offset +=32;
|
||||
//I = pH
|
||||
memmove(I.bytes, this->buffer_recv+offset, 32);
|
||||
offset +=32;
|
||||
//D = zH
|
||||
memmove(D.bytes, this->buffer_recv+offset, 32);
|
||||
offset +=32;
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("clsag_prepare", "I", (char*)I_x.bytes, (char*)I.bytes);
|
||||
hw::ledger::check32("clsag_prepare", "D", (char*)D_x.bytes, (char*)D.bytes);
|
||||
hw::ledger::check32("clsag_prepare", "a", (char*)a_x.bytes, (char*)a.bytes);
|
||||
hw::ledger::check32("clsag_prepare", "aG", (char*)aG_x.bytes, (char*)aG.bytes);
|
||||
hw::ledger::check32("clsag_prepare", "aH", (char*)aH_x.bytes, (char*)aH.bytes);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::clsag_hash(const rct::keyV &data, rct::key &hash) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const rct::keyV data_x = data;
|
||||
rct::key hash_x;
|
||||
this->controle_device->mlsag_hash(data_x, hash_x);
|
||||
#endif
|
||||
|
||||
size_t cnt;
|
||||
int offset;
|
||||
|
||||
cnt = data.size();
|
||||
for (size_t i = 0; i<cnt; i++) {
|
||||
offset = set_command_header(INS_CLSAG, 0x02, i+1);
|
||||
//options
|
||||
this->buffer_send[offset] = (i==(cnt-1))?0x00:0x80; //last
|
||||
offset += 1;
|
||||
//msg part
|
||||
memmove(this->buffer_send+offset, data[i].bytes, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
}
|
||||
|
||||
//c/hash
|
||||
memmove(hash.bytes, &this->buffer_recv[0], 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("mlsag_hash", "hash", (char*)hash_x.bytes, (char*)hash.bytes);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool device_ledger::clsag_sign(const rct::key &c, const rct::key &a, const rct::key &p, const rct::key &z, const rct::key &mu_P, const rct::key &mu_C, rct::key &s) {
|
||||
AUTO_LOCK_CMD();
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
const rct::key c_x = c;
|
||||
const rct::key a_x = hw::ledger::decrypt(a);
|
||||
const rct::key p_x = hw::ledger::decrypt(p);
|
||||
const rct::key z_x = z;
|
||||
const rct::key mu_P_x = mu_P;
|
||||
const rct::key mu_C_x = mu_C;
|
||||
rct::key s_x;
|
||||
this->controle_device->clsag_sign(c_x, a_x, p_x, z_x, mu_P_x, mu_C_x, s_x);
|
||||
#endif
|
||||
|
||||
/*
|
||||
rct::key s0_p_mu_P;
|
||||
sc_mul(s0_p_mu_P.bytes,mu_P.bytes,p.bytes);
|
||||
rct::key s0_add_z_mu_C;
|
||||
sc_muladd(s0_add_z_mu_C.bytes,mu_C.bytes,z.bytes,s0_p_mu_P.bytes);
|
||||
sc_mulsub(s.bytes,c.bytes,s0_add_z_mu_C.bytes,a.bytes);
|
||||
*/
|
||||
|
||||
int offset = set_command_header_noopt(INS_CLSAG, 0x03);
|
||||
|
||||
//c
|
||||
//discard, unse internal one
|
||||
//a
|
||||
this->send_secret(a.bytes, offset);
|
||||
//p
|
||||
this->send_secret(p.bytes, offset);
|
||||
//z
|
||||
memmove(this->buffer_send+offset, z.bytes, 32);
|
||||
offset += 32;
|
||||
//mu_P
|
||||
memmove(this->buffer_send+offset, mu_P.bytes, 32);
|
||||
offset += 32;
|
||||
//mu_C
|
||||
memmove(this->buffer_send+offset, mu_C.bytes, 32);
|
||||
offset += 32;
|
||||
|
||||
this->buffer_send[4] = offset-5;
|
||||
this->length_send = offset;
|
||||
this->exchange();
|
||||
|
||||
offset = 0;
|
||||
//s
|
||||
memmove(s.bytes, this->buffer_recv+offset, 32);
|
||||
|
||||
#ifdef DEBUG_HWDEVICE
|
||||
hw::ledger::check32("clsag_sign", "s", (char*)s_x.bytes, (char*)s.bytes);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool device_ledger::close_tx() {
|
||||
AUTO_LOCK_CMD();
|
||||
send_simple(INS_CLOSE_TX);
|
||||
|
||||
@@ -44,8 +44,8 @@ namespace hw {
|
||||
|
||||
/* Minimal supported version */
|
||||
#define MINIMAL_APP_VERSION_MAJOR 1
|
||||
#define MINIMAL_APP_VERSION_MINOR 3
|
||||
#define MINIMAL_APP_VERSION_MICRO 1
|
||||
#define MINIMAL_APP_VERSION_MINOR 6
|
||||
#define MINIMAL_APP_VERSION_MICRO 0
|
||||
|
||||
#define VERSION(M,m,u) ((M)<<16|(m)<<8|(u))
|
||||
#define VERSION_MAJOR(v) (((v)>>16)&0xFF)
|
||||
@@ -297,6 +297,11 @@ namespace hw {
|
||||
bool mlsag_hash(const rct::keyV &long_message, rct::key &c) override;
|
||||
bool mlsag_sign( const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) override;
|
||||
|
||||
bool clsag_prepare(const rct::key &p, const rct::key &z, rct::key &I, rct::key &D, const rct::key &H, rct::key &a, rct::key &aG, rct::key &aH) override;
|
||||
bool clsag_hash(const rct::keyV &data, rct::key &hash) override;
|
||||
bool clsag_sign(const rct::key &c, const rct::key &a, const rct::key &p, const rct::key &z, const rct::key &mu_P, const rct::key &mu_C, rct::key &s) override;
|
||||
|
||||
|
||||
bool close_tx(void) override;
|
||||
|
||||
};
|
||||
|
||||
@@ -678,8 +678,10 @@ namespace trezor {
|
||||
throw exc::TrezorException("Trezor firmware 2.0.10 and lower are not supported. Please update.");
|
||||
}
|
||||
|
||||
// default client version, higher versions check will be added
|
||||
unsigned client_version = 1;
|
||||
if (trezor_version >= pack_version(2, 3, 1)){
|
||||
client_version = 3;
|
||||
}
|
||||
|
||||
#ifdef WITH_TREZOR_DEBUGGING
|
||||
// Override client version for tests
|
||||
|
||||
@@ -561,11 +561,6 @@ namespace tx {
|
||||
assign_to_repeatable(tsx_data.mutable_minor_indices(), tx.subaddr_indices.begin(), tx.subaddr_indices.end());
|
||||
}
|
||||
|
||||
// TODO: use HF_VERSION_CLSAG after CLSAG is merged
|
||||
if (tsx_data.hard_fork() >= 13){
|
||||
throw exc::ProtocolException("CLSAG is not yet implemented");
|
||||
}
|
||||
|
||||
// Rsig decision
|
||||
auto rsig_data = tsx_data.mutable_rsig_data();
|
||||
m_ct.rsig_type = get_rsig_type(tx.rct_config, tx.splitted_dsts.size());
|
||||
@@ -1017,14 +1012,24 @@ namespace tx {
|
||||
}
|
||||
}
|
||||
|
||||
// CLSAG support comes here once it is merged to the Monero
|
||||
m_ct.rv->p.MGs.reserve(m_ct.signatures.size());
|
||||
for(size_t i = 0; i < m_ct.signatures.size(); ++i) {
|
||||
rct::mgSig mg;
|
||||
if (!cn_deserialize(m_ct.signatures[i], mg)) {
|
||||
throw exc::ProtocolException("Cannot deserialize mg[i]");
|
||||
if (m_ct.rv->type == rct::RCTTypeCLSAG){
|
||||
m_ct.rv->p.CLSAGs.reserve(m_ct.signatures.size());
|
||||
for (size_t i = 0; i < m_ct.signatures.size(); ++i) {
|
||||
rct::clsag clsag;
|
||||
if (!cn_deserialize(m_ct.signatures[i], clsag)) {
|
||||
throw exc::ProtocolException("Cannot deserialize clsag[i]");
|
||||
}
|
||||
m_ct.rv->p.CLSAGs.push_back(clsag);
|
||||
}
|
||||
} else {
|
||||
m_ct.rv->p.MGs.reserve(m_ct.signatures.size());
|
||||
for (size_t i = 0; i < m_ct.signatures.size(); ++i) {
|
||||
rct::mgSig mg;
|
||||
if (!cn_deserialize(m_ct.signatures[i], mg)) {
|
||||
throw exc::ProtocolException("Cannot deserialize mg[i]");
|
||||
}
|
||||
m_ct.rv->p.MGs.push_back(mg);
|
||||
}
|
||||
m_ct.rv->p.MGs.push_back(mg);
|
||||
}
|
||||
|
||||
m_ct.tx.rct_signatures = *(m_ct.rv);
|
||||
|
||||
@@ -309,7 +309,7 @@ namespace tx {
|
||||
throw std::invalid_argument("RV not initialized");
|
||||
}
|
||||
auto tp = m_ct.rv->type;
|
||||
return tp == rct::RCTTypeBulletproof || tp == rct::RCTTypeBulletproof2;
|
||||
return tp == rct::RCTTypeBulletproof || tp == rct::RCTTypeBulletproof2 || tp == rct::RCTTypeCLSAG;
|
||||
}
|
||||
|
||||
bool is_offloading() const {
|
||||
|
||||
@@ -41,6 +41,8 @@ const hardfork_t mainnet_hard_forks[] = {
|
||||
{ 13, 114969, 0, 1559292691 },
|
||||
{ 14, 115257, 0, 1559292774 },
|
||||
{ 15, 160777, 0, 1573280497 },
|
||||
{ 16, 253999, 0, 1600576508 },
|
||||
{ 17, 254287, 0, 1600576524 },
|
||||
};
|
||||
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
|
||||
|
||||
@@ -54,7 +56,8 @@ const hardfork_t testnet_hard_forks[] = {
|
||||
{ 13, 30, 0, 1559292691 },
|
||||
{ 14, 35, 0, 1559292774 },
|
||||
{ 15, 40, 0, 1573280497 },
|
||||
{ 16, 45, 0, 1589210508 },
|
||||
{ 16, 45, 0, 1600576508 },
|
||||
{ 17, 50, 0, 1600576524 },
|
||||
};
|
||||
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
||||
|
||||
@@ -74,5 +77,7 @@ const hardfork_t stagenet_hard_forks[] = {
|
||||
{ 10, 269000, 0, 1550153694 },
|
||||
{ 11, 269720, 0, 1550225678 },
|
||||
{ 12, 454721, 0, 1571419280 },
|
||||
{ 13, 675405, 0, 1598180817 },
|
||||
{ 14, 676125, 0, 1598180818 },
|
||||
};
|
||||
const size_t num_stagenet_hard_forks = sizeof(stagenet_hard_forks) / sizeof(stagenet_hard_forks[0]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user