diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2019-01-10 15:56:44 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2019-01-10 15:56:54 +0100 |
commit | cebe910718ae4f099f292736192a4e725ad02b94 (patch) | |
tree | 6740bdadac251e354a5a7b4fe4498f426c6290c0 /test/functional | |
parent | d7943bd008357eed01cc3a4fb7b24afcd5a523d6 (diff) | |
parent | fa48baf23eb2ec5e9b71e3e07c24432fc1fed39c (diff) | |
download | bitcoin-cebe910718ae4f099f292736192a4e725ad02b94.tar.xz |
Merge #15039: wallet: Avoid leaking nLockTime fingerprint when anti-fee-sniping
fa48baf23eb2ec5e9b71e3e07c24432fc1fed39c wallet: Avoid leaking locktime fingerprint when anti-fee-sniping (MarcoFalke)
453803adc9325b83fc0532a8328d455e8bdf4de6 [test] wallet_txn_clone: Correctly clone txin sequence (MarcoFalke)
Pull request description:
The wallet sets the locktime to the current height of our active chain. This is fine, as long as our node is connected to other nodes. However, when we fall back and get stuck at a particular height (e.g. taking the wallet offline), the same (potentially unique) locktime is used for all transactions. This makes it easier for passive observers to cluster transactions by wallet.
For reference, I visualized "locktime-reuse" with the data:
* blocks 545k-555k (both inclusive)
* locktimes<=60k
* excluding coinbase txs
![distribution of height-based tx locktimes used at least twice](https://user-images.githubusercontent.com/6399679/50446163-b8256d80-0913-11e9-9832-40b76052b2b9.png)
Tree-SHA512: 2af259dd8f9f863312e2732d80ca8ba6a20c8d6d1c486b10a48479e1c85ccf13b0c38723740ebadde0f28d321cd9c133ad3e5d1e925472eb27681143bda2d0e7
Diffstat (limited to 'test/functional')
-rwxr-xr-x | test/functional/test_runner.py | 1 | ||||
-rwxr-xr-x | test/functional/wallet_create_tx.py | 35 | ||||
-rwxr-xr-x | test/functional/wallet_txn_clone.py | 2 |
3 files changed, 37 insertions, 1 deletions
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index a094433942..8c6f6706e7 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -174,6 +174,7 @@ BASE_SCRIPTS = [ 'wallet_fallbackfee.py', 'feature_minchainwork.py', 'rpc_getblockstats.py', + 'wallet_create_tx.py', 'p2p_fingerprint.py', 'feature_uacomment.py', 'wallet_coinbase_category.py', diff --git a/test/functional/wallet_create_tx.py b/test/functional/wallet_create_tx.py new file mode 100755 index 0000000000..27dc0fb279 --- /dev/null +++ b/test/functional/wallet_create_tx.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# Copyright (c) 2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import ( + assert_equal, +) + + +class CreateTxWalletTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = False + self.num_nodes = 1 + + def skip_test_if_missing_module(self): + self.skip_if_no_wallet() + + def run_test(self): + self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled') + assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200) + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex']) + assert_equal(tx['locktime'], 0) + + self.log.info('Check that anti-fee-sniping is enabled when we mine a recent block') + self.nodes[0].generate(1) + txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1) + tx = self.nodes[0].decoderawtransaction(self.nodes[0].gettransaction(txid)['hex']) + assert 0 < tx['locktime'] <= 201 + + +if __name__ == '__main__': + CreateTxWalletTest().main() diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py index d78c105c17..1c2e0a9cb7 100755 --- a/test/functional/wallet_txn_clone.py +++ b/test/functional/wallet_txn_clone.py @@ -65,7 +65,7 @@ class TxnMallTest(BitcoinTestFramework): # Construct a clone of tx1, to be malleated rawtx1 = self.nodes[0].getrawtransaction(txid1, 1) - clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"]}] + clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"], "sequence": rawtx1["vin"][0]["sequence"]}] clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][0]["value"], rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][1]["value"]} clone_locktime = rawtx1["locktime"] |