Compare commits

...

28 Commits

Author SHA1 Message Date
wowario 301e33520c Merge pull request 'bump version' (#439) from wowario/wownero:tag-release-1 into master
1 year ago
wowario 2285e6640a
bump version
1 year ago
dsc cf3bba3aee Merge pull request 'wowletify' (#438) from wowletify into master
1 year ago
dsc e2c99252fd wowletify
1 year ago
wowario ab42be18f2 Merge pull request 'tag-release' (#435) from wowario/wownero:tag-release into master
1 year ago
dsc 44c482913f
Wownero fails to compile on armv7a. To fix we can:
1 year ago
wowario 07864cc53f
add seed nodes
1 year ago
wowario 2d8b094e09
update README.md
1 year ago
wowario cc0889aa59 Merge pull request 'wallet: faster value conveyance via five various velocity advances' (#433) from wowario/wownero:pr8046 into master
1 year ago
wowario 23d1a8d68e
update checkpoints
1 year ago
wowario 35c9cf9c88
bump version
1 year ago
wowario 833ac01ed9 Merge pull request 'epee: add missing header' (#431) from sneurlax/wownero:fix/gcc11 into master
1 year ago
wowario dc3981618d
remove use_view_tags, revert fractional_threshold
1 year ago
moneromooo-monero 2eeb3fc1bf
wallet2: speedup large tx construction: reserve vector memory
1 year ago
Crypto City 940811465f
wallet2: speedup large tx construction: batch ringdb lookups
1 year ago
Crypto City 4a60dfbb3e
wallet2: speedup large tx construction: no pointless clsag generation
1 year ago
Crypto City 7cdb8244ee
wallet2: speedup large tx construction: batch ringdb updates
1 year ago
moneromooo-monero 0f8a3eded6
wallet2: speedup large tx construction: cache public key validity
1 year ago
wowario 0c3ffa66ce Merge pull request 'Update year to 2023' (#432) from nicolasvansaberhagen/wownero:master into master
1 year ago
wow nero 01903438a0 Merge pull request 'update year to 2023' (#1) from nicolasvansaberhagen-patch-1 into master
1 year ago
wow nero 3692b631b3 update year to 2023
1 year ago
sleepy pocket monster 39379d7022 epee: add missing header
2 years ago
wowario ac12e02fcb Merge pull request 'broadcast donation sub-address' (#430) from wowario/wownero:addy into master
2 years ago
wowario e85ee60d35
broadcast donation sub-address
2 years ago
wowario 6a561e5d83 Merge pull request 'fixing tor hidden service ports' (#428) from nahuhh/wownero:tor into master
2 years ago
wow nero 9efbb8896c reflect restricted rpc port in wownero.conf
2 years ago
wow nero 7412b75d42 fix onion peers
2 years ago
wow nero ee0c3ed694 adjust binds and use rpc-restricted-bind flags
2 years ago

@ -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.1 | 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.
@ -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.1"
#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

@ -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
Loading…
Cancel
Save