mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-18 22:35:39 +01:00
Merge bitcoin/bitcoin#34268: [29.x] backports + final changes for 29.3
b834447fb2[doc] generate manpages 29.3rc1 (glozow)e9c978391f[build] bump version to 29.3rc1 (glozow)e973b61dbb[doc] update release notes for 29.3rc1 (glozow)f4b78c42e5test: Add a test for anchor outputs in the wallet (Ava Chow)c6e7765c0awallet: Throw an error in sendall if the tx size cannot be calculated (Ava Chow)bab1ac827bwallet: Determine IsFromMe by checking for TXOs of inputs (Ava Chow)71633a9b5ctest: Test wallet 'from me' status change (Ava Chow)daef5852f0guix: Fix `osslsigncode` tests (Hennadii Stepanov)7a71850a6dRemove unreliable seed from chainparams.cpp, and the associated README (SatsAndSports)2e4688618bminer: fix `addPackageTxs` unsigned integer overflow (ismaelsadeeq) Pull request description: Backports: - #34227 - #33723 - #33475 - #33268 And final changes for 29.3rc1 ACKs for top commit: achow101: ACKb834447fb2janb84: ACKb834447fb2sedited: ACKb834447fb2Tree-SHA512: 68e02fbde7162f728229f4bfc803bedda6d269e54593ebe40da607f6bd25b2b10bc4297bfa0bc977ce2dc6b558efe6571a7f875090e0f916fc09e5b67432ba30
This commit is contained in:
@@ -28,9 +28,9 @@ get_directory_property(precious_variables CACHE_VARIABLES)
|
||||
#=============================
|
||||
set(CLIENT_NAME "Bitcoin Core")
|
||||
set(CLIENT_VERSION_MAJOR 29)
|
||||
set(CLIENT_VERSION_MINOR 2)
|
||||
set(CLIENT_VERSION_MINOR 3)
|
||||
set(CLIENT_VERSION_BUILD 0)
|
||||
set(CLIENT_VERSION_RC 0)
|
||||
set(CLIENT_VERSION_RC 1)
|
||||
set(CLIENT_VERSION_IS_RELEASE "true")
|
||||
set(COPYRIGHT_YEAR "2025")
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
((gnu packages bash) #:select (bash-minimal))
|
||||
(gnu packages bison)
|
||||
((gnu packages certs) #:select (nss-certs))
|
||||
((gnu packages check) #:select (libfaketime))
|
||||
((gnu packages cmake) #:select (cmake-minimal))
|
||||
(gnu packages commencement)
|
||||
(gnu packages compression)
|
||||
@@ -209,7 +210,17 @@ and abstract ELF, PE and MachO formats.")
|
||||
(base32
|
||||
"1j47vwq4caxfv0xw68kw5yh00qcpbd56d7rq6c483ma3y7s96yyz"))))
|
||||
(build-system cmake-build-system)
|
||||
(inputs (list openssl))
|
||||
(arguments
|
||||
(list
|
||||
#:phases
|
||||
#~(modify-phases %standard-phases
|
||||
(replace 'check
|
||||
(lambda* (#:key tests? #:allow-other-keys)
|
||||
(if tests?
|
||||
(invoke "faketime" "-f" "@2025-01-01 00:00:00" ;; Tests fail after 2025.
|
||||
"ctest" "--output-on-failure" "--no-tests=error")
|
||||
(format #t "test suite not run~%")))))))
|
||||
(inputs (list libfaketime openssl))
|
||||
(home-page "https://github.com/mtrojnar/osslsigncode")
|
||||
(synopsis "Authenticode signing and timestamping tool")
|
||||
(description "osslsigncode is a small tool that implements part of the
|
||||
|
||||
@@ -10,14 +10,13 @@ to addrman with).
|
||||
|
||||
Update `MIN_BLOCKS` in `makeseeds.py` and the `-m`/`--minblocks` arguments below, as needed.
|
||||
|
||||
The seeds compiled into the release are created from sipa's, achow101's and luke-jr's
|
||||
The seeds compiled into the release are created from sipa's and achow101's
|
||||
DNS seed, virtu's crawler, and asmap community AS map data. Run the following commands
|
||||
from the `/contrib/seeds` directory:
|
||||
|
||||
```
|
||||
curl https://bitcoin.sipa.be/seeds.txt.gz | gzip -dc > seeds_main.txt
|
||||
curl https://21.ninja/seeds.txt.gz | gzip -dc >> seeds_main.txt
|
||||
curl https://luke.dashjr.org/programs/bitcoin/files/charts/seeds.txt >> seeds_main.txt
|
||||
curl https://mainnet.achownodes.xyz/seeds.txt.gz | gzip -dc >> seeds_main.txt
|
||||
curl https://signet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_signet.txt
|
||||
curl https://testnet.achownodes.xyz/seeds.txt.gz | gzip -dc > seeds_test.txt
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-CLI "1" "October 2025" "bitcoin-cli v29.2.0" "User Commands"
|
||||
.TH BITCOIN-CLI "1" "January 2026" "bitcoin-cli v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-cli \- manual page for bitcoin-cli v29.2.0
|
||||
bitcoin-cli \- manual page for bitcoin-cli v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,<command> \/\fR[\fI\,params\/\fR]
|
||||
@@ -15,7 +15,7 @@ bitcoin-cli \- manual page for bitcoin-cli v29.2.0
|
||||
.B bitcoin-cli
|
||||
[\fI\,options\/\fR] \fI\,help <command>\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core RPC client version v29.2.0
|
||||
Bitcoin Core RPC client version v29.3.0rc1
|
||||
.PP
|
||||
The bitcoin\-cli utility provides a command line interface to interact with a Bitcoin Core RPC server.
|
||||
.PP
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-QT "1" "October 2025" "bitcoin-qt v29.2.0" "User Commands"
|
||||
.TH BITCOIN-QT "1" "January 2026" "bitcoin-qt v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-qt \- manual page for bitcoin-qt v29.2.0
|
||||
bitcoin-qt \- manual page for bitcoin-qt v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-qt
|
||||
[\fI\,options\/\fR] [\fI\,URI\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core version v29.2.0
|
||||
Bitcoin Core version v29.3.0rc1
|
||||
.PP
|
||||
The bitcoin\-qt application provides a graphical interface for interacting with Bitcoin Core.
|
||||
.PP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-TX "1" "October 2025" "bitcoin-tx v29.2.0" "User Commands"
|
||||
.TH BITCOIN-TX "1" "January 2026" "bitcoin-tx v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-tx \- manual page for bitcoin-tx v29.2.0
|
||||
bitcoin-tx \- manual page for bitcoin-tx v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,<hex-tx> \/\fR[\fI\,commands\/\fR]
|
||||
@@ -9,7 +9,7 @@ bitcoin-tx \- manual page for bitcoin-tx v29.2.0
|
||||
.B bitcoin-tx
|
||||
[\fI\,options\/\fR] \fI\,-create \/\fR[\fI\,commands\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-tx utility version v29.2.0
|
||||
Bitcoin Core bitcoin\-tx utility version v29.3.0rc1
|
||||
.PP
|
||||
The bitcoin\-tx tool is used for creating and modifying bitcoin transactions.
|
||||
.PP
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-UTIL "1" "October 2025" "bitcoin-util v29.2.0" "User Commands"
|
||||
.TH BITCOIN-UTIL "1" "January 2026" "bitcoin-util v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-util \- manual page for bitcoin-util v29.2.0
|
||||
bitcoin-util \- manual page for bitcoin-util v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-util
|
||||
[\fI\,options\/\fR] [\fI\,command\/\fR]
|
||||
@@ -9,7 +9,7 @@ bitcoin-util \- manual page for bitcoin-util v29.2.0
|
||||
.B bitcoin-util
|
||||
[\fI\,options\/\fR] \fI\,grind <hex-block-header>\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-util utility version v29.2.0
|
||||
Bitcoin Core bitcoin\-util utility version v29.3.0rc1
|
||||
.PP
|
||||
The bitcoin\-util tool provides bitcoin related functionality that does not rely on the ability to access a running node. Available [commands] are listed below.
|
||||
.SH OPTIONS
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIN-WALLET "1" "October 2025" "bitcoin-wallet v29.2.0" "User Commands"
|
||||
.TH BITCOIN-WALLET "1" "January 2026" "bitcoin-wallet v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v29.2.0
|
||||
bitcoin-wallet \- manual page for bitcoin-wallet v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoin-wallet
|
||||
[\fI\,options\/\fR] \fI\,<command>\/\fR
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core bitcoin\-wallet utility version v29.2.0
|
||||
Bitcoin Core bitcoin\-wallet utility version v29.3.0rc1
|
||||
.PP
|
||||
bitcoin\-wallet is an offline tool for creating and interacting with Bitcoin Core wallet files.
|
||||
.PP
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.49.3.
|
||||
.TH BITCOIND "1" "October 2025" "bitcoind v29.2.0" "User Commands"
|
||||
.TH BITCOIND "1" "January 2026" "bitcoind v29.3.0rc1" "User Commands"
|
||||
.SH NAME
|
||||
bitcoind \- manual page for bitcoind v29.2.0
|
||||
bitcoind \- manual page for bitcoind v29.3.0rc1
|
||||
.SH SYNOPSIS
|
||||
.B bitcoind
|
||||
[\fI\,options\/\fR]
|
||||
.SH DESCRIPTION
|
||||
Bitcoin Core daemon version v29.2.0
|
||||
Bitcoin Core daemon version v29.3.0rc1
|
||||
.PP
|
||||
The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay transactions and blocks, as well as relaying addresses.
|
||||
.PP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Bitcoin Core version 29.x is now available from:
|
||||
Bitcoin Core version 29.3rc1 is now available from:
|
||||
|
||||
<https://bitcoincore.org/bin/bitcoin-core-29.x/>
|
||||
<https://bitcoincore.org/bin/bitcoin-core-29.3/test.rc1/>
|
||||
|
||||
This release includes various bug fixes and performance
|
||||
improvements, as well as updated translations.
|
||||
@@ -37,6 +37,36 @@ unsupported systems.
|
||||
Notable changes
|
||||
===============
|
||||
|
||||
### P2P
|
||||
|
||||
- #33050 net, validation: don't punish peers for consensus-invalid txs
|
||||
- #33723 chainparams: remove dnsseed.bitcoin.dashjr-list-of-p2p-nodes.us
|
||||
|
||||
### Validation
|
||||
|
||||
- #32473 Introduce per-txin sighash midstate cache for legacy/p2sh/segwitv0 scripts
|
||||
- #33105 validation: detect witness stripping without re-running Script checks
|
||||
|
||||
### Wallet
|
||||
|
||||
- #33268 wallet: Identify transactions spending 0-value outputs, and add tests for anchor outputs in a wallet
|
||||
- #34156 wallet: fix unnamed legacy wallet migration failure
|
||||
- #34226 wallet: test: Relative wallet failed migration cleanup
|
||||
- #34123 wallet: migration, avoid creating spendable wallet from a watch-only legacy wallet
|
||||
- #34215 wallettool: fix unnamed createfromdump failure walletsdir deletion
|
||||
|
||||
### Mining
|
||||
|
||||
- #33475 bugfix: miner: fix `addPackageTxs` unsigned integer overflow
|
||||
|
||||
### Build
|
||||
|
||||
- #34227 guix: Fix `osslsigncode` tests
|
||||
|
||||
### Documentation
|
||||
|
||||
- #33623 doc: document capnproto and libmultiprocess deps in 29.x
|
||||
|
||||
### Test
|
||||
|
||||
- #33612 test: change log rate limit version gate
|
||||
@@ -51,8 +81,17 @@ Credits
|
||||
|
||||
Thanks to everyone who directly contributed to this release:
|
||||
|
||||
- Anthony Towns
|
||||
- Antoine Poinsot
|
||||
- Ava Chow
|
||||
- David Gumberg
|
||||
- Eugene Siegel
|
||||
- fanquake
|
||||
- furszy
|
||||
- Hennadii Stepanov
|
||||
- ismaelsadeeq
|
||||
- Pieter Wuille
|
||||
- SatsAndSports
|
||||
- willcl-ark
|
||||
|
||||
As well as to everyone that helped with translations on
|
||||
|
||||
@@ -146,7 +146,6 @@ public:
|
||||
// release ASAP to avoid it where possible.
|
||||
vSeeds.emplace_back("seed.bitcoin.sipa.be."); // Pieter Wuille, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("dnsseed.bluematt.me."); // Matt Corallo, only supports x9
|
||||
vSeeds.emplace_back("dnsseed.bitcoin.dashjr-list-of-p2p-nodes.us."); // Luke Dashjr
|
||||
vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch."); // Jonas Schnelli, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("seed.btc.petertodd.net."); // Peter Todd, only supports x1, x5, x9, and xd
|
||||
vSeeds.emplace_back("seed.bitcoin.sprovoost.nl."); // Sjors Provoost
|
||||
|
||||
@@ -394,8 +394,8 @@ void BlockAssembler::addPackageTxs(int& nPackagesSelected, int& nDescendantsUpda
|
||||
|
||||
++nConsecutiveFailed;
|
||||
|
||||
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight >
|
||||
m_options.nBlockMaxWeight - m_options.block_reserved_weight) {
|
||||
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight +
|
||||
m_options.block_reserved_weight > m_options.nBlockMaxWeight) {
|
||||
// Give up if we're close to full and haven't succeeded in a while
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1486,7 +1486,6 @@ RPCHelpMan sendall()
|
||||
CoinFilterParams coins_params;
|
||||
coins_params.min_amount = 0;
|
||||
for (const COutput& output : AvailableCoins(*pwallet, &coin_control, fee_rate, coins_params).All()) {
|
||||
CHECK_NONFATAL(output.input_bytes > 0);
|
||||
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
|
||||
continue;
|
||||
}
|
||||
@@ -1505,6 +1504,9 @@ RPCHelpMan sendall()
|
||||
|
||||
// estimate final size of tx
|
||||
const TxSize tx_size{CalculateMaximumSignedTxSize(CTransaction(rawTx), pwallet.get())};
|
||||
if (tx_size.vsize == -1) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, "Unable to determine the size of the transaction, the wallet contains unsolvable descriptors");
|
||||
}
|
||||
const CAmount fee_from_size{fee_rate.GetFee(tx_size.vsize)};
|
||||
const std::optional<CAmount> total_bump_fees{pwallet->chain().calculateCombinedBumpFee(outpoints_spent, fee_rate)};
|
||||
CAmount effective_value = total_input_value - fee_from_size - total_bump_fees.value_or(0);
|
||||
|
||||
@@ -1702,7 +1702,13 @@ isminetype CWallet::IsMine(const COutPoint& outpoint) const
|
||||
|
||||
bool CWallet::IsFromMe(const CTransaction& tx) const
|
||||
{
|
||||
return (GetDebit(tx, ISMINE_ALL) > 0);
|
||||
LOCK(cs_wallet);
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
if (IsMine(txin.prevout)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CAmount CWallet::GetDebit(const CTransaction& tx, const isminefilter& filter) const
|
||||
|
||||
@@ -50,6 +50,7 @@ DUMMY_MIN_OP_RETURN_SCRIPT = CScript([OP_RETURN] + ([OP_0] * (MIN_PADDING - 1)))
|
||||
assert len(DUMMY_MIN_OP_RETURN_SCRIPT) == MIN_PADDING
|
||||
|
||||
PAY_TO_ANCHOR = CScript([OP_1, bytes.fromhex("4e73")])
|
||||
ANCHOR_ADDRESS = "bcrt1pfeesnyr2tx"
|
||||
|
||||
def key_to_p2pk_script(key):
|
||||
key = check_key(key)
|
||||
|
||||
@@ -170,6 +170,8 @@ BASE_SCRIPTS = [
|
||||
'wallet_listreceivedby.py --descriptors',
|
||||
'wallet_abandonconflict.py --legacy-wallet',
|
||||
'wallet_abandonconflict.py --descriptors',
|
||||
'wallet_anchor.py --legacy-wallet',
|
||||
'wallet_anchor.py --descriptors',
|
||||
'feature_reindex.py',
|
||||
'feature_reindex_readonly.py',
|
||||
'wallet_labels.py --legacy-wallet',
|
||||
|
||||
128
test/functional/wallet_anchor.py
Executable file
128
test/functional/wallet_anchor.py
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2025-present The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import time
|
||||
|
||||
from test_framework.blocktools import MAX_FUTURE_BLOCK_TIME
|
||||
from test_framework.descriptors import descsum_create
|
||||
from test_framework.messages import (
|
||||
COutPoint,
|
||||
CTxIn,
|
||||
CTxInWitness,
|
||||
CTxOut,
|
||||
)
|
||||
from test_framework.script_util import (
|
||||
ANCHOR_ADDRESS,
|
||||
PAY_TO_ANCHOR,
|
||||
)
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_raises_rpc_error,
|
||||
)
|
||||
from test_framework.wallet import MiniWallet
|
||||
|
||||
class WalletAnchorTest(BitcoinTestFramework):
|
||||
def add_options(self, parser):
|
||||
self.add_wallet_options(parser)
|
||||
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def test_0_value_anchor_listunspent(self):
|
||||
self.log.info("Test that 0-value anchor outputs are detected as UTXOs")
|
||||
|
||||
# Create an anchor output, and spend it
|
||||
sender = MiniWallet(self.nodes[0])
|
||||
anchor_tx = sender.create_self_transfer(fee_rate=0, version=3)["tx"]
|
||||
anchor_tx.vout.append(CTxOut(0, PAY_TO_ANCHOR))
|
||||
anchor_tx.rehash() # Rehash after modifying anchor_tx
|
||||
anchor_spend = sender.create_self_transfer(version=3)["tx"]
|
||||
anchor_spend.vin.append(CTxIn(COutPoint(anchor_tx.sha256, 1), b""))
|
||||
anchor_spend.wit.vtxinwit.append(CTxInWitness())
|
||||
anchor_spend.rehash() # Rehash after modifying anchor_spend
|
||||
submit_res = self.nodes[0].submitpackage([anchor_tx.serialize().hex(), anchor_spend.serialize().hex()])
|
||||
assert_equal(submit_res["package_msg"], "success")
|
||||
anchor_txid = anchor_tx.hash
|
||||
anchor_spend_txid = anchor_spend.hash
|
||||
|
||||
# Mine each tx in separate blocks
|
||||
self.generateblock(self.nodes[0], sender.get_address(), [anchor_tx.serialize().hex()])
|
||||
anchor_tx_height = self.nodes[0].getblockcount()
|
||||
self.generateblock(self.nodes[0], sender.get_address(), [anchor_spend.serialize().hex()])
|
||||
|
||||
# Mock time forward and generate some blocks to avoid rescanning of latest blocks
|
||||
self.nodes[0].setmocktime(int(time.time()) + MAX_FUTURE_BLOCK_TIME + 1)
|
||||
self.generate(self.nodes[0], 10)
|
||||
|
||||
self.nodes[0].createwallet(wallet_name="anchor", disable_private_keys=True)
|
||||
wallet = self.nodes[0].get_wallet_rpc("anchor")
|
||||
|
||||
wallet.importaddress(ANCHOR_ADDRESS, rescan=False)
|
||||
|
||||
# The wallet should have no UTXOs, and not know of the anchor tx or its spend
|
||||
assert_equal(wallet.listunspent(), [])
|
||||
assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", wallet.gettransaction, anchor_txid)
|
||||
assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", wallet.gettransaction, anchor_spend_txid)
|
||||
|
||||
# Rescanning the block containing the anchor so that listunspent will list the output
|
||||
wallet.rescanblockchain(0, anchor_tx_height)
|
||||
utxos = wallet.listunspent()
|
||||
assert_equal(len(utxos), 1)
|
||||
assert_equal(utxos[0]["txid"], anchor_txid)
|
||||
assert_equal(utxos[0]["address"], ANCHOR_ADDRESS)
|
||||
assert_equal(utxos[0]["amount"], 0)
|
||||
wallet.gettransaction(anchor_txid)
|
||||
assert_raises_rpc_error(-5, "Invalid or non-wallet transaction id", wallet.gettransaction, anchor_spend_txid)
|
||||
|
||||
# Rescan the rest of the blockchain to see the anchor was spent
|
||||
wallet.rescanblockchain()
|
||||
assert_equal(wallet.listunspent(), [])
|
||||
wallet.gettransaction(anchor_spend_txid)
|
||||
|
||||
def test_cannot_sign_anchors(self):
|
||||
self.log.info("Test that the wallet cannot spend anchor outputs")
|
||||
for disable_privkeys in [False, True]:
|
||||
self.nodes[0].createwallet(wallet_name=f"anchor_spend_{disable_privkeys}", disable_private_keys=disable_privkeys)
|
||||
wallet = self.nodes[0].get_wallet_rpc(f"anchor_spend_{disable_privkeys}")
|
||||
if self.options.descriptors:
|
||||
import_res = wallet.importdescriptors([
|
||||
{"desc": descsum_create(f"addr({ANCHOR_ADDRESS})"), "timestamp": "now"},
|
||||
{"desc": descsum_create(f"raw({PAY_TO_ANCHOR.hex()})"), "timestamp": "now"}
|
||||
])
|
||||
assert_equal(import_res[0]["success"], disable_privkeys)
|
||||
assert_equal(import_res[1]["success"], disable_privkeys)
|
||||
else:
|
||||
wallet.importaddress(ANCHOR_ADDRESS)
|
||||
|
||||
anchor_txid = self.default_wallet.sendtoaddress(ANCHOR_ADDRESS, 1)
|
||||
self.generate(self.nodes[0], 1)
|
||||
|
||||
wallet = self.nodes[0].get_wallet_rpc("anchor_spend_True")
|
||||
utxos = wallet.listunspent()
|
||||
assert_equal(len(utxos), 1)
|
||||
assert_equal(utxos[0]["txid"], anchor_txid)
|
||||
assert_equal(utxos[0]["address"], ANCHOR_ADDRESS)
|
||||
assert_equal(utxos[0]["amount"], 1)
|
||||
|
||||
if self.options.descriptors:
|
||||
assert_raises_rpc_error(-4, "Missing solving data for estimating transaction size", wallet.send, [{self.default_wallet.getnewaddress(): 0.9999}])
|
||||
assert_raises_rpc_error(-4, "Unable to determine the size of the transaction, the wallet contains unsolvable descriptors", wallet.sendall, recipients=[self.default_wallet.getnewaddress()])
|
||||
else:
|
||||
assert_raises_rpc_error(-4, "Insufficient funds", wallet.send, [{self.default_wallet.getnewaddress(): 0.9999}])
|
||||
assert_raises_rpc_error(-6, "Total value of UTXO pool too low to pay for transaction. Try using lower feerate or excluding uneconomic UTXOs with 'send_max' option.", wallet.sendall, recipients=[self.default_wallet.getnewaddress()])
|
||||
assert_raises_rpc_error(-4, "Error: Private keys are disabled for this wallet", wallet.sendtoaddress, self.default_wallet.getnewaddress(), 0.9999)
|
||||
assert_raises_rpc_error(-4, "Unable to determine the size of the transaction, the wallet contains unsolvable descriptors", wallet.sendall, recipients=[self.default_wallet.getnewaddress()], inputs=utxos)
|
||||
|
||||
def run_test(self):
|
||||
self.default_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
|
||||
self.test_0_value_anchor_listunspent()
|
||||
self.test_cannot_sign_anchors()
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletAnchorTest(__file__).main()
|
||||
@@ -5,9 +5,11 @@
|
||||
"""Test the listtransactions API."""
|
||||
|
||||
from decimal import Decimal
|
||||
import time
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from test_framework.blocktools import MAX_FUTURE_BLOCK_TIME
|
||||
from test_framework.messages import (
|
||||
COIN,
|
||||
tx_from_hex,
|
||||
@@ -17,7 +19,9 @@ from test_framework.util import (
|
||||
assert_array_result,
|
||||
assert_equal,
|
||||
assert_raises_rpc_error,
|
||||
find_vout_for_address,
|
||||
)
|
||||
from test_framework.wallet_util import get_generate_key
|
||||
|
||||
|
||||
class ListTransactionsTest(BitcoinTestFramework):
|
||||
@@ -114,6 +118,8 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||
self.run_invalid_parameters_test()
|
||||
self.test_op_return()
|
||||
|
||||
self.test_from_me_status_change()
|
||||
|
||||
def run_rbf_opt_in_test(self):
|
||||
"""Test the opt-in-rbf flag for sent and received transactions."""
|
||||
|
||||
@@ -327,6 +333,47 @@ class ListTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
assert 'address' not in op_ret_tx
|
||||
|
||||
def test_from_me_status_change(self):
|
||||
self.log.info("Test gettransaction after changing a transaction's 'from me' status")
|
||||
self.nodes[0].createwallet("fromme")
|
||||
default_wallet = self.nodes[0].get_wallet_rpc(self.default_wallet_name)
|
||||
wallet = self.nodes[0].get_wallet_rpc("fromme")
|
||||
|
||||
# The 'fee' field of gettransaction is only added when the transaction is 'from me'
|
||||
# Run twice, once for a transaction in the mempool, again when it confirms
|
||||
for confirm in [False, True]:
|
||||
key = get_generate_key()
|
||||
default_wallet.importprivkey(key.privkey)
|
||||
|
||||
send_res = default_wallet.send(outputs=[{key.p2wpkh_addr: 1}, {wallet.getnewaddress(): 1}])
|
||||
assert_equal(send_res["complete"], True)
|
||||
vout = find_vout_for_address(self.nodes[0], send_res["txid"], key.p2wpkh_addr)
|
||||
utxos = [{"txid": send_res["txid"], "vout": vout}]
|
||||
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
|
||||
|
||||
# Send to the test wallet, ensuring that one input is for the descriptor we will import,
|
||||
# and that there are other inputs belonging to only the sending wallet
|
||||
send_res = default_wallet.send(outputs=[{wallet.getnewaddress(): 1.5}], inputs=utxos, add_inputs=True)
|
||||
assert_equal(send_res["complete"], True)
|
||||
txid = send_res["txid"]
|
||||
self.nodes[0].syncwithvalidationinterfacequeue()
|
||||
tx_info = wallet.gettransaction(txid)
|
||||
assert "fee" not in tx_info
|
||||
assert_equal(any(detail["category"] == "send" for detail in tx_info["details"]), False)
|
||||
|
||||
if confirm:
|
||||
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
|
||||
# Mock time forward and generate blocks so that the import does not rescan the transaction
|
||||
self.nodes[0].setmocktime(int(time.time()) + MAX_FUTURE_BLOCK_TIME + 1)
|
||||
self.generate(self.nodes[0], 10, sync_fun=self.no_op)
|
||||
|
||||
wallet.importprivkey(key.privkey)
|
||||
# TODO: We should check that the fee matches, but since the transaction spends inputs
|
||||
# not known to the wallet, it is incorrectly calculating the fee.
|
||||
# assert_equal(wallet.gettransaction(txid)["fee"], fee)
|
||||
tx_info = wallet.gettransaction(txid)
|
||||
assert "fee" in tx_info
|
||||
assert_equal(any(detail["category"] == "send" for detail in tx_info["details"]), True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
ListTransactionsTest(__file__).main()
|
||||
|
||||
Reference in New Issue
Block a user