v0.21.2
This commit is contained in:
parent
2944bf24af
commit
eef63f7034
@ -3,7 +3,7 @@ define(_CLIENT_VERSION_MAJOR, 0)
|
||||
define(_CLIENT_VERSION_MINOR, 21)
|
||||
define(_CLIENT_VERSION_REVISION, 2)
|
||||
define(_CLIENT_VERSION_BUILD, 0)
|
||||
define(_CLIENT_VERSION_RC, 7)
|
||||
define(_CLIENT_VERSION_RC, 0)
|
||||
define(_CLIENT_VERSION_IS_RELEASE, true)
|
||||
define(_COPYRIGHT_YEAR, 2022)
|
||||
define(_COPYRIGHT_HOLDERS,[The %s developers])
|
||||
|
||||
120
doc/litecoin-release-notes/release-notes-0.21.2.md
Normal file
120
doc/litecoin-release-notes/release-notes-0.21.2.md
Normal file
@ -0,0 +1,120 @@
|
||||
Litecoin Core version 0.21.2 is now available from:
|
||||
|
||||
<https://download.litecoin.org/litecoin-0.21.2/>.
|
||||
|
||||
This is the largest update ever, providing full node, wallet, and mining support for MWEB.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
<https://github.com/litecoin-project/litecoin/issues>
|
||||
|
||||
To receive security and update notifications, please subscribe to:
|
||||
|
||||
<https://groups.google.com/forum/#!forum/litecoin-dev>
|
||||
|
||||
|
||||
How to upgrade:
|
||||
==============
|
||||
|
||||
Firstly, thank you for running Litecoin Core and helping secure the network!
|
||||
|
||||
As you’re running an older version of Litecoin Core, shut it down. Wait until it’s completely shut down - which might take a few minutes for older versions - then follow these simple steps:
|
||||
For Windows: simply run the installer
|
||||
For Mac: copy over to `/Applications/Litecoin-Qt`
|
||||
For Linux: copy cover `litecoind`/`litecoin-qt`.
|
||||
|
||||
NB: upgrading directly from an ‘end of life’ version of Litecoin Core is possible, but it might take a while if the data directory needs to be migrated. Old wallet versions of Litecoin Core are generally supported.
|
||||
|
||||
|
||||
Compatibility:
|
||||
==============
|
||||
|
||||
Litecoin Core is supported and extensively tested on operating systems using the Linux kernel, macOS 10.10+, Windows 7 and newer. It’s not recommended to use Litecoin Core on unsupported systems.
|
||||
|
||||
Litecoin Core should also work on most other Unix-like systems, but is not as frequently tested on them.
|
||||
|
||||
MWEB fields added to BlockIndex, and block serialization format has changed. Downgrading to older versions is unsafe.
|
||||
|
||||
If upgrading to 0.21.2 *after* MWEB has activated, you must resync to download MWEB blocks.
|
||||
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
Consensus changes
|
||||
-----------------
|
||||
|
||||
- This release implements the proposed MWEB consensus rules
|
||||
([LIP002](https://github.com/litecoin-project/lips/blob/master/lip-0002.mediawiki),
|
||||
[LIP003](https://github.com/litecoin-project/lips/blob/master/lip-0003.mediawiki), and
|
||||
[LIP004](https://github.com/litecoin-project/lips/blob/master/lip-0004.mediawiki))
|
||||
|
||||
P2P and network changes
|
||||
-----------------------
|
||||
|
||||
- A new service flag, NODE_MWEB (1 << 24), was added to signal to peers that the node supports MWEB.
|
||||
When connected peers both advertise this capability, they are expected to provide all MWEB data when
|
||||
sharing transactions, blocks, and compact blocks with each other.
|
||||
|
||||
- Nodes now announce compact block version 3 support, informing peers that they can provide MWEB data
|
||||
in compact blocks.
|
||||
|
||||
|
||||
Updated RPCs
|
||||
------------
|
||||
|
||||
- `getblockheader` now returns an additional `mweb_header` field containing
|
||||
all of the MWEB header data, and an `mweb_amount` field containing the total
|
||||
number of coins pegged-in to the MWEB after applying the block.
|
||||
|
||||
- `getblock` now returns an additional `mweb` field containing MWEB header info,
|
||||
and all of the inputs, outputs, and kernels in the MWEB block.
|
||||
|
||||
- Added `mwebweight`, `descendantmwebweight`, `ancestormwebweight`, and `mweb`
|
||||
fields to `getrawmempool`, `getmempoolancestors`, `getmempooldescendants`,
|
||||
and `getmempoolentry`.
|
||||
|
||||
- Added new fields to describe MWEB transaction inputs, outputs, and kernels
|
||||
for `getrawtransaction`.
|
||||
|
||||
Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below.
|
||||
|
||||
New settings
|
||||
------------
|
||||
|
||||
- Added "fMWEBFeatures" option for enabling the new "Advanced MWEB Features"
|
||||
control.
|
||||
|
||||
Wallet Database
|
||||
---------------
|
||||
|
||||
- Added "mweb_coin" type which stores MWEB coins and their derived keys.
|
||||
|
||||
- Added CHDChain version 4 which includes an MWEB key index counter and
|
||||
the stealth address scan key.
|
||||
|
||||
- Added CKeyMetadata version 14 which includes the MWEB key index.
|
||||
|
||||
- Added FEATURE_MWEB = 210000 minimum database version.
|
||||
|
||||
Wallet RPC changes
|
||||
------------------
|
||||
|
||||
- Added 'listwallettransactions' which matches the transaction list display values.
|
||||
|
||||
GUI changes
|
||||
-----------
|
||||
|
||||
- Added an "Advanced MWEB Features" control for testing. It’s only available
|
||||
when the "-debug" argument is supplied, and the option is turned on in the
|
||||
settings dialog.
|
||||
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- [The Bitcoin Core Developers]
|
||||
- DavidBurkett
|
||||
- hectorchu
|
||||
- losh11
|
||||
@ -1,203 +1,120 @@
|
||||
0.21.1 Release Notes
|
||||
====================
|
||||
Litecoin Core version 0.21.2 is now available from:
|
||||
|
||||
Bitcoin Core version 0.21.1 is now available from:
|
||||
<https://download.litecoin.org/litecoin-0.21.2/>.
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-0.21.1/>
|
||||
|
||||
This minor release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
This is the largest update ever, providing full node, wallet, and mining support for MWEB.
|
||||
|
||||
Please report bugs using the issue tracker at GitHub:
|
||||
|
||||
<https://github.com/bitcoin/bitcoin/issues>
|
||||
<https://github.com/litecoin-project/litecoin/issues>
|
||||
|
||||
To receive security and update notifications, please subscribe to:
|
||||
|
||||
<https://bitcoincore.org/en/list/announcements/join/>
|
||||
<https://groups.google.com/forum/#!forum/litecoin-dev>
|
||||
|
||||
How to Upgrade
|
||||
|
||||
How to upgrade:
|
||||
==============
|
||||
|
||||
If you are running an older version, shut it down. Wait until it has completely
|
||||
shut down (which might take a few minutes in some cases), then run the
|
||||
installer (on Windows) or just copy over `/Applications/Bitcoin-Qt` (on Mac)
|
||||
or `bitcoind`/`bitcoin-qt` (on Linux).
|
||||
Firstly, thank you for running Litecoin Core and helping secure the network!
|
||||
|
||||
Upgrading directly from a version of Bitcoin Core that has reached its EOL is
|
||||
possible, but it might take some time if the data directory needs to be migrated. Old
|
||||
wallet versions of Bitcoin Core are generally supported.
|
||||
As you’re running an older version of Litecoin Core, shut it down. Wait until it’s completely shut down - which might take a few minutes for older versions - then follow these simple steps:
|
||||
For Windows: simply run the installer
|
||||
For Mac: copy over to `/Applications/Litecoin-Qt`
|
||||
For Linux: copy cover `litecoind`/`litecoin-qt`.
|
||||
|
||||
Compatibility
|
||||
NB: upgrading directly from an ‘end of life’ version of Litecoin Core is possible, but it might take a while if the data directory needs to be migrated. Old wallet versions of Litecoin Core are generally supported.
|
||||
|
||||
|
||||
Compatibility:
|
||||
==============
|
||||
|
||||
Bitcoin Core is supported and extensively tested on operating systems
|
||||
using the Linux kernel, macOS 10.14+, and Windows 7 and newer. Bitcoin
|
||||
Core should also work on most other Unix-like systems but is not as
|
||||
frequently tested on them. It is not recommended to use Bitcoin Core on
|
||||
unsupported systems.
|
||||
Litecoin Core is supported and extensively tested on operating systems using the Linux kernel, macOS 10.10+, Windows 7 and newer. It’s not recommended to use Litecoin Core on unsupported systems.
|
||||
|
||||
From Bitcoin Core 0.22.0 onwards, macOS versions earlier than 10.14 are no
|
||||
longer supported. Additionally, Bitcoin Core does not yet change appearance
|
||||
when macOS "dark mode" is activated.
|
||||
Litecoin Core should also work on most other Unix-like systems, but is not as frequently tested on them.
|
||||
|
||||
MWEB fields added to BlockIndex, and block serialization format has changed. Downgrading to older versions is unsafe.
|
||||
|
||||
If upgrading to 0.21.2 *after* MWEB has activated, you must resync to download MWEB blocks.
|
||||
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
## Taproot Soft Fork
|
||||
Consensus changes
|
||||
-----------------
|
||||
|
||||
Included in this release are the mainnet and testnet activation
|
||||
parameters for the taproot soft fork (BIP341) which also adds support
|
||||
for schnorr signatures (BIP340) and tapscript (BIP342).
|
||||
- This release implements the proposed MWEB consensus rules
|
||||
([LIP002](https://github.com/litecoin-project/lips/blob/master/lip-0002.mediawiki),
|
||||
[LIP003](https://github.com/litecoin-project/lips/blob/master/lip-0003.mediawiki), and
|
||||
[LIP004](https://github.com/litecoin-project/lips/blob/master/lip-0004.mediawiki))
|
||||
|
||||
If activated, these improvements will allow users of single-signature
|
||||
scripts, multisignature scripts, and complex contracts to all use
|
||||
identical-appearing commitments that enhance their privacy and the
|
||||
fungibility of all bitcoins. Spenders will enjoy lower fees and the
|
||||
ability to resolve many multisig scripts and complex contracts with the
|
||||
same efficiency, low fees, and large anonymity set as single-sig users.
|
||||
Taproot and schnorr also include efficiency improvements for full nodes
|
||||
such as the ability to batch signature verification. Together, the
|
||||
improvements lay the groundwork for future potential
|
||||
upgrades that may improve efficiency, privacy, and fungibility further.
|
||||
P2P and network changes
|
||||
-----------------------
|
||||
|
||||
Activation for taproot is being managed using a variation of BIP9
|
||||
versionbits called Speedy Trial (described in BIP341). Taproot's
|
||||
versionbit is bit 2, and nodes will begin tracking which blocks signal
|
||||
support for taproot at the beginning of the first retarget period after
|
||||
taproot’s start date of 24 April 2021. If 90% of blocks within a
|
||||
2,016-block retarget period (about two weeks) signal support for taproot
|
||||
prior to the first retarget period beginning after the time of 11 August
|
||||
2021, the soft fork will be locked in, and taproot will then be active
|
||||
as of block 709632 (expected in early or mid November).
|
||||
- A new service flag, NODE_MWEB (1 << 24), was added to signal to peers that the node supports MWEB.
|
||||
When connected peers both advertise this capability, they are expected to provide all MWEB data when
|
||||
sharing transactions, blocks, and compact blocks with each other.
|
||||
|
||||
Should taproot not be locked in via Speedy Trial activation, it is
|
||||
expected that a follow-up activation mechanism will be deployed, with
|
||||
changes to address the reasons the Speedy Trial method failed.
|
||||
- Nodes now announce compact block version 3 support, informing peers that they can provide MWEB data
|
||||
in compact blocks.
|
||||
|
||||
This release includes the ability to pay taproot addresses, although
|
||||
payments to such addresses are not secure until taproot activates.
|
||||
It also includes the ability to relay and mine taproot transactions
|
||||
after activation. Beyond those two basic capabilities, this release
|
||||
does not include any code that allows anyone to directly use taproot.
|
||||
The addition of taproot-related features to Bitcoin Core's wallet is
|
||||
expected in later releases once taproot activation is assured.
|
||||
|
||||
All users, businesses, and miners are encouraged to upgrade to this
|
||||
release (or a subsequent compatible release) unless they object to
|
||||
activation of taproot. If taproot is locked in, then upgrading before
|
||||
block 709632 is highly recommended to help enforce taproot's new rules
|
||||
and to avoid the unlikely case of seeing falsely confirmed transactions.
|
||||
|
||||
Miners who want to activate Taproot should preferably use this release
|
||||
to control their signaling. The `getblocktemplate` RPC results will
|
||||
automatically be updated to signal once the appropriate start has been
|
||||
reached and continue signaling until the timeout occurs or taproot
|
||||
activates. Alternatively, miners may manually start signaling on bit 2
|
||||
at any time; if taproot activates, they will need to ensure they update
|
||||
their nodes before block 709632 or non-upgraded nodes could cause them to mine on
|
||||
an invalid chain. See the [versionbits
|
||||
FAQ](https://bitcoincore.org/en/2016/06/08/version-bits-miners-faq/) for
|
||||
details.
|
||||
|
||||
|
||||
For more information about taproot, please see the following resources:
|
||||
|
||||
- Technical specifications
|
||||
- [BIP340 Schnorr signatures for secp256k1](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)
|
||||
- [BIP341 Taproot: SegWit version 1 spending rules](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)
|
||||
- [BIP342 Validation of Taproot scripts](https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki)
|
||||
|
||||
- Popular articles;
|
||||
- [Taproot Is Coming: What It Is, and How It Will Benefit Bitcoin](https://bitcoinmagazine.com/technical/taproot-coming-what-it-and-how-it-will-benefit-bitcoin)
|
||||
- [What do Schnorr Signatures Mean for Bitcoin?](https://academy.binance.com/en/articles/what-do-schnorr-signatures-mean-for-bitcoin)
|
||||
- [The Schnorr Signature & Taproot Softfork Proposal](https://blog.bitmex.com/the-schnorr-signature-taproot-softfork-proposal/)
|
||||
|
||||
- Development history overview
|
||||
- [Taproot](https://bitcoinops.org/en/topics/taproot/)
|
||||
- [Schnorr signatures](https://bitcoinops.org/en/topics/schnorr-signatures/)
|
||||
- [Tapscript](https://bitcoinops.org/en/topics/tapscript/)
|
||||
- [Soft fork activation](https://bitcoinops.org/en/topics/soft-fork-activation/)
|
||||
|
||||
- Other
|
||||
- [Questions and answers related to taproot](https://bitcoin.stackexchange.com/questions/tagged/taproot)
|
||||
- [Taproot review](https://github.com/ajtowns/taproot-review)
|
||||
|
||||
Updated RPCs
|
||||
------------
|
||||
|
||||
- Due to [BIP 350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki)
|
||||
being implemented, behavior for all RPCs that accept addresses is changed when
|
||||
a native witness version 1 (or higher) is passed. These now require a Bech32m
|
||||
encoding instead of a Bech32 one, and Bech32m encoding will be used for such
|
||||
addresses in RPC output as well. No version 1 addresses should be created
|
||||
for mainnet until consensus rules are adopted that give them meaning
|
||||
(e.g. through [BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)).
|
||||
Once that happens, Bech32m is expected to be used for them, so this shouldn't
|
||||
affect any production systems, but may be observed on other networks where such
|
||||
addresses already have meaning (like signet).
|
||||
- `getblockheader` now returns an additional `mweb_header` field containing
|
||||
all of the MWEB header data, and an `mweb_amount` field containing the total
|
||||
number of coins pegged-in to the MWEB after applying the block.
|
||||
|
||||
0.21.1 change log
|
||||
=================
|
||||
- `getblock` now returns an additional `mweb` field containing MWEB header info,
|
||||
and all of the inputs, outputs, and kernels in the MWEB block.
|
||||
|
||||
### Consensus
|
||||
- #21377 Speedy trial support for versionbits (ajtowns)
|
||||
- #21686 Speedy trial activation parameters for Taproot (achow101)
|
||||
- Added `mwebweight`, `descendantmwebweight`, `ancestormwebweight`, and `mweb`
|
||||
fields to `getrawmempool`, `getmempoolancestors`, `getmempooldescendants`,
|
||||
and `getmempoolentry`.
|
||||
|
||||
### P2P protocol and network code
|
||||
- #20852 allow CSubNet of non-IP networks (vasild)
|
||||
- #21043 Avoid UBSan warning in ProcessMessage(…) (practicalswift)
|
||||
- Added new fields to describe MWEB transaction inputs, outputs, and kernels
|
||||
for `getrawtransaction`.
|
||||
|
||||
### Wallet
|
||||
- #21166 Introduce DeferredSignatureChecker and have SignatureExtractorClass subclass it (achow101)
|
||||
- #21083 Avoid requesting fee rates multiple times during coin selection (achow101)
|
||||
Changes to Wallet or GUI related RPCs can be found in the GUI or Wallet section below.
|
||||
|
||||
### RPC and other APIs
|
||||
- #21201 Disallow sendtoaddress and sendmany when private keys disabled (achow101)
|
||||
New settings
|
||||
------------
|
||||
|
||||
### Build system
|
||||
- #21486 link against -lsocket if required for `*ifaddrs` (fanquake)
|
||||
- #20983 Fix MSVC build after gui#176 (hebasto)
|
||||
- Added "fMWEBFeatures" option for enabling the new "Advanced MWEB Features"
|
||||
control.
|
||||
|
||||
### Tests and QA
|
||||
- #21380 Add fuzzing harness for versionbits (ajtowns)
|
||||
- #20812 fuzz: Bump FuzzedDataProvider.h (MarcoFalke)
|
||||
- #20740 fuzz: Update FuzzedDataProvider.h from upstream (LLVM) (practicalswift)
|
||||
- #21446 Update vcpkg checkout commit (sipsorcery)
|
||||
- #21397 fuzz: Bump FuzzedDataProvider.h (MarcoFalke)
|
||||
- #21081 Fix the unreachable code at `feature_taproot` (brunoerg)
|
||||
- #20562 Test that a fully signed tx given to signrawtx is unchanged (achow101)
|
||||
- #21571 Make sure non-IP peers get discouraged and disconnected (vasild, MarcoFalke)
|
||||
- #21489 fuzz: cleanups for versionbits fuzzer (ajtowns)
|
||||
Wallet Database
|
||||
---------------
|
||||
|
||||
### Miscellaneous
|
||||
- #20861 BIP 350: Implement Bech32m and use it for v1+ segwit addresses (sipa)
|
||||
- Added "mweb_coin" type which stores MWEB coins and their derived keys.
|
||||
|
||||
- Added CHDChain version 4 which includes an MWEB key index counter and
|
||||
the stealth address scan key.
|
||||
|
||||
- Added CKeyMetadata version 14 which includes the MWEB key index.
|
||||
|
||||
- Added FEATURE_MWEB = 210000 minimum database version.
|
||||
|
||||
Wallet RPC changes
|
||||
------------------
|
||||
|
||||
- Added 'listwallettransactions' which matches the transaction list display values.
|
||||
|
||||
GUI changes
|
||||
-----------
|
||||
|
||||
- Added an "Advanced MWEB Features" control for testing. It’s only available
|
||||
when the "-debug" argument is supplied, and the option is turned on in the
|
||||
settings dialog.
|
||||
|
||||
### Documentation
|
||||
- #21384 add signet to bitcoin.conf documentation (jonatack)
|
||||
- #21342 Remove outdated comment (hebasto)
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Aaron Clauson
|
||||
- Andrew Chow
|
||||
- Anthony Towns
|
||||
- Bruno Garcia
|
||||
- Fabian Jahr
|
||||
- fanquake
|
||||
- Hennadii Stepanov
|
||||
- Jon Atack
|
||||
- Luke Dashjr
|
||||
- MarcoFalke
|
||||
- Pieter Wuille
|
||||
- practicalswift
|
||||
- randymcmillan
|
||||
- Sjors Provoost
|
||||
- Vasil Dimov
|
||||
- W. J. van der Laan
|
||||
|
||||
As well as to everyone that helped with translations on
|
||||
[Transifex](https://www.transifex.com/bitcoin/bitcoin/).
|
||||
- [The Bitcoin Core Developers]
|
||||
- DavidBurkett
|
||||
- hectorchu
|
||||
- losh11
|
||||
@ -8,11 +8,12 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <mw/consensus/Params.h>
|
||||
|
||||
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
|
||||
/** MWEB: The maximum size of an MWEB block is just over 11 MB, plus 4 MB for a full segwit block. Add a ~1 MB buffer just to be safe. */
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE_WITH_MWEB = 16'000'000;
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE_WITH_MWEB = MAX_BLOCK_SERIALIZED_SIZE + mw::MAX_BLOCK_BYTES;
|
||||
/** The maximum allowed weight for a block, see BIP 141 (network rule) */
|
||||
static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
|
||||
/** The maximum allowed number of signature check operations in a block (network rule) */
|
||||
|
||||
@ -195,7 +195,7 @@ public:
|
||||
|
||||
auto output_type = OutputType::BECH32;
|
||||
auto reserve_dest = std::make_shared<ReserveDestination>(m_wallet.get(), output_type);
|
||||
if (reserve_dest->GetReservedDestination(dest, true)) {
|
||||
if (reserve_dest->GetReservedDestination(dest, false)) {
|
||||
return reserve_dest;
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,23 @@ MW_NAMESPACE
|
||||
/// Consensus parameters
|
||||
/// Any change to these will cause a hardfork!
|
||||
/// </summary>
|
||||
static constexpr std::size_t MAX_BLOCK_WEIGHT = 21'000;
|
||||
static constexpr size_t BYTES_PER_WEIGHT = 42;
|
||||
|
||||
static constexpr size_t BASE_KERNEL_WEIGHT = 2;
|
||||
static constexpr size_t STEALTH_EXCESS_WEIGHT = 1;
|
||||
static constexpr size_t KERNEL_WITH_STEALTH_WEIGHT = BASE_KERNEL_WEIGHT + STEALTH_EXCESS_WEIGHT;
|
||||
|
||||
static constexpr size_t BASE_OUTPUT_WEIGHT = 17;
|
||||
static constexpr size_t STANDARD_OUTPUT_FIELDS_WEIGHT = 1;
|
||||
static constexpr size_t STANDARD_OUTPUT_WEIGHT = BASE_OUTPUT_WEIGHT + STANDARD_OUTPUT_FIELDS_WEIGHT;
|
||||
|
||||
static constexpr size_t MAX_NUM_INPUTS = 50'000;
|
||||
static constexpr size_t INPUT_BYTES = 196;
|
||||
|
||||
static constexpr std::size_t MAX_BLOCK_WEIGHT = 200'000; // Nodes won't accept blocks over this weight
|
||||
static constexpr std::size_t MAX_MINE_WEIGHT = 20'000; // Miners won't create blocks over this weight. Non-consensus
|
||||
static constexpr size_t MAX_BLOCK_BYTES = 180 + (3 * 5) + // 180 bytes per header and 5 bytes each for input, output, and kernel vec size
|
||||
(MAX_NUM_INPUTS * INPUT_BYTES) + // 50k inputs at 196 bytes each (ignoring extradata)
|
||||
(MAX_BLOCK_WEIGHT * 60); // Ignoring inputs, no tx component is ever more than 60 bytes per unit of weight
|
||||
|
||||
END_NAMESPACE
|
||||
@ -8,22 +8,6 @@
|
||||
class Weight
|
||||
{
|
||||
public:
|
||||
static constexpr size_t BYTES_PER_WEIGHT = 42;
|
||||
|
||||
static constexpr size_t BASE_KERNEL_WEIGHT = 2;
|
||||
static constexpr size_t STEALTH_EXCESS_WEIGHT = 1;
|
||||
static constexpr size_t KERNEL_WITH_STEALTH_WEIGHT = BASE_KERNEL_WEIGHT + STEALTH_EXCESS_WEIGHT;
|
||||
|
||||
static constexpr size_t BASE_OUTPUT_WEIGHT = 17;
|
||||
static constexpr size_t STANDARD_OUTPUT_FIELDS_WEIGHT = 1;
|
||||
static constexpr size_t STANDARD_OUTPUT_WEIGHT = BASE_OUTPUT_WEIGHT + STANDARD_OUTPUT_FIELDS_WEIGHT;
|
||||
|
||||
static constexpr size_t MAX_NUM_INPUTS = 50'000;
|
||||
static constexpr size_t INPUT_BYTES = 196;
|
||||
static constexpr size_t MAX_MWEB_BYTES = 180 + (3 * 5) + // 180 bytes per header and 5 bytes each for input, output, and kernel vec size
|
||||
(MAX_NUM_INPUTS * INPUT_BYTES) + // 50k inputs at 196 bytes each (ignoring extradata)
|
||||
(mw::MAX_BLOCK_WEIGHT * 60); // Ignoring inputs, no tx component is ever more than 60 bytes per unit of weight
|
||||
|
||||
static size_t Calculate(const TxBody& tx_body)
|
||||
{
|
||||
size_t input_weight = std::accumulate(
|
||||
@ -57,7 +41,7 @@ public:
|
||||
|
||||
static bool ExceedsMaximum(const TxBody& tx_body)
|
||||
{
|
||||
return tx_body.GetInputs().size() > MAX_NUM_INPUTS || Calculate(tx_body) > mw::MAX_BLOCK_WEIGHT;
|
||||
return tx_body.GetInputs().size() > mw::MAX_NUM_INPUTS || Calculate(tx_body) > mw::MAX_BLOCK_WEIGHT;
|
||||
}
|
||||
|
||||
static size_t CalcInputWeight(const std::vector<uint8_t>& extra_data)
|
||||
@ -71,7 +55,7 @@ public:
|
||||
const std::vector<uint8_t>& extra_data = {})
|
||||
{
|
||||
// Kernels with a stealth excess cost extra.
|
||||
size_t base_weight = has_stealth_excess ? KERNEL_WITH_STEALTH_WEIGHT : BASE_KERNEL_WEIGHT;
|
||||
size_t base_weight = has_stealth_excess ? mw::KERNEL_WITH_STEALTH_WEIGHT : mw::BASE_KERNEL_WEIGHT;
|
||||
|
||||
return base_weight + ExtraBytesToWeight(pegout_script.size()) + ExtraBytesToWeight(extra_data.size());
|
||||
}
|
||||
@ -82,7 +66,7 @@ public:
|
||||
const std::vector<uint8_t>& extra_data = {})
|
||||
{
|
||||
// Kernels with a stealth excess cost extra.
|
||||
size_t base_weight = has_stealth_excess ? KERNEL_WITH_STEALTH_WEIGHT : BASE_KERNEL_WEIGHT;
|
||||
size_t base_weight = has_stealth_excess ? mw::KERNEL_WITH_STEALTH_WEIGHT : mw::BASE_KERNEL_WEIGHT;
|
||||
|
||||
size_t pegout_weight = std::accumulate(
|
||||
pegouts.begin(), pegouts.end(), (size_t)0,
|
||||
@ -97,13 +81,13 @@ public:
|
||||
// Outputs have a weight of 'BASE_OUTPUT_WEIGHT' plus 2 weight for standard fields, and 1 weight for every 'BYTES_PER_WEIGHT' extra_data bytes
|
||||
static size_t CalcOutputWeight(const bool standard_fields, const std::vector<uint8_t>& extra_data = {})
|
||||
{
|
||||
size_t base_weight = standard_fields ? STANDARD_OUTPUT_WEIGHT : BASE_OUTPUT_WEIGHT;
|
||||
size_t base_weight = standard_fields ? mw::STANDARD_OUTPUT_WEIGHT : mw::BASE_OUTPUT_WEIGHT;
|
||||
return base_weight + ExtraBytesToWeight(extra_data.size());
|
||||
}
|
||||
|
||||
private:
|
||||
static size_t ExtraBytesToWeight(const size_t extra_bytes)
|
||||
{
|
||||
return (extra_bytes + (BYTES_PER_WEIGHT - 1)) / BYTES_PER_WEIGHT;
|
||||
return (extra_bytes + (mw::BYTES_PER_WEIGHT - 1)) / mw::BYTES_PER_WEIGHT;
|
||||
}
|
||||
};
|
||||
@ -52,7 +52,7 @@ mw::Transaction::CPtr TxBuilder::BuildTx(
|
||||
.Sub(kernel_offset)
|
||||
.Total();
|
||||
|
||||
// MW: TODO - This is only needed for peg-ins or when no change
|
||||
// MW: FUTURE - This is only needed for peg-ins or when no change
|
||||
SecretKey stealth_blind = SecretKey::Random();
|
||||
|
||||
// Create the kernel
|
||||
|
||||
@ -60,50 +60,50 @@ static std::vector<Kernel> CreateKernels(const size_t plain_kernels, const size_
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ExceedsMaximum)
|
||||
{
|
||||
BOOST_CHECK(Weight::MAX_NUM_INPUTS == 50'000);
|
||||
BOOST_CHECK(Weight::BASE_KERNEL_WEIGHT == 2);
|
||||
BOOST_CHECK(Weight::KERNEL_WITH_STEALTH_WEIGHT == 3);
|
||||
BOOST_CHECK(Weight::BASE_OUTPUT_WEIGHT == 17);
|
||||
BOOST_CHECK(Weight::STANDARD_OUTPUT_WEIGHT == 18);
|
||||
BOOST_CHECK(Weight::BYTES_PER_WEIGHT == 42);
|
||||
BOOST_CHECK(mw::MAX_BLOCK_WEIGHT == 21'000);
|
||||
BOOST_CHECK(mw::MAX_NUM_INPUTS == 50'000);
|
||||
BOOST_CHECK(mw::BASE_KERNEL_WEIGHT == 2);
|
||||
BOOST_CHECK(mw::KERNEL_WITH_STEALTH_WEIGHT == 3);
|
||||
BOOST_CHECK(mw::BASE_OUTPUT_WEIGHT == 17);
|
||||
BOOST_CHECK(mw::STANDARD_OUTPUT_WEIGHT == 18);
|
||||
BOOST_CHECK(mw::BYTES_PER_WEIGHT == 42);
|
||||
BOOST_CHECK(mw::MAX_BLOCK_WEIGHT == 200'000);
|
||||
|
||||
|
||||
// 1,000 outputs + 1,000 stealth kernels = 21,000 Weight
|
||||
// 10,000 outputs + 10,000 plain kernels = 200,000 Weight
|
||||
{
|
||||
std::vector<Input> inputs(Weight::MAX_NUM_INPUTS);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(1000);
|
||||
std::vector<Kernel> kernels = CreateKernels(0, 1000);
|
||||
std::vector<Input> inputs(mw::MAX_NUM_INPUTS);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(10'000);
|
||||
std::vector<Kernel> kernels = CreateKernels(10'000, 0);
|
||||
|
||||
TxBody tx(inputs, outputs, kernels);
|
||||
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 21'000);
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 200'000);
|
||||
BOOST_CHECK(!Weight::ExceedsMaximum(tx));
|
||||
}
|
||||
|
||||
// 50,000 inputs max, so 50,001 should exceed maximum
|
||||
{
|
||||
std::vector<Input> inputs(Weight::MAX_NUM_INPUTS + 1);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(1000);
|
||||
std::vector<Kernel> kernels = CreateKernels(0, 1000);
|
||||
std::vector<Input> inputs(mw::MAX_NUM_INPUTS + 1);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(10'000);
|
||||
std::vector<Kernel> kernels = CreateKernels(10'000, 0);
|
||||
BOOST_CHECK(inputs.size() == 50'001);
|
||||
|
||||
TxBody tx(inputs, outputs, kernels);
|
||||
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 21'000);
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 200'000);
|
||||
BOOST_CHECK(Weight::ExceedsMaximum(tx));
|
||||
}
|
||||
|
||||
// 1,000 outputs + 1,000 stealth kernels and 1 plain kernel = 21,002 Weight
|
||||
// 10,000 outputs + 10,000 plain kernels and 1 stealth kernel = 200,003 Weight
|
||||
{
|
||||
std::vector<Input> inputs(Weight::MAX_NUM_INPUTS);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(1000);
|
||||
std::vector<Kernel> kernels = CreateKernels(1, 1000);
|
||||
std::vector<Input> inputs(mw::MAX_NUM_INPUTS);
|
||||
std::vector<Output> outputs = CreateStandardOutputs(10'000);
|
||||
std::vector<Kernel> kernels = CreateKernels(10'000, 1);
|
||||
BOOST_CHECK(inputs.size() == 50'000);
|
||||
|
||||
TxBody tx(inputs, outputs, kernels);
|
||||
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 21'002);
|
||||
BOOST_CHECK(Weight::Calculate(tx) == 200'003);
|
||||
BOOST_CHECK(Weight::ExceedsMaximum(tx));
|
||||
}
|
||||
|
||||
|
||||
@ -220,7 +220,7 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
|
||||
return false;
|
||||
if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST)
|
||||
return false;
|
||||
if (nBlockMWEBWeight + packageMWEBWeight >= mw::MAX_BLOCK_WEIGHT)
|
||||
if (nBlockMWEBWeight + packageMWEBWeight >= mw::MAX_MINE_WEIGHT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -68,11 +68,11 @@ uint64_t MWEB::CalcMWEBWeight(const MWEB::TxType& mweb_type, const bool change_o
|
||||
uint64_t mweb_weight = 0;
|
||||
|
||||
if (mweb_type == MWEB::TxType::PEGIN || mweb_type == MWEB::TxType::MWEB_TO_MWEB) {
|
||||
mweb_weight += Weight::STANDARD_OUTPUT_WEIGHT; // MW: FUTURE - Look at actual recipients list, but for now we only support 1 MWEB recipient.
|
||||
mweb_weight += mw::STANDARD_OUTPUT_WEIGHT; // MW: FUTURE - Look at actual recipients list, but for now we only support 1 MWEB recipient.
|
||||
}
|
||||
|
||||
if (change_on_mweb) {
|
||||
mweb_weight += Weight::STANDARD_OUTPUT_WEIGHT;
|
||||
mweb_weight += mw::STANDARD_OUTPUT_WEIGHT;
|
||||
}
|
||||
|
||||
if (mweb_type != MWEB::TxType::LTC_TO_LTC) {
|
||||
@ -134,8 +134,8 @@ void Transact::AddMWEBTx(InProcessTx& new_tx)
|
||||
[](CAmount amt, const CInputCoin& input) { return amt + (input.IsMWEB() ? 0 : input.GetAmount()); }
|
||||
);
|
||||
if (ltc_input_amount > 0) {
|
||||
assert(new_tx.total_fee < ltc_input_amount);
|
||||
const CAmount ltc_fee = new_tx.total_fee - new_tx.mweb_fee;
|
||||
assert(ltc_fee <= ltc_input_amount);
|
||||
pegin_amount = (ltc_input_amount - (ltc_fee + ltc_change));
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
#include <tinyformat.h>
|
||||
|
||||
static const CAmount BASE_MWEB_FEE = 1'000;
|
||||
static const CAmount BASE_MWEB_FEE = 100;
|
||||
|
||||
CFeeRate::CFeeRate(const CAmount& nFeePaid, size_t nBytes_, uint64_t mweb_weight)
|
||||
: m_nFeePaid(nFeePaid), m_nBytes(nBytes_), m_weight(mweb_weight)
|
||||
|
||||
@ -49,7 +49,7 @@ static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
|
||||
* standard and should be done with care and ideally rarely. It makes sense to
|
||||
* only increase the dust limit after prior releases were already not creating
|
||||
* outputs below the new threshold */
|
||||
static const unsigned int DUST_RELAY_TX_FEE = 3000;
|
||||
static const unsigned int DUST_RELAY_TX_FEE = 30'000;
|
||||
/**
|
||||
* Standard script verification flags that standard transactions will comply
|
||||
* with. However scripts violating these flags may still be present in valid
|
||||
|
||||
@ -136,6 +136,10 @@ OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet) :
|
||||
ui->minimizeToTray->setEnabled(false);
|
||||
}
|
||||
|
||||
if (!gArgs.IsArgSet("-debug")) {
|
||||
ui->mwebFeatures->setVisible(false);
|
||||
}
|
||||
|
||||
GUIUtil::handleCloseWindowShortcut(this);
|
||||
}
|
||||
|
||||
|
||||
@ -82,7 +82,7 @@ void OptionsModel::Init(bool resetSettings)
|
||||
|
||||
if (!settings.contains("fMWEBFeatures"))
|
||||
settings.setValue("fMWEBFeatures", false);
|
||||
fMWEBFeatures = settings.value("fMWEBFeatures", false).toBool();
|
||||
fMWEBFeatures = settings.value("fMWEBFeatures", false).toBool() && gArgs.IsArgSet("-debug");
|
||||
|
||||
// These are shared with the core or have a command-line parameter
|
||||
// and we want command-line parameters to overwrite the GUI settings.
|
||||
|
||||
@ -267,7 +267,6 @@ QString TransactionDesc::toHTML_Amounts(interfaces::Wallet& wallet, const interf
|
||||
strHTML += "<br>";
|
||||
}
|
||||
}
|
||||
// MW: TODO - Pegouts?
|
||||
|
||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>";
|
||||
if (toSelf)
|
||||
@ -304,6 +303,8 @@ QString TransactionDesc::toHTML_Amounts(interfaces::Wallet& wallet, const interf
|
||||
if (fAllToMe) {
|
||||
// Payment to self
|
||||
CAmount nValue = wtx.credit - wtx.change;
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wtx.credit) + "<br>";
|
||||
strHTML += "<b>" + tr("Change") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wtx.change) + "<br>";
|
||||
strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>";
|
||||
strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
|
||||
}
|
||||
|
||||
@ -651,7 +651,7 @@ public:
|
||||
};
|
||||
|
||||
/** A parsed mweb descriptor. */
|
||||
class MWEBDescriptor final : public DescriptorImpl // MW: TODO - Finish this
|
||||
class MWEBDescriptor final : public DescriptorImpl
|
||||
{
|
||||
SecretKey m_scanSecret;
|
||||
|
||||
@ -894,7 +894,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t key_exp_index, Span<const c
|
||||
if (Func("mweb", expr)) {
|
||||
auto pubkey = ParsePubkey(key_exp_index, expr, false, out, error);
|
||||
if (!pubkey) return nullptr;
|
||||
return MakeUnique<MWEBDescriptor>(std::move(pubkey), SecretKey::Null()); // MW: TODO - Lookup scan_secret
|
||||
return MakeUnique<MWEBDescriptor>(std::move(pubkey), SecretKey::Null());
|
||||
}
|
||||
if (ctx == ParseScriptContext::TOP && Func("combo", expr)) {
|
||||
auto pubkey = ParsePubkey(key_exp_index, expr, true, out, error);
|
||||
@ -1135,7 +1135,6 @@ std::string GetDescriptorChecksum(const std::string& descriptor)
|
||||
std::unique_ptr<Descriptor> InferDescriptor(const DestinationAddr& script, const SigningProvider& provider)
|
||||
{
|
||||
if (script.IsMWEB()) {
|
||||
// MW: TODO - Lookup scan_secret
|
||||
CPubKey pubkey(script.GetMWEBAddress().GetSpendPubKey().vec());
|
||||
return MakeUnique<MWEBDescriptor>(InferPubkey(pubkey, ParseScriptContext::TOP, provider), SecretKey::Null());
|
||||
}
|
||||
|
||||
@ -674,7 +674,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
|
||||
// Check dust with default relay fee:
|
||||
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000;
|
||||
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
||||
BOOST_CHECK_EQUAL(nDustThreshold, 5460);
|
||||
// dust:
|
||||
t.vout[0].nValue = nDustThreshold - 1;
|
||||
reason.clear();
|
||||
|
||||
@ -1728,6 +1728,8 @@ void LegacyScriptPubKeyMan::LoadMWEBKeychain()
|
||||
return;
|
||||
}
|
||||
|
||||
m_storage.SetMinVersion(FEATURE_MWEB);
|
||||
|
||||
// try to get the seed
|
||||
CKey seed;
|
||||
if (!GetKey(m_hd_chain.seed_id, seed)) {
|
||||
|
||||
@ -35,6 +35,10 @@ AssembledTx TxAssembler::CreateTransaction(
|
||||
{
|
||||
VerifyRecipients(recipients);
|
||||
|
||||
if (boost::get<StealthAddress>(&coin_control.destChange)) {
|
||||
throw CreateTxError(_("Custom MWEB change addresses not yet supported"));
|
||||
}
|
||||
|
||||
InProcessTx new_tx;
|
||||
new_tx.recipients = recipients;
|
||||
new_tx.recipient_amount = std::accumulate(
|
||||
@ -398,8 +402,8 @@ bool TxAssembler::AttemptCoinSelection(InProcessTx& new_tx, const CAmount& nTarg
|
||||
// First try to construct an MWEB-to-MWEB transaction
|
||||
CoinSelectionParams mweb_to_mweb = new_tx.coin_selection_params;
|
||||
mweb_to_mweb.input_preference = InputPreference::MWEB_ONLY;
|
||||
mweb_to_mweb.mweb_change_output_weight = Weight::STANDARD_OUTPUT_WEIGHT;
|
||||
mweb_to_mweb.mweb_nochange_weight = Weight::KERNEL_WITH_STEALTH_WEIGHT + (new_tx.recipients.size() * Weight::STANDARD_OUTPUT_WEIGHT);
|
||||
mweb_to_mweb.mweb_change_output_weight = mw::STANDARD_OUTPUT_WEIGHT;
|
||||
mweb_to_mweb.mweb_nochange_weight = mw::KERNEL_WITH_STEALTH_WEIGHT + (new_tx.recipients.size() * mw::STANDARD_OUTPUT_WEIGHT);
|
||||
mweb_to_mweb.change_output_size = 0;
|
||||
mweb_to_mweb.change_spend_size = 0;
|
||||
mweb_to_mweb.tx_noinputs_size = 0;
|
||||
@ -412,8 +416,8 @@ bool TxAssembler::AttemptCoinSelection(InProcessTx& new_tx, const CAmount& nTarg
|
||||
const bool change_on_mweb = MWEB::IsChangeOnMWEB(m_wallet, MWEB::TxType::PEGIN, new_tx.recipients, new_tx.coin_control.destChange);
|
||||
CoinSelectionParams params_pegin = new_tx.coin_selection_params;
|
||||
params_pegin.input_preference = InputPreference::ANY;
|
||||
params_pegin.mweb_change_output_weight = change_on_mweb ? Weight::STANDARD_OUTPUT_WEIGHT : 0;
|
||||
params_pegin.mweb_nochange_weight = Weight::KERNEL_WITH_STEALTH_WEIGHT + (new_tx.recipients.size() * Weight::STANDARD_OUTPUT_WEIGHT);
|
||||
params_pegin.mweb_change_output_weight = change_on_mweb ? mw::STANDARD_OUTPUT_WEIGHT : 0;
|
||||
params_pegin.mweb_nochange_weight = mw::KERNEL_WITH_STEALTH_WEIGHT + (new_tx.recipients.size() * mw::STANDARD_OUTPUT_WEIGHT);
|
||||
params_pegin.change_output_size = change_on_mweb ? 0 : new_tx.coin_selection_params.change_output_size;
|
||||
params_pegin.change_spend_size = change_on_mweb ? 0 : new_tx.coin_selection_params.change_spend_size;
|
||||
|
||||
@ -439,7 +443,7 @@ bool TxAssembler::AttemptCoinSelection(InProcessTx& new_tx, const CAmount& nTarg
|
||||
// If LTC-to-LTC fails, create a peg-out transaction
|
||||
CoinSelectionParams params_pegout = new_tx.coin_selection_params;
|
||||
params_pegout.input_preference = InputPreference::ANY;
|
||||
params_pegout.mweb_change_output_weight = Weight::STANDARD_OUTPUT_WEIGHT;
|
||||
params_pegout.mweb_change_output_weight = mw::STANDARD_OUTPUT_WEIGHT;
|
||||
params_pegout.mweb_nochange_weight = Weight::CalcKernelWeight(true, new_tx.recipients.front().GetScript());
|
||||
params_pegout.change_output_size = 0;
|
||||
params_pegout.change_spend_size = 0;
|
||||
|
||||
@ -2236,7 +2236,7 @@ void CWallet::ReacceptWalletTransactions()
|
||||
|
||||
int nDepth = wtx.GetDepthInMainChain();
|
||||
|
||||
if (!wtx.IsCoinBase() && (nDepth == 0 && !wtx.isAbandoned())) {
|
||||
if (!wtx.IsCoinBase() && !wtx.IsHogEx() && (nDepth == 0 && !wtx.isAbandoned())) {
|
||||
mapSorted.insert(std::make_pair(wtx.nOrderPos, &wtx));
|
||||
}
|
||||
}
|
||||
@ -4631,7 +4631,7 @@ const CWalletTx* CWallet::FindWalletTxByKernelId(const mw::Hash& kernel_id) cons
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
auto kernel_iter = mapKernelsMWEB.find(kernel_id);
|
||||
if (kernel_iter != mapOutputsMWEB.end()) {
|
||||
if (kernel_iter != mapKernelsMWEB.end()) {
|
||||
auto tx_iter = mapWallet.find(kernel_iter->second);
|
||||
if (tx_iter != mapWallet.end()) {
|
||||
return &tx_iter->second;
|
||||
|
||||
@ -63,11 +63,11 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
|
||||
//! -paytxfee default
|
||||
constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
|
||||
//! -fallbackfee default
|
||||
static const CAmount DEFAULT_FALLBACK_FEE = 0;
|
||||
static const CAmount DEFAULT_FALLBACK_FEE = 200'000;
|
||||
//! -discardfee default
|
||||
static const CAmount DEFAULT_DISCARD_FEE = 10000;
|
||||
static const CAmount DEFAULT_DISCARD_FEE = 10'000;
|
||||
//! -mintxfee default
|
||||
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
|
||||
static const CAmount DEFAULT_TRANSACTION_MINFEE = 10'000;
|
||||
/**
|
||||
* maximum fee increase allowed to do partial spend avoidance, even for nodes with this feature disabled by default
|
||||
*
|
||||
|
||||
@ -26,7 +26,9 @@ enum WalletFeature
|
||||
|
||||
FEATURE_PRE_SPLIT_KEYPOOL = 169900, // Upgraded to HD SPLIT and can have a pre-split keypool
|
||||
|
||||
FEATURE_LATEST = FEATURE_PRE_SPLIT_KEYPOOL
|
||||
FEATURE_MWEB = 210000, // Wallet with MWEB keys and coins
|
||||
|
||||
FEATURE_LATEST = FEATURE_MWEB
|
||||
};
|
||||
|
||||
bool IsFeatureSupported(int wallet_version, int feature_version);
|
||||
|
||||
@ -36,7 +36,7 @@ class MaxUploadTest(BitcoinTestFramework):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [[
|
||||
"-maxuploadtarget=3200",
|
||||
"-maxuploadtarget=6400",
|
||||
"-acceptnonstdtxn=1",
|
||||
"-peertimeout=9999", # bump because mocktime might cause a disconnect otherwise
|
||||
]]
|
||||
@ -90,8 +90,8 @@ class MaxUploadTest(BitcoinTestFramework):
|
||||
getdata_request = msg_getdata()
|
||||
getdata_request.inv.append(CInv(MSG_BLOCK, big_old_block))
|
||||
|
||||
max_bytes_per_day = 3200*1024*1024
|
||||
daily_buffer = 144 * 4000000 * 4 # MWEB uses a buffer 4x the max serialized segwit block
|
||||
max_bytes_per_day = 6400*1024*1024
|
||||
daily_buffer = 144 * 25800195 # MWEB uses a buffer 4x the max serialized segwit block
|
||||
max_bytes_available = max_bytes_per_day - daily_buffer
|
||||
success_count = max_bytes_available // old_block_size
|
||||
|
||||
|
||||
@ -1199,7 +1199,7 @@ class TaprootTest(BitcoinTestFramework):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
# Node 0 has Taproot inactive, Node 1 active.
|
||||
self.extra_args = [["-par=1", "-vbparams=taproot:1:1"], ["-par=1"]]
|
||||
self.extra_args = [["-par=1", "-dustrelayfee=0.00003", "-mintxfee=0.00001", "-vbparams=taproot:1:1"], ["-par=1", "-dustrelayfee=0.00003", "-mintxfee=0.00001"]]
|
||||
|
||||
def block_submit(self, node, txs, msg, err_msg, cb_pubkey=None, fees=0, sigops_weight=0, witness=False, accept=False):
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ class MempoolLimitTest(BitcoinTestFramework):
|
||||
self.extra_args = [[
|
||||
"-acceptnonstdtxn=1",
|
||||
"-maxmempool=5",
|
||||
"-mintxfee=0.00001",
|
||||
"-spendzeroconfchange=0",
|
||||
]]
|
||||
self.supports_cli = False
|
||||
|
||||
@ -19,6 +19,7 @@ MAX_INITIAL_BROADCAST_DELAY = 15 * 60 # 15 minutes in seconds
|
||||
class MempoolUnbroadcastTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.extra_args = [["-mintxfee=0.00001"]] * self.num_nodes
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
@ -98,8 +98,8 @@ class MWEBBasicTest(BitcoinTestFramework):
|
||||
assert_equal(len(utxos), 1)
|
||||
assert sum(x['amount'] for x in utxos) < 1
|
||||
|
||||
self.log.info("Mine 5 blocks. Peg-out maturity is 6 blocks, so coins shouldn't be available yet.")
|
||||
self.nodes[1].generate(5)
|
||||
self.log.info("Mine 4 more blocks. Peg-out maturity is 6 blocks, so coins shouldn't be available yet.")
|
||||
self.nodes[1].generate(4)
|
||||
self.sync_all()
|
||||
|
||||
self.log.info("Check for UTXO on node 1")
|
||||
|
||||
@ -81,7 +81,7 @@ class MWEBWalletBasicTest(BitcoinTestFramework):
|
||||
assert n1_tx2['fee'] < 0 and n1_tx2['fee'] > -0.1
|
||||
|
||||
self.log.info("Verify node2's wallet receives the first pegout transaction")
|
||||
n2_tx2 = node2.gettransaction(txid=tx2_id)
|
||||
n2_tx2 = node2.listwallettransactions(txid=tx2_id)[0]
|
||||
assert_equal(n2_tx2['amount'], 15)
|
||||
assert_equal(n2_tx2['confirmations'], 0)
|
||||
assert tx2_id in node1.getrawmempool()
|
||||
|
||||
@ -31,7 +31,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
self.setup_clean_chain = True
|
||||
# This test isn't testing tx relay. Set whitelist on the peers for
|
||||
# instant tx relay.
|
||||
self.extra_args = [['-whitelist=noban@127.0.0.1', '-vbparams=mweb:-2:0']] * self.num_nodes
|
||||
self.extra_args = [['-whitelist=noban@127.0.0.1', "-mintxfee=0.00001", '-vbparams=mweb:-2:0']] * self.num_nodes
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
@ -231,7 +231,7 @@ class WalletTest(BitcoinTestFramework):
|
||||
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
|
||||
|
||||
self.log.info("Test sendmany with fee_rate param (explicit fee rate in sat/vB)")
|
||||
fee_rate_sat_vb = 2
|
||||
fee_rate_sat_vb = 20
|
||||
fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
|
||||
explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000
|
||||
|
||||
@ -260,12 +260,12 @@ class WalletTest(BitcoinTestFramework):
|
||||
assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
|
||||
|
||||
# Test setting explicit fee rate just below the minimum.
|
||||
self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
|
||||
self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0.99999999)
|
||||
self.log.info("Test sendmany raises 'fee rate too low' if fee_rate of 9.99999999 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (9.999 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)",
|
||||
self.nodes[2].sendmany, amounts={address: 10}, fee_rate=9.99999999)
|
||||
|
||||
self.log.info("Test sendmany raises if fee_rate of 0 or -1 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)",
|
||||
self.nodes[2].sendmany, amounts={address: 10}, fee_rate=0)
|
||||
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendmany, amounts={address: 10}, fee_rate=-1)
|
||||
|
||||
@ -415,7 +415,7 @@ class WalletTest(BitcoinTestFramework):
|
||||
assert prebalance > 2
|
||||
address = self.nodes[1].getnewaddress()
|
||||
amount = 3
|
||||
fee_rate_sat_vb = 2
|
||||
fee_rate_sat_vb = 20
|
||||
fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
|
||||
# Test passing fee_rate as an integer
|
||||
txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=fee_rate_sat_vb)
|
||||
@ -428,7 +428,7 @@ class WalletTest(BitcoinTestFramework):
|
||||
|
||||
prebalance = self.nodes[2].getbalance()
|
||||
amount = Decimal("0.001")
|
||||
fee_rate_sat_vb = 1.23
|
||||
fee_rate_sat_vb = 10.23
|
||||
fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
|
||||
# Test passing fee_rate as a string
|
||||
txid = self.nodes[2].sendtoaddress(address=address, amount=amount, fee_rate=str(fee_rate_sat_vb))
|
||||
@ -443,12 +443,12 @@ class WalletTest(BitcoinTestFramework):
|
||||
assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
|
||||
|
||||
# Test setting explicit fee rate just below the minimum.
|
||||
self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 0.99999999 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
|
||||
self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=0.99999999)
|
||||
self.log.info("Test sendtoaddress raises 'fee rate too low' if fee_rate of 9.99999999 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (9.999 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)",
|
||||
self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=9.99999999)
|
||||
|
||||
self.log.info("Test sendtoaddress raises if fee_rate of 0 or -1 is passed")
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)",
|
||||
assert_raises_rpc_error(-6, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)",
|
||||
self.nodes[2].sendtoaddress, address=address, amount=10, fee_rate=0)
|
||||
assert_raises_rpc_error(-3, OUT_OF_RANGE, self.nodes[2].sendtoaddress, address=address, amount=1.0, fee_rate=-1)
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ class CreateTxWalletTest(BitcoinTestFramework):
|
||||
|
||||
def test_tx_size_too_large(self):
|
||||
# More than 10kB of outputs, so that we hit -maxtxfee with a high feerate
|
||||
outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.000025 for _ in range(400)}
|
||||
outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.00025 for _ in range(400)}
|
||||
raw_tx = self.nodes[0].createrawtransaction(inputs=[], outputs=outputs)
|
||||
|
||||
for fee_setting in ['-minrelaytxfee=0.01', '-mintxfee=0.01', '-paytxfee=0.01']:
|
||||
|
||||
@ -163,7 +163,7 @@ class KeyPoolTest(BitcoinTestFramework):
|
||||
assert_equal(res[0]['success'], True)
|
||||
w1.walletpassphrase('test', 100)
|
||||
|
||||
res = w1.sendtoaddress(address=address, amount=0.00010000)
|
||||
res = w1.sendtoaddress(address=address, amount=0.00020000)
|
||||
nodes[0].generate(1)
|
||||
destination = addr.pop()
|
||||
|
||||
@ -172,24 +172,24 @@ class KeyPoolTest(BitcoinTestFramework):
|
||||
assert_raises_rpc_error(-4, "Transaction needs a change address, but we can't generate it. Please call keypoolrefill first.", w2.walletcreatefundedpsbt, inputs=[], outputs=[{addr.pop(): 0.00005000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
|
||||
|
||||
# creating a 10,000 sat transaction without change, with a manual input, should still be possible
|
||||
res = w2.walletcreatefundedpsbt(inputs=w2.listunspent(), outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
|
||||
res = w2.walletcreatefundedpsbt(inputs=w2.listunspent(), outputs=[{destination: 0.00020000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
|
||||
assert_equal("psbt" in res, True)
|
||||
|
||||
# creating a 10,000 sat transaction without change should still be possible
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00020000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010})
|
||||
assert_equal("psbt" in res, True)
|
||||
# should work without subtractFeeFromOutputs if the exact fee is subtracted from the amount
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00008900}], options={"feeRate": 0.00010})
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00018900}], options={"feeRate": 0.00010})
|
||||
assert_equal("psbt" in res, True)
|
||||
|
||||
# dust change should be removed
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00008800}], options={"feeRate": 0.00010})
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00018800}], options={"feeRate": 0.00010})
|
||||
assert_equal("psbt" in res, True)
|
||||
|
||||
# create a transaction without change at the maximum fee rate, such that the output is still spendable:
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.0008824})
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00020000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00155099})
|
||||
assert_equal("psbt" in res, True)
|
||||
assert_equal(res["fee"], Decimal("0.00009706"))
|
||||
assert_equal(res["fee"], Decimal("0.00017060"))
|
||||
|
||||
# creating a 10,000 sat transaction with a manual change address should be possible
|
||||
res = w2.walletcreatefundedpsbt(inputs=[], outputs=[{destination: 0.00010000}], options={"subtractFeeFromOutputs": [0], "feeRate": 0.00010, "changeAddress": addr.pop()})
|
||||
|
||||
@ -256,29 +256,29 @@ class WalletSendTest(BitcoinTestFramework):
|
||||
assert res["complete"]
|
||||
|
||||
self.log.info("Test setting explicit fee rate")
|
||||
res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate="1", add_to_wallet=False)
|
||||
res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate="1", add_to_wallet=False)
|
||||
res1 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate="10", add_to_wallet=False)
|
||||
res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate="10", add_to_wallet=False)
|
||||
assert_equal(self.nodes[1].decodepsbt(res1["psbt"])["fee"], self.nodes[1].decodepsbt(res2["psbt"])["fee"])
|
||||
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=7, add_to_wallet=False)
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=10, add_to_wallet=False)
|
||||
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00007"))
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.0001"))
|
||||
|
||||
# "unset" and None are treated the same for estimate_mode
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=2, estimate_mode="unset", add_to_wallet=False)
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=20, estimate_mode="unset", add_to_wallet=False)
|
||||
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00002"))
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.0002"))
|
||||
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=4.531, add_to_wallet=False)
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=14.531, add_to_wallet=False)
|
||||
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00004531"))
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00014531"))
|
||||
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=3, add_to_wallet=False)
|
||||
res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=30, add_to_wallet=False)
|
||||
fee = self.nodes[1].decodepsbt(res["psbt"])["fee"]
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.00003"))
|
||||
assert_fee_amount(fee, Decimal(len(res["hex"]) / 2), Decimal("0.0003"))
|
||||
|
||||
# Test that passing fee_rate as both an argument and an option raises.
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=1, fee_rate=1, add_to_wallet=False,
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=10, fee_rate=10, add_to_wallet=False,
|
||||
expect_error=(-8, "Pass the fee_rate either as an argument, or in the options object, but not both"))
|
||||
|
||||
assert_raises_rpc_error(-8, "Use fee_rate (sat/vB) instead of feeRate", w0.send, {w1.getnewaddress(): 1}, 6, "conservative", 1, {"feeRate": 0.01})
|
||||
@ -303,15 +303,15 @@ class WalletSendTest(BitcoinTestFramework):
|
||||
expect_error=(-3, "Expected type number for conf_target, got {}".format(k)))
|
||||
|
||||
# Test setting explicit fee rate just below the minimum and at zero.
|
||||
self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 0.99999999 is passed")
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0.99999999,
|
||||
expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0.99999999,
|
||||
expect_error=(-4, "Fee rate (0.999 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
|
||||
self.log.info("Explicit fee rate raises RPC error 'fee rate too low' if fee_rate of 9.99999999 is passed")
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=9.99999999,
|
||||
expect_error=(-4, "Fee rate (9.999 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)"))
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=9.99999999,
|
||||
expect_error=(-4, "Fee rate (9.999 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)"))
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate=0,
|
||||
expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
|
||||
expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)"))
|
||||
self.test_send(from_wallet=w0, to_wallet=w1, amount=1, arg_fee_rate=0,
|
||||
expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (1.000 sat/vB)"))
|
||||
expect_error=(-4, "Fee rate (0.000 sat/vB) is lower than the minimum fee rate setting (10.000 sat/vB)"))
|
||||
|
||||
# TODO: Return hex if fee rate is below -maxmempool
|
||||
# res = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, conf_target=0.1, estimate_mode="sat/b", add_to_wallet=False)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user