forked from such-gitea/wownero
Compare commits
27 Commits
release-v0
...
wowletify
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2c99252fd | ||
|
|
ab42be18f2 | ||
|
|
44c482913f | ||
|
|
07864cc53f | ||
|
|
2d8b094e09 | ||
|
|
cc0889aa59 | ||
|
|
23d1a8d68e | ||
|
|
35c9cf9c88 | ||
|
|
833ac01ed9 | ||
|
|
dc3981618d | ||
|
|
2eeb3fc1bf | ||
|
|
940811465f | ||
|
|
4a60dfbb3e | ||
|
|
7cdb8244ee | ||
|
|
0f8a3eded6 | ||
|
|
0c3ffa66ce | ||
|
|
01903438a0 | ||
|
|
3692b631b3 | ||
|
|
39379d7022 | ||
|
|
ac12e02fcb | ||
|
|
e85ee60d35 | ||
|
|
6a561e5d83 | ||
|
|
9efbb8896c | ||
|
|
7412b75d42 | ||
|
|
ee0c3ed694 | ||
|
|
053c7bccb5 | ||
|
|
4fdf8c01cb |
34
README.md
34
README.md
@@ -1,6 +1,6 @@
|
||||
# ~~Mo~~Wownero - Such privacy! Many coins! Wow! 🐕
|
||||
|
||||
Copyright (c) 2014-2021 The Monero Project.
|
||||
Copyright (c) 2014-2023 The Monero Project.
|
||||
Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
|
||||
## Resources
|
||||
@@ -16,16 +16,21 @@ Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
|
||||
- Telegram: [t.me/wownero](https://t.me/wownero)
|
||||
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
|
||||
- WOW Stash Web Wallet: [wowstash.app](https://wowstash.app)
|
||||
- Stack Wallet iOS & Android Mobile Wallet: [stackwallet.com](https://stackwallet.com)
|
||||
- Wonerujo Android Mobile Wallet: [google store](https://play.google.com/store/apps/details?id=com.m2049r.wowwallet)
|
||||
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
|
||||
- Map of Nodes: [wownero.fyi](https://wownero.fyi)
|
||||
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
|
||||
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
|
||||
|
||||
## Exchanges
|
||||
|
||||
- [AltQuick](https://altquick.com/market/Wownero)
|
||||
- [Majestic Bank](https://majesticbank.sc)
|
||||
- [TradeOgre](https://tradeogre.com/exchange/BTC-WOW)
|
||||
|
||||
### Blockchain Explorers
|
||||
|
||||
- https://explore.wownero.com
|
||||
- http://gffjxd5nn2heslj6jv5ts2ok5j6xi6m3pwlpz7le4i5bu56sirbxfiqd.onion:8081
|
||||
- https://wownero.club
|
||||
|
||||
## Introduction
|
||||
|
||||
@@ -36,11 +41,11 @@ Wownero is a privacy-centric memecoin that was fairly launched on April 1, 2018
|
||||
Wownero is a 100% community-sponsored endeavor. Supporting services are also graciously provided by sponsors:
|
||||
|
||||
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/macstadium.png"
|
||||
alt="MacStadium"
|
||||
height="100">](https://www.macstadium.com)
|
||||
alt="MacStadium"
|
||||
height="100">](https://www.macstadium.com)
|
||||
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/jetbrains.png"
|
||||
alt="JetBrains"
|
||||
height="100">](https://www.jetbrains.com)
|
||||
alt="JetBrains"
|
||||
height="100">](https://www.jetbrains.com)
|
||||
|
||||
Developers are volunteers doing this mostly for shits and giggles. If you would like to support our shenanigans and stimulant addictions, please consider donating to [WFS proposals](https://funding.wownero.com/proposals) or the dev slush fund.
|
||||
|
||||
@@ -72,13 +77,13 @@ Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](
|
||||
|
||||
Join `#wownero` on IRC OFTC to participate in development conversation.
|
||||
|
||||
## Scheduled software upgrades
|
||||
## Scheduled software/network upgrades
|
||||
|
||||
Wownero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Wownero (end users and service providers) should run current versions and upgrade their software on a regular schedule. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Wownero software version. Below is the historical schedule and the projected schedule for the next upgrade.
|
||||
Dates are provided in the format YYYY-MM-DD.
|
||||
|
||||
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
|
||||
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
|
||||
|-------------------------------|------------| ----------------- |-------------------------|-----------------------------| ---------------------------------------------------------------------------------- |
|
||||
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
||||
| 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
||||
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
|
||||
@@ -88,7 +93,8 @@ Dates are provided in the format YYYY-MM-DD.
|
||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.1.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.2.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
||||
| XXX,XXX | 2023-XX-XX | Kunty Karen | v0.11.0.0 | v0.11.0.0 | View tags, fee changes, adjusted dynamic block weight algorithm, multisig security fixes, RPC broadcast node donation sub-address
|
||||
|
||||
X's indicate that these details have not been determined as of commit date.
|
||||
|
||||
@@ -181,7 +187,7 @@ Type `help` in CLI wallet to see standard commands (for advanced options, type `
|
||||
add the following:
|
||||
```
|
||||
HiddenServiceDir /var/lib/tor/wownero/
|
||||
HiddenServicePort 34568 127.0.0.1:34568
|
||||
HiddenServicePort 34569 127.0.0.1:34569
|
||||
HiddenServicePort 34566 127.0.0.1:34566
|
||||
HiddenServiceVersion 3
|
||||
```
|
||||
@@ -196,7 +202,7 @@ save and close nano
|
||||
```
|
||||
|
||||
* `sudo cat /var/lib/tor/wownero/hostname`
|
||||
copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero) and [here](https://forum.wownero.com/t/wownero-tor-onion-sites/623)
|
||||
copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero) and [here](https://forum.wownero.com/t/wownero-tor-onion-sites/623)
|
||||
|
||||
To share your node over p2p, uncomment first line of wownerod.conf and add your onion address.
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <limits>
|
||||
#include <string.h>
|
||||
#include "net/buffer.h"
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <limits>
|
||||
#include <string.h>
|
||||
#include "memwipe.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
Binary file not shown.
@@ -224,6 +224,7 @@ namespace cryptonote
|
||||
ADD_CHECKPOINT2(332100, "d32c409058c1eceb9a105190c7a5f480b2d6f49f318b18652b49ae971c710124", "0x7c538441cca36");
|
||||
ADD_CHECKPOINT2(334000, "17d3b15f8e1a73e1c61335ee7979e9e3d211b9055e8a7fb2481e5f49a51b1c22", "0x7ddd5a79d69c4");
|
||||
ADD_CHECKPOINT2(348500, "2d43a157f369e2aa26a329b56456142ecd1361f5808c688d97112a2e3bbd23f4", "0x90889ed877ada");
|
||||
ADD_CHECKPOINT2(489400, "b14f49eae77398117ea93435676100d8b655a804689f73a5a4d0d5e71160d603", "0x1123c39bb52f7e");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace dns_utils
|
||||
std::string address_from_txt_record(const std::string& s)
|
||||
{
|
||||
// make sure the txt record has "oa1:xmr" and find it
|
||||
auto pos = s.find("oa1:xmr");
|
||||
auto pos = s.find("oa1:wow");
|
||||
if (pos == std::string::npos)
|
||||
return {};
|
||||
// search from there to find "recipient_address="
|
||||
@@ -412,14 +412,14 @@ std::string address_from_txt_record(const std::string& s)
|
||||
auto pos2 = s.find(";", pos);
|
||||
if (pos2 != std::string::npos)
|
||||
{
|
||||
// length of address == 95, we can at least validate that much here
|
||||
if (pos2 - pos == 95)
|
||||
// length of address == 97, we can at least validate that much here
|
||||
if (pos2 - pos == 97)
|
||||
{
|
||||
return s.substr(pos, 95);
|
||||
return s.substr(pos, 97);
|
||||
}
|
||||
else if (pos2 - pos == 106) // length of address == 106 --> integrated address
|
||||
else if (pos2 - pos == 108) // length of address == 108 --> integrated address
|
||||
{
|
||||
return s.substr(pos, 106);
|
||||
return s.substr(pos, 108);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -40,6 +40,9 @@
|
||||
#include "oaes_lib.h"
|
||||
#include "variant2_int_sqrt.h"
|
||||
#include "variant4_random_math.h"
|
||||
#include "CryptonightR_JIT.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define MEMORY (1 << 21) // 2MB scratchpad
|
||||
#define ITER (1 << 20)
|
||||
@@ -48,9 +51,72 @@
|
||||
#define INIT_SIZE_BLK 8
|
||||
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define THREADV __declspec(thread)
|
||||
#else
|
||||
#define THREADV __thread
|
||||
#endif
|
||||
|
||||
extern void aesb_single_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
||||
extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
||||
|
||||
static void local_abort(const char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
#ifdef NDEBUG
|
||||
_exit(1);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
volatile int use_v4_jit_flag = -1;
|
||||
|
||||
static inline int use_v4_jit(void)
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
|
||||
if (use_v4_jit_flag != -1)
|
||||
return use_v4_jit_flag;
|
||||
|
||||
const char *env = getenv("MONERO_USE_CNV4_JIT");
|
||||
if (!env) {
|
||||
use_v4_jit_flag = 1;
|
||||
}
|
||||
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||
use_v4_jit_flag = 0;
|
||||
}
|
||||
else {
|
||||
use_v4_jit_flag = 1;
|
||||
}
|
||||
return use_v4_jit_flag;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
static inline int force_software_aes(void)
|
||||
{
|
||||
static int use = -1;
|
||||
|
||||
if (use != -1)
|
||||
return use;
|
||||
|
||||
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
|
||||
if (!env) {
|
||||
use = 0;
|
||||
}
|
||||
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||
use = 0;
|
||||
}
|
||||
else {
|
||||
use = 1;
|
||||
}
|
||||
return use;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define VARIANT1_1(p) \
|
||||
do if (variant == 1) \
|
||||
{ \
|
||||
@@ -117,48 +183,74 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||
#define VARIANT2_SHUFFLE_ADD_SSE2(base_ptr, offset) \
|
||||
do if (variant >= 2) \
|
||||
{ \
|
||||
const __m128i chunk1 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10))); \
|
||||
__m128i chunk1 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10))); \
|
||||
const __m128i chunk2 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20))); \
|
||||
const __m128i chunk3 = _mm_load_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30))); \
|
||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10)), _mm_add_epi64(chunk3, _b1)); \
|
||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \
|
||||
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \
|
||||
if (variant >= 4) \
|
||||
{ \
|
||||
chunk1 = _mm_xor_si128(chunk1, chunk2); \
|
||||
_c = _mm_xor_si128(_c, chunk3); \
|
||||
_c = _mm_xor_si128(_c, chunk1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VARIANT2_SHUFFLE_ADD_NEON(base_ptr, offset) \
|
||||
do if (variant >= 2) \
|
||||
{ \
|
||||
const uint64x2_t chunk1 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x10))); \
|
||||
uint64x2_t chunk1 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x10))); \
|
||||
const uint64x2_t chunk2 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x20))); \
|
||||
const uint64x2_t chunk3 = vld1q_u64(U64((base_ptr) + ((offset) ^ 0x30))); \
|
||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x10)), vaddq_u64(chunk3, vreinterpretq_u64_u8(_b1))); \
|
||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \
|
||||
vst1q_u64(U64((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \
|
||||
if (variant >= 4) \
|
||||
{ \
|
||||
chunk1 = veorq_u64(chunk1, chunk2); \
|
||||
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk3)); \
|
||||
_c = vreinterpretq_u8_u64(veorq_u64(vreinterpretq_u64_u8(_c), chunk1)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VARIANT2_PORTABLE_SHUFFLE_ADD(base_ptr, offset) \
|
||||
#define VARIANT2_PORTABLE_SHUFFLE_ADD(out, a_, base_ptr, offset) \
|
||||
do if (variant >= 2) \
|
||||
{ \
|
||||
uint64_t* chunk1 = U64((base_ptr) + ((offset) ^ 0x10)); \
|
||||
uint64_t* chunk2 = U64((base_ptr) + ((offset) ^ 0x20)); \
|
||||
uint64_t* chunk3 = U64((base_ptr) + ((offset) ^ 0x30)); \
|
||||
\
|
||||
const uint64_t chunk1_old[2] = { chunk1[0], chunk1[1] }; \
|
||||
uint64_t chunk1_old[2] = { SWAP64LE(chunk1[0]), SWAP64LE(chunk1[1]) }; \
|
||||
const uint64_t chunk2_old[2] = { SWAP64LE(chunk2[0]), SWAP64LE(chunk2[1]) }; \
|
||||
const uint64_t chunk3_old[2] = { SWAP64LE(chunk3[0]), SWAP64LE(chunk3[1]) }; \
|
||||
\
|
||||
uint64_t b1[2]; \
|
||||
memcpy_swap64le(b1, b + 16, 2); \
|
||||
chunk1[0] = SWAP64LE(SWAP64LE(chunk3[0]) + b1[0]); \
|
||||
chunk1[1] = SWAP64LE(SWAP64LE(chunk3[1]) + b1[1]); \
|
||||
chunk1[0] = SWAP64LE(chunk3_old[0] + b1[0]); \
|
||||
chunk1[1] = SWAP64LE(chunk3_old[1] + b1[1]); \
|
||||
\
|
||||
uint64_t a0[2]; \
|
||||
memcpy_swap64le(a0, a, 2); \
|
||||
chunk3[0] = SWAP64LE(SWAP64LE(chunk2[0]) + a0[0]); \
|
||||
chunk3[1] = SWAP64LE(SWAP64LE(chunk2[1]) + a0[1]); \
|
||||
memcpy_swap64le(a0, a_, 2); \
|
||||
chunk3[0] = SWAP64LE(chunk2_old[0] + a0[0]); \
|
||||
chunk3[1] = SWAP64LE(chunk2_old[1] + a0[1]); \
|
||||
\
|
||||
uint64_t b0[2]; \
|
||||
memcpy_swap64le(b0, b, 2); \
|
||||
chunk2[0] = SWAP64LE(SWAP64LE(chunk1_old[0]) + b0[0]); \
|
||||
chunk2[1] = SWAP64LE(SWAP64LE(chunk1_old[1]) + b0[1]); \
|
||||
chunk2[0] = SWAP64LE(chunk1_old[0] + b0[0]); \
|
||||
chunk2[1] = SWAP64LE(chunk1_old[1] + b0[1]); \
|
||||
if (variant >= 4) \
|
||||
{ \
|
||||
uint64_t out_copy[2]; \
|
||||
memcpy_swap64le(out_copy, out, 2); \
|
||||
chunk1_old[0] ^= chunk2_old[0]; \
|
||||
chunk1_old[1] ^= chunk2_old[1]; \
|
||||
out_copy[0] ^= chunk3_old[0]; \
|
||||
out_copy[1] ^= chunk3_old[1]; \
|
||||
out_copy[0] ^= chunk1_old[0]; \
|
||||
out_copy[1] ^= chunk1_old[1]; \
|
||||
memcpy_swap64le(out, out_copy, 2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VARIANT2_INTEGER_MATH_DIVISION_STEP(b, ptr) \
|
||||
@@ -201,18 +293,18 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||
#endif
|
||||
|
||||
#define VARIANT2_2_PORTABLE() \
|
||||
if (variant >= 2) { \
|
||||
if (variant == 2 || variant == 3) { \
|
||||
xor_blocks(long_state + (j ^ 0x10), d); \
|
||||
xor_blocks(d, long_state + (j ^ 0x20)); \
|
||||
}
|
||||
|
||||
#define VARIANT2_2() \
|
||||
do if (variant >= 2) \
|
||||
do if (variant == 2 || variant == 3) \
|
||||
{ \
|
||||
*U64(hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \
|
||||
*(U64(hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \
|
||||
hi ^= SWAP64LE(*U64(hp_state + (j ^ 0x20))); \
|
||||
lo ^= SWAP64LE(*(U64(hp_state + (j ^ 0x20)) + 1)); \
|
||||
*U64(local_hp_state + (j ^ 0x10)) ^= SWAP64LE(hi); \
|
||||
*(U64(local_hp_state + (j ^ 0x10)) + 1) ^= SWAP64LE(lo); \
|
||||
hi ^= SWAP64LE(*U64(local_hp_state + (j ^ 0x20))); \
|
||||
lo ^= SWAP64LE(*(U64(local_hp_state + (j ^ 0x20)) + 1)); \
|
||||
} while (0)
|
||||
|
||||
#define V4_REG_LOAD(dst, src) \
|
||||
@@ -225,34 +317,56 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||
} while (0)
|
||||
|
||||
#define VARIANT4_RANDOM_MATH_INIT() \
|
||||
v4_reg r[8]; \
|
||||
struct V4_Instruction code[TOTAL_LATENCY * ALU_COUNT + 1]; \
|
||||
v4_reg r[9]; \
|
||||
struct V4_Instruction code[NUM_INSTRUCTIONS_MAX + 1]; \
|
||||
int jit = use_v4_jit(); \
|
||||
do if (variant >= 4) \
|
||||
{ \
|
||||
for (int i = 0; i < 4; ++i) \
|
||||
V4_REG_LOAD(r + i, (uint8_t*)(state.hs.w + 12) + sizeof(v4_reg) * i); \
|
||||
v4_random_math_init(code, height); \
|
||||
if (jit) \
|
||||
{ \
|
||||
int ret = v4_generate_JIT_code(code, hp_jitfunc, 4096); \
|
||||
if (ret < 0) \
|
||||
local_abort("Error generating CryptonightR code"); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VARIANT4_RANDOM_MATH(a, b, r, _b, _b1) \
|
||||
do if (variant >= 4) \
|
||||
{ \
|
||||
uint64_t t; \
|
||||
memcpy(&t, b, sizeof(uint64_t)); \
|
||||
uint64_t t[2]; \
|
||||
memcpy(t, b, sizeof(uint64_t)); \
|
||||
\
|
||||
if (sizeof(v4_reg) == sizeof(uint32_t)) \
|
||||
t ^= SWAP64LE((r[0] + r[1]) | ((uint64_t)(r[2] + r[3]) << 32)); \
|
||||
t[0] ^= SWAP64LE((r[0] + r[1]) | ((uint64_t)(r[2] + r[3]) << 32)); \
|
||||
else \
|
||||
t ^= SWAP64LE((r[0] + r[1]) ^ (r[2] + r[3])); \
|
||||
t[0] ^= SWAP64LE((r[0] + r[1]) ^ (r[2] + r[3])); \
|
||||
\
|
||||
memcpy(b, &t, sizeof(uint64_t)); \
|
||||
memcpy(b, t, sizeof(uint64_t)); \
|
||||
\
|
||||
V4_REG_LOAD(r + 4, a); \
|
||||
V4_REG_LOAD(r + 5, (uint64_t*)(a) + 1); \
|
||||
V4_REG_LOAD(r + 6, _b); \
|
||||
V4_REG_LOAD(r + 7, _b1); \
|
||||
V4_REG_LOAD(r + 8, (uint64_t*)(_b1) + 1); \
|
||||
\
|
||||
if (jit) \
|
||||
(*hp_jitfunc)(r); \
|
||||
else \
|
||||
v4_random_math(code, r); \
|
||||
\
|
||||
memcpy(t, a, sizeof(uint64_t) * 2); \
|
||||
\
|
||||
if (sizeof(v4_reg) == sizeof(uint32_t)) { \
|
||||
t[0] ^= SWAP64LE(r[2] | ((uint64_t)(r[3]) << 32)); \
|
||||
t[1] ^= SWAP64LE(r[0] | ((uint64_t)(r[1]) << 32)); \
|
||||
} else { \
|
||||
t[0] ^= SWAP64LE(r[2] ^ r[3]); \
|
||||
t[1] ^= SWAP64LE(r[0] ^ r[1]); \
|
||||
} \
|
||||
memcpy(a, t, sizeof(uint64_t) * 2); \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -318,7 +432,7 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||
|
||||
#define pre_aes() \
|
||||
j = state_index(a); \
|
||||
_c = _mm_load_si128(R128(&hp_state[j])); \
|
||||
_c = _mm_load_si128(R128(&local_hp_state[j])); \
|
||||
_a = _mm_load_si128(R128(a)); \
|
||||
|
||||
/*
|
||||
@@ -331,32 +445,26 @@ extern void aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *ex
|
||||
* This code is based upon an optimized implementation by dga.
|
||||
*/
|
||||
#define post_aes() \
|
||||
VARIANT2_SHUFFLE_ADD_SSE2(hp_state, j); \
|
||||
VARIANT2_SHUFFLE_ADD_SSE2(local_hp_state, j); \
|
||||
_mm_store_si128(R128(c), _c); \
|
||||
_mm_store_si128(R128(&hp_state[j]), _mm_xor_si128(_b, _c)); \
|
||||
VARIANT1_1(&hp_state[j]); \
|
||||
_mm_store_si128(R128(&local_hp_state[j]), _mm_xor_si128(_b, _c)); \
|
||||
VARIANT1_1(&local_hp_state[j]); \
|
||||
j = state_index(c); \
|
||||
p = U64(&hp_state[j]); \
|
||||
p = U64(&local_hp_state[j]); \
|
||||
b[0] = p[0]; b[1] = p[1]; \
|
||||
VARIANT2_INTEGER_MATH_SSE2(b, c); \
|
||||
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
||||
__mul(); \
|
||||
VARIANT2_2(); \
|
||||
VARIANT2_SHUFFLE_ADD_SSE2(hp_state, j); \
|
||||
VARIANT2_SHUFFLE_ADD_SSE2(local_hp_state, j); \
|
||||
a[0] += hi; a[1] += lo; \
|
||||
p = U64(&hp_state[j]); \
|
||||
p = U64(&local_hp_state[j]); \
|
||||
p[0] = a[0]; p[1] = a[1]; \
|
||||
a[0] ^= b[0]; a[1] ^= b[1]; \
|
||||
VARIANT1_2(p + 1); \
|
||||
_b1 = _b; \
|
||||
_b = _c; \
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define THREADV __declspec(thread)
|
||||
#else
|
||||
#define THREADV __thread
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union cn_slow_hash_state
|
||||
{
|
||||
@@ -371,6 +479,9 @@ union cn_slow_hash_state
|
||||
|
||||
THREADV uint8_t *hp_state = NULL;
|
||||
THREADV int hp_allocated = 0;
|
||||
THREADV v4_random_math_JIT_func hp_jitfunc = NULL;
|
||||
THREADV uint8_t *hp_jitfunc_memory = NULL;
|
||||
THREADV int hp_jitfunc_allocated = 0;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define cpuid(info,x) __cpuidex(info,x,0)
|
||||
@@ -409,25 +520,6 @@ STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
|
||||
* @return true if the CPU supports AES, false otherwise
|
||||
*/
|
||||
|
||||
STATIC INLINE int force_software_aes(void)
|
||||
{
|
||||
static int use = -1;
|
||||
|
||||
if (use != -1)
|
||||
return use;
|
||||
|
||||
const char *env = getenv("MONERO_USE_SOFTWARE_AES");
|
||||
if (!env) {
|
||||
use = 0;
|
||||
}
|
||||
else if (!strcmp(env, "0") || !strcmp(env, "no")) {
|
||||
use = 0;
|
||||
}
|
||||
else {
|
||||
use = 1;
|
||||
}
|
||||
return use;
|
||||
}
|
||||
|
||||
STATIC INLINE int check_aes_hw(void)
|
||||
{
|
||||
@@ -666,10 +758,10 @@ void cn_slow_hash_allocate_state(void)
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__) || defined(__NetBSD__)
|
||||
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, 0, 0);
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0);
|
||||
#endif
|
||||
if(hp_state == MAP_FAILED)
|
||||
hp_state = NULL;
|
||||
@@ -680,6 +772,35 @@ void cn_slow_hash_allocate_state(void)
|
||||
hp_allocated = 0;
|
||||
hp_state = (uint8_t *) malloc(MEMORY);
|
||||
}
|
||||
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
hp_jitfunc_memory = (uint8_t *) VirtualAlloc(hp_jitfunc_memory, 4096 + 4095,
|
||||
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__) || defined(__NetBSD__)
|
||||
#ifdef __NetBSD__
|
||||
#define RESERVED_FLAGS PROT_MPROTECT(PROT_EXEC)
|
||||
#else
|
||||
#define RESERVED_FLAGS 0
|
||||
#endif
|
||||
hp_jitfunc_memory = mmap(0, 4096 + 4096, PROT_READ | PROT_WRITE | RESERVED_FLAGS,
|
||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
#else
|
||||
hp_jitfunc_memory = mmap(0, 4096 + 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#endif
|
||||
if(hp_jitfunc_memory == MAP_FAILED)
|
||||
hp_jitfunc_memory = NULL;
|
||||
#endif
|
||||
hp_jitfunc_allocated = 1;
|
||||
if (hp_jitfunc_memory == NULL)
|
||||
{
|
||||
hp_jitfunc_allocated = 0;
|
||||
hp_jitfunc_memory = malloc(4096 + 4095);
|
||||
}
|
||||
hp_jitfunc = (v4_random_math_JIT_func)((size_t)(hp_jitfunc_memory + 4095) & ~4095);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -702,8 +823,22 @@ void cn_slow_hash_free_state(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!hp_jitfunc_allocated)
|
||||
free(hp_jitfunc_memory);
|
||||
else
|
||||
{
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
VirtualFree(hp_jitfunc_memory, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(hp_jitfunc_memory, 4096 + 4095);
|
||||
#endif
|
||||
}
|
||||
|
||||
hp_state = NULL;
|
||||
hp_allocated = 0;
|
||||
hp_jitfunc = NULL;
|
||||
hp_jitfunc_memory = NULL;
|
||||
hp_jitfunc_allocated = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -787,7 +922,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -799,7 +934,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||
|
||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,7 +982,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
// add the xor to the pseudo round
|
||||
aes_pseudo_round_xor(text, text, expandedKey, &hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||
aes_pseudo_round_xor(text, text, expandedKey, &local_hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -857,7 +992,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
{
|
||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||
{
|
||||
xor_blocks(&text[j * AES_BLOCK_SIZE], &hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||
xor_blocks(&text[j * AES_BLOCK_SIZE], &local_hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||
}
|
||||
}
|
||||
@@ -877,6 +1012,44 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
}
|
||||
|
||||
#elif !defined NO_AES && (defined(__arm__) || defined(__aarch64__))
|
||||
#ifdef __aarch64__
|
||||
#include <sys/mman.h>
|
||||
THREADV uint8_t *hp_state = NULL;
|
||||
THREADV int hp_malloced = 0;
|
||||
|
||||
void cn_slow_hash_allocate_state(void)
|
||||
{
|
||||
if(hp_state != NULL)
|
||||
return;
|
||||
|
||||
#ifndef MAP_HUGETLB
|
||||
#define MAP_HUGETLB 0
|
||||
#endif
|
||||
hp_state = mmap(0, MEMORY, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON | MAP_HUGETLB, -1, 0);
|
||||
|
||||
if(hp_state == MAP_FAILED)
|
||||
hp_state = NULL;
|
||||
if(hp_state == NULL)
|
||||
{
|
||||
hp_malloced = 1;
|
||||
hp_state = (uint8_t *) malloc(MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
void cn_slow_hash_free_state(void)
|
||||
{
|
||||
if(hp_state == NULL)
|
||||
return;
|
||||
|
||||
if (hp_malloced)
|
||||
free(hp_state);
|
||||
else
|
||||
munmap(hp_state, MEMORY);
|
||||
hp_state = NULL;
|
||||
hp_malloced = 0;
|
||||
}
|
||||
#else
|
||||
void cn_slow_hash_allocate_state(void)
|
||||
{
|
||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||
@@ -888,6 +1061,7 @@ void cn_slow_hash_free_state(void)
|
||||
// As above
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define RDATA_ALIGN16 __attribute__ ((aligned(16)))
|
||||
@@ -901,6 +1075,8 @@ void cn_slow_hash_free_state(void)
|
||||
|
||||
#define U64(x) ((uint64_t *) (x))
|
||||
|
||||
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
||||
|
||||
STATIC INLINE void xor64(uint64_t *a, const uint64_t b)
|
||||
{
|
||||
*a ^= b;
|
||||
@@ -926,6 +1102,23 @@ union cn_slow_hash_state
|
||||
* and moving between vector and regular registers stalls the pipeline.
|
||||
*/
|
||||
#include <arm_neon.h>
|
||||
#ifndef __APPLE__
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#endif
|
||||
|
||||
STATIC INLINE int check_aes_hw(void)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return 1;
|
||||
#else
|
||||
static int supported = -1;
|
||||
|
||||
if(supported < 0)
|
||||
supported = (getauxval(AT_HWCAP) & HWCAP_AES) != 0;
|
||||
return supported;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE)
|
||||
|
||||
@@ -935,24 +1128,24 @@ union cn_slow_hash_state
|
||||
|
||||
#define pre_aes() \
|
||||
j = state_index(a); \
|
||||
_c = vld1q_u8(&hp_state[j]); \
|
||||
_c = vld1q_u8(&local_hp_state[j]); \
|
||||
_a = vld1q_u8((const uint8_t *)a); \
|
||||
|
||||
#define post_aes() \
|
||||
VARIANT2_SHUFFLE_ADD_NEON(hp_state, j); \
|
||||
VARIANT2_SHUFFLE_ADD_NEON(local_hp_state, j); \
|
||||
vst1q_u8((uint8_t *)c, _c); \
|
||||
vst1q_u8(&hp_state[j], veorq_u8(_b, _c)); \
|
||||
VARIANT1_1(&hp_state[j]); \
|
||||
vst1q_u8(&local_hp_state[j], veorq_u8(_b, _c)); \
|
||||
VARIANT1_1(&local_hp_state[j]); \
|
||||
j = state_index(c); \
|
||||
p = U64(&hp_state[j]); \
|
||||
p = U64(&local_hp_state[j]); \
|
||||
b[0] = p[0]; b[1] = p[1]; \
|
||||
VARIANT2_PORTABLE_INTEGER_MATH(b, c); \
|
||||
VARIANT4_RANDOM_MATH(a, b, r, &_b, &_b1); \
|
||||
__mul(); \
|
||||
VARIANT2_2(); \
|
||||
VARIANT2_SHUFFLE_ADD_NEON(hp_state, j); \
|
||||
VARIANT2_SHUFFLE_ADD_NEON(local_hp_state, j); \
|
||||
a[0] += hi; a[1] += lo; \
|
||||
p = U64(&hp_state[j]); \
|
||||
p = U64(&local_hp_state[j]); \
|
||||
p[0] = a[0]; p[1] = a[1]; \
|
||||
a[0] ^= b[0]; a[1] ^= b[1]; \
|
||||
VARIANT1_2(p + 1); \
|
||||
@@ -1022,7 +1215,6 @@ __asm__(
|
||||
STATIC INLINE void aes_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey, int nblocks)
|
||||
{
|
||||
const uint8x16_t *k = (const uint8x16_t *)expandedKey, zero = {0};
|
||||
uint8x16_t tmp;
|
||||
int i;
|
||||
|
||||
for (i=0; i<nblocks; i++)
|
||||
@@ -1057,7 +1249,6 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
|
||||
{
|
||||
const uint8x16_t *k = (const uint8x16_t *)expandedKey;
|
||||
const uint8x16_t *x = (const uint8x16_t *)xor;
|
||||
uint8x16_t tmp;
|
||||
int i;
|
||||
|
||||
for (i=0; i<nblocks; i++)
|
||||
@@ -1110,16 +1301,17 @@ STATIC INLINE void aligned_free(void *ptr)
|
||||
}
|
||||
#endif /* FORCE_USE_HEAP */
|
||||
|
||||
STATIC INLINE void xor_blocks(uint8_t* a, const uint8_t* b)
|
||||
{
|
||||
U64(a)[0] ^= U64(b)[0];
|
||||
U64(a)[1] ^= U64(b)[1];
|
||||
}
|
||||
|
||||
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed, uint64_t height)
|
||||
{
|
||||
RDATA_ALIGN16 uint8_t expandedKey[240];
|
||||
|
||||
#ifndef FORCE_USE_HEAP
|
||||
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
|
||||
#else
|
||||
uint8_t *hp_state = (uint8_t *)aligned_malloc(MEMORY,16);
|
||||
#endif
|
||||
|
||||
uint8_t *local_hp_state;
|
||||
uint8_t text[INIT_SIZE_BYTE];
|
||||
RDATA_ALIGN16 uint64_t a[2];
|
||||
RDATA_ALIGN16 uint64_t b[4];
|
||||
@@ -1130,12 +1322,22 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
|
||||
size_t i, j;
|
||||
uint64_t *p = NULL;
|
||||
oaes_ctx *aes_ctx = NULL;
|
||||
int useAes = !force_software_aes() && check_aes_hw();
|
||||
|
||||
static void (*const extra_hashes[4])(const void *, size_t, char *) =
|
||||
{
|
||||
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
|
||||
};
|
||||
|
||||
// this isn't supposed to happen, but guard against it for now.
|
||||
if(hp_state == NULL)
|
||||
cn_slow_hash_allocate_state();
|
||||
|
||||
// locals to avoid constant TLS dereferencing
|
||||
local_hp_state = hp_state;
|
||||
|
||||
// locals to avoid constant TLS dereferencing
|
||||
/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */
|
||||
|
||||
if (prehashed) {
|
||||
@@ -1153,11 +1355,26 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
* the 2MB large random access buffer.
|
||||
*/
|
||||
|
||||
if(useAes)
|
||||
{
|
||||
aes_expand_key(state.hs.b, expandedKey);
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
aes_pseudo_round(text, text, expandedKey, INIT_SIZE_BLK);
|
||||
memcpy(&hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aes_ctx = (oaes_ctx *) oaes_alloc();
|
||||
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||
|
||||
memcpy(&local_hp_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
|
||||
@@ -1173,6 +1390,8 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
_b = vld1q_u8((const uint8_t *)b);
|
||||
_b1 = vld1q_u8(((const uint8_t *)b) + AES_BLOCK_SIZE);
|
||||
|
||||
if(useAes)
|
||||
{
|
||||
for(i = 0; i < ITER / 2; i++)
|
||||
{
|
||||
pre_aes();
|
||||
@@ -1181,6 +1400,17 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
_c = veorq_u8(_c, _a);
|
||||
post_aes();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0; i < ITER / 2; i++)
|
||||
{
|
||||
pre_aes();
|
||||
aesb_single_round((uint8_t *) &_c, (uint8_t *) &_c, (uint8_t *) &_a);
|
||||
post_aes();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* CryptoNight Step 4: Sequentially pass through the mixing buffer and use 10 rounds
|
||||
* of AES encryption to mix the random data back into the 'text' buffer. 'text'
|
||||
@@ -1188,11 +1418,27 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
|
||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||
|
||||
if(useAes)
|
||||
{
|
||||
aes_expand_key(&state.hs.b[32], expandedKey);
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
// add the xor to the pseudo round
|
||||
aes_pseudo_round_xor(text, text, expandedKey, &hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||
aes_pseudo_round_xor(text, text, expandedKey, &local_hp_state[i * INIT_SIZE_BYTE], INIT_SIZE_BLK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
|
||||
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||
{
|
||||
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||
{
|
||||
xor_blocks(&text[j * AES_BLOCK_SIZE], &local_hp_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], aes_ctx->key->exp_data);
|
||||
}
|
||||
}
|
||||
oaes_free((OAES_CTX **) &aes_ctx);
|
||||
}
|
||||
|
||||
/* CryptoNight Step 5: Apply Keccak to the state again, and then
|
||||
@@ -1205,10 +1451,6 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
memcpy(state.init, text, INIT_SIZE_BYTE);
|
||||
hash_permutation(&state.hs);
|
||||
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
||||
|
||||
#ifdef FORCE_USE_HEAP
|
||||
aligned_free(hp_state);
|
||||
#endif
|
||||
}
|
||||
#else /* aarch64 && crypto */
|
||||
|
||||
@@ -1330,6 +1572,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
{
|
||||
uint8_t text[INIT_SIZE_BYTE];
|
||||
uint8_t a[AES_BLOCK_SIZE];
|
||||
uint8_t a1[AES_BLOCK_SIZE];
|
||||
uint8_t b[AES_BLOCK_SIZE * 2];
|
||||
uint8_t c[AES_BLOCK_SIZE];
|
||||
uint8_t c1[AES_BLOCK_SIZE];
|
||||
@@ -1389,10 +1632,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
// Iteration 1
|
||||
j = state_index(a);
|
||||
p = &long_state[j];
|
||||
aesb_single_round(p, p, a);
|
||||
copy_block(c1, p);
|
||||
aesb_single_round(p, c1, a);
|
||||
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||
copy_block(p, c1);
|
||||
xor_blocks(p, b);
|
||||
VARIANT1_1(p);
|
||||
|
||||
@@ -1401,14 +1644,15 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
p = &long_state[j];
|
||||
copy_block(c, p);
|
||||
|
||||
copy_block(a1, a);
|
||||
VARIANT2_PORTABLE_INTEGER_MATH(c, c1);
|
||||
VARIANT4_RANDOM_MATH(a, c, r, b, b + AES_BLOCK_SIZE);
|
||||
VARIANT4_RANDOM_MATH(a1, c, r, b, b + AES_BLOCK_SIZE);
|
||||
mul(c1, c, d);
|
||||
VARIANT2_2_PORTABLE();
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
||||
sum_half_blocks(a, d);
|
||||
swap_blocks(a, c);
|
||||
xor_blocks(a, c);
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||
sum_half_blocks(a1, d);
|
||||
swap_blocks(a1, c);
|
||||
xor_blocks(a1, c);
|
||||
VARIANT1_2(U64(c) + 1);
|
||||
copy_block(p, c);
|
||||
|
||||
@@ -1416,6 +1660,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
copy_block(b + AES_BLOCK_SIZE, b);
|
||||
}
|
||||
copy_block(b, c1);
|
||||
copy_block(a, a1);
|
||||
}
|
||||
|
||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||
@@ -1443,7 +1688,9 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
#else
|
||||
// Portable implementation as a fallback
|
||||
|
||||
void slow_hash_allocate_state(void)
|
||||
#define hp_jitfunc ((v4_random_math_JIT_func)NULL)
|
||||
|
||||
void cn_slow_hash_allocate_state(void)
|
||||
{
|
||||
// Do nothing, this is just to maintain compatibility with the upgraded slow-hash.c
|
||||
return;
|
||||
@@ -1536,6 +1783,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
union cn_slow_hash_state state;
|
||||
uint8_t text[INIT_SIZE_BYTE];
|
||||
uint8_t a[AES_BLOCK_SIZE];
|
||||
uint8_t a1[AES_BLOCK_SIZE];
|
||||
uint8_t b[AES_BLOCK_SIZE * 2];
|
||||
uint8_t c1[AES_BLOCK_SIZE];
|
||||
uint8_t c2[AES_BLOCK_SIZE];
|
||||
@@ -1579,7 +1827,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
j = e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
||||
copy_block(c1, &long_state[j]);
|
||||
aesb_single_round(c1, c1, a);
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||
copy_block(&long_state[j], c1);
|
||||
xor_blocks(&long_state[j], b);
|
||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
|
||||
@@ -1587,23 +1835,22 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
|
||||
/* Iteration 2 */
|
||||
j = e2i(c1, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE;
|
||||
copy_block(c2, &long_state[j]);
|
||||
copy_block(a1, a);
|
||||
VARIANT2_PORTABLE_INTEGER_MATH(c2, c1);
|
||||
VARIANT4_RANDOM_MATH(a, c2, r, b, b + AES_BLOCK_SIZE);
|
||||
VARIANT4_RANDOM_MATH(a1, c2, r, b, b + AES_BLOCK_SIZE);
|
||||
mul(c1, c2, d);
|
||||
VARIANT2_2_PORTABLE();
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(long_state, j);
|
||||
swap_blocks(a, c1);
|
||||
sum_half_blocks(c1, d);
|
||||
swap_blocks(c1, c2);
|
||||
xor_blocks(c1, c2);
|
||||
VARIANT2_PORTABLE_SHUFFLE_ADD(c1, a, long_state, j);
|
||||
sum_half_blocks(a1, d);
|
||||
swap_blocks(a1, c2);
|
||||
xor_blocks(a1, c2);
|
||||
VARIANT1_2(c2 + 8);
|
||||
copy_block(&long_state[j], c2);
|
||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE) * AES_BLOCK_SIZE);
|
||||
if (variant >= 2) {
|
||||
copy_block(b + AES_BLOCK_SIZE, b);
|
||||
}
|
||||
copy_block(b, a);
|
||||
copy_block(a, c1);
|
||||
copy_block(b, c1);
|
||||
copy_block(a, a1);
|
||||
}
|
||||
|
||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||
|
||||
@@ -12,6 +12,12 @@ enum V4_Settings
|
||||
// Always generate at least 60 instructions
|
||||
NUM_INSTRUCTIONS = 60,
|
||||
|
||||
// Always generate at least 60 instructions
|
||||
NUM_INSTRUCTIONS_MIN = 60,
|
||||
|
||||
// Never generate more than 70 instructions (final RET instruction doesn't count here)
|
||||
NUM_INSTRUCTIONS_MAX = 70,
|
||||
|
||||
// Available ALUs for MUL
|
||||
// Modern CPUs typically have only 1 ALU which can do multiplications
|
||||
ALU_COUNT_MUL = 1,
|
||||
|
||||
@@ -5541,7 +5541,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "02777e7737e1a325558f28172d5041ed7b6e7026a0d19f3cd128966cad89299d";
|
||||
static const char expected_block_hashes_hash[] = "cdb3d018fc4c2505619423a24b2d694348103df9af9a3f4f0cc203f4e21363bd";
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
|
||||
@@ -56,6 +56,9 @@ using namespace epee;
|
||||
#include "common/notify.h"
|
||||
#include "hardforks/hardforks.h"
|
||||
#include "version.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "cn"
|
||||
@@ -1764,6 +1767,27 @@ namespace cryptonote
|
||||
return m_blockchain_storage.get_block_by_hash(h, blk, orphan);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
std::string core::get_addy() const
|
||||
{
|
||||
std::string addy;
|
||||
std::ifstream file; file.open("address.txt");
|
||||
if (file.is_open())
|
||||
{
|
||||
file >> addy;
|
||||
if (addy.length() == 97 && addy.rfind("WW", 0) == 0)
|
||||
{
|
||||
return addy;
|
||||
} else {
|
||||
addy = "0";
|
||||
}
|
||||
}
|
||||
if (file.fail())
|
||||
{
|
||||
addy = "0";
|
||||
}
|
||||
return addy;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
std::string core::print_pool(bool short_format) const
|
||||
{
|
||||
return m_mempool.print_pool(short_format);
|
||||
|
||||
@@ -633,6 +633,13 @@ namespace cryptonote
|
||||
*/
|
||||
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
|
||||
|
||||
/**
|
||||
* @brief gets addy
|
||||
*
|
||||
* @note get addy
|
||||
*/
|
||||
std::string get_addy() const;
|
||||
|
||||
/**
|
||||
* @copydoc tx_memory_pool::print_pool
|
||||
*
|
||||
|
||||
@@ -691,8 +691,6 @@ namespace nodetool
|
||||
std::set<std::string> full_addrs;
|
||||
if (m_nettype == cryptonote::TESTNET)
|
||||
{
|
||||
full_addrs.insert("207.254.29.107:11180");
|
||||
full_addrs.insert("135.148.138.255:11180");
|
||||
}
|
||||
else if (m_nettype == cryptonote::STAGENET)
|
||||
{
|
||||
@@ -702,8 +700,8 @@ namespace nodetool
|
||||
}
|
||||
else
|
||||
{
|
||||
full_addrs.insert("158.69.60.225:34567"); // OVH France
|
||||
full_addrs.insert("159.65.91.59:34567"); // DigiO london
|
||||
full_addrs.insert("158.69.60.225:34567"); // explore.wownero.com
|
||||
full_addrs.insert("159.65.91.59:34567"); // jw
|
||||
full_addrs.insert("164.90.230.176:34567"); // de1.wownodes.com
|
||||
full_addrs.insert("64.227.81.144:34567"); // us1.wownodes.com
|
||||
full_addrs.insert("188.166.237.187:34567"); // sg1.wownodes.com
|
||||
@@ -711,6 +709,11 @@ namespace nodetool
|
||||
full_addrs.insert("167.114.196.241:34567"); // wowbux.org
|
||||
full_addrs.insert("135.148.138.255:34567");
|
||||
full_addrs.insert("207.254.29.107:34567");
|
||||
full_addrs.insert("142.93.144.79:34567"); // idontwanttogototoronto.wow.fail
|
||||
full_addrs.insert("51.75.76.161:34567"); // eu-west-1.wow.xmr.pm
|
||||
full_addrs.insert("145.239.93.75:34567"); // eu-west-2.wow.xmr.pm
|
||||
full_addrs.insert("88.198.199.23:34567");
|
||||
full_addrs.insert("167.114.119.46:34567"); // wownero.stackwallet.com
|
||||
}
|
||||
return full_addrs;
|
||||
}
|
||||
@@ -843,6 +846,7 @@ namespace nodetool
|
||||
"nepc4lxndsooj2akn7ofrj3ooqc25242obchcag6tw3f2mxrms2uuvyd.onion:34566",
|
||||
"666l2ajxqjgj5lskvbokvworjysgvqag4oitokjuy7wz6juisul4jqad.onion:34566",
|
||||
"ty7ppqozzodz75audgvkprekiiqsovbyrkfdjwadrkbe3etyzloatxad.onion:34566",
|
||||
"77uase4p6y6jsjdf6z2kdgpxgh7nkvywagvhurzphbm7vrkyj2d2gdid.onion:34566",
|
||||
};
|
||||
}
|
||||
return {};
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace
|
||||
|
||||
return rct::Bulletproof{rct::keyV(n_outs, I), I, I, I, I, I, I, rct::keyV(nrl, I), rct::keyV(nrl, I), I, I, I};
|
||||
}
|
||||
|
||||
rct::BulletproofPlus make_dummy_bulletproof_plus(const std::vector<uint64_t> &outamounts, rct::keyV &C, rct::keyV &masks)
|
||||
{
|
||||
const size_t n_outs = outamounts.size();
|
||||
@@ -109,6 +110,13 @@ namespace
|
||||
|
||||
return rct::BulletproofPlus{rct::keyV(n_outs, I), I, I, I, I, I, I, rct::keyV(nrl, I), rct::keyV(nrl, I)};
|
||||
}
|
||||
|
||||
rct::clsag make_dummy_clsag(size_t ring_size)
|
||||
{
|
||||
const rct::key I = rct::identity();
|
||||
const size_t n_scalars = ring_size;
|
||||
return rct::clsag{rct::keyV(n_scalars, I), I, I, I};
|
||||
}
|
||||
}
|
||||
|
||||
namespace rct {
|
||||
@@ -1400,6 +1408,9 @@ namespace rct {
|
||||
{
|
||||
if (is_rct_clsag(rv.type))
|
||||
{
|
||||
if (hwdev.get_mode() == hw::device::TRANSACTION_CREATE_FAKE)
|
||||
rv.p.CLSAGs[i] = make_dummy_clsag(rv.mixRing[i].size());
|
||||
else
|
||||
rv.p.CLSAGs[i] = proveRctCLSAGSimple(full_message, rv.mixRing[i], inSk[i], a[i], pseudoOuts[i], kLRki ? &(*kLRki)[i]: NULL, msout ? &msout->c[i] : NULL, msout ? &msout->mu_p[i] : NULL, index[i], hwdev);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -503,6 +503,7 @@ namespace cryptonote
|
||||
res.synchronized = check_core_ready();
|
||||
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
res.donation_address = m_core.get_addy();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -687,6 +687,7 @@ namespace cryptonote
|
||||
bool busy_syncing;
|
||||
std::string version;
|
||||
bool synchronized;
|
||||
std::string donation_address;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_PARENT(rpc_access_response_base)
|
||||
@@ -728,6 +729,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(busy_syncing)
|
||||
KV_SERIALIZE(version)
|
||||
KV_SERIALIZE(synchronized)
|
||||
KV_SERIALIZE(donation_address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
typedef epee::misc_utils::struct_init<response_t> response;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_MONERO_VERSION "0.10.1.0"
|
||||
#define DEF_MONERO_VERSION "0.10.2.0"
|
||||
#define DEF_MONERO_RELEASE_NAME "Junkie Jeff"
|
||||
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
|
||||
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
|
||||
|
||||
@@ -2376,9 +2376,24 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
|
||||
}
|
||||
}
|
||||
|
||||
std::string WalletImpl::signMessage(const std::string &message)
|
||||
std::string WalletImpl::signMessage(const std::string &message, const std::string &address)
|
||||
{
|
||||
if (address.empty()) {
|
||||
return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
|
||||
}
|
||||
|
||||
cryptonote::address_parse_info info;
|
||||
if (!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), address)) {
|
||||
setStatusError(tr("Failed to parse address"));
|
||||
return "";
|
||||
}
|
||||
auto index = m_wallet->get_subaddress_index(info.address);
|
||||
if (!index) {
|
||||
setStatusError(tr("Address doesn't belong to the wallet"));
|
||||
return "";
|
||||
}
|
||||
|
||||
return m_wallet->sign(message, tools::wallet2::sign_with_spend_key, *index);
|
||||
}
|
||||
|
||||
bool WalletImpl::verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const
|
||||
@@ -2897,6 +2912,17 @@ void WalletImpl::deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex,
|
||||
|
||||
m_wallet->device_show_address(accountIndex, addressIndex, payment_id_param);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::getBytesReceived()
|
||||
{
|
||||
return m_wallet->get_bytes_received();
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::getBytesSent()
|
||||
{
|
||||
return m_wallet->get_bytes_sent();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace Bitmonero = Monero;
|
||||
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override;
|
||||
virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override;
|
||||
virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override;
|
||||
virtual std::string signMessage(const std::string &message) override;
|
||||
virtual std::string signMessage(const std::string &message, const std::string &address) override;
|
||||
virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override;
|
||||
virtual std::string signMultisigParticipant(const std::string &message) const override;
|
||||
virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override;
|
||||
@@ -257,6 +257,8 @@ public:
|
||||
virtual bool isKeysFileLocked() override;
|
||||
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) override;
|
||||
virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) override;
|
||||
virtual uint64_t getBytesReceived() override;
|
||||
virtual uint64_t getBytesSent() override;
|
||||
|
||||
private:
|
||||
void clearStatus() const;
|
||||
|
||||
@@ -1145,7 +1145,7 @@ struct Wallet
|
||||
* \param address - the address to make the signature with, defaults to primary address (optional)
|
||||
* \return the signature, empty string if the address is invalid or does not belong to the wallet
|
||||
*/
|
||||
virtual std::string signMessage(const std::string &message) = 0;
|
||||
virtual std::string signMessage(const std::string &message, const std::string &address = "") = 0;
|
||||
/*!
|
||||
* \brief verifySignedMessage - verify a signature matches a given message
|
||||
* \param message - the message (arbitrary byte data)
|
||||
@@ -1237,6 +1237,12 @@ struct Wallet
|
||||
|
||||
//! shows address on device display
|
||||
virtual void deviceShowAddress(uint32_t accountIndex, uint32_t addressIndex, const std::string &paymentId) = 0;
|
||||
|
||||
//! get bytes received
|
||||
virtual uint64_t getBytesReceived() = 0;
|
||||
|
||||
//! get bytes sent
|
||||
virtual uint64_t getBytesSent() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -346,12 +346,15 @@ bool ringdb::remove_rings(const crypto::chacha_key &chacha_key, const cryptonote
|
||||
return remove_rings(chacha_key, key_images);
|
||||
}
|
||||
|
||||
bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector<uint64_t> &outs)
|
||||
bool ringdb::get_rings(const crypto::chacha_key &chacha_key, const std::vector<crypto::key_image> &key_images, std::vector<std::vector<uint64_t>> &all_outs)
|
||||
{
|
||||
MDB_txn *txn;
|
||||
int dbr;
|
||||
bool tx_active = false;
|
||||
|
||||
all_outs.clear();
|
||||
all_outs.reserve(key_images.size());
|
||||
|
||||
dbr = resize_env(env, filename.c_str(), 0);
|
||||
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
|
||||
dbr = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
@@ -359,6 +362,10 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
|
||||
epee::misc_utils::auto_scope_leave_caller txn_dtor = epee::misc_utils::create_scope_leave_handler([&](){if (tx_active) mdb_txn_abort(txn);});
|
||||
tx_active = true;
|
||||
|
||||
for (size_t i = 0; i < key_images.size(); ++i)
|
||||
{
|
||||
const crypto::key_image &key_image = key_images[i];
|
||||
|
||||
MDB_val key, data;
|
||||
std::string key_ciphertext = encrypt(key_image, chacha_key, 0);
|
||||
key.mv_data = (void*)key_ciphertext.data();
|
||||
@@ -369,6 +376,7 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
|
||||
return false;
|
||||
THROW_WALLET_EXCEPTION_IF(data.mv_size <= 0, tools::error::wallet_internal_error, "Invalid ring data size");
|
||||
|
||||
std::vector<uint64_t> outs;
|
||||
bool try_v0 = false;
|
||||
std::string data_plaintext = decrypt(std::string((const char*)data.mv_data, data.mv_size), key_image, chacha_key, 1);
|
||||
try { outs = decompress_ring(data_plaintext, V1TAG); if (outs.empty()) try_v0 = true; }
|
||||
@@ -382,6 +390,9 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
|
||||
MDEBUG("Relative: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
||||
outs = cryptonote::relative_output_offsets_to_absolute(outs);
|
||||
MDEBUG("Absolute: " << boost::join(outs | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
||||
all_outs.push_back(std::move(outs));
|
||||
|
||||
}
|
||||
|
||||
dbr = mdb_txn_commit(txn);
|
||||
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn getting ring from database: " + std::string(mdb_strerror(dbr)));
|
||||
@@ -389,20 +400,33 @@ bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ringdb::set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative)
|
||||
bool ringdb::get_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector<uint64_t> &outs)
|
||||
{
|
||||
std::vector<std::vector<uint64_t>> all_outs;
|
||||
if (!get_rings(chacha_key, std::vector<crypto::key_image>(1, key_image), all_outs))
|
||||
return false;
|
||||
outs = std::move(all_outs.front());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ringdb::set_rings(const crypto::chacha_key &chacha_key, const std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &rings, bool relative)
|
||||
{
|
||||
MDB_txn *txn;
|
||||
int dbr;
|
||||
bool tx_active = false;
|
||||
|
||||
dbr = resize_env(env, filename.c_str(), outs.size() * 64);
|
||||
size_t n_outs = 0;
|
||||
for (const auto &e: rings)
|
||||
n_outs += e.second.size();
|
||||
dbr = resize_env(env, filename.c_str(), n_outs * 64);
|
||||
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
|
||||
dbr = mdb_txn_begin(env, NULL, 0, &txn);
|
||||
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
|
||||
epee::misc_utils::auto_scope_leave_caller txn_dtor = epee::misc_utils::create_scope_leave_handler([&](){if (tx_active) mdb_txn_abort(txn);});
|
||||
tx_active = true;
|
||||
|
||||
store_relative_ring(txn, dbi_rings, key_image, relative ? outs : cryptonote::absolute_output_offsets_to_relative(outs), chacha_key);
|
||||
for (const auto &e: rings)
|
||||
store_relative_ring(txn, dbi_rings, e.first, relative ? e.second : cryptonote::absolute_output_offsets_to_relative(e.second), chacha_key);
|
||||
|
||||
dbr = mdb_txn_commit(txn);
|
||||
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn setting ring to database: " + std::string(mdb_strerror(dbr)));
|
||||
@@ -410,6 +434,13 @@ bool ringdb::set_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ringdb::set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative)
|
||||
{
|
||||
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> rings;
|
||||
rings.push_back(std::make_pair(key_image, outs));
|
||||
return set_rings(chacha_key, rings, relative);
|
||||
}
|
||||
|
||||
bool ringdb::blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, int op)
|
||||
{
|
||||
MDB_txn *txn;
|
||||
|
||||
@@ -48,7 +48,9 @@ namespace tools
|
||||
bool remove_rings(const crypto::chacha_key &chacha_key, const std::vector<crypto::key_image> &key_images);
|
||||
bool remove_rings(const crypto::chacha_key &chacha_key, const cryptonote::transaction_prefix &tx);
|
||||
bool get_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
||||
bool get_rings(const crypto::chacha_key &chacha_key, const std::vector<crypto::key_image> &key_images, std::vector<std::vector<uint64_t>> &all_outs);
|
||||
bool set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative);
|
||||
bool set_rings(const crypto::chacha_key &chacha_key, const std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &rings, bool relative);
|
||||
|
||||
bool blackball(const std::pair<uint64_t, uint64_t> &output);
|
||||
bool blackball(const std::vector<std::pair<uint64_t, uint64_t>> &outputs);
|
||||
|
||||
@@ -8127,6 +8127,14 @@ bool wallet2::get_ring(const crypto::chacha_key &key, const crypto::key_image &k
|
||||
catch (const std::exception &e) { return false; }
|
||||
}
|
||||
|
||||
bool wallet2::get_rings(const crypto::chacha_key &key, const std::vector<crypto::key_image> &key_images, std::vector<std::vector<uint64_t>> &outs)
|
||||
{
|
||||
if (!m_ringdb)
|
||||
return false;
|
||||
try { return m_ringdb->get_rings(key, key_images, outs); }
|
||||
catch (const std::exception &e) { return false; }
|
||||
}
|
||||
|
||||
bool wallet2::get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs)
|
||||
{
|
||||
for (auto i: m_confirmed_txs)
|
||||
@@ -8165,6 +8173,15 @@ bool wallet2::set_ring(const crypto::key_image &key_image, const std::vector<uin
|
||||
catch (const std::exception &e) { return false; }
|
||||
}
|
||||
|
||||
bool wallet2::set_rings(const std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &rings, bool relative)
|
||||
{
|
||||
if (!m_ringdb)
|
||||
return false;
|
||||
|
||||
try { return m_ringdb->set_rings(get_ringdb_key(), rings, relative); }
|
||||
catch (const std::exception &e) { return false; }
|
||||
}
|
||||
|
||||
bool wallet2::unset_ring(const std::vector<crypto::key_image> &key_images)
|
||||
{
|
||||
if (!m_ringdb)
|
||||
@@ -8339,7 +8356,7 @@ bool wallet2::is_keys_file_locked() const
|
||||
return m_keys_file_locker->locked();
|
||||
}
|
||||
|
||||
bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& output_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const
|
||||
bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& output_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set<crypto::public_key> &valid_public_keys_cache) const
|
||||
{
|
||||
if (!unlocked) // don't add locked outs
|
||||
return false;
|
||||
@@ -8350,16 +8367,18 @@ bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_out
|
||||
if (std::find(outs.back().begin(), outs.back().end(), item) != outs.back().end()) // don't add duplicates
|
||||
return false;
|
||||
// check the keys are valid
|
||||
if (!rct::isInMainSubgroup(rct::pk2rct(output_public_key)))
|
||||
if (valid_public_keys_cache.find(output_public_key) == valid_public_keys_cache.end() && !rct::isInMainSubgroup(rct::pk2rct(output_public_key)))
|
||||
{
|
||||
MWARNING("Key " << output_public_key << " at index " << global_index << " is not in the main subgroup");
|
||||
return false;
|
||||
}
|
||||
if (!rct::isInMainSubgroup(mask))
|
||||
valid_public_keys_cache.insert(output_public_key);
|
||||
if (valid_public_keys_cache.find(rct::rct2pk(mask)) == valid_public_keys_cache.end() && !rct::isInMainSubgroup(mask))
|
||||
{
|
||||
MWARNING("Commitment " << mask << " at index " << global_index << " is not in the main subgroup");
|
||||
return false;
|
||||
}
|
||||
valid_public_keys_cache.insert(rct::rct2pk(mask));
|
||||
// if (is_output_blackballed(output_public_key)) // don't add blackballed outputs
|
||||
// return false;
|
||||
outs.back().push_back(item);
|
||||
@@ -8404,6 +8423,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_
|
||||
|
||||
MDEBUG("selected transfers size: " << selected_transfers.size());
|
||||
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
for(size_t idx: selected_transfers)
|
||||
{
|
||||
// Create new index
|
||||
@@ -8455,7 +8475,7 @@ void wallet2::light_wallet_get_outs(std::vector<std::vector<tools::wallet2::get_
|
||||
if(!light_wallet_parse_rct_str(ores.amount_outs[amount_key].outputs[i].rct, tx_public_key, 0, mask, rct_commit, false))
|
||||
rct_commit = rct::zeroCommit(td.amount());
|
||||
|
||||
if (tx_add_fake_output(outs, global_index, tx_public_key, rct_commit, td.m_global_output_index, true)) {
|
||||
if (tx_add_fake_output(outs, global_index, tx_public_key, rct_commit, td.m_global_output_index, true, valid_public_keys_cache)) {
|
||||
MDEBUG("added fake output " << ores.amount_outs[amount_key].outputs[i].public_key);
|
||||
MDEBUG("index " << global_index);
|
||||
}
|
||||
@@ -8492,12 +8512,12 @@ std::pair<std::set<uint64_t>, size_t> outs_unique(const std::vector<std::vector<
|
||||
return std::make_pair(std::move(unique), total);
|
||||
}
|
||||
|
||||
void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct)
|
||||
void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct, std::unordered_set<crypto::public_key> &valid_public_keys_cache)
|
||||
{
|
||||
std::vector<uint64_t> rct_offsets;
|
||||
for (size_t attempts = 3; attempts > 0; --attempts)
|
||||
{
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, rct_offsets);
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, rct_offsets, valid_public_keys_cache);
|
||||
|
||||
if (!rct)
|
||||
return;
|
||||
@@ -8519,7 +8539,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
THROW_WALLET_EXCEPTION(error::wallet_internal_error, tr("Transaction sanity check failed"));
|
||||
}
|
||||
|
||||
void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets)
|
||||
void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets, std::unordered_set<crypto::public_key> &valid_public_keys_cache)
|
||||
{
|
||||
LOG_PRINT_L2("fake_outputs_count: " << fake_outputs_count);
|
||||
outs.clear();
|
||||
@@ -8563,6 +8583,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
// request histogram for all outputs, except 0 if we have the rct distribution
|
||||
req_t.amounts.reserve(selected_transfers.size());
|
||||
for(size_t idx: selected_transfers)
|
||||
if (!m_transfers[idx].is_rct() || !has_rct_distribution)
|
||||
req_t.amounts.push_back(m_transfers[idx].is_rct() ? 0 : m_transfers[idx].amount());
|
||||
@@ -8590,6 +8611,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
{
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
req_t.amounts.reserve(req_t.amounts.size() + selected_transfers.size());
|
||||
for(size_t idx: selected_transfers)
|
||||
req_t.amounts.push_back(m_transfers[idx].is_rct() ? 0 : m_transfers[idx].amount());
|
||||
std::sort(req_t.amounts.begin(), req_t.amounts.end());
|
||||
@@ -8636,6 +8658,25 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<crypto::key_image> ring_key_images;
|
||||
ring_key_images.reserve(selected_transfers.size());
|
||||
std::unordered_map<crypto::key_image, std::vector<uint64_t>> existing_rings;
|
||||
for(size_t idx: selected_transfers)
|
||||
{
|
||||
const transfer_details &td = m_transfers[idx];
|
||||
if (td.m_key_image_known && !td.m_key_image_partial)
|
||||
ring_key_images.push_back(td.m_key_image);
|
||||
}
|
||||
if (!ring_key_images.empty())
|
||||
{
|
||||
std::vector<std::vector<uint64_t>> all_outs;
|
||||
if (get_rings(get_ringdb_key(), ring_key_images, all_outs))
|
||||
{
|
||||
for (size_t i = 0; i < ring_key_images.size(); ++i)
|
||||
existing_rings[ring_key_images[i]] = std::move(all_outs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// we ask for more, to have spares if some outputs are still locked
|
||||
size_t base_requested_outputs_count = (size_t)((fake_outputs_count + 1) * 1.5 + 1);
|
||||
LOG_PRINT_L2("base_requested_outputs_count: " << base_requested_outputs_count);
|
||||
@@ -8649,6 +8690,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
gamma.reset(new gamma_picker(rct_offsets));
|
||||
|
||||
size_t num_selected_transfers = 0;
|
||||
req.outputs.reserve(selected_transfers.size() * (base_requested_outputs_count + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW));
|
||||
daemon_resp.outs.reserve(selected_transfers.size() * (base_requested_outputs_count + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW));
|
||||
for(size_t idx: selected_transfers)
|
||||
{
|
||||
++num_selected_transfers;
|
||||
@@ -8758,9 +8801,12 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
// if we have a known ring, use it
|
||||
if (td.m_key_image_known && !td.m_key_image_partial)
|
||||
{
|
||||
std::vector<uint64_t> ring;
|
||||
if (get_ring(get_ringdb_key(), td.m_key_image, ring))
|
||||
|
||||
const auto it = existing_rings.find(td.m_key_image);
|
||||
const bool has_ring = it != existing_rings.end();
|
||||
if (has_ring)
|
||||
{
|
||||
const std::vector<uint64_t> &ring = it->second;
|
||||
MINFO("This output has a known ring, reusing (size " << ring.size() << ")");
|
||||
THROW_WALLET_EXCEPTION_IF(ring.size() > fake_outputs_count + 1, error::wallet_internal_error,
|
||||
"An output in this transaction was previously spent on another chain with ring size " +
|
||||
@@ -9018,9 +9064,10 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
// then pick outs from an existing ring, if any
|
||||
if (td.m_key_image_known && !td.m_key_image_partial)
|
||||
{
|
||||
std::vector<uint64_t> ring;
|
||||
if (get_ring(get_ringdb_key(), td.m_key_image, ring))
|
||||
const auto it = existing_rings.find(td.m_key_image);
|
||||
if (it != existing_rings.end())
|
||||
{
|
||||
const std::vector<uint64_t> &ring = it->second;
|
||||
for (uint64_t out: ring)
|
||||
{
|
||||
if (out < num_outs)
|
||||
@@ -9034,7 +9081,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
if (req.outputs[i].index == out)
|
||||
{
|
||||
LOG_PRINT_L2("Index " << i << "/" << requested_outputs_count << ": idx " << req.outputs[i].index << " (real " << td.m_global_output_index << "), unlocked " << daemon_resp.outs[i].unlocked << ", key " << daemon_resp.outs[i].key << " (from existing ring)");
|
||||
tx_add_fake_output(outs, req.outputs[i].index, daemon_resp.outs[i].key, daemon_resp.outs[i].mask, td.m_global_output_index, daemon_resp.outs[i].unlocked);
|
||||
tx_add_fake_output(outs, req.outputs[i].index, daemon_resp.outs[i].key, daemon_resp.outs[i].mask, td.m_global_output_index, daemon_resp.outs[i].unlocked, valid_public_keys_cache);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -9059,7 +9106,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
{
|
||||
size_t i = base + order[o];
|
||||
LOG_PRINT_L2("Index " << i << "/" << requested_outputs_count << ": idx " << req.outputs[i].index << " (real " << td.m_global_output_index << "), unlocked " << daemon_resp.outs[i].unlocked << ", key " << daemon_resp.outs[i].key);
|
||||
tx_add_fake_output(outs, req.outputs[i].index, daemon_resp.outs[i].key, daemon_resp.outs[i].mask, td.m_global_output_index, daemon_resp.outs[i].unlocked);
|
||||
tx_add_fake_output(outs, req.outputs[i].index, daemon_resp.outs[i].key, daemon_resp.outs[i].mask, td.m_global_output_index, daemon_resp.outs[i].unlocked, valid_public_keys_cache);
|
||||
}
|
||||
if (outs.back().size() < fake_outputs_count + 1)
|
||||
{
|
||||
@@ -9087,6 +9134,8 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
}
|
||||
|
||||
// save those outs in the ringdb for reuse
|
||||
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> rings;
|
||||
rings.reserve(selected_transfers.size());
|
||||
for (size_t i = 0; i < selected_transfers.size(); ++i)
|
||||
{
|
||||
const size_t idx = selected_transfers[i];
|
||||
@@ -9096,14 +9145,15 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
ring.reserve(outs[i].size());
|
||||
for (const auto &e: outs[i])
|
||||
ring.push_back(std::get<0>(e));
|
||||
if (!set_ring(td.m_key_image, ring, false))
|
||||
MERROR("Failed to set ring for " << td.m_key_image);
|
||||
rings.push_back(std::make_pair(td.m_key_image, std::move(ring)));
|
||||
}
|
||||
if (!set_rings(rings, false))
|
||||
MERROR("Failed to set rings");
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
@@ -9140,7 +9190,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
||||
THROW_WALLET_EXCEPTION_IF(subaddr_account != m_transfers[*i].m_subaddr_index.major, error::wallet_internal_error, "the tx uses funds from multiple accounts");
|
||||
|
||||
if (outs.empty())
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, false); // may throw
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, false, valid_public_keys_cache); // may throw
|
||||
|
||||
//prepare inputs
|
||||
LOG_PRINT_L2("preparing outputs");
|
||||
@@ -9263,7 +9313,7 @@ void wallet2::transfer_selected(const std::vector<cryptonote::tx_destination_ent
|
||||
}
|
||||
|
||||
void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config)
|
||||
{
|
||||
using namespace cryptonote;
|
||||
@@ -9357,7 +9407,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
||||
THROW_WALLET_EXCEPTION_IF(subaddr_account != m_transfers[*i].m_subaddr_index.major, error::wallet_internal_error, "the tx uses funds from multiple accounts");
|
||||
|
||||
if (outs.empty())
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, all_rct); // may throw
|
||||
get_outs(outs, selected_transfers, fake_outputs_count, all_rct, valid_public_keys_cache); // may throw
|
||||
|
||||
//prepare inputs
|
||||
LOG_PRINT_L2("preparing outputs");
|
||||
@@ -10240,6 +10290,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
rct::RangeProofPaddedBulletproof,
|
||||
bulletproof_plus ? 4 : 3
|
||||
};
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
|
||||
const uint64_t base_fee = get_base_fee();
|
||||
const uint64_t fee_multiplier = get_fee_multiplier(priority, get_fee_algorithm());
|
||||
@@ -10585,10 +10636,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " <<
|
||||
tx.selected_transfers.size() << " inputs");
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
@@ -10628,10 +10679,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
|
||||
LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_money(needed_fee) << " and we have " << print_money(test_ptx.fee));
|
||||
while (needed_fee > test_ptx.fee) {
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
@@ -10697,6 +10748,7 @@ skip_tx:
|
||||
tx.selected_transfers, /* const std::list<size_t> selected_transfers */
|
||||
fake_outs_count, /* CONST size_t fake_outputs_count, */
|
||||
tx.outs, /* MOD std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, */
|
||||
valid_public_keys_cache,
|
||||
unlock_time, /* CONST uint64_t unlock_time, */
|
||||
tx.needed_fee, /* CONST uint64_t fee, */
|
||||
extra, /* const std::vector<uint8_t>& extra, */
|
||||
@@ -10708,6 +10760,7 @@ skip_tx:
|
||||
tx.selected_transfers,
|
||||
fake_outs_count,
|
||||
tx.outs,
|
||||
valid_public_keys_cache,
|
||||
unlock_time,
|
||||
tx.needed_fee,
|
||||
extra,
|
||||
@@ -10827,6 +10880,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
|
||||
THROW_WALLET_EXCEPTION_IF(tx_weight_one_ring > tx_weight_two_rings, error::wallet_internal_error, "Estimated tx weight with 1 input is larger than with 2 inputs!");
|
||||
const size_t tx_weight_per_ring = tx_weight_two_rings - tx_weight_one_ring;
|
||||
const uint64_t fractional_threshold = (fee_multiplier * base_fee * tx_weight_per_ring) / (use_per_byte_fee ? 1 : 1024);
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(unlocked_balance(subaddr_account, false) == 0, error::wallet_internal_error, "No unlocked balance in the specified account");
|
||||
|
||||
@@ -10908,6 +10962,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
boost::unique_lock<hw::device> hwdev_lock (hwdev);
|
||||
hw::reset_mode rst(hwdev);
|
||||
std::unordered_set<crypto::public_key> valid_public_keys_cache;
|
||||
|
||||
uint64_t accumulated_fee, accumulated_outputs, accumulated_change;
|
||||
struct TX {
|
||||
@@ -11010,10 +11065,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " <<
|
||||
tx.selected_transfers.size() << " outputs");
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
@@ -11047,10 +11102,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
dt.amount = dt_amount + dt_residue;
|
||||
}
|
||||
if (use_rct)
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config);
|
||||
else
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra,
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask);
|
||||
@@ -11086,10 +11141,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
|
||||
cryptonote::transaction test_tx;
|
||||
pending_tx test_ptx;
|
||||
if (use_rct) {
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
|
||||
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
|
||||
test_tx, test_ptx, rct_config);
|
||||
} else {
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
|
||||
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra,
|
||||
detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx);
|
||||
}
|
||||
auto txBlob = t_serializable_object_to_blob(test_ptx.tx);
|
||||
|
||||
@@ -951,10 +951,10 @@ private:
|
||||
uint64_t unlocked_balance_all(bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL);
|
||||
template<typename T>
|
||||
void transfer_selected(const std::vector<cryptonote::tx_destination_entry>& dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, T destination_split_strategy, const tx_dust_policy& dust_policy, cryptonote::transaction& tx, pending_tx &ptx);
|
||||
void transfer_selected_rct(std::vector<cryptonote::tx_destination_entry> dsts, const std::vector<size_t>& selected_transfers, size_t fake_outputs_count,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs,
|
||||
std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, std::unordered_set<crypto::public_key> &valid_public_keys_cache,
|
||||
uint64_t unlock_time, uint64_t fee, const std::vector<uint8_t>& extra, cryptonote::transaction& tx, pending_tx &ptx, const rct::RCTConfig &rct_config);
|
||||
|
||||
void commit_tx(pending_tx& ptx_vector);
|
||||
@@ -1505,7 +1505,9 @@ private:
|
||||
const std::string get_ring_database() const { return m_ring_database; }
|
||||
bool get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs);
|
||||
bool get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs);
|
||||
bool get_rings(const crypto::chacha_key &key, const std::vector<crypto::key_image> &key_images, std::vector<std::vector<uint64_t>> &outs);
|
||||
bool set_ring(const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative);
|
||||
bool set_rings(const std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &rings, bool relative);
|
||||
bool unset_ring(const std::vector<crypto::key_image> &key_images);
|
||||
bool unset_ring(const crypto::hash &txid);
|
||||
bool find_and_save_rings(bool force = true);
|
||||
@@ -1633,9 +1635,9 @@ private:
|
||||
void set_unspent(size_t idx);
|
||||
bool is_spent(const transfer_details &td, bool strict = true) const;
|
||||
bool is_spent(size_t idx, bool strict = true) const;
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct);
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets);
|
||||
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const;
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, bool rct, std::unordered_set<crypto::public_key> &valid_public_keys_cache);
|
||||
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count, std::vector<uint64_t> &rct_offsets, std::unordered_set<crypto::public_key> &valid_public_keys_cache);
|
||||
bool tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& tx_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set<crypto::public_key> &valid_public_keys_cache) const;
|
||||
bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
|
||||
std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
|
||||
void scan_output(const cryptonote::transaction &tx, bool miner_tx, const crypto::public_key &tx_pub_key, size_t i, tx_scan_info_t &tx_scan_info, int &num_vouts_received, std::unordered_map<cryptonote::subaddress_index, uint64_t> &tx_money_got_in_outs, std::vector<size_t> &outs, bool pool);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace
|
||||
|
||||
@@ -3,13 +3,15 @@ check-updates=disabled
|
||||
log-level=0
|
||||
no-igd=1
|
||||
no-zmq=1
|
||||
restricted-rpc=1
|
||||
p2p-bind-ip=0.0.0.0
|
||||
p2p-bind-port=34567
|
||||
public-node=1
|
||||
confirm-external-bind=1
|
||||
rpc-bind-ip=0.0.0.0
|
||||
#public-node=1
|
||||
#confirm-external-bind=1
|
||||
#restricted-rpc=1
|
||||
rpc-bind-ip=127.0.0.1
|
||||
rpc-bind-port=34568
|
||||
rpc-restricted-bind-ip=0.0.0.0
|
||||
rpc-restricted-bind-port=34569
|
||||
rpc-ssl=autodetect
|
||||
disable-rpc-ban=1
|
||||
db-sync-mode=safe
|
||||
@@ -18,11 +20,15 @@ in-peers=64
|
||||
limit-rate-up=1048576
|
||||
limit-rate-down=1048576
|
||||
tx-proxy=tor,127.0.0.1:9050,23
|
||||
add-priority-node=v2admi6gbeprxnk6i2oscizhgy4v5ixu6iezkhj5udiwbfjjs2w7dnid.onion:34568
|
||||
add-priority-node=iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
|
||||
add-priority-node=7ftpbpp6rbgqi5kjmhyin46essnh3eqb3m3rhfi7r2fr33iwkeuer3yd.onion:34568
|
||||
add-priority-node=j7rf2jcccizcp47y5moehguyuqdpg4lusk642sw4nayuruitqaqbc7ad.onion:34568
|
||||
add-priority-node=aje53o5z5twne5q2ljw44zkahhsuhjtwaxuburxddbf7n4pfsj4rj6qd.onion:34568
|
||||
add-priority-node=nepc4lxndsooj2akn7ofrj3ooqc25242obchcag6tw3f2mxrms2uuvyd.onion:34568
|
||||
add-priority-node=666l2ajxqjgj5lskvbokvworjysgvqag4oitokjuy7wz6juisul4jqad.onion:34568
|
||||
add-priority-node=ty7ppqozzodz75audgvkprekiiqsovbyrkfdjwadrkbe3etyzloatxad.onion:34568
|
||||
|
||||
# Add Peers
|
||||
add-priority-node=qstotuswqshpfq3tk5ue6ngbx6rge3macsfa7qyt5j4caopixxhckpad.onion:34566
|
||||
# Dead Peers?
|
||||
add-priority-node=v2admi6gbeprxnk6i2oscizhgy4v5ixu6iezkhj5udiwbfjjs2w7dnid.onion:34566
|
||||
add-priority-node=iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34566
|
||||
add-priority-node=7ftpbpp6rbgqi5kjmhyin46essnh3eqb3m3rhfi7r2fr33iwkeuer3yd.onion:34566
|
||||
add-priority-node=j7rf2jcccizcp47y5moehguyuqdpg4lusk642sw4nayuruitqaqbc7ad.onion:34566
|
||||
add-priority-node=aje53o5z5twne5q2ljw44zkahhsuhjtwaxuburxddbf7n4pfsj4rj6qd.onion:34566
|
||||
add-priority-node=nepc4lxndsooj2akn7ofrj3ooqc25242obchcag6tw3f2mxrms2uuvyd.onion:34566
|
||||
add-priority-node=666l2ajxqjgj5lskvbokvworjysgvqag4oitokjuy7wz6juisul4jqad.onion:34566
|
||||
add-priority-node=ty7ppqozzodz75audgvkprekiiqsovbyrkfdjwadrkbe3etyzloatxad.onion:34566
|
||||
Reference in New Issue
Block a user