mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
Merge fa91ad3420 into merged_master (Bitcoin PR bitcoin/bitcoin#34268)
This commit is contained in:
commit
7036b9351f
17 changed files with 257 additions and 28 deletions
|
|
@ -28,9 +28,9 @@ get_directory_property(precious_variables CACHE_VARIABLES)
|
|||
#=============================
|
||||
set(CLIENT_NAME "Elements 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")
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -300,7 +300,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
|
||||
|
|
|
|||
|
|
@ -463,8 +463,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1631,6 +1631,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);
|
||||
|
|
|
|||
|
|
@ -1721,7 +1721,13 @@ isminetype CWallet::IsMine(const COutPoint& outpoint) const
|
|||
|
||||
bool CWallet::IsFromMe(const CTransaction& tx) const
|
||||
{
|
||||
return (GetDebit(tx, ISMINE_ALL) > CAmountMap());
|
||||
LOCK(cs_wallet);
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
if (IsMine(txin.prevout)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CAmountMap 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)
|
||||
|
|
|
|||
|
|
@ -206,6 +206,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',
|
||||
|
|
|
|||
133
test/functional/wallet_anchor.py
Executable file
133
test/functional/wallet_anchor.py
Executable file
|
|
@ -0,0 +1,133 @@
|
|||
#!/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, SkipTest
|
||||
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()
|
||||
# ELEMENTS: Pay-to-anchor outputs carry a 0-value, spendable scriptPubKey.
|
||||
# Elements consensus (`VerifyAmounts` in confidential_validation.cpp) rejects
|
||||
# any 0-value output whose scriptPubKey is not `IsUnspendable()`, so the P2A
|
||||
# construction used by this test cannot be broadcast on an Elements chain.
|
||||
raise SkipTest("Pay-to-anchor outputs are rejected by Elements consensus (0-value spendable output)")
|
||||
|
||||
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."""
|
||||
|
||||
|
|
@ -329,6 +335,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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue