mirror of
https://codeberg.org/nahuhh/wownero
synced 2026-03-05 06:07:35 -05:00
Compare commits
21 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 |
58
README.md
58
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.
|
||||
|
||||
@@ -64,31 +69,32 @@ Wownero is hosted by Open Collective Europe, a Brussels-based non-profit that ho
|
||||
|
||||
## Release staging and Contributing
|
||||
|
||||
**Anyone is welcome to contribute to Wownero's codebase!**
|
||||
**Anyone is welcome to contribute to Wownero's codebase!**
|
||||
|
||||
If you have a fix or code change, feel free to submit it as a pull request. Ahead of a scheduled software upgrade, a development branch will be created with the new release version tag. Pull requests that address bugs should be made to Master. Pull requests that require review and testing (generally, optimizations and new features) should be made to the development branch. All pull requests will be considered safe until the US dollar valuation of 1 Wownero equals $1000. After this valuation has been reached, more research will be needed to introduce experimental cryptography and/or code into the codebase.
|
||||
|
||||
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://git.wownero.com/wownero/meta/issues) repo.
|
||||
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://git.wownero.com/wownero/meta/issues) repo.
|
||||
|
||||
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.
|
||||
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
|
||||
| 63,469 | 2018-11-11 | Dank Doge | v0.4.0.0 | v0.4.0.0 | LWMA v4
|
||||
| 81,769 | 2019-02-19 | Erotic EggplantEmoji | v0.5.0.0 | v0.5.0.2 | Cryptonight/wow, LWMA v1 with N=144, Updated Bulletproofs, Fee Per Byte, Auto-churn
|
||||
| 114,969 | 2019-06-14 | F For Fappening | v0.6.1.0 | v0.6.1.2 | RandomWOW, new block weight algorithm, slightly more efficient RingCT format
|
||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.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
|
||||
|-------------------------------|------------| ----------------- |-------------------------|-----------------------------| ---------------------------------------------------------------------------------- |
|
||||
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
||||
| 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
||||
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
|
||||
| 63,469 | 2018-11-11 | Dank Doge | v0.4.0.0 | v0.4.0.0 | LWMA v4
|
||||
| 81,769 | 2019-02-19 | Erotic EggplantEmoji | v0.5.0.0 | v0.5.0.2 | Cryptonight/wow, LWMA v1 with N=144, Updated Bulletproofs, Fee Per Byte, Auto-churn
|
||||
| 114,969 | 2019-06-14 | F For Fappening | v0.6.1.0 | v0.6.1.2 | RandomWOW, new block weight algorithm, slightly more efficient RingCT format
|
||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.2.0 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
||||
| 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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -206,4 +212,4 @@ More information on running Tor and i2p nodes is available [here](https://forum.
|
||||
|
||||
```
|
||||
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
|
||||
```
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,13 @@ 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,7 +1408,10 @@ namespace rct {
|
||||
{
|
||||
if (is_rct_clsag(rv.type))
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user