mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 14:53:43 +01:00
Merge #20612: [0.21] final rc3 backports
48134a09addoc: Update wallet database installation guide for macOS (Hennadii Stepanov)f51e1cb291build: Use Homebrew's sqlite package if it is available (Hennadii Stepanov)48f8929aadbuild, refactor: Check that Homebrew's qt5 package is actually installed (Hennadii Stepanov)96124a2041build: Check that Homebrew's berkeley-db4 package is actually installed (Hennadii Stepanov)61e316e661Don't set BDB flags when configuring without (Jonas Schnelli)ce13b99020Add regression test for incorrect decoding (Pieter Wuille)1caa32e3f2Improve heuristic hex transaction decoding (Pieter Wuille)0d3c140c4dtest: add coverage for passing fee rate as a string (Jon Atack)06c84232b3wallet, bugfix: allow send to take string fee rate values (Jon Atack)bead935470Send and require SENDADDRV2 before VERACK (Pieter Wuille)9e806887a8Don't send 'sendaddrv2' to pre-70016 software (Pieter Wuille) Pull request description: ACKs for top commit: laanwj: ACK48134a09adTree-SHA512: 92f1199b96ab7775f88e882ec7fedf43118a4b8452d1c8d0b1cf072d8de153bbb601c7381bc1c5c80c93803c6f9942d54646e9c74e3a6703ce13854fb383fd5e
This commit is contained in:
15
configure.ac
15
configure.ac
@@ -646,16 +646,19 @@ case $host in
|
||||
dnl It's safe to add these paths even if the functionality is disabled by
|
||||
dnl the user (--without-wallet or --without-gui for example).
|
||||
|
||||
bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
|
||||
qt5_prefix=$($BREW --prefix qt5 2>/dev/null)
|
||||
if test x$bdb_prefix != x && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
|
||||
if test "x$use_bdb" != xno && $BREW list --versions berkeley-db4 >/dev/null && test "x$BDB_CFLAGS" = "x" && test "x$BDB_LIBS" = "x"; then
|
||||
bdb_prefix=$($BREW --prefix berkeley-db4 2>/dev/null)
|
||||
dnl This must precede the call to BITCOIN_FIND_BDB48 below.
|
||||
BDB_CFLAGS="-I$bdb_prefix/include"
|
||||
BDB_LIBS="-L$bdb_prefix/lib -ldb_cxx-4.8"
|
||||
fi
|
||||
if test x$qt5_prefix != x; then
|
||||
PKG_CONFIG_PATH="$qt5_prefix/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export PKG_CONFIG_PATH
|
||||
|
||||
if test "x$use_sqlite" != xno && $BREW list --versions sqlite3 >/dev/null; then
|
||||
export PKG_CONFIG_PATH="$($BREW --prefix sqlite3 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
fi
|
||||
|
||||
if $BREW list --versions qt5 >/dev/null; then
|
||||
export PKG_CONFIG_PATH="$($BREW --prefix qt5 2>/dev/null)/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
|
||||
@@ -19,7 +19,7 @@ Then install [Homebrew](https://brew.sh).
|
||||
|
||||
## Dependencies
|
||||
```shell
|
||||
brew install automake berkeley-db4 libtool boost miniupnpc pkg-config python qt libevent qrencode sqlite
|
||||
brew install automake libtool boost miniupnpc pkg-config python qt libevent qrencode
|
||||
```
|
||||
|
||||
If you run into issues, check [Homebrew's troubleshooting page](https://docs.brew.sh/Troubleshooting).
|
||||
@@ -30,7 +30,22 @@ If you want to build the disk image with `make deploy` (.dmg / optional), you ne
|
||||
brew install librsvg
|
||||
```
|
||||
|
||||
## Berkeley DB
|
||||
The wallet support requires one or both of the dependencies ([*SQLite*](#sqlite) and [*Berkeley DB*](#berkeley-db)) in the sections below.
|
||||
To build Bitcoin Core without wallet, see [*Disable-wallet mode*](#disable-wallet-mode).
|
||||
|
||||
#### SQLite
|
||||
|
||||
Usually, macOS installation already has a suitable SQLite installation.
|
||||
Also, the Homebrew package could be installed:
|
||||
|
||||
```shell
|
||||
brew install sqlite
|
||||
```
|
||||
|
||||
In that case the Homebrew package will prevail.
|
||||
|
||||
#### Berkeley DB
|
||||
|
||||
It is recommended to use Berkeley DB 4.8. If you have to build it yourself,
|
||||
you can use [this](/contrib/install_db4.sh) script to install it
|
||||
like so:
|
||||
@@ -41,7 +56,11 @@ like so:
|
||||
|
||||
from the root of the repository.
|
||||
|
||||
**Note**: You only need Berkeley DB if the wallet is enabled (see [*Disable-wallet mode*](/doc/build-osx.md#disable-wallet-mode)).
|
||||
Also, the Homebrew package could be installed:
|
||||
|
||||
```shell
|
||||
brew install berkeley-db4
|
||||
```
|
||||
|
||||
## Build Bitcoin Core
|
||||
|
||||
@@ -72,14 +91,14 @@ from the root of the repository.
|
||||
make deploy
|
||||
```
|
||||
|
||||
## `disable-wallet` mode
|
||||
## Disable-wallet mode
|
||||
When the intention is to run only a P2P node without a wallet, Bitcoin Core may be
|
||||
compiled in `disable-wallet` mode with:
|
||||
compiled in disable-wallet mode with:
|
||||
```shell
|
||||
./configure --disable-wallet
|
||||
```
|
||||
|
||||
In this case there is no dependency on Berkeley DB 4.8 and SQLite.
|
||||
In this case there is no dependency on [*Berkeley DB*](#berkeley-db) and [*SQLite*](#sqlite).
|
||||
|
||||
Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
|
||||
|
||||
|
||||
@@ -119,31 +119,72 @@ static bool CheckTxScriptsSanity(const CMutableTransaction& tx)
|
||||
|
||||
static bool DecodeTx(CMutableTransaction& tx, const std::vector<unsigned char>& tx_data, bool try_no_witness, bool try_witness)
|
||||
{
|
||||
// General strategy:
|
||||
// - Decode both with extended serialization (which interprets the 0x0001 tag as a marker for
|
||||
// the presense of witnesses) and with legacy serialization (which interprets the tag as a
|
||||
// 0-input 1-output incomplete transaction).
|
||||
// - Restricted by try_no_witness (which disables legacy if false) and try_witness (which
|
||||
// disables extended if false).
|
||||
// - Ignore serializations that do not fully consume the hex string.
|
||||
// - If neither succeeds, fail.
|
||||
// - If only one succeeds, return that one.
|
||||
// - If both decode attempts succeed:
|
||||
// - If only one passes the CheckTxScriptsSanity check, return that one.
|
||||
// - If neither or both pass CheckTxScriptsSanity, return the extended one.
|
||||
|
||||
CMutableTransaction tx_extended, tx_legacy;
|
||||
bool ok_extended = false, ok_legacy = false;
|
||||
|
||||
// Try decoding with extended serialization support, and remember if the result successfully
|
||||
// consumes the entire input.
|
||||
if (try_witness) {
|
||||
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION);
|
||||
try {
|
||||
ssData >> tx;
|
||||
// If transaction looks sane, we don't try other mode even if requested
|
||||
if (ssData.empty() && (!try_no_witness || CheckTxScriptsSanity(tx))) {
|
||||
return true;
|
||||
}
|
||||
ssData >> tx_extended;
|
||||
if (ssData.empty()) ok_extended = true;
|
||||
} catch (const std::exception&) {
|
||||
// Fall through.
|
||||
}
|
||||
}
|
||||
|
||||
// Optimization: if extended decoding succeeded and the result passes CheckTxScriptsSanity,
|
||||
// don't bother decoding the other way.
|
||||
if (ok_extended && CheckTxScriptsSanity(tx_extended)) {
|
||||
tx = std::move(tx_extended);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try decoding with legacy serialization, and remember if the result successfully consumes the entire input.
|
||||
if (try_no_witness) {
|
||||
CDataStream ssData(tx_data, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||
try {
|
||||
ssData >> tx;
|
||||
if (ssData.empty()) {
|
||||
return true;
|
||||
}
|
||||
ssData >> tx_legacy;
|
||||
if (ssData.empty()) ok_legacy = true;
|
||||
} catch (const std::exception&) {
|
||||
// Fall through.
|
||||
}
|
||||
}
|
||||
|
||||
// If legacy decoding succeeded and passes CheckTxScriptsSanity, that's our answer, as we know
|
||||
// at this point that extended decoding either failed or doesn't pass the sanity check.
|
||||
if (ok_legacy && CheckTxScriptsSanity(tx_legacy)) {
|
||||
tx = std::move(tx_legacy);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If extended decoding succeeded, and neither decoding passes sanity, return the extended one.
|
||||
if (ok_extended) {
|
||||
tx = std::move(tx_extended);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If legacy decoding succeeded and extended didn't, return the legacy one.
|
||||
if (ok_legacy) {
|
||||
tx = std::move(tx_legacy);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If none succeeded, we failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2364,10 +2364,16 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::WTXIDRELAY));
|
||||
}
|
||||
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
|
||||
|
||||
// Signal ADDRv2 support (BIP155).
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
|
||||
if (greatest_common_version >= 70016) {
|
||||
// BIP155 defines addrv2 and sendaddrv2 for all protocol versions, but some
|
||||
// implementations reject messages they don't know. As a courtesy, don't send
|
||||
// it to nodes with a version before 70016, as no software is known to support
|
||||
// BIP155 that doesn't announce at least that protocol version number.
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
|
||||
}
|
||||
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
|
||||
|
||||
pfrom.nServices = nServices;
|
||||
pfrom.SetAddrLocal(addrMe);
|
||||
@@ -2540,6 +2546,17 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_type == NetMsgType::SENDADDRV2) {
|
||||
if (pfrom.fSuccessfullyConnected) {
|
||||
// Disconnect peers that send SENDADDRV2 message after VERACK; this
|
||||
// must be negotiated between VERSION and VERACK.
|
||||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
}
|
||||
pfrom.m_wants_addrv2 = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pfrom.fSuccessfullyConnected) {
|
||||
LogPrint(BCLog::NET, "Unsupported message \"%s\" prior to verack from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
|
||||
return;
|
||||
@@ -2607,11 +2624,6 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_type == NetMsgType::SENDADDRV2) {
|
||||
pfrom.m_wants_addrv2 = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg_type == NetMsgType::SENDHEADERS) {
|
||||
LOCK(cs_main);
|
||||
State(pfrom.GetId())->fPreferHeaders = true;
|
||||
|
||||
@@ -4083,7 +4083,7 @@ static RPCHelpMan send()
|
||||
UniValueType(), // outputs (ARR or OBJ, checked later)
|
||||
UniValue::VNUM, // conf_target
|
||||
UniValue::VSTR, // estimate_mode
|
||||
UniValue::VNUM, // fee_rate
|
||||
UniValueType(), // fee_rate, will be checked by AmountFromValue() in SetFeeEstimateMode()
|
||||
UniValue::VOBJ, // options
|
||||
}, true
|
||||
);
|
||||
|
||||
@@ -717,10 +717,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
result = node.fundrawtransaction(rawtx) # uses self.min_relay_tx_fee (set by settxfee)
|
||||
btc_kvb_to_sat_vb = 100000 # (1e5)
|
||||
result1 = node.fundrawtransaction(rawtx, {"fee_rate": 2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee})
|
||||
result1 = node.fundrawtransaction(rawtx, {"fee_rate": str(2 * btc_kvb_to_sat_vb * self.min_relay_tx_fee)})
|
||||
result2 = node.fundrawtransaction(rawtx, {"feeRate": 2 * self.min_relay_tx_fee})
|
||||
result3 = node.fundrawtransaction(rawtx, {"fee_rate": 10 * btc_kvb_to_sat_vb * self.min_relay_tx_fee})
|
||||
result4 = node.fundrawtransaction(rawtx, {"feeRate": 10 * self.min_relay_tx_fee})
|
||||
result4 = node.fundrawtransaction(rawtx, {"feeRate": str(10 * self.min_relay_tx_fee)})
|
||||
# Test that funding non-standard "zero-fee" transactions is valid.
|
||||
result5 = self.nodes[3].fundrawtransaction(rawtx, {"fee_rate": 0})
|
||||
result6 = self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 0})
|
||||
|
||||
@@ -190,11 +190,11 @@ class PSBTTest(BitcoinTestFramework):
|
||||
self.log.info("Test walletcreatefundedpsbt fee rate of 10000 sat/vB and 0.1 BTC/kvB produces a total fee at or slightly below -maxtxfee (~0.05290000)")
|
||||
res1 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 10000, "add_inputs": True})
|
||||
assert_approx(res1["fee"], 0.055, 0.005)
|
||||
res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.1, "add_inputs": True})
|
||||
res2 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": "0.1", "add_inputs": True})
|
||||
assert_approx(res2["fee"], 0.055, 0.005)
|
||||
|
||||
self.log.info("Test min fee rate checks with walletcreatefundedpsbt are bypassed, e.g. a fee_rate under 1 sat/vB is allowed")
|
||||
res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": 0.99999999, "add_inputs": True})
|
||||
res3 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"fee_rate": "0.99999999", "add_inputs": True})
|
||||
assert_approx(res3["fee"], 0.00000381, 0.0000001)
|
||||
res4 = self.nodes[1].walletcreatefundedpsbt(inputs, outputs, 0, {"feeRate": 0.00000999, "add_inputs": True})
|
||||
assert_approx(res4["fee"], 0.00000381, 0.0000001)
|
||||
|
||||
@@ -372,6 +372,13 @@ class RawTransactionsTest(BitcoinTestFramework):
|
||||
encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
|
||||
decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction
|
||||
assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
|
||||
# known ambiguous transaction in the chain (see https://github.com/bitcoin/bitcoin/issues/20579)
|
||||
encrawtx = "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000ffffffff03f4c1fb4b0000000016001497cfc76442fe717f2a3f0cc9c175f7561b6619970000000000000000266a24aa21a9ed957d1036a80343e0d1b659497e1b48a38ebe876a056d45965fac4a85cda84e1900000000000000002952534b424c4f434b3a8e092581ab01986cbadc84f4b43f4fa4bb9e7a2e2a0caf9b7cf64d939028e22c0120000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
decrawtx = self.nodes[0].decoderawtransaction(encrawtx)
|
||||
decrawtx_wit = self.nodes[0].decoderawtransaction(encrawtx, True)
|
||||
assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # fails to decode as non-witness transaction
|
||||
assert_equal(decrawtx, decrawtx_wit) # the witness interpretation should be chosen
|
||||
assert_equal(decrawtx['vin'][0]['coinbase'], "03c68708046ff8415c622f4254432e434f4d2ffabe6d6de1965d02c68f928e5b244ab1965115a36f56eb997633c7f690124bbf43644e23080000000ca3d3af6d005a65ff0200fd00000000")
|
||||
|
||||
# Basic signrawtransaction test
|
||||
addr = self.nodes[1].getnewaddress()
|
||||
|
||||
@@ -396,9 +396,9 @@ class P2PInterface(P2PConnection):
|
||||
assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED)
|
||||
if message.nVersion >= 70016:
|
||||
self.send_message(msg_wtxidrelay())
|
||||
self.send_message(msg_verack())
|
||||
if self.support_addrv2:
|
||||
self.send_message(msg_sendaddrv2())
|
||||
self.send_message(msg_verack())
|
||||
self.nServices = message.nServices
|
||||
|
||||
# Connection helper methods
|
||||
|
||||
@@ -235,7 +235,8 @@ class WalletTest(BitcoinTestFramework):
|
||||
fee_rate_btc_kvb = fee_rate_sat_vb * 1e3 / 1e8
|
||||
explicit_fee_rate_btc_kvb = Decimal(fee_rate_btc_kvb) / 1000
|
||||
|
||||
txid = self.nodes[2].sendmany(amounts={address: 10}, fee_rate=fee_rate_sat_vb)
|
||||
# Test passing fee_rate as a string
|
||||
txid = self.nodes[2].sendmany(amounts={address: 10}, fee_rate=str(fee_rate_sat_vb))
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all(self.nodes[0:3])
|
||||
balance = self.nodes[2].getbalance()
|
||||
@@ -244,6 +245,17 @@ class WalletTest(BitcoinTestFramework):
|
||||
node_0_bal += Decimal('10')
|
||||
assert_equal(self.nodes[0].getbalance(), node_0_bal)
|
||||
|
||||
# Test passing fee_rate as an integer
|
||||
amount = Decimal("0.0001")
|
||||
txid = self.nodes[2].sendmany(amounts={address: amount}, fee_rate=fee_rate_sat_vb)
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all(self.nodes[0:3])
|
||||
balance = self.nodes[2].getbalance()
|
||||
node_2_bal = self.check_fee_amount(balance, node_2_bal - amount, explicit_fee_rate_btc_kvb, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
|
||||
assert_equal(balance, node_2_bal)
|
||||
node_0_bal += amount
|
||||
assert_equal(self.nodes[0].getbalance(), node_0_bal)
|
||||
|
||||
for key in ["totalFee", "feeRate"]:
|
||||
assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
|
||||
|
||||
@@ -405,7 +417,7 @@ class WalletTest(BitcoinTestFramework):
|
||||
amount = 3
|
||||
fee_rate_sat_vb = 2
|
||||
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)
|
||||
tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
|
||||
self.nodes[0].generate(1)
|
||||
@@ -414,6 +426,19 @@ class WalletTest(BitcoinTestFramework):
|
||||
fee = prebalance - postbalance - Decimal(amount)
|
||||
assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
|
||||
|
||||
prebalance = self.nodes[2].getbalance()
|
||||
amount = Decimal("0.001")
|
||||
fee_rate_sat_vb = 1.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))
|
||||
tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
|
||||
self.nodes[0].generate(1)
|
||||
self.sync_all(self.nodes[0:3])
|
||||
postbalance = self.nodes[2].getbalance()
|
||||
fee = prebalance - postbalance - amount
|
||||
assert_fee_amount(fee, tx_size, Decimal(fee_rate_btc_kvb))
|
||||
|
||||
for key in ["totalFee", "feeRate"]:
|
||||
assert_raises_rpc_error(-8, "Unknown named parameter key", self.nodes[2].sendtoaddress, address=address, amount=1, fee_rate=1, key=1)
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
|
||||
self.sync_mempools((rbf_node, peer_node))
|
||||
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
|
||||
if mode == "fee_rate":
|
||||
bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": NORMAL})
|
||||
bumped_psbt = rbf_node.psbtbumpfee(rbfid, {"fee_rate": str(NORMAL)})
|
||||
bumped_tx = rbf_node.bumpfee(rbfid, {"fee_rate": NORMAL})
|
||||
else:
|
||||
bumped_psbt = rbf_node.psbtbumpfee(rbfid)
|
||||
|
||||
@@ -256,8 +256,8 @@ 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="1", add_to_wallet=False)
|
||||
res2 = self.test_send(from_wallet=w0, to_wallet=w1, amount=1, fee_rate="1", 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)
|
||||
|
||||
Reference in New Issue
Block a user