aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/config.ini.in1
-rw-r--r--test/functional/README.md2
-rw-r--r--test/functional/data/README.md2
-rw-r--r--test/functional/data/blockheader_testnet3.hex548
-rwxr-xr-xtest/functional/example_test.py4
-rwxr-xr-xtest/functional/feature_assumeutxo.py41
-rwxr-xr-xtest/functional/feature_assumevalid.py6
-rwxr-xr-xtest/functional/feature_config_args.py20
-rwxr-xr-xtest/functional/feature_filelock.py3
-rwxr-xr-xtest/functional/feature_framework_unit_tests.py1
-rwxr-xr-xtest/functional/feature_init.py54
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py6
-rwxr-xr-xtest/functional/feature_signet.py6
-rwxr-xr-xtest/functional/feature_versionbits_warning.py2
-rwxr-xr-xtest/functional/interface_usdt_coinselection.py19
-rwxr-xr-xtest/functional/interface_usdt_mempool.py35
-rwxr-xr-xtest/functional/interface_usdt_net.py53
-rwxr-xr-xtest/functional/interface_usdt_utxocache.py12
-rwxr-xr-xtest/functional/interface_usdt_validation.py4
-rwxr-xr-xtest/functional/mempool_accept.py2
-rwxr-xr-xtest/functional/mempool_ephemeral_dust.py8
-rwxr-xr-xtest/functional/mempool_persist.py6
-rwxr-xr-xtest/functional/p2p_addr_relay.py6
-rwxr-xr-xtest/functional/p2p_addrfetch.py2
-rwxr-xr-xtest/functional/p2p_addrv2_relay.py4
-rwxr-xr-xtest/functional/p2p_blockfilters.py4
-rwxr-xr-xtest/functional/p2p_blocksonly.py8
-rwxr-xr-xtest/functional/p2p_compactblocks.py26
-rwxr-xr-xtest/functional/p2p_compactblocks_blocksonly.py9
-rwxr-xr-xtest/functional/p2p_dos_header_tree.py88
-rwxr-xr-xtest/functional/p2p_eviction.py6
-rwxr-xr-xtest/functional/p2p_filter.py8
-rwxr-xr-xtest/functional/p2p_fingerprint.py6
-rwxr-xr-xtest/functional/p2p_ibd_stalling.py8
-rwxr-xr-xtest/functional/p2p_initial_headers_sync.py6
-rwxr-xr-xtest/functional/p2p_invalid_locator.py4
-rwxr-xr-xtest/functional/p2p_invalid_messages.py8
-rwxr-xr-xtest/functional/p2p_leak.py8
-rwxr-xr-xtest/functional/p2p_mutated_blocks.py6
-rwxr-xr-xtest/functional/p2p_nobloomfilter_messages.py2
-rwxr-xr-xtest/functional/p2p_node_network_limited.py2
-rwxr-xr-xtest/functional/p2p_opportunistic_1p1c.py2
-rwxr-xr-xtest/functional/p2p_orphan_handling.py8
-rwxr-xr-xtest/functional/p2p_segwit.py16
-rwxr-xr-xtest/functional/p2p_sendheaders.py24
-rwxr-xr-xtest/functional/p2p_sendtxrcncl.py30
-rwxr-xr-xtest/functional/p2p_timeouts.py8
-rwxr-xr-xtest/functional/p2p_tx_download.py31
-rwxr-xr-xtest/functional/p2p_tx_privacy.py2
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py14
-rwxr-xr-xtest/functional/rpc_deprecated.py22
-rwxr-xr-xtest/functional/rpc_getdescriptorinfo.py7
-rwxr-xr-xtest/functional/rpc_psbt.py2
-rwxr-xr-xtest/functional/rpc_rawtransaction.py4
-rwxr-xr-xtest/functional/rpc_txoutproof.py2
-rw-r--r--test/functional/test-shell.md15
-rw-r--r--test/functional/test_framework/authproxy.py15
-rw-r--r--test/functional/test_framework/compressor.py58
-rwxr-xr-xtest/functional/test_framework/messages.py37
-rwxr-xr-xtest/functional/test_framework/p2p.py42
-rwxr-xr-xtest/functional/test_framework/test_framework.py111
-rwxr-xr-xtest/functional/test_framework/test_node.py27
-rw-r--r--test/functional/test_framework/test_shell.py7
-rw-r--r--test/functional/test_framework/util.py7
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/tool_signet_miner.py7
-rwxr-xr-xtest/functional/tool_wallet.py10
-rwxr-xr-xtest/functional/wallet_abandonconflict.py4
-rwxr-xr-xtest/functional/wallet_avoid_mixing_output_types.py2
-rwxr-xr-xtest/functional/wallet_crosschain.py38
-rwxr-xr-xtest/functional/wallet_descriptor.py1
-rwxr-xr-xtest/functional/wallet_encryption.py2
-rwxr-xr-xtest/functional/wallet_fast_rescan.py1
-rwxr-xr-xtest/functional/wallet_importdescriptors.py23
-rwxr-xr-xtest/functional/wallet_listdescriptors.py1
-rwxr-xr-xtest/functional/wallet_miniscript.py1
-rwxr-xr-xtest/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py135
-rwxr-xr-xtest/functional/wallet_multisig_descriptor_psbt.py1
-rwxr-xr-xtest/functional/wallet_reorgsrestore.py116
-rwxr-xr-xtest/functional/wallet_rescan_unconfirmed.py1
-rwxr-xr-xtest/functional/wallet_taproot.py1
-rwxr-xr-xtest/functional/wallet_upgradewallet.py19
-rwxr-xr-xtest/fuzz/test_runner.py2
-rw-r--r--test/lint/README.md2
-rwxr-xr-xtest/util/test_runner.py2
86 files changed, 861 insertions, 1048 deletions
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3a5998697d..f1d05371ee 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,7 +16,6 @@ function(create_test_config)
endmacro()
set_configure_variable(ENABLE_WALLET ENABLE_WALLET)
- set_configure_variable(WITH_SQLITE USE_SQLITE)
set_configure_variable(WITH_BDB USE_BDB)
set_configure_variable(BUILD_CLI BUILD_BITCOIN_CLI)
set_configure_variable(BUILD_UTIL BUILD_BITCOIN_UTIL)
diff --git a/test/config.ini.in b/test/config.ini.in
index 3bf79ef25d..cdd13a9d8c 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -16,7 +16,6 @@ RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
[components]
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
-@USE_SQLITE_TRUE@USE_SQLITE=true
@USE_BDB_TRUE@USE_BDB=true
@BUILD_BITCOIN_CLI_TRUE@ENABLE_CLI=true
@BUILD_BITCOIN_UTIL_TRUE@ENABLE_BITCOIN_UTIL=true
diff --git a/test/functional/README.md b/test/functional/README.md
index a34bf1827c..cf0f2fd0e3 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -183,7 +183,7 @@ way is the use the `profile_with_perf` context manager, e.g.
with node.profile_with_perf("send-big-msgs"):
# Perform activity on the node you're interested in profiling, e.g.:
for _ in range(10000):
- node.p2ps[0].send_message(some_large_message)
+ node.p2ps[0].send_without_ping(some_large_message)
```
To see useful textual output, run
diff --git a/test/functional/data/README.md b/test/functional/data/README.md
index eb217d6071..bb03422f95 100644
--- a/test/functional/data/README.md
+++ b/test/functional/data/README.md
@@ -32,7 +32,7 @@ pkh(xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg
It uses `pkh()` because `tr()` outputs at low heights are not spendable (`unexpected-witness`).
-This makes each block determinisic except for its timestamp and nonce, which
+This makes each block deterministic except for its timestamp and nonce, which
are stored in `mainnet_alt.json` and used to reconstruct the chain without
having to redo the proof-of-work.
diff --git a/test/functional/data/blockheader_testnet3.hex b/test/functional/data/blockheader_testnet3.hex
deleted file mode 100644
index 882133aa2b..0000000000
--- a/test/functional/data/blockheader_testnet3.hex
+++ /dev/null
@@ -1,548 +0,0 @@
-fork:0000002043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea3309000000000943e54375082c03172552ae841bab31ebf2463484574f6ce6fe9c3723e3defb719a485dffff001db8b63209
-fork:00000020da2809ab72cf2502ecb29137dbe63e51fb82fb5babe6c9530dd86dea000000005dfcdc47012c19a2708b53e820c71b529f616a45529d48bad484948c84685d572d9c485dffff001dd3530a08
-0100000043497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000bac8b0fa927c0ac8234287e33c5f74d38d354820e24756ad709d7038fc5f31f020e7494dffff001d03e4b672
-0100000006128e87be8b1b4dea47a7247d5528d2702c96826c7a648497e773b800000000e241352e3bec0a95a6217e10c3abb54adfa05abb12c126695595580fb92e222032e7494dffff001d00d23534
-0100000020782a005255b657696ea057d5b98f34defcf75196f64f6eeac8026c0000000041ba5afc532aae03151b8aa87b65e1594f97504a768e010c98c0add79216247186e7494dffff001d058dc2b6
-0100000010befdc16d281e40ecec65b7c9976ddc8fd9bc9752da5827276e898b000000004c976d5776dda2da30d96ee810cd97d23ba852414990d64c4c720f977e651f2daae7494dffff001d02a97640
-01000000dde5b648f594fdd2ec1c4083762dd13b197bb1381e74b1fff90a5d8b00000000b3c6c6c1118c3b6abaa17c5aa74ee279089ad34dc3cec3640522737541cb016818e8494dffff001d02da84c0
-01000000a1213bd4754a6606444b97b5e8c46e9b7832773ff434bd5f87ac45bc00000000d1e7026986a9cd247b5b85a3f30ecbabb6d61840d0abb81f905c411d5fc145e831e8494dffff001d004138f9
-010000007b0a09f26fdde2c432167d8349681c7801d0128f4dfae4dc5e68336600000000c1d71f59ce4419c793eb829380a41dc1ad48c19fcb0083b8f67094d5cae263ad81e8494dffff001d004ddad5
-01000000a62bc0c08afc1d12e6c6a7eb4a464c848190ac0e44123d5fa63a9ee2000000000214335cde9edeb6aa0195f68c08e5e46b07043e24aeff51fd9a3ff992ce6976a0e8494dffff001d02f33927
-01000000f9e2142a93185496f7b21314d8b6fa736d0a30fa3a6d339ab3a1ba9c0000000061974472615d348df6de106dbaaa08cf4dec65e39cefc62af6097b967b9bea52fde8494dffff001d00ca48a2
-010000001e93aa99c8ff9749037d74a2207f299502fa81d56a4ea2ad5330ff50000000002ec2266c3249ce2e079059e0aec01a2d8d8306a468ad3f18f06051f2c3b1645435e9494dffff001d008918cf
-010000002e9afd58b91f15c3ec9eb0f01ed9d503134da1918b6bb416a9920e700000000029fb495afdb58f3a26d1c90fafec93aed840e2fa37ad6173ba1e7fadb7121ee57de9494dffff001d02e7f318
-0100000027e0ca29a9802c0a2390ecfa90a9bd814fecc54446510e155652dead000000007e8d5344557575c8f018cc62a32e8e0bd80638643b4ec34945ec4662fcab138142ea494dffff001d04acbc3c
-01000000001f3ada9b561378e324e80ee68facd5d232f72f773b86328393054700000000eaf3be35e3f0ace8b6abdeb5509d72999eae2329657238b53fa437e319c8e96b99ea494dffff001d027801a8
-01000000781bc7847e15c3b936a6a6a178e38fa29ee6e4916a8a62e10795c69200000000d44c3443fa8bd88bf32b94b9257f09ce6fb6ec0d5420504d631568f8685200dfa1ea494dffff001d01f781d0
-01000000133991a938b505ee8f6f347f313c3372d82a9d8b42b08b0dd0fc086400000000a0ef58c239e0197a65aa248c2cf52c437d8c8ea30d1b835e630a87c941f7d4e9adea494dffff001d030ef2e0
-0100000028d34cdb13e555032e4bec55fcce3d0fef8212803fb1bab851e1259400000000542c71544b9f28bd5a6fec95ecd509ae49d0b04f8718c685d0751f71d38285d0c3ea494dffff001d056b3115
-010000006b00cf1ce31b33fe1e2c4648a0834dedd972ffb2a2f341f75ad7cbc400000000adebf7afcbf176f765aec16b74d92896f55c3d65e14dd1a8becee0871000291751eb494dffff001d006f85e8
-0100000043a78ddf30a2d28a42cc66f90d13cb8211ee0fca9dbf8a4cce8c19fe000000004edbd2b89cb6d6fd69b575a62bd4e3103b1e0ce19e31bccf9a093ad8ccd753cf7deb494dffff001d0591a0b3
-01000000489ac81592595a4004e14331cb096ffef12b1daf709f6378e9c3558d00000000c757bebd6f2c2c071a3cf739a4cf98b27441809790a5cf40652b46df8a98a473b0eb494dffff001d011aedb6
-01000000a9c570a45d959023551f9a694ace9c12206174f21383f30949ca3b9b00000000eaf93dbbfb3551a1ff8b6bd5ba4cea7508e790c23cd07b9d9e791936a79d5fd4b3eb494dffff001d0385a7dd
-01000000d35d5fa860dc70c8bdaf12f18e16d8b4cc29d141c28d59cc317fe5ed00000000507dae091a9657b6c073863ca71ba6989a2cf4417fb81e940668568a35d34a7119ec494dffff001d00effec3
-0100000073379e3ff3dffd006e0090e52ac571a9a309490a23e64d15f8af291a0000000051f1c5b2b7c8f980e7715b4d3ce0180f99c44a16fc9c00ede2f5984b8d7cc22d16ed494dffff001d0082467f
-01000000869845a3343adddfa5b1f534b507d9b67c3685b0f1d89d526cdbd34200000000823623e8c6fe2c449065d2c0ae57aeb4bfd8e9687126a6c99d1ce916e2fca63f4ded494dffff001d034f940c
-010000005da49f64cf0025ab1111651d94748b00bdb00b780744b88b42f962c200000000fee9e254a5a74c858297e89ebcd2305ad2707a8acc131ad07f6abc0d8e38def969ee494dffff001d05c512e2
-010000006a65bc120bf3e6dfadc3b9543e48f8876cb826aed0d8f809bc34bb220000000090f489f48c88442aa7d9250f743b386558ba1fa2e7e240e5d32195d56cf1c34ffff0494dffff001d014394ce
-01000000e3f21ff9cc51ef282bf6bebc90e6f96968a36a704452192724c839bd00000000b6d553c98016b66fcb4856ffedc13a2de720288d4c2e8fed86206981259791a23af1494dffff001d017f7044
-01000000e16daff1b16a81a3058d982e79550c9c9ba84a207a8b84ae092eb4b300000000f2f34dd423f99930aee95815b2885906f9cdeaba04a9bb076c1f359c2031732059f1494dffff001d01b322bb
-0100000059ebd22dc26158414c60868355e78ab4b6891345fd97602f6c106d9c00000000e6c5bea3888e891bc5f9f8fcd166d332071d3b434e933763fb20db50e47dad3f5ef1494dffff001d0067a0e5
-0100000015ddbe82f202b27febceb00547dc19653604ef434f080848f22e3b0900000000e26e8971a53396413f0f39b88a697f593993999c8d07fa2dde608111fb2ccbd3daf1494dffff001d04362f37
-01000000a76595e37692f85d5de0438da8e75b5f611fd7b7071816b9ace8ba2b000000004cfb6d8faca8e8e77a71359d2cf0d12d2e52f266591f5fb807aa737c90869d2a81f2494dffff001d040e87a6
-01000000a774311853f32f32d87081529bb0506d5e4e90f7e455bb640081215f00000000228b387354daa9e5d38201811fe746591ab08a66bb3c4fc796a45535acb8c61baaf2494dffff001d01ebfd80
-01000000d0efaa4f6924659f1e0221f910e99f6fae76b36b759b212852d1343a000000005e40d3b65982e929433ee02037a60f05b62e70e6d51f608974fb1f2926169398bff2494dffff001d05c41c3a
-010000004c600547d8ed4b9dc946bb455f64917131dd98974bf2dfda05afc3a800000000e5b01ac4a611211847b0777b9ba9e396b0b7348ac401041e4fb6168ed091691ccef2494dffff001d037a60b7
-01000000f571553e5aa32b8374bd5a0f3c58834a46e05727b64dbe62a942376600000000a91cac1e92c7c597af565594565f5b54e658fd2e022e4fc35eb92aa165d9aa4fd3f2494dffff001d02687811
-01000000d8273e218df68e333782ab3b79929a8609404bd85bc225b46debba3700000000e91f9128f70a0502d338221316a0a3a1f4181821f9d2220c3fce7b5cf8e305d514f3494dffff001d01f22226
-01000000ad615025da247d14a4f092f21c4fddc6d1a84e0b4b0929f9ccf81c180000000069cabd55fc74596566ed1548b6b4ac23943d33e817028d8bc8695a7bba82256e6df3494dffff001d00e066e2
-01000000e7da808f2e62c3ec1b443e2979c972f5f69f32146cb4385bcb6fdca2000000002f4092fa4879ecc1a39471c41f8fae20f10ad2204bcda34e79ac37cbbda973757df3494dffff001d0316a8a6
-01000000928b86c36f27d22c7d2baf27f31b50bbec7754d33d12aa37342723db00000000ece3fdbc63b66327abb251165ac0e19b1a02fb79295c9b6eb8b38b68c1c59107dff4494dffff001d05bcddf0
-0100000088c96b45d3e252cdc38780843e3679d74e858a1d218f9e3e0866335e00000000432cba2143d62f6349faf4f7956f7354733518c22a309284d96236a9d8c9616e0ef5494dffff001d026ebb97
-01000000885d76fd42926155ff9ebb1d3c41a517d7beb70564b98c3608719f740000000011a3bb257acf328a5bf1258bbb653b88a40b2d2a66db695a1ff1aa9d31d5186590f5494dffff001d02bcabdb
-0100000093f416076c9b2eb0d147e8ce3bac03aa0784e44a6de6fc6f61183a2800000000be46ca90dd31022ee15f74c221208eadf1840e208a6adcaf127a60cc61d959c4d2f6494dffff001d02d68fd2
-01000000f9da861df4a86158e751c062e0a82d3c90e9038330f6447df4aee3d000000000972534907cdd1bc56f21adde0850dd17d988711a5c36ff81ec84610b4f762e9ae3f6494dffff001d00e96635
-01000000303a04a9f551e93a8ca88ceaba1c1d28892323564988ab7f99a9c0d70000000087a11f1aa5769968461b251ca9229f59acad999284e29976331cc13da46432364ff7494dffff001d012c54d2
-010000006b82062aabb19e4cc89addeded5c65ec28684cb54d30d463719f094800000000a98137fab92249e632091c38e3fe4c7fd8bba11bc956fe83c41357e217929e1e8ff7494dffff001d01edcd15
-01000000f7332e78d21adde6e52aa20362c71c1fd7bc745b3edff6e72497067500000000d521571198d3d2c4124b8bd9ba7842716b3bdd93236a92ca6af7c0a7adf9633c2df8494dffff001d031b1c13
-01000000c9ebcb8ea6f7e6a611117d0268639625cee28155c88708b4c09d4aea000000002d4c50f85979f0d2491d015206d867b273b353c253a173abf18dfbc5d96d088e50fa494dffff001d0397f4fc
-01000000562c889f95c49db05f6a33277aae9bfe68e92f00a5d6f67ac8c366a100000000b7b0896c4a53b6aab15282cf53e1119676d89be0eda11064cadc40dc8ec194dc66fa494dffff001d01f0369e
-01000000d41cef71d625aa5380f6cdc6452c67951e7e4f5b27b7904b4c2da413000000001c1e1096ab473aba614651fb98f47a375c03ec470daccff39a2d2d65bfd881b47bfa494dffff001d02454a15
-0100000095359a35957b89dd268576d562f49db7939baeda6de4855426ab5d9c000000006f68039da08fc314bcc71631be6f4b2ef5e0a2f9491fc078b11fad3dd49ac287a0fb494dffff001d02fbc213
-010000007d505f65addb5a3b50eb33cc5cd3bcafe03ee597c4027166aad2d2630000000090d221539ba3dabdcf0eacfa9d63f272c59dcc07e5e193271a24f4c11caf2c24d9fb494dffff001d05542cd6
-0100000013d5bb77b9235002acc75014e0c061c79de1752d3edc6859b4c0df7a000000000d17f332abe46c092877537ae764aa99e9b25d6bdd94f4007eac43f4861cf4675cfc494dffff001d02f62def
-01000000612ec5ae40cb2a58e18d3124fd70664a4fcb9329f7d268d4bcaefacb00000000f7bc31a9984831440cfae529df94ba1680fa15b4490454454920ea8947af4a3765fc494dffff001d01c6c1af
-01000000f13ce1836e92f0d12e4892eb229cbf6d50b9b2080af16b01f00b25de000000003f8f64092fddae84dad92736fb7d350e25bda6118bb1c660b06a4a5730fd352815fd494dffff001d055e65b0
-01000000ee24ae636bd70cadac603bf8cc631369bafbdfa8ac8effbc7dcb0fa5000000006faf8082545aef971aa4f92bd411947929c4949362300cd1302ec8bf74091fbe35fd494dffff001d0139a790
-010000006350a3cd2181f0eb75fa8c4022634ad85b6b9e1f9b7346a2eef5517900000000a09d738f407e2dcc888e8ecbde93458d8599720e0359a380d503ee56c688ef72f9fd494dffff001d02661caa
-01000000a29d92b014057dbff2775280b8bae8b3877fa9a345f4972034c0711b00000000447bae5734b6c67dc36ae088869c18740a836d7a9feff0b349efdd7373a21358fdfd494dffff001d01b13c06
-01000000dcbf4a9455bf33482c2e17640cb89711468c0def1ba9f6e26e5a4aed00000000b555247649a364adb88b07afac3aa2f9ddf5c379154cb17d22f69fd74c84a2e24afe494dffff001d03144aac
-010000000429b2aa02abcb8275705dc6482230dcb7c8678388fe7d75022c1ed800000000d5efd425dce6deb5750306ce8a0e5d045e0a607ee0b530866833e956dbeea0575ffe494dffff001d026ba2bb
-01000000871d8a30b3b39373d71fb9c5c7d8d7a3c005ad688d9c8ca974cd330e000000005ec14d2b9adfccae05f78556b12fe2ca03cddd8bd67896fa5c6b6fb090e90177a3fe494dffff001d0147b26b
-0100000019fd8a4e03a52e43322506693b696af00b828361e2a0968898708e43000000003853a270a7d9e6ad80fbf911146428c7ed63b2a1154df748f5a980fe20e9e8e2b3fe494dffff001d04538437
-01000000d250d67bd2679caba305e5e13698c7880098a1a4383c2f464fe9006d00000000d793e7c2c9416eae3d8d81046985db5f3d1df7922e869fda6ec5b22181ee46f725ff494dffff001d02391748
-010000009d83b8dbaae3dee980529b6dbd307df153a22b5b0fc35ea694a1faad000000003cfd458875824fadce673ca8c3125fd12c36b7230035b5f056a12d4e0d6b7e6b7eff494dffff001d0448653d
-01000000a7d1ff0415c1d1be8a11c7dc20557e001d2fd96c0f396f52969e330d00000000ca20885f915b1d3c5e614cf76067fcf8d9894204db63664d512806ceab58ea27d2ff494dffff001d0327cc00
-01000000d98a10f08f4a7aa698ba8564a85bf821b747c7a44f656fb2e3b9335f00000000dad4bbd7663a69c07ff9579434972bb203d0d78d07858ddc7ca32513101c964e3d004a4dffff001d04df7568
-0100000031965a378dbb0d024df444b3ebf894f370d28df8abdd54565b598b9e000000007ad93f6eed4656fa7c0a606c08b067be35dfa5392eda5d77f133dabdfd08739794004a4dffff001d04facfab
-0100000004cc9e4dad8b5d2166fb175e7bfe13ad56018dc81255d335336b8b38000000002d011ec2248c2899ca72a01673535807e2cd0fbcd4465ebafe2a002f3f6c9ec1a3004a4dffff001d04d4b0a1
-010000002093e7853950d588f1a36601643a97b7e187f6b7b274ae43d82410a6000000008ea10bf2d0d535c64d9db748aec8723566b270e0becacdb07438273654e59feea8004a4dffff001d04d4db49
-01000000eff17d4b5360e16151019597f732fc8f6e3b19ecf0c88e2ab1a2bd3a000000005d9b9c1d04856052c8f01497c9ce05d01c4c80c1c4296b15549ace3e04e2cc24e2004a4dffff001d02358897
-01000000bf5ea56c32a49508f0987cf0b18513d285edbe987b0dad25ceef3f1b00000000ba933ef648e2544227c7db41de45f0cf39aa612478c126e5ce5393668e230f1213014a4dffff001d044c6575
-0100000091ff63e6ab577bdc347fc87265fc316d53303bf28d0294a24791143300000000a97e4a6f79bb595fe0239f31549d5b06e13e7d5062e3707ebab0f38f0df5d1832e014a4dffff001d0083c449
-01000000bc749fb377c9a937702bd4ff35d376b43f5bc56726029a93a38e8232000000002bad8475b38ccd82eb98377132453c72706ae9626de3f913e8da2cca6795481166014a4dffff001d0594c61b
-01000000a02349924ea393906e7fe3ffc2b9d152fdf55bcc1bace5251517168100000000448e52c8902abd28f82f3ff5eec8c97ab16b71b61674713cbc4f9a896f733b5ba5014a4dffff001d05c09af9
-0100000011f5cea7297afda99c9a141c4d438ff7708f451b571b4aa57b4b69f00000000087550789e53e3c66c4ce24d145f615c95f593d7557fa3ae2eee2a1f985549f9bfc014a4dffff001d00e035ee
-010000004ba4c615f54d1557c5f691cb614cecb9edbad0011ebbd3b94fd458ee00000000c9782c5584bbe7c3a51f048dbf1e428e0b0e092607ea6514c401f13a45afd2b6cd024a4dffff001d049ecd2a
-01000000718886f10113146ac974a449c8b5bb205e0307f42d1b81990cf1991e00000000b88f0b4d80b631a24a15d7c640ecc15ee82188bb16d692be42467e21b3971c1421044a4dffff001d03e07f40
-0100000081fbffbf5c27e4e908c14bc8f303a4d91bb71ae05445e839c531ec81000000002aefeed1a7378f70e1f434bde89af706e1777993d25d9a95f5b4f4a0d83bcda8d8044a4dffff001d02cda9e0
-010000006d7f371b437cc054548511f0f9ec50b6e04bb4f3a4915a099c3bad36000000005b72bacbca2f6bb848d4753733f6427849b1aa4805b244e2751c38ff8d3e339c41054a4dffff001d0018ffae
-01000000b82c2d751368b79004a8e15e5b9f1bc7f620d5de2d6105d83d8ec2f6000000000cdfbd9bd57b78356abb0d07551b0c5c20d5258091604be05674d4d19455df2fb8054a4dffff001d003c4d86
-010000006efef1bc9d35256bbe500ee9c92230e0f987296e373e20ee7f3da4710000000030a2d3961a799e229a81337790254ebaefa055bb85ec7f03e5c8e9c3250eb35ad7054a4dffff001d0514a76d
-01000000e789ed685960b594652b9b83a28ded0995725d6ad82b2f358058cbe80000000035b73fb2084e2e8faa28334b17c12668004b7cc8965831aaba65b38b7c54ba97ff064a4dffff001d055247e5
-010000000606ede205a1002e0995f8d009de821d488e22fb37167bcc9120afbe00000000f6f0d5c7f8204a7142f2e37a7cb406e0a57fd7c9784c12111c55a1cde5418ed11a074a4dffff001d01a5f8d1
-010000006da3e0f7fa132425557519508e4e97cbec301a33e25d4b65ac054a0d00000000d657340c13f9f8accfc3af62529a25d3d9e656caf2993fd3166f73850f397c228e074a4dffff001d0309686d
-01000000cb9c32345bb264b3b2a6e96c8843f65c9598e4948737c569c0a00073000000000894a15ed694c745d87d2135f90eb9dcf8b454937b48c82132d52405e0d4c4689f074a4dffff001d02d5845a
-0100000095349f59ed0c0ce5ab0de43b9d55fbc7b8afac7eb6dacebeaaf290f100000000df9bf22064b03cf08e658257b5d19662fdbe3d7acd27894cef0d3f9ff5a657bbbc074a4dffff001d00a13d79
-010000000be1a15c8ae486da44f0585514eea60780091e52e35f838cd1572bf50000000077333896bed3021acee751bf0c073d95bbdc99125f4298c052db8998bf7c3270f9084a4dffff001d008f86bf
-01000000c0b7b630de7b1bd92c4be9d32e19faeadd68f60316ec97db96eaec0f000000005e3c98a964d941f4abd129531d0ee81cd5e7dc098179c3188ba36ccd1e5f9fff7e094a4dffff001d03d8a118
-01000000ae3c51439dc8f2bdd807e1d88c25a5a0b1a3005bcbb50bbb4e48493f00000000ac719d460d514cc4489597ac78e995276865ac07d7606a313c12b16e769b9294f50a4a4dffff001d04735f73
-01000000ce12350c698e84085e7b62c039249c63cb6a6cc9404776c9cc7fba8800000000ca128b2e74fafb345ad249d61c538f75a2a230bbf2266d470d47986555894deb370b4a4dffff001d001c0a17
-010000003dcca8252a636d4c0b8bc4ed9285b749434aaebc29965fc691a635ea00000000baebe5ae323c2bc5c316f6a8f1947b4666c7707c9ae127a03e6429fea7624ae53b0b4a4dffff001d00b4a44c
-01000000f6cd7f4cec06d5c6aea54e64b45f049640680e4cb8249cf18587b314000000004a1b2b51da86ee82eadce5d3b852aa8f9b3e63106d877e129c5cf450b47f5c02480c4a4dffff001d02552721
-01000000c64e139bfae4adcd96860bbef3969b84851dc4d4fd8d06f16cd03698000000005e4b195fd24b314f69f7bb5b0139861b0f07a1286b8f6f42dbb6c82524bfdb93890c4a4dffff001d033b3297
-01000000a3e811a098612235feb5e1acb407cd98132a9d5f4dd99aa8d8b576ea0000000025a13ad0cce0eeae69ddb545bda3b490230e68dbf0687af3ddfa132caebadd7cb30c4a4dffff001d04a39aa9
-01000000ab5ab86fe14c9c765d8cdfd67f9bd5d41505f9f9f67e4da1851f099700000000beb6740250c060fa7b472f4daea18186d47e266dfafc88f088d7efe3ca5a2ac1060d4a4dffff001d0511eae4
-010000006ee9f67721369cabaf6e3e9045b2efb70bc1344256dda634a92eec5200000000d5b0833f82460e5ea635a31c60314eec20bb317f2cdaf354023ed4225e31f264380e4a4dffff001d03a74f10
-01000000b3ef61423747695daed4acef8980b5ef4c8feaaa908b3fdc6fbecdab000000004fd416b35e12b775e2899ba509a06822ed8b6627311364f5195d32ca6a314dbb3d0e4a4dffff001d0255ab96
-010000001c75c30c7bb6391ec7d94f6d52bd2aeb0b8f5224907b0106791ccdd70000000016f86bf97a3dda131f108ab4ab456d5ed3cc5e67eec631d8fa044b95c19f3449410e4a4dffff001d048e1c98
-01000000a8bb0604235d5310973b23a5c797442a1ae8c07b96d8cd33c191b45300000000322948a4806acfeca2b32248d0e183c8eb09d5e5ef48adf33777307635414cc05b0e4a4dffff001d00edcc80
-010000004d37f2af0c42371bb77b52cfe7f539e550e126631dbae6056e54dec80000000014238140ff083fe67f0d5c0627857c4330c4c96187964f42b680ec460ad0ccd6620e4a4dffff001d048185d3
-0100000087e774423a88647a4567d3a15e7099b7f271d8d846066af9776ef4ca000000000d90cd436a707875c28222178146cb93f6b048dc4e7555cf37b96757e3b90a5b740e4a4dffff001d030ccab4
-010000002f3be6a1d59b7786d8601330a47f030fcdf2354275fbafa8f4c129490000000098a23359c17ca2678e2039c8ff9081b18c4913749c9a081ac3f62958f09fa472e10e4a4dffff001d00c7fe6b
-0100000050ac3cacdb94018a26258b82299da1307ccf3e2bf62a8f4acc19e02c00000000e09f513a024d3e13473d7a65f79073b36a90cc228613672d2a47812368ff42d1df0f4a4dffff001d007f726d
-010000000e044393202d6b239c902d3f634e3dfdfa31ae439d339238ab1688e30000000055b5d3d496e196d624a471b818ba0b1778417ae335a544033536654fdda3eef6e80f4a4dffff001d03ed4240
-010000006396e6ba5ef4924d42f4f3114ec7507b81bce51e9e2eb51ca9c53c420000000049af9208af7b7a06d65ce1cfcab6ad9123a8dd7538fb0aca332c63429ff48d59ee0f4a4dffff001d056528d3
-01000000497b15826573b28c3e83a5d0c5ed30cf48b97dd6bd797849144ea2400000000018b50db063333a3261b9b41e887b4aa5b69becdc9967550507c120e22a76496710104a4dffff001d0408eda5
-01000000f5ddc74872eb899f5113e002f642e7b507f871d99a9900edba304aa0000000008f6546b850a14744afc3fe55f76f3959f40799bf4dcefe01ae4dba5903cf2fb553104a4dffff001d018f658e
-01000000918a758ed54c9f495edb24ef3fe0f4432ede25853c324fc0f33a458f000000007a8e49b22114f17b5933fc7a8005421ff8370b8c48fa04c24323e91bd02d701492104a4dffff001d053e6e0f
-0100000035893f7cdeb0e9af7d9fbda1584ef6d5219dfbb141b07b31257a1658000000008b9b3abfbe24d0e375deebb5f41e74949203c00772a678ba69c1126156c5489bfa104a4dffff001d012a69fb
-01000000b6f8c48e94ca346b12373281acbaa08fa54d1cfdcd9c01e020cdda9f00000000be5b4753c6062e3eaed75f5412e43d6dce8d242c5816b436689f795f90536f28cf114a4dffff001d01b6887f
-010000006006db00d70ce04a9940c203dc865b3c5d070f8c2d1295498ccd6c32000000008bc41e410a44b764dacb38c1138a3ff2c038a188a063509c6fed4aacaae72ee67b124a4dffff001d009531e5
-010000005e0dc170558d7b2872ddc85f481531dd823dffa66cc620c065adef7700000000e82e91ade6f25c8c6f4c053aa62d94926324ced07ba2f3aae072b13a2c5dc5f89e124a4dffff001d05ae2281
-0100000056320cab20bc1daf4fe3cf0115f2436523e44c40ebcf8c18e6b5822f00000000ce415eab9cba354ae042c22ac9f06c1a69d7a5dba67136fabef93d82f374dd3e01134a4dffff001d05a0d736
-01000000ccb063ab7d74a4030fd155615f046f95c8068078557568ce6b8092fc00000000ff33b27214141ef3d183b1d2499666c8635a57943ef5f515f4e60515f9ea0064c1134a4dffff001d021fa95a
-010000007f6d7a61bd46dd27be404b8c883b812c2899095462591dcd75a96f1e0000000091777c00b7168a888d7a7db4b5f78758129e79ef909f92a84110b9f33f9c4c5505144a4dffff001d03526c4d
-010000006be8cfe3e176d34d1a46f68b7d20a01ad3f9e2aa6f7540ef6a32573c00000000a870da2f87071c1366a22e77c829a6b85d745ab2279e0333872518d58b8dc0181a144a4dffff001d042c5db7
-010000009cb87223258aba43742de401d0157ee2b4057da95b23e1665880725700000000d54d368cd4243da3793fe3ba2af1570dd44a905d77ecd1a5cbd07cb8f72ad80f30144a4dffff001d048f280c
-0100000052b771a3a85c26bc796ae0841ae894c6ad4527b062c94812d98b9c5800000000eeed0f4d975db8f66788f809ecf8c351d19ff5805276ef31983bc5682548342d52144a4dffff001d01aa3be1
-010000007ca07eb5637ef7696d7bf985b9114de19317a9abdfbe4ee79d8bcb1a00000000d7172956946d5547bd98c6a7040d353c3cb6285fbad096a1780f3b7503539adf3b154a4dffff001d0333fec4
-01000000326f947390bf03abdda16f673d26326d4b159e0b7f732a67286ba8e40000000085701296d47b03f388fd85431c2a9fc817afc9b24870a9a7da850d3a43a8154b71154a4dffff001d0164b7d2
-01000000a45af68df42f6f23ecc47e1cd0f41d47c1e5a26e8343951f9881e51400000000b7c1565d19d406d8c56448571d7e7da2ac559bf9b43887e16e4f416276ccb99b8e164a4dffff001d02ec606d
-010000007eaec4cfdb152a8ecf8ec155b7343e2cc04750be00b96c61a477e57c00000000096a9263a5008a48e1c2b527b922a81cfc269fd401ce429976c587a951ff00798b174a4dffff001d015bd123
-01000000db36ec19328691975cb8c6666866be64b5be79ae42bee9fce3b5db5800000000b5e73d7d102476db3ca2379bdd891b311140b49626ef42937356ccdb8fed589103184a4dffff001d032d07eb
-01000000d8f8a6686ecdeac529caa3ab9ecfa84a5fb62b06849ee09b8331d89e0000000038b408676c2a78fc63ddc1807804d17e8ad9433387cc3cc0edd68c07e4a714b610184a4dffff001d0437e51c
-01000000c54675276e0401706aa93db6494dd7d1058b19424f23c8d7c01076da000000001c4375c8056b0ded0fa3d7fc1b5511eaf53216aed72ea95e1b5d19eccbe855f91a184a4dffff001d0336a226
-01000000bca72b7ccb44f1f0dd803f2c321143c9dda7f5a2a6ed87c76aac918a000000004266985f02f11bdffa559a233f5600c95c04bd70340e75673cadaf3ef6ac72b448194a4dffff001d035c84d8
-01000000769d6d6e4672a620669baa56dd39d066523e461762ad3610fb2055b400000000c50652340352ad79b799b870e3fa2c80804d0fc54063b413e0e2d6dc66ca3f9a55194a4dffff001d022510a4
-01000000e846583e9bd64108b3b89ad3883bec7731ddf1688a4cc8f79530fed800000000d2954cb816c87a9572bf822138dc84b5f6847fb502cce3d6073f9ffe40588571a1194a4dffff001d045d675b
-010000001d72012c553d72f1f75863310ac0450e53a9e9026b9bf9556ca024ee000000001b7142acd57304290a2ade0e2c96d4fbd3ec924a02a5a0cd30c04f0e96265423ef194a4dffff001d041600b6
-01000000d2c5dfbfa04c7b67457c58f55a8d190dc5f8ec5ab94af969dfb748ba0000000069492041bb66f32c9bd69b74e7ba9bff6d4122e931eacf9c89b45eca2c35eb25211a4a4dffff001d03bca431
-01000000880be932720bbf22f1b14da0e6d16c2773f83699935d390e8621533f000000000f5d2500bce42137fe905225ed9a7380eceb7445c89011bfcc740cf2e9985a034e1a4a4dffff001d03d30924
-0100000000b0b174d61c08a92313345717ca7776a75cb67b77662c04ea7d3e2b00000000c8ac0a2fb1c01e0e0a5339d296eb072b2b9f9cb1d410a1fdd69a2c797094dda56c1a4a4dffff001d05225e37
-0100000089535760639df16a512f9caed73be0edf8c9b5466fcea14336f4a1bc000000001527b6224d45722c8ee351976c69c8fca59c11d3daef7abf1d189aab0e959f7ba71b4a4dffff001d0551b67c
-01000000a61d5d887f8fd4c86f7111c2c5a4d0d593665b527cdf84dac7a0d57d0000000069b7df87a13603be78ccb048370aa1d2da0969f3b1822791d24aa921f8e268ffc51b4a4dffff001d055313f2
-010000007f678f2bbdae181d396123431faacd0b956633c30a55a9595ae6657f0000000085daad94e57797b9340c299e483531dfcd0f3c6996da98ffb2ab31bbe34e346a001c4a4dffff001d03ef37a0
-0100000054112b758ce49f1fd22d613250599ffe92c48202b6a477b9289f3d7900000000006302548e973a0d5764711fe84e1900dccedad0de9f054fbaaed3735b70ed62391c4a4dffff001d057c8c98
-01000000bb142886ff32916975d060c649c9119aca0b47e3f169acd3b7f1b9dd00000000ff166532d3f30299c5a82856e3411957dbe35fe7e17c4f58b92b2ef12c399dd7d41c4a4dffff001d04a2a121
-0100000029a936f51d08ad1f1353890300131fb7c04e20606eb48197dc863eb200000000c7bffe64778d6b4815226c6aab915985d8937fb0d3aaaa983bb513c69305caade61c4a4dffff001d0514cd03
-010000007d16758418920cd6d81283aa30108f20f37dc7114076e23025bb881800000000bda8c051f6e99590cbea0919b7a4189e4d3620ff3f46caa4b797fd52e204ff1fcc1d4a4dffff001d047ea807
-0100000087a6243ae1dc858cf91caf8a1f92dc473bdb14203c573b9d9bc134cb000000004caa084ebef276e6c454dff401271b39e55da21a8cd5a3afdf2d0e0f94b94a2dda1d4a4dffff001d039d9a6d
-010000002d0a1a0b18f1f74ee797beef1bd4766a050a3480b5d7457303b5c54e00000000955ec547d5ff2bcbb3c9f108828e431a674576e1de0b8da794bfa3a70b794281ef1d4a4dffff001d0019c619
-0100000060500ea2003736b74596d4a507f5cf001daa55e7c93b53c77d32a32e00000000c545bbc6ae68433be1fbbf0ebf59f22751af853d0a6fd6c944458aa73ec7a014f71d4a4dffff001d03d8b5ea
-01000000cc3d1b428029cae46634a9b96857475b2bc59619b8408e615f65b7b9000000003563548d04e24c89e7706a3f4ad681bebb3017133e87f7434d824db4e51f479b891e4a4dffff001d038a2031
-0100000073da9ccb3fdbdb4a9e3723a4bd5270c70ef3e78f448fad7e77a8eda0000000001f0a3749af61eeb59aff1499892c6641d1a464a26c156608d02cb74c264786ccfe1e4a4dffff001d0284512b
-01000000ef5a98df2a193c1f8a5c271dc4d45de465b7122dfeefe96fedad105100000000cf330295467623ec1378dc6fa312103ad8a210b3e1351f2f4b6a57ac43fcd472071f4a4dffff001d050ac986
-0100000048256cc5b9ec6e7a12c378c93c1dd2ada859c9a9997adca75166c935000000008e3430573cfde2f3e1eece8aefe661dd841bcb665d35832415bab4f7526785229a1f4a4dffff001d02ae4b52
-01000000eb5d7c4b706d8891ddae3ba5bb57fcf509689fbc196f3ef73837f27b00000000226e90ccf96f41e04f011e69a86e18e96c09df6fbba19416132247f1d2a6e4073b204a4dffff001d0488c17c
-01000000e5214de98aa5cdf1766c5129649895816f49ec82e93c4bbda787897f000000000abd68f73823585582e65529a8739e90bd943fc4e214ac00a20ca0369b70d45d7d204a4dffff001d041786ab
-01000000fd4fc04cdc29aaa117b16b2420aadb9bb92fd19ef2a7aec3c40f71250000000078e5266df52051011f39eb29939c8782564563c20b3856f7aaafa6dc52921359e8204a4dffff001d0205fe6e
-010000007252c67173d343874ecfab4d5f57ab5936f2d87f173047c99c20e73500000000d2b61f338da6ac531884c623db2804c0d7eeb84263b501524cbab6d5edfdf56f00214a4dffff001d0027a318
-010000005a7746eb6d1d19cdb24466e0a87a23b6ba8c2e461ba8928edb84253b00000000f1b03cf0680b9ef33fd311f6bbc6db3f1c164f9341f48a02df1905cec4ce241b2e214a4dffff001d03246ebd
-01000000e93f1fd6ddca6d8fdc3ef50fe0f31769200f8fde592a0d5d6f8e1d290000000078966e9f0a2d4452ab2418249fa6fb1a325a04f039d015899141a82aa5a6c05c92224a4dffff001d01d8361e
-01000000dd5f3ae3d2c2876ffbfe0956b914fe72750b160b667b5bef5aaee61400000000434d2b0f298874c3f6d8467c07dea6883a650de00d48298cd6fb48e8322e1058b4234a4dffff001d0161f3ff
-01000000f814899e7f50c4494806f75523c9d8ea6c0198d13f1f14431fb541ff000000005b1015187325285e42c022e0c8388c0bd00a7efb0b28cd0828a5e9575bc040011d244a4dffff001d0579aa5d
-010000000f72c6372c87d91f2df95b0c9e91cafab596f29270cb01cc67186040000000001fe6898ac074a680fe7458ff87a03956db73a880d2ace6539efcc43002bd97ed87244a4dffff001d0434b3b7
-010000007cb39114d2372ca1d5dbcc3a1137cf9314a666349dd79b268be1f15100000000b17cb4572964d7c6d671e7cc67b04b9fb1b68b31e52e6b4f956f3a0b72ccc4ccc5244a4dffff001d057875e3
-01000000f8d8634fa1aab0666f63fbebfd61e0ffc1dcc647e218414c528e17dd0000000073a2c54d536c19f0d09156efbad18ca6f96b1e9f3bc8490342958f24ed8fc32d28254a4dffff001d0130c923
-01000000943aae5118b0abf4ff55e050b234c21d223871e815e9fae6fdaf693c000000006fd85c0213cfe9863573596a4d5f1509ac41a91b572e6c1bdafe46d9249a5fa4e9254a4dffff001d05878bcb
-010000006c6040618ce7a449cc26ad0578a7c897b4464ee32260014fc5ce6bf20000000096567fa4ac682f9bec7e646452d3bd69088000b19bf7a90eaccc197b632fa79bf3254a4dffff001d02a22cd0
-01000000c067deb4fa218c0f26a247766a969af8a475e5c88c004c300c1c69b100000000ec5a827a707edd70451f070665bf6a9e6f4dd8f815b0265296790f24024142b181264a4dffff001d00e76cbc
-010000005cba08b87cefedceed1e60297564a3eb9e9e2bf942bf63f74fdd7f3300000000e3082dfad468d5c0c8e2f8857a999f898081c8cf59e48857997152445a57218095264a4dffff001d05a30a7d
-010000001dcc225203fab8d972215ad2311203570fe49707799e6871908e37d900000000cea1cec6febbeb980af51f052dc20065b95b2d65520205616a95284480a4219abf264a4dffff001d01b05d9b
-01000000644fa81c1f8c64f08712b41b616a24d3e8af833a4f370c188068133a0000000069f2096bbede7015fee2fb307f7d7dd084641b7f4af5c3074dc7b2b6df03277c80274a4dffff001d01dcf233
-01000000ba750a8cc870173cd7f17dff4c23c228282d9aebc2bbd5ebd9449c7b00000000b28b51c3a1a322c8e29c2b6808ded7981dc085cd7fb529184eff6ce556e09ccefc274a4dffff001d02c039a8
-01000000e0f40d912882e77044fee84e325fdfffbb3aa0fb1fe6ba864d5be65d000000006141e05ebe4e62fc76d0c9f1e61a4d17e6509209309f6fdbaab476fa227f1f4fc9284a4dffff001d0306d223
-0100000003e8e5f89f6d5ee55c6e8ee0d4c1e88d8e4a3a5f05f0c9ec32d580e5000000004e2b02e05fea22c5067327060d3c00482569021252423d372cad30746408d0fcea284a4dffff001d0410f81a
-01000000f389178af7b0ea88a83ae251392f7eb336771c8d7ae666d1219f2455000000005f98a8017e8458e6081be384b89f4ed68a6aaee5ac41cc0ad2331929e657deb27b294a4dffff001d04c90ab8
-01000000d8cec9c7b6dd3093ad29b64c234258bce36693f87a4167d6234342cb00000000d5cfb9095ceb210b374686dfc11fb8d8c7932c30b4a3916c7fa4fa7b760a0831122a4a4dffff001d01708f58
-01000000d850850454d9b392ab01e886bacb717a5615f8f70b6a4ef9bf788df50000000075f11e157a482aa640ea8dc7e038ffcbff0e9aa758ff092222fabc325b9c1a56152a4a4dffff001d021f806d
-010000003cf1b7fbfa5978d5ce1cae5a5f454d41f840cebb72ad3d600f551901000000004503bb32aa7568d6abb1df7a05b80be6ffad47e5a55886488736b5c344a41d431f2a4a4dffff001d048df744
-010000002d7f6a8f2dec6f914a7a63052facc546567fbb02742dddb150427ab10000000031ea5d7ad7f128ec4daa2855b7944503da503818a75f049dd6980e636aaf59af242a4a4dffff001d017a6543
-010000008976cdb2c5a16c0929b45f29784ad52cf3db3035f112e562ed42447700000000bee2958fb6624ca2382e4a6a1bd7aedc2c58edcb7266a106c76d4504fd39eb89682a4a4dffff001d04d4a620
-01000000d6d7f91896014f1f4419628791a5bc39263704165d3e14e23895f57b000000001ae0ce43e200fa010ca331ee891ce9ee93d468c602703a23ca2eeb693c1e05e1862a4a4dffff001d025a8bf1
-010000002be250378c6001da52d435aaa1240522ccb14a94880ff0e0d1eee82a0000000046297804a9aabf1d08096b034a84364055573c45d09be862c33ae30beb3b5ab5ae2a4a4dffff001d01a34339
-01000000064ac21081e5a5c6509f634ffae17551bd322e46d3396ac49b8d68b300000000d15854d1e5ba349daf72089f470b24557a2be25105b7831a3f18a62fb8bab677342c4a4dffff001d050c273a
-01000000ad1cbb656f4799fd8e9de9acb70a47d589ef5311dadade94c494ff60000000007546bbac9ae1c8980da6e8c154b368eb4df305b6f3f27ff38f195a13c9ee0484922c4a4dffff001d059b5c46
-010000009f0d835251ab6812b04939a5889a36d50f4d7486ef98a7f61e45f062000000008dab4ee487e33f872140c04372bbdb6c573b7e9e4ec31cb5d8dff36da17bd8f20d2d4a4dffff001d016572b5
-01000000d1105edb3d0105e862f3bc95a034c0d0815a79505b4b68fdcce9083e0000000061573706774bc7a579a7968281e10612b4551195e16c8051381cdd3a6f93f479292d4a4dffff001d039dfead
-01000000d1e7c872bf92ed9d9007926fbe72d976079ae35efd6f81ba4101a98600000000b4bbecee818dd986e5ab82f36dbd5ccc29ab134614e304c0a397e14082fe7bb73e2d4a4dffff001d00b8c45f
-010000009287b073f80a1a91caa1f664b8c9c578837f878e6ff04108db28d9c8000000007dc81aba2560e72756db13b1e427c9fb4bdec85486c65da8aca5bf968a5bf51e412d4a4dffff001d03a98277
-01000000a3f00f008ca15686450bda91266f8d01a99f345c7846e9e5bfcc2628000000005ac244c2a763cbc311a245df0d6f98a29e187165048a9da449d29edddf6b1923d42d4a4dffff001d02df0172
-0100000012ced3b143532ef3999faae421b6bd79c8ad62a4dc8db862cb05bbf70000000060e6e42fad3fdc3d353a22f1699b5ead453eb11343a0e603ffd8c77cdc773be2892e4a4dffff001d04945d60
-01000000f0c39624b690456af00d742f323762471854e1db5c96099adad5e53d00000000a2367f2d2214ef900583269eb812ed05d4a8aba11d40081eef999ef16af1d5ebd72e4a4dffff001d02d98796
-01000000294a2e12b2716816a62d761c624248fcc10ae22cc1a80290432c85cb00000000fc4f1ed498c5f31fe90b10389f12566a3350a5080db1dba1f01f8834e5813ca9e42e4a4dffff001d054ad0b6
-01000000774ed03a366b9909cb163ca0178cc6b42847461c4a672a537fb7aee600000000225666176205fe41ad268ba6f5d15633a5381c18fbb6cd2f83700ef928c58fd7362f4a4dffff001d04928537
-0100000083900a5d5ac952d05976df43ee7e280faf6105038a4afa75c4d8a2a50000000091cd49f33c9f5b51fc61790d25539d2e896e87c8c195cf305b499bdf42e029a0d82f4a4dffff001d03994aeb
-0100000010336b8cdbaaa1bd6ba9b1e41e85e17bec5b68bc8ff043e5731ed09200000000fc5eecfa90d46aeeda36bb1a2f2da61e4f9be81253033ae55625d00acb13ef35f92f4a4dffff001d049e0a22
-01000000ec5b52a76675e3b1de2e75ad45d6498684a0e81092c5ee36e7fbf60b00000000474d71b72f905a8084842ce4202c2ab9795f3abcf51aa7c458349d21eb6e310498304a4dffff001d015d80bc
-010000007af7e899b49494f77c351fe434981ad8b6352ad62527ed9d6d23a8a700000000bcc43ee02af281701574077d6916c07d6bd15cb96c623f6f304de260f616bd57ec304a4dffff001d03a0956e
-01000000f22be93799f6fd1527bfa224601261300d38571dddedd804c0c7b94e00000000ca1cb89732eb51c0ace08a564445a2ee762a2cc819209886cd0a09993951544ffb314a4dffff001d03b10c74
-0100000099146a7924d99cd7a2c1e17ce7206712a8349399b34ec98eb706d3b3000000002c4fb29a89bfe568586dd52c4db39c3daed014bce2d94f66d79dadb82bd8300024324a4dffff001d04edf452
-01000000e5139dd4cf7511d9eddccb69d2c7aa0917cbe49eb660fe9293667aa80000000068e91b23282bef6f06f22e479587d03f6e1a2e4891b5d644541f1e10275e52e142324a4dffff001d03ef54c9
-0100000052a5c0e3a6cc34383a58d939053af3261acf266ba6cfd3165435bb2f00000000a32d9b10b7b75323db98d486828a5ea4f9e7a2609b76e496f6d86e0ab13a31587c324a4dffff001d0031025a
-010000002ed6742b063239cad1841ce6bcf676a59c66e65eb4a0ccf68ac4eceb00000000efbe4df65aa1137ba3efae5236178fe6646d6eb96a177d5394bba48066a87448a7324a4dffff001d053cfc69
-010000004d4a3f638bb32808c3667937b3a0847eb780a3b3fe70875027adac3e000000000ecc7b73d8cd5d377d74d836bb6e3473478554a923154286ddaf6985948fd9d3f9324a4dffff001d05bead3d
-010000007b86d803ae4a477ebf754711cab10b1b7799dcd50fdd6f25cec45e1c0000000033c06971fe80386570f8daafda6e4ab7e72a18624e211481e7b96633c625a52b3a334a4dffff001d01146b3f
-0100000034231ba96cab51515ffaa9831930a46d1a8df9bb83d343690edd9ca000000000848736034ba62c9f4f3410b11d2a5ec921592f40b2ad6b1d442ecb3188049e27f5334a4dffff001d00a7bc36
-010000009427d53219ae3be5d968cd3dbe9f52232b0b32f662bbf74b4c2cab8f00000000755e1e0417036010faf0520d2524c806dda1e3fce2ea99dd4e70a42efe44f64011344a4dffff001d02c03350
-01000000db9740f3109d4450584d3223ec605be1f62457d8af2c22671b93b260000000009e93a056a6515e7916fc049578708d188c2146d3c12638acac92e0b72e076edd72344a4dffff001d037e783f
-01000000de444daddd51d48d32e2119e59629110ecb69dda27ba85d7e85d40e00000000069b02fd420c2e86a575941a89e46d174a4e0fbc1379dbd6f6d88f3ee58613e5087344a4dffff001d001d016a
-01000000a173420cdd0ccf0695a0a341d4f8cd0dc7cd8fd3aa3d01b68066561400000000cf0fb8b5f6fe33f698450ec147ef896ad953e677b4033e50400ec15454d3067fde344a4dffff001d03475525
-01000000343f2b87a053dfebef86bf7108c93e449c6e289e71a75489fe6125130000000088d412c44abb44236383afd182862dde877813143d21d92a3cc373d4bd4017455c354a4dffff001d02b22dbe
-010000004375b71a891e69ba37f9c0cc54373be6796f43ba90b16b12564414a400000000e3abf5981a1bd6457ec0cdcab76cc2a176dc0d7e16f6d3781aebc684f13cc4fd81354a4dffff001d00caa9dc
-01000000f7b2f9d9a6f44012728b6e09c48750838780f1e1cac9cbaa09e011420000000014bdd0dbddd8e6c917324a49df6459de897031f514b77999c8476d287e47f23b84354a4dffff001d026719b9
-01000000a688cd51d1d4a0cf1b438ae4347bd2e0b07fef348ddeb6a4168f71e000000000e7da7a46f5efaf4fc835468b21620987dbdf8b5f66daa0ffefcca5b0cae2e533a8354a4dffff001d0017ef75
-0100000010f5b842b85241ab32f795ad605ee899389c64c77126503e8eba7f4d00000000df686a7f31c2c1de6a608553b26d6336434719fa45428eb3df59bbef75ce9e7ecf354a4dffff001d02e94089
-01000000ee47f9bf0d5d6d59bafc6ade45ae6da0702b2ae98b792f7a6b95d13f000000009c13741588ce9e729f1b29b82823a97da91a3c6bb89d03c9b33c6cda9d71f0aedc354a4dffff001d00ab6a3b
-01000000a0396d99b1042613554a8fe19f38a485daa2eb5b65f5347f3375a838000000008985dce081d487c7eb8f8b871738869922dd73120c75242333c45895bb91e64638364a4dffff001d04d09fc0
-010000000787ce301e6110773cfffc92ae93a3e017ce136ac2fbe2004bfd06ad0000000069ed55457af8174da637b03acdfcaaaa36cf822ec6e72145526cbfc03a6a83f546364a4dffff001d02fc547b
-01000000ae76485a78a7a225541cf8025578b9085d39b45d7c2f68669f05eb7c000000005ebf1334d253dd7a7ee381625bc200973e7af65a8a022de034d6955e37823c628b364a4dffff001d06e25145
-0100000057ccd09f8dfb8ff31d4ec9e743ce56ed5c5c501046d709f49c356f08000000003f818cdbb02b1a468aa23e9795f7518ca5a92276559fc40bca459a79e010bee2f7364a4dffff001d04a53656
-0100000042284cac669ab917936f5b96469048d55214c074eee3c7aec95a07f200000000334a4de0559a4db974ee451fe484a0376a44470a1495797992b9a6a0ec7b24cea5374a4dffff001d03a8bda4
-010000005d820c5c53908a13f372a860b57050b9c60ac3360a7bc865fec2029200000000d29036af962f1d725133c89721cc7dea6d3cffda3a529c82e39397027aad7efbce374a4dffff001d02146600
-010000003c3b2d4120567d650494757e86595b7e9c70223af627fa1857ae9cd000000000a4f56464ac27919b3cf8c9ae4390e679cbb2f878dd7098057431c0d92171fb29d7374a4dffff001d01dfdf26
-010000007e74fa0f82027865fdf1aa434e494c2a60e6a9e1b70d2f7c4fc21ae5000000008a360dec0defc12a33c3d959a7ed168aff8e34547db15b516e1b8cca754c0de543384a4dffff001d0568ea46
-010000004960b70d04579667192055ae5e019eae175dd65050e58be04d10b7f5000000002eb73ccd1a64ddd448405955586fe5c95bc54928eb34679f74bfb4c9da8e1b92aa384a4dffff001d00cfcabe
-010000008954c37766bb7293e105c476cf2b320cf9932b9543b1398823757c0400000000f85f4ed98adf68f14127aea968a338f2109597b484a808dfc8638112ad0623428f394a4dffff001d036b2da4
-0100000052d3ed4b6951d3d5db9100bf46b7dbfb177917539341431898a0aa5700000000d226fea91b99c5a31a034d340f647b722e50950c96a876eb96569efaeaf3b227a13a4a4dffff001d0051797f
-010000002d54616f93e70461538548ac861c860a8bb9077c3452be5b4c00d4c5000000003f88cda74f26fa4ceb0a97161e771a8b1f6caff1069f7b53ab49386916f3820b213b4a4dffff001d024510e3
-01000000e226b7f57fe7d32fc6166057172a4c2931bd4bc3b619a036df08c95a000000005b7df01117c335ca3e8a802376e171e537f090dbe2e3bd1fc291e45e219a8717323b4a4dffff001d05d6def5
-010000005412ebec87fb8c61287f1d2fa1c52617ded826adec22368b84c42bb5000000007992420cd0f0f24840c8d92a4a865e6c906e473c23f1cbe3c183de70c2b2bf42453b4a4dffff001d02a246ad
-01000000ba24ca40c17418d7bab5a3cac3c0bf00b9d3a0c09ec5771d0b14015c00000000a30e3f1429bf2a8ed14ca6ec9f3396b8593b8bb6ac1e4d35bd435f05058094ea983b4a4dffff001d02c75930
-010000006e823e852756b7106a0ba02b1b51045d87582001c006a2e8807cd612000000003c11b146d43fd62ec36b733942a52ba0c352c95a3f078808a38d080898cb8330dd3b4a4dffff001d053f9e6a
-010000003f03adc125b43a2c8cf9d47ac43dc81fddbcf12ffccc11ebb226520300000000b17c3beacfe667f4014c9da9057fdb6252978fa76dc4dc2d9ddef0562d293d39333c4a4dffff001d0467b375
-010000002bdffedf5912eb0e14baefa637c22cd523c8eb4147bb111db143ce9c00000000e24fd45c98a5b07ef9b236be48aaa1085b1bdf993a1c0db1dc04766895b8a2fb813c4a4dffff001d01c464fc
-0100000011c1b397772463dcb8430f661d548b3c55c61d415918681d6c4d4180000000008c32f04b4b70f43c849a8f424c3a82352cc0bc6bb25b2c2ec4a039964ea563c4893c4a4dffff001d05292e68
-01000000a0e705a21be059d1f8780cdcea04e7008b7497cfe8faa0fb59a666600000000059f060dbd892c1499758c7ce9bf8779d8e4dc298484ceeeca6467c17769fad5ccf3c4a4dffff001d013a65ce
-01000000492c5c9b8543822db5ad8694cce758fa2019bd5b6f12db4160bee95b00000000f640c60ea438dc020048599869836f5323ef47477ee17caddf076ed428898f71da3c4a4dffff001d0065ac66
-0100000095e3a7f3bdbcfd7a40901eefd95edb7d6d60562f6a427f7986d0861e0000000059ac3c37adfa89b9a907ef9d485c57262e9283e1eb96069c2de04369ef1b3c76e23c4a4dffff001d046e85da
-010000000a3f0effcb7af394aacaaa6e2383ec478034ae4ec4d488e47153d21000000000e25e353605728130ebf943b1f468937fc489589975c13765fd677e5050b487df2f3d4a4dffff001d00fe3805
-01000000a1f0d96d647241f42d4a3e02ea933690a4cc33542ed89de511c914c600000000153aef1fb8837f74a82054a0d9df9c566ea9d50df292ff62288082f311dd4212333d4a4dffff001d03d34187
-01000000f78b3189170c0de482943849707aa16247e5d62772953eb54bcc4d9a000000002183968b34446981f960895ed3713dd60fede3a9eeba1d40389123c6c409d3ba6a3e4a4dffff001d03d38a89
-0100000059835cec3351179502bdf8f4b0a0542d3ad336e22549c2a78f1af97d00000000f7f8e1a8f0b4bc0337d67fa4a2fceac7e83adda354d6fa3ba18dcf7e6fa2f2b2c43e4a4dffff001d01558b25
-01000000c6a2e4d395a1899b4be7d915c8dc660efc1298a34b66263044f5a5bf00000000e64b9c2a409a4a1310fb4b4f59559f79b15dc85e686eefc07b0b0a6b7fb6ee5bf03e4a4dffff001d05113e7f
-0100000067e62d9c29833a10aa99f00514ec678c06a234e05f5a1de4412988ce00000000e4a12fde56c03eea1acb5eb1b57d35ab1da6e55d544e8212c47ce277416b1b3e0e3f4a4dffff001d00652740
-01000000d468ac8c936b469fdbc0510d88d031ad3d22c3858abb8f89184f0b84000000000fa35a88c8fd0bf5897b921ac75fac304760f6d60ed2355cca82e689ebc0cd53513f4a4dffff001d0405baa5
-01000000d69dcd4cfb5a9ecda166293b3c0bd72e21a804b3a565c8ec4783f8e900000000b3ec99d78bf68d284104779999ff447ab7bc73a783e9fab814c6741e71849cf0d63f4a4dffff001d0355fe58
-01000000a4ee15d19e3a355d221af4e4d6b69a84510a60857ead0af7e3b086c1000000001c25b8c364fd6f8417d45b9501384908824493931b544baabf2299e25277305540404a4dffff001d052500d7
-01000000deea32ce4f7ba1bee123958ad36ad37df8d53372f518a88761d14ff600000000aaeef85b297622ecf311dc5d29669fd4e3863454c6feea361ece4f547ba52e6a96404a4dffff001d03a82644
-01000000b8751c32196c89a35575c5ea97c6395e6dde705aa771287c867b909200000000cad183a8636b222a8ab775d34658b1de92ed57818e26203ee43ffbd4d8bef95b28414a4dffff001d0587f431
-0100000035a68fc6ca182ccb6663ee8b7e44556b950a8351bf2c64cd75dc2d0400000000d59d2a49b1883c6f7ac68a9d2649dc0dde3f0205e19d8fdaf8065381f9ba61cccf414a4dffff001d0592553d
-010000002e5b592b34f37b1ae9fe17aa093d2d9c815aaafc5ce3dfb8b91e33d200000000a2990b3a24b766c99702c1d157925089bcd0d377cb70cacd30be33a3c90bd067e0414a4dffff001d03c217d4
-01000000773bd09b330364f704d0b3fa46d8431c5572a100faf117958fc15a3f00000000e739176d62b588566afa47f5fbbc0ec01aa3f058c036ca0ee8f3cd13e4223e01ed414a4dffff001d056b45a8
-01000000e9aa44db469453b2c657b1e4f3e29aba0532b1ba7ce4a8bd8dd00c4a00000000fa5f2cec2dd5e7122182c8e4b2f10a1cff77ce7972ceb53308b827aed06751fbf1424a4dffff001d00523f0e
-01000000337df8fe8603beee390360abeed7e956a280fda2dd5aa238e110de090000000071f85d3e358a18a3a3465a1bc93f17e7725549a9507d1b218dfe6d1dc349641e9d434a4dffff001d0042c372
-0100000048bb0f9a7dc5c4fc15e8a4c5ce0adefc49c10db0a582e0476c1498ea00000000640a330a8e9f920e7684276e987d7f5a682838ef8510fbfdc9de08474ed3e74ac5434a4dffff001d01a51ad1
-0100000098349ad38c19d6e481627c6523d9d4f52c031525b8660ed55c215679000000008c06f072a655daa64b9910b1894ca250077f930333c0281c843a1198a6a0924629444a4dffff001d02e40f45
-010000003ad363a33fab1606f7a32896d093b06b84a7d6e9784047cf8b9bc953000000003093ae1fa781fb09af9fe147aa05ed26e90f6e7312a448e934afcb4554d74c11b2444a4dffff001d0029912b
-010000006b8abc2fe01dc3a118f4d18c4f0b36b640fc85987db55437099aad3600000000f2e0926ac96d0c8010e095b34c5089f549f2fc8fa626e20b2f0b68dd46a72c2c06454a4dffff001d00149193
-01000000665559872e38dd76cd839459a94b0f6efeaded839d785b2c43c0be1900000000c305ed4fdbd3a11585c8805863472f53be7fb65b7b4404a688c070e8197bf40edc454a4dffff001d01b3084a
-010000008fc81523766707ea9cdc7926f5771527eb6a5e6810f86a836ec81d5900000000408efc695c947acb1c0239a9b011d77e55b702fe9c2f6082571ca3bd9ad46bccfb454a4dffff001d05bb7361
-01000000efcd6d1c267d0b764044e85d112b6a32cabb8698bd13b4e947c178ed00000000fc53d40de77f595e1419b205c2dbda50be0a5595c45e001f8dfeaa8d3f19d90f1e464a4dffff001d01fe7935
-01000000339acd071c0a09f678896b302b2c79833152e048f4536994737db5f5000000003c651e6ebe94d51b8d1d1542f3b43f0c26298e4e5c8fb3d275e4e13062800f6c9b464a4dffff001d05eb40cd
-01000000ce3f890a2580af6e15d0305dbf50d1fdce03678b626ef2c6f7be3c7a0000000092b0e20be269413c7f519a5e7fc316074aa24e930b8a3edb8a618077567aa832ee464a4dffff001d03713885
-0100000006f4241b0703e90950c5ec74c3e033c39e7b0c7b9b877d5515a6ef9600000000eceece737cbc2bfaba21cd1cd8515d614c2a39ea26d9b41b7daa77a17dd5ea5121474a4dffff001d0326e2f6
-01000000e65e080e4f1df42a905b85fd5d0f0b2d70f3e987e0fbba97cb41111900000000812ce3ea678b31aafecb99db5b0ca6718f9fb3474e0baed35aa6aa7290f5a40972474a4dffff001d043e313c
-01000000ef823ae34b33e5aaba6945f46e6c2bea1df86769d877ac0b8ddb0811000000001962162ca36701e79b5ee44367d46a8ad8421b1f80aad651a02022a7b9e1e0a3a2484a4dffff001d0259a126
-01000000c65b1537a27f39bbe1a2884f77807c958faa56f3819aa5e4d49472bf00000000ba78186dcdbed13712e6c29812a54fa620fca9ccf297b8219f7ca736e36e46b7df484a4dffff001d036752dc
-01000000d48b9919f537d161b9ba4404e9ba71bda419efe7173ec3569243364a00000000501790f1566c93f0edd817937da1e287147de7bd62629b65b395935017fdc80758494a4dffff001d023a2b4b
-0100000083aa1f8934efdf864a78a3594d5c16f7fc8303fa38c01cff7c0c94ec000000005f8a10b8f3b9a4f159bb071ed05f349849e16774cfd79990af242f0ff6a60ea5314a4a4dffff001d04ad807d
-01000000f699462ec6c1179023d1504bd5b9510cad887286984b783c943a33610000000074895c719bedafb41d7e5833189d876220fc5cdca55c6ad4b94a971a8e96a259374a4a4dffff001d002f84a0
-0100000077393e4b34076f0a6b6aa9350c799c7b32756a200eb1a7619e1b036f000000004c6b88dde02bd09335ea8bfb6db1e0094a58bdcb59d5ab78303034ff972b8538484a4a4dffff001d013ccb67
-010000004828e19e639deeb00d55f748421f46dc94eebd75e376104740535adf0000000014da74d7e2da39b2b2d676b957e3edc3619f4999922f3fa66c95b64be8fd92a34b4a4a4dffff001d0260001e
-0100000092f7a9432462b827705bf9b31224972d61cc9fa8d478939e015ce3540000000076cf4d344b2c5db45b55ea38207cc477342c74b993c401b753378509761729637c4a4a4dffff001d03396962
-01000000b87a944ec8bbd6a73f5a6054efcea696124dcfacb88876995bcff95d000000002dc8a455f4bd8723a5d58a675c5a5e833ee411490a443f6d47f08a6fbf7594a2024b4a4dffff001d03699294
-01000000bc2c1291105e0c6209906934c0f1fe57c4ad13dd74e43830b293c6ee00000000070ef89563a7d8b1c7232b9e391813476ce93c9160051ed55bd396c6747618ee364b4a4dffff001d03bbea80
-0100000062db800da374d1b83b1b460566da0a35d277bdec5a6ef743132b2499000000004af49eb22a467e87048f4625dc9021249c16561d372366a21e8c20cad2c65aaea44b4a4dffff001d0142e34c
-01000000e09e577320f539aef8178a3ec09dc306b301acf52e135839fb3fc55300000000734d92340bc4c287b0ef2b88001bac1f41bf5c6d3c725e0fc39e7c593d6ebd4f9f4d4a4dffff001d00bd8009
-01000000389998eeb4bc9b68abc63e8ed99218d00b857dcc5591966d46af4eb500000000752857853f92f5ca863f3254bf18ec5e3c62e1223c3f7968894048d40413daf3e64d4a4dffff001d00cc8cd4
-010000005faf1cf2ae1e1231a1b5aab191614ffeeec0ca86d86e105233c681230000000026dc493ba668f17fde5156a19662ca1a5bfd93b2376edf51ef9e3d623e4ef4a0f64d4a4dffff001d0183b4ab
-0100000005bf42fd63d8189e37f471cd3e8a411bf81b4ff8e65532897b755caf00000000e53a837e9e3c05a4b635531c91c39c3c45565dc75e413228dc93d0c764327f86154e4a4dffff001d036f8a98
-01000000dd081cffd3a2812f5c770b8e79aea5e63d67b972ebb5d9dfe8cea3a9000000000803c135f2c72cbd06b77cc2a2a13a3c063028bf4b188b4760bafa112e71e579f74e4a4dffff001d05fe4d4d
-01000000a9496d62f029c4b765548666b71a84adeeb9dd5674148b708b7aa70e00000000ad1924dbb0711c96b12ad1376816374008b98ffc43677b0990bca7973432f814334f4a4dffff001d0190dbb1
-01000000ffcc01d81e891bb248fda71e6338614dbea2d46b8e5f71460e6ae2aa000000005510b8c188460a26868d9bb3fc9bca7fca4d9b20f573e182466398f793d5ea8e44504a4dffff001d004f08f5
-010000004300ed388b39e36268421a7b15d337598edb40c8c290166b4376f2490000000054d4f73e569ddc7e67130ea0a43a352064bf3ded26f80877536b0e7277237a7857504a4dffff001d0268c158
-01000000d7e1a7d5fb8d460e90f62666eb9891f9fab06cc2c220899498cb01ec000000006a6a5be5a31aa8a7ced02f8ece18f44261e96ee9176b772fe654f1764cf6a4fd89504a4dffff001d02c96f9d
-0100000049599a3ddafecc620c9ad61cc4520a0c70fae3d34dec595669587d260000000018073767fa7a1ef0c4a570f373492a822b5fad5fe3092dde239bcd8081fd3e8c8d504a4dffff001d000e0681
-01000000eed0b252aae103849e6805f28147abd17f294fe55c5c2d966d8850a500000000e15a0907e27914f317962823d82981df6f2dbd256738860027c740ac3f842bcba6504a4dffff001d05ebd48f
-0100000031b485a9bc2b16f2ae5108ec786708f3f14447551e7f0f0a8575c75a00000000f6dc88e1c894cf88e930d30adcab0380af8fe00c3ebce9969c0e43242ca422b372514a4dffff001d0103697c
-01000000ed18faa5febd8be98c42fe2a1a5dc9e8ddb6a618d0a05d924c522b4500000000811cb2e938cc88f159a82f1e160d80f4c6b429ef51c63ac9f2724810ff7694880b524a4dffff001d0097c6fa
-010000008738d8fc729ed970f5223d77d8e776d5e0569ef2385a33596dcbc77e000000000bff98f2293caadd5f7fa74a7c5b3e2399268c171e5adb490d8e1dde1d4926d7a0524a4dffff001d02132278
-010000007ff2786f280df6f5039bfcdc1d2d18eab08e4120a5f67c769b8b464a0000000077b5007a1d08cd2a6abe2cb56a279ee4167092775aabf4245a55723455f7297059534a4dffff001d03c30540
-0100000002ddd5983c40e70e36643ebbe8567a8c115dd7a21262b8c61d693acd00000000504305d5fc375c8303ca009ce2bb783798b303208c8744fce95d0656375b682ab0544a4dffff001d0483c2bf
-01000000bc5ffef87baf263ab01ed870a064c46731fdb99beb941bb6ab73fb05000000001679c9d394f4c959d3fa9e054a4e89af624f9206a777368a00d1cb6b175ac5f7ce544a4dffff001d02c1d1b7
-01000000a0fa21e1683774f057767d4545610a63a4c0ffdb774a6577224116cb0000000025db6d92e12ad8376e7e37c12b541faf358404c4b5617b9b287a43c2db4a067b6f554a4dffff001d04cfae4f
-010000003abf3b8f61bdfc588bb0440b0f61cc8894cee1291298996712b3e3c8000000009160b7843ed42d0b5ba734634abb2dbb231e68bc37a1d508b2f27ad88d040e3e5a564a4dffff001d00028074
-01000000f23f3229508a7b80a755b69ab0dabb405f5eb566419eb60e2cc1ce780000000015819a3494e7b49042529989b007e8f89a6f69f6d22acd6f0132c270923a192eb9564a4dffff001d05ecd17d
-010000005fc1bed214932ceb26a0a81a4dcc6fe290e5b7fbcdbc490f89c310e900000000c6fe4434b767859a8b403df5f195e223e622058ea98abcb0517bec7c5a734fd4c4564a4dffff001d030425fe
-01000000390b6d99e31e1f64e6c16a94e7fed310d80bcccf9c7f9e82fd8bb1120000000012d6f8906065837ccd176ea73171077e73a29257d7e0309377e710ebb5629009fe564a4dffff001d0391c3f4
-01000000005ca35550b9d7bb3026a8a9e5c512e0c4714f11e3066f99be7323100000000045ab4575f33ef6bfc4b1c9fce77ea21cb9b606acf2b9a0331b8f9f931169fbbc64584a4dffff001d03f6a4c3
-010000007f0ab1ef14e058aa9823bc23ecaefb694cabcc7de8ca93966dc1cdd300000000272ef40d0354ece93dda9c8370dbaf29c6a2894fecd84a063c5d3de0ba90a088de584a4dffff001d049fcb9e
-01000000f6707f93948703990287c88f79c47c2171dbfa2890d69c742ca6dca5000000001f75bdfb31993e02ff9de178dd3f1d765fd7bfb4dc87280c40f21270d7384df6fc584a4dffff001d00b0d294
-01000000096d0d56aa45bfdc9561a804aebf045d86dbe4538ba8abfc483800a9000000007a22463cae54d2b07238b58272c2f47c7bbc3bfc92a15d836f014d34160dc3c10f594a4dffff001d03465905
-01000000edc840e0c2f736161507190b975b87e70ee7842a0449b1bc785975070000000073998e2bd1d6f08ceccde03077d9d86adda70cd56234563c8d37e275767765de74594a4dffff001d03c9895c
-01000000fa8f5340eb43544d2562339f1854add2ca2336be9ef3f1659cd2b3c300000000048d698b6d1dbdaecb6b5fa3cdf3c0b06346e43c2aa592606736404a17c7080af85a4a4dffff001d02cc3a19
-01000000683e618822053eeeb0d0a85cb955b3eff25df82e41beb94adae2e81600000000ef84f5c1c80ce84101f205ed007bef67688a709a1638b20bdec8e2d5404820f6cd5b4a4dffff001d0004d110
-010000001a4ac80ae8fba6ec44d500b823515af90fc24eae8aed36d88f73b39100000000d20b7be0fb4d88ad841c2d111b49b33e7d3b786ab431f3b32e6a75d2cb8299bfcf5c4a4dffff001d02b5e1c6
-010000005d8227de291d61223a71e9c11f27298dfda9b82538dc67ecfbbae9b800000000f75f109d50bb4674cee3023c0780403b4998067852cdb56881e69c4412c445b2485d4a4dffff001d00bd7afd
-01000000140bf311410ecb5324301a67d5303bf817dc0401cb674e1c9d2b05e600000000cfd1b67825492351322e5e64da5db259d9eb1fa2b309a9917c921685232c9435775d4a4dffff001d03dbbfd3
-01000000a51f6b0e1785a625b71505e4c9ffe60acbae34d5a8e463376b0dd37100000000124c2dfbc87a28fbf04646cef5ecc103f568b8d28ab19661327995a7389d7325c05d4a4dffff001d003facb6
-0100000017b0e14d03cd3cfd82a7e8d54fdf338b7679ffc731ee9eece8d10b3500000000c96f851c0cf08646a15dfc49640c994343795b9609e87350e83f7c69fed804eecb5d4a4dffff001d0180f4c6
-010000007efda66c68e131be2f78ac7331d1d50f0203205a1532e96bebf3c3a10000000075eebc78e8a107eeb04c122618d963c038a00c956a67fe0c4933351c92f68def235e4a4dffff001d03a98d25
-01000000528b90ace50435d962ef0e1457a28b1c140e887060f6b277b37211de00000000739c079a15781e97e60a15e05212ca04c97d6c7509737d5daacdcc61982672e8355e4a4dffff001d053ea865
-010000005533106eb5b75af3ca4e3fb1196fa4c0d4e22413617c385e4ae0984d00000000a6b546b2b262c57c6691555d6f2720383c481ad64f7525c0c266669014632fa2ab5e4a4dffff001d01af78b0
-01000000c6d164638ea706719ccf9a75c7b1cba7a4ab982815490ddc3b2567fb00000000ba99c12105363f09230c6331157d8cd67336745aa9e0ecc46494634e26f875439e604a4dffff001d012bdbc1
-01000000364f362c384a75bde3177d475a8c85340d4fd4ab0ed0b30f17c3317400000000df6d00f0aa27587fab36da531d0c21a27e8b9ba3e7be77a780dc8277fdadad078e614a4dffff001d04ab300f
-010000006fe6f7e2e0d1df2b6d71c090c4fa296a2d7d175c9b7853851d0fb03500000000610e56ccf020380fa1918b77eae3eab93231c4bb8d741efdae7c5256d7f01604d9614a4dffff001d032e0df9
-010000009f469645bedab4134a07b9bf6108960de1a2ddac68d59eef58b493a400000000faff99059c41eaf7d7ebdd38efd9b0e5a3ceb2ecdbf2df4b266f4bab573363371a624a4dffff001d024ad9f7
-01000000d4767418fc518c1dad34cddcdbaf06e38a73f680556295a88bae600100000000be0a584aa45ca81a0ec8e4943b91a7e3cd4b33fa67da59db3a15979326eb5e0973634a4dffff001d05e4339e
-010000000bcd63dc71092a95a3cfa24deb7a99c097b5f74ee21389f4cf2cec0600000000c590cf15019323e3eef49355d341374d4eb747c85118d2af7ccf749bd6322d81c6634a4dffff001d0453fbbc
-01000000e244d491df952155b701e23db092c318752154d0c94b7f1918c139b800000000a7f1371e40c1c7479a0182184e7858b9fc654b553014683443fba375927f9d4f36654a4dffff001d03e0298c
-0100000028836ee71421916bfbb216200b5943426946b65d28ead2f6f6b639f3000000000494ca74bd3ac3a44c3e8d2bad9337945f89e45eb63fee5b9860d46a7d4c9d893b654a4dffff001d00ef98f7
-0100000017116f1db86d264512d1e919a74da904290965abc0492169532572230000000060081ea832d5c3e9f675736cf23993c36e8eecdde049a44fcf955ea24e7e9366c0654a4dffff001d034412fb
-01000000e79cb282d213491706610e7fc8b02ea62a98e437829b076db087e081000000006fd1b2d70cc93f628dc0f1ec50b4fa820007225cf827e3f94aa581c30f5ae51528684a4dffff001d02c8f506
-010000009539a568fa254f13b10401a64dbf10d2709111822efb587824955f8a00000000a4cc887854ee5ae17aee01ff839bc7cf869aaea30fef9c8782eecf239da4e83f30684a4dffff001d03f4d7dc
-01000000b021d8608d5c1517ed201830c7ab24f957ae2d71794ff149c7d11af300000000e58177c0a9f4858d209aa9008b6fae86b6b436c84c906e5faae402e0b14093cb39684a4dffff001d01e43108
-01000000b9d79c9f24321d231a894313febb7c5c264796a1bf60815a0cbcc96a00000000951b66c72f193f3b8374fcf39baa8183795f647fa69a5b2e21ee6505ca3ffe2ba2684a4dffff001d016977c7
-0100000083cbbadd846fd2fca57ab49a7f4b5ad6b1b64889b046ecc00424fe15000000002e26a89403d2d4d2c0cd13b959f9b86c6b6baee4ad0d99e6d04ce21995039981ad684a4dffff001d05ba9aa4
-01000000e435195dc29f89337100e0c2e80944137d2ca37e8e00256fad8b3bf200000000a644a58880e151d73b166f2ee7264025292968dfc2ac6b19516b9fea051a001b3d694a4dffff001d00a59466
-01000000fc27d9c3e7632342b188f423df64d41d8b8ca4c75b7d8a47fadfb13400000000f092bd85e17e84ee69919ffaa3a1936fa24ced5b3d0d0ca073398a256c5293dd4c694a4dffff001d004914dc
-010000001dc0cbac620aa5469e889e5709b5ffd3dde92cce25715e084d2265d000000000bb549c5ad4bbfcde450dd1998da568ba168ce940479f92d795235e95ffaff538c4694a4dffff001d01cf90a7
-01000000403be502a01dc5d45288d1f305acdc9e15cdad638ad918392738320300000000cb513c7878b4d2c2376dd1a8d91aafcbfce7fb3ebe6bf419ad69e7408d8e620cf2694a4dffff001d0000764d
-01000000919b3148b047d8639e8b46bcc4845d91654c03c6249ea4c443e9b99d0000000061a3e0d8305112ea97d9a2c29b258bd047cf7169c70b4136ba66feffee680f03b56a4a4dffff001d03c843b3
-01000000f90755f869f150d7c4a7191ffb3f74cc1752d0e1c8fa6ea51ed182cc00000000cbdf8c487a3679669f416aa49e20d8665e75ad2895d1256589b996a7f57fdfc6f76a4a4dffff001d003cdf61
-0100000047b42b4f634f26c6344841cba855c2cd7ad377cb35a8774e5e7f58d000000000cf16ae92ffab695258610ee3db7e1681447afcfe60c28ab3ae30e3ecc06de718036c4a4dffff001d036703df
-010000009c57f3083374e7552e56d053b0f07fe93a47f6a30430fd36eb40b5250000000017eec598976bfbc55ab4c5d48e00162f31b6aca31bc42ab7084f1f139049b2c60d6c4a4dffff001d03b92cbe
-0100000087de9b5ae134e6f3c94361941a079bc41b84ccd02a3416e43369ebeb00000000a0fed8fa4afb32368c57427cc0d9b44869fe8faee44f71910e9408636b82f3b2166c4a4dffff001d02379365
-010000000d544d94180289b766a4cf81e3ce5299f938c7ca3f6956424558ea700000000016164d5a284a0b308928c567c1db87c566e87d1f4810489c8256edb290b21512776c4a4dffff001d003abad2
-01000000555e499668283fc21cbbf2d5d911334ef50c6a58264fe4a9f1c7406b0000000042bf33d98dc089614e3ce83d39736949489ae64bdd1fc477f451c2b6b523c8b88e6c4a4dffff001d0210c9fa
-01000000fba43e3e3dda545e1f21d1743123d5b717b0ca9c3b6bab06ee978fc6000000007b3e06d1951308c10625b2c7eeb400f1d9de694922b34bc48bc31cc57945ed609f6c4a4dffff001d0256b7c5
-0100000046b8f387b47ed742c035e8619551c1ed480d111d4e8d8fb231265fb400000000ebe3b715280fa9cb3a6de1d7ed2b27c7f769fa8db53956a443bf9fb8051c96502c6d4a4dffff001d0587e243
-010000009987e9a48351803b25ab0eb6b84ef62d92e33a73b2133687e126c09d000000001460afd3c98403c75ab5858f765e6bdc9a91a9a7377d64f262b0c4d4764fea93936d4a4dffff001d04816e32
-01000000f38c31b10930176f539d4c5c54f22a4e65bdf568ca89ca65518207d300000000ca13d344cf8d51261573a71698c8fe10b7e5d9f7134ae4e60682ff793b1b0278cd6d4a4dffff001d028a436a
-01000000f0cc611660dbbddda4cc05700f1ceaa209e1d9e166117e5a4c2748670000000014f341b19c7417fc5b4231ae70027556174a78af7e554174541c36e2e1af9265e96d4a4dffff001d00d47799
-010000003f732830a72d4d1043e43e627abb770e9586c38b530c03331655c0b400000000a28bc5d7b507b81bd9208b9e304460a400dab435a53afd843782a9f9e7ef0b076e6e4a4dffff001d006eba5c
-010000001c219fb9bf6eab86c72b3d3bc789b446d5f214222d91c752c4cfdbdb00000000a62967c97b01f47d3a252fd612e772eba117edc1f6033fafae4fa66eabcefcc7096f4a4dffff001d019c3e0f
-0100000006de9b309fdeb6361b60029f1c7d6de6c99ff2819609a8c236d9feb300000000cbac2ac965c6b2ea471a630cc99ffa835915fd914c107b2db2dae5050b2ea9f36b6f4a4dffff001d05df3994
-010000002b59084f6b07d1210181294223741d72117914a497e7a07d0c730d4000000000b3ff096b0e79008a55e1816779ba4811e3ff6f3a064b6cf84bb4b1dcc433890cbf6f4a4dffff001d04090899
-010000007001e49d2d872afdb4cc1836b2d91ea483fc7aca9abed6e2e78a8438000000007444e881fd0c51e363543a35b27effae3cff02aa828a8de3c37bdc2db2b090bcc46f4a4dffff001d016b52c7
-01000000d5c3785332c02c192281491fb6b1af615bee7e2a2fcbbc124ba72e8700000000787f53156727d75d5b5a8d88aa93400ca4d53b9d90ac33da81545750405cedd3dc6f4a4dffff001d034694bb
-010000009309d876716d2ead60108db4f93782659182759f0b351cd92ba9644900000000fd05849b870af4a38ba121721850a8cd344ca95c3aef88c1ccf25288776264d0b6704a4dffff001d00d1727e
-01000000e9206fbdca986700b3747c62ab8169e60181ffdd3f5ca43923ffe8b900000000e08afbe6f2f42beeb5891d78d6774548971dcc9b3b7d3407821e3df29fa1aa0fc1704a4dffff001d045d66ba
-01000000bc31e83685c5e76b127e81f12e8867ab8342c02ca51f137a6abed1b3000000001e6e383300d86f0ab1c84d68a38e3a64f94eda07cb5d7b6b20072cd5a610cdaa42714a4dffff001d00cd948d
-01000000048a5ab82d24f3dd8bcf472d9081d4aaf4f16a16113821e0ec9d244000000000c1f04bbd361fc5125d1721c032aa88337bfdd16267b16498a8f80f00e2d3ab23cd724a4dffff001d02989202
-01000000e891684a9cdf9608002bb1861338f42e0a42ab96d9656f9f40edd3280000000055248a96fb577bd5c2c929f6b0c5757284ebdd13d09200fd4c342604ea3e5ccb7e734a4dffff001d031094b0
-01000000904984b520e8c777654412655520279fad1f546529d4b255136e42430000000035c50c2c01355804c412bece60540459c86d4a93f336396a664e88acd642347600744a4dffff001d017ae930
-01000000a31367e28327fdcc4b9c28664e5aceff0c6439f86378f8d88a42017200000000c26f017904f09d6c5cdd1b33194d0505a594a6b37ce0a7635ba56ad35e63183f14744a4dffff001d023e46b9
-01000000e78b13a567fa3b7f4329ea4a3700acba52539ea92128bd929e05853000000000980fb406fb9cd2562abbcbd3d2a9698da8aeb255af37c1237a552dbdddabc17d39744a4dffff001d057ca591
-0100000085f94fc42a95c9958bc3e963daf2c1550d97ca945988180a9fa276d100000000931a84625efbff3f1fa30974dc3b58d89a3a6c8c71b673e6a9b84e659fd657d3dc744a4dffff001d05acf2dd
-01000000877bc8f841c9fc5f943d51655b089a4d7f545cf233f7b3289d6b113600000000d9df6431534132d6fa686d7496a4825304f8aca55654260c56d4edeaa4ee7bbae2744a4dffff001d05c15bd3
-010000006730e2f111da5208e30dc182cc59c9318675812c24b596e3e5398a4d0000000092c49fe9e2c4008f430cb72949871a174abca604b3e4731d51dc02337cda177ea2754a4dffff001d059577de
-01000000a924ed313100b3de054fcb9e9748a12692e0f66d375cc05e01f163760000000039cbb3487e69c00c58056f6cbb3d5a3c136effa76d0d9f0df9fa8963ac0a197bd0754a4dffff001d050295f7
-010000009d977cb94b7caab58fbe8bfb6339a7bc09dc50a8aed9dec7a624e25000000000a1275135d09b38392ea718c862397f389bd358fc242242072db18a35a211ca93fb754a4dffff001d025f7654
-01000000f03542a950904c6e1ff7e8ddcd6c53a9438000df6d3846300afe005a00000000ba9ebb9774f0bacb321c7960e0e13443d58270ddc5493313d96c7784c47f1ae4ff754a4dffff001d042989ea
-0100000092f5763855630332ff4790e27b1a8a37975899d435190bb50f8448d800000000c0e15d72865802279f4f5cd13fc86749ce27aac9fd4ba5a8b57c973a82d04a017d764a4dffff001d03bc04b5
-01000000b2dd87c5ae6f6368f5c00991d7d900c14441b315e0fe3cce598cf0a8000000003e0462da7bb4bbbf44948d8cb4af46d7fb0017f598329f2139f52c76a433ff819a764a4dffff001d01486ffc
-010000009369370b1d364678e42fbb797a4ee0121fbc3916e5cffbfc5a8e1a620000000031774efc0e33444c762baf022787fbede880fdf466dfd754e3e457f4afe839b32a774a4dffff001d043d36f6
-01000000514da16d5dd2a4f82d4e52941092e8508c4cb7339e4895eb255cd87d00000000b6b3d4911dd13b8bb3d06b75eefd834250ee263cec3e94d9b4c93f600e1de90f5f774a4dffff001d01e3c40d
-01000000f3a31ef7b1009ab512e3f3f03860dec8a09c3e7ec246e75163708bd80000000035f2a99aa12f8fa65fa0ec244ebc42cb7161e80bfcbfb1bf3bd89c3585368fe504784a4dffff001d01275ec4
-010000003526d4c92a0e4a1ef78043d2832b94108ae0d3dd21f7738e2033f3c700000000a5ce8a4c43d3b59b6fdc38416eff39c2d1068817022c79a4426b071b85a30cfdb9784a4dffff001d0052c6fc
-01000000875794831d6f2c236759cca424704c18b8d89ef9f39347aa4b4fe46800000000dd4ed8001a3ef95027770fea474b5e63fefb27ec2f6b8648865f15e69308ff8734794a4dffff001d004298dc
-01000000fb0922edf49601327afef737beb3d683f98b19d128f1ae64725b5abb00000000bf3d088f283f962487807e618960923be192a236beef35f4392d7ecfeb6832ed38794a4dffff001d049e4ba7
-01000000046dac6511ee9b24b34cc63cd704497d6383d1794cc058b28badd5d300000000e885af2ab2be11c610d75db7eb1bd6eaea463efae811fec483ffa41aa7e83f8b687b4a4dffff001d04f872ed
-01000000a658975dbe7c08a66b40f3a2e2f0ef98a255d60a79ba975b89a06204000000001e7d0335d1b38ddfa9aa6303ef27c0c6929af97154ab2062f3934a8a29b78a58137c4a4dffff001d04ecec44
-010000008c36b480e7358039d56678918d633d9e92a8f3bca09cfff8286e3fa60000000013ac254600fca551cfb3665dc3beaf8114aec034861d36308d5e6b213f7c01c5a57c4a4dffff001d0061a279
-01000000169009ccd47ab6783ed3657ecb5c962b3b3d3d0edad231df0c9f193700000000623d61fe4724621efeddafcda266ef8edb29c8f2ae051f4c6cf6eb2edd214e5ca87c4a4dffff001d045f755f
-010000000b89ccf6b22dc7ff1668cd3de5d6a812f1e5ef46b512cc9e352f3f3b000000007c644560629caa21e1a3fb2bc113deb42f78541283833c4a3abbe6a6fb6d877dd17c4a4dffff001d0588650d
-010000003f9e8ff2fbb3e04c36c9683dd534a2d4fee5607825e10a2b4885e8e90000000034dbb7fb145e4c0ef8b98d4a03758ad3e9fde5016b147095494046dade14e834df7c4a4dffff001d0320c105
-010000004ee7497463e160c70196b1412a2ccbd2cc41062a773c4a3202b7b047000000007cd53c97e3e7d4f9f8e172a6168aee8539dcf2f4aa98caefe37be637000aaff9fc7c4a4dffff001d04b19e89
-01000000999ad8365c277b20b05558240e3c383ebea0d478faa53122dfa506b50000000088b03731e11466e46268a2473feb0bfb996a77f1d39d1ad9a23d27aa158ef8719b7d4a4dffff001d041a251c
-01000000864569f3105e048d65a9151047f0ca03a5c3311c39dfd84c35bc279b00000000b0c3d72e0b5e89d3cdd7b5d44396e6a4ef92f4a2e7e198a6ee583768d86c839fd47d4a4dffff001d0348f715
-01000000783b15ae83eabb19aac502a6fbae8c6b4b2d8dff30a1c3cb2af0b318000000005e2072b31fecdf48b38a60a1613a73f8c370cb4a857c74844ae17ae30adc9677ca7e4a4dffff001d05a98d10
-010000009b974d3c625f7fcd4e18d7b8e5d53ec6db57b0987f7ceef46e9175c20000000005c8b8ec09654909eb66cb5d6f22c7ba56afafbd3e6486fe8885c7f0ef53b77bd27e4a4dffff001d03cabe9d
-01000000d04963c151d6298a97a6ad4c762ccbacec3dabe179b3c39ab96eafed0000000004aa8cff9a7ef9a2029c8f3d45561888c3c50d9d7e9610de7c7976f159bd0d55ff7e4a4dffff001d02e2bf3e
-0100000032b6290c64c98539ce9570e69dec2e354bce3909fb62badb2c6dbbdc0000000027cb02841e5e22c93f1e2b61c1cb40553e97205e0956a3b01777c137d3264cdb107f4a4dffff001d03e0d16d
-01000000b96ea7181758239d2d12e3c43cb81c47110526fe397595956ec24e1800000000e89deade7ce10d96cd17b1371d1bd50a16e04c997331c3a49baa0ba0cf84e6c5de7f4a4dffff001d02ea02c6
-01000000c80ecafc4bca833c5f2b956f4acd585becd120bc9712517eca873bd5000000003c4a3ed10ee0ff614113e34850ec14018c7286ba1868f4eb541ba0c68a0db05def7f4a4dffff001d05c8b8b2
-01000000c451a1fcaa893e25e72b921e74bbbe82e4489aaeff82806bae8e2ff3000000004d8c8758514bb308bd043ba7c6ab04555831f523ef439b44b6c2d26755a110b86e804a4dffff001d01868381
-01000000b8d4747b5c3a2d6c8e50e389fc938ef7b8c04eb4104c17a2e2694f6000000000aed381b06d2dfe28d0ce14b4f43f5c167dcfbc80d44e37054a014a828a2c8c7236814a4dffff001d05517119
-01000000d0a1893dfc1470c05078598f83a28af1e44df83621ef6a34319f1f79000000008c68d3c55f59e4264a26c2cd1a6a3ed4d45c98eefd14bbfb9a26cf55ba30611d2b824a4dffff001d038d2dc8
-01000000d892825bf696f9c10eead1e3e97dfd043618e0123b72dd058988f92a000000007b921b39ee758310c934e9fc074942513e85716327fa08526e089895530fe6bbca824a4dffff001d0276d82a
-0100000062f08100a53cfee15d6960d2915fecda72ac40a116600d176bd6eb5a000000007d4eefd21df4c8472009c501a9c023613b9b67c27231f130cfa72d97978ae996d2824a4dffff001d04f2f222
-01000000c5b9489065fa7e1ac4facc51a5a0ccc2111911609f43386ebe7ca1d200000000a0db3bbb22a2a8441d84dbe335c24959ea3d3d6e91bf67e66bbcb0d7e0a9c4836a834a4dffff001d04181366
-010000007c967c39b155d44a57d37c46bcb47506c0b00a7987d9debe642c4c1a000000009969fab4c50985190c20867d5eb2622f8994a72c05fb9c91ab057be79a80526d94834a4dffff001d0391a66f
-0100000015276dffb7a0360993a5a83751944fc88a2d3f13f8e9363e5f3cdce300000000cdaef86e7120eb9f7e0e9c1b3009b4581d1133e5e2371f0da2a0b7d314465f8dd8834a4dffff001d04184062
-01000000d9e737d6b012027382d48297bfa52d08eac8ff7aac62810a3bc6798900000000be2b0f66f65fd65f4d4e387b96041ee0aeadeb736b467f8b64e12663a7f8b92971844a4dffff001d016cbc40
-010000002059d85f0b361f764b21d2254602420fbd84fff571daed5304862a42000000000c0bdb3ed18e03a8b3b92ee43926dfcab9a2bc048c98afa86c1f24e1f7f1ab7e23894a4dffff001d03dc41a4
-01000000c34c5ce16980a5ee4c66a17ca4d8619600a15f7e0dff5edec12209ae00000000e7be4fb74031df2ddaab02750360d6b806cfb54cfb9519ee517c20fd9c636b2332894a4dffff001d05c8f18a
-0100000071f7cdf7526fe514f6a17de62bfd240d2eb1fd5f8e406da3833394490000000025156dd8c9381fef3564ec230644a84f35524ee664c3643ccec644088b95d86f7c8a4a4dffff001d054f7dff
-010000005b09986f4fe70f0f864a258266fc73e908e170c29b3cfcac9ca9fbe800000000e0f8760379c70b7d7904b5a50c59bc16afc4529114d9b9ac1de43e698debefdba18b4a4dffff001d04457234
-0100000067391d93a161d82b8f968b7041a48507ace6bb30d4dfcc789e0b6f7b00000000a035032fecaa07e192fa2c97f683fc201a50f90c7ce4abcc33ee37aa528503e60b8c4a4dffff001d02bc415c
-01000000ddb642656ce71cdf2052b12984eb8c297eed7803ebf000dc63a262ce00000000b9bb4103d0d93289e9f9448ed7e63a8ac751ceaa41d1cc9627d2bca7d7c28a16598c4a4dffff001d02242de7
-010000005705c3df459247a82aaa9c3d836ee2661cfe00c826faa3f2a8462222000000002204f4022b778f21a952719904fcddbefad0afb48be8305e89ddaac4ec8b133c8f8c4a4dffff001d01ef8ecc
-01000000560f99e148e5e82dc838535b9cbb5a6116eae26b586531fc2e2a8315000000007760f7a3f07d88e8c7361e1223ea4a9e4fc5f9d8c421037578ac06d921f11095528f4a4dffff001d0392d460
-01000000cb6dafa616960c0d1b87c67ce99dd7238f3891d280444d7a15099f710000000090adecefcdd85452dce9b830a3ceb9240da10806a62404f8b7048c2d85ea0f7d818f4a4dffff001d0331ed48
-010000008f7e1c2ed57b82e56977639379c6cc7eaccdfde5f181fa381b0495610000000023130ef1dba152270b2153aefbb5d4e29c22be3e79b2041ca20620c1b381e099ce8f4a4dffff001d05e4da4e
-0100000005b132a4f74a8799a57a4202d0eeb09612cc08d295401f007c4530dd0000000073340035d03933e01bff3c47f14a5b0a8ceae33be12a8dd521315628ebf42eb3f98f4a4dffff001d003a7958
-010000004e6790a025117e8aa81fd453c7c6c236da838f3dacb169abe51897d500000000091aa6ac0aa796201482553ebe24961fdb79bcb2c1b0902f2ecd2c9e7c705d830e934a4dffff001d001badf1
-01000000ef72b16c3d1e58804b715c8ca9d02f2158524171a8a4742d0a07974900000000ecb21277a56d483af3a7ea1615a8a6d0566bf87ef230146ed4a8cc8fbae417b2fc934a4dffff001d0370ca3b
-010000004fca0bc6408f652b0d9f79713e880890605c993fe954bb73808f2cba00000000a70a8a17b106c669acb346ac08ca99344b307121658cb8cab8d00eba9adf7c9138944a4dffff001d0328fe63
-01000000077ee2849664864a66985199aa49b030f66c79f8022116c979e234b30000000087be9e1e4f0bda5f90e3c1db350737e4f390064d8aec43d6e00ea92a27c2957ee4944a4dffff001d03af3fb8
-010000008b0d4a2ecef90647f9d1a923020adf2bc138626877f0f855fde5000a00000000ecaa67add6b1f10ff91e5df491b59ab1594c357b39ba9f1f06022b078844375e99944a4dffff001d0037c556
-010000000bafbf706c6cdcd91f5fd082255862927a4d3a0457f7d7fcc6ff3e7600000000087028b6299590346eafb168c13132979b89b4912750975d9bac131a7d4c68c3e2964a4dffff001d0525ab4d
-0100000025d15b892b9a091f18e865d579f536c655f18a4994e960b06227a643000000005a2a640ca55a1660daf5363b670daa00560628bc3c39a6dc88d7d59cf2dcb669d0974a4dffff001d0226a908
-010000006843e8fc9750cbf5174a0a778ae5a6a63186683d1296a8514359770d00000000c5eb73e7834883d87b8c0ceef4ba9b850fe503039eee9b28bad767afdf0d0416d7984a4dffff001d05d4fe47
-01000000e3756d4e486befea24a302f095aa87c984f583a66687fae68d92ed1c00000000549848fd7d128b20aae864145aa351ba58eee3feffd7a8089c7adf4445b8de874b994a4dffff001d0496907a
-01000000cb8461389ac8693f9f277f037cec93d37eb8b6a6558cbe10bdacd1c3000000008aa6ad7fa12e8ce311c1c659166e587c880e3a6fcdae871eed1bb350d713f25113994a4dffff001d04744479
-010000005573c2792f3790bb99c05da5d71c9a24bce92ffeec84093243a1aeae000000005945dda5801905c0a507e521331b06a9263279c4761dfcdaef431c0a76698688b4994a4dffff001d0546400c
-01000000afbc89759982446b305b9f48cdb547f3c95760014fe738ec3e32dc8e00000000fea6f2fb7688cb32351b15857d3f250e581af5b20d9379070b5542a00c42ca70699a4a4dffff001d00ac7c0f
-01000000e17f97a9d791f0724271f652f057075f27d96aeb365838d8ab17191500000000a91c00538ff6917dce0bf745e5a040479862ef7134de60320297eb029f7bc07f469a4a4dffff001d03b1cae3
-0100000050e436836fe519456bd7faabec5d522aa80bca6a53af3f9d57457c4f00000000c66962dac9d02aab13c8501636c123f672ab771c8e088e1b24275b105d222c7e569a4a4dffff001d02c1415f
-01000000dd654b9a8a51371c852e448ca417a3fb05413a70672783ecb1346f640000000044fae19fa72a7abcbf78d966a5097415b961a316322184bce818191677a3f129fc9a4a4dffff001d01c6aeea
-010000004386a29fd8c55a0c47b8e97c6d04e1267549de89abb6db75a577d6ee00000000fa993f2f31763c2969af7e8c181a32cb663e07bd210ec14e29fff768621d4b58459a4a4dffff001d03c6039f
-01000000c5cb299e1b345b77d730c527034828c846f23bd3630ff74355c2d9ed0000000056ad317661356b368d8589f343000fb68353f92172d8c7f68a9c9792cc94ca5c779a4a4dffff001d0485feb1
-0100000028fd73f5c4415839b41e887ecd606661462ad914da28c2140afdedd100000000af9d78520fff7f6212f88c7c98521e2c9a8d2a23740ed2068e1b2a55e0c7aba71d9b4a4dffff001d03a07cff
-010000000cb32bab66fb7c93a66f841608c74f61dc36d662cb01f30a8f01efd400000000f8bef1ce0194b9aee865355e8e5b0881092bb9fe8e3842c4f7110f7306caec26629b4a4dffff001d004d55fa
-01000000c2a8b9e3677de7a6f7286c8a458cd5f09409c254209d9d8c445e0d24000000006bf3416c661bd39443f16a48fb560e97558e2cdab18da1e598086cd40a2ac6ca379b4a4dffff001d02c8a75b
-01000000653dea66e42fd4d1019adec51e1f7493b06f458f960a6b08501d8534000000009ec37ca4395220c81233283dfbe020c1982b43c3cec6b82ff425173ef558a51a5c9b4a4dffff001d05681cfd
-01000000443c685dd9cd61dbb1d4c1964e8eef7a1e6c6688b38775c2707b2f2e00000000cfb0c5cc863b3809bb9c642a497ab8eb5a2b0e6cb448fb1a12b08c3d0f3b1e13989c4a4dffff001d04a008e2
-0100000059ded6607bd4ccfeb4348c41b04a13343602879158b8d9aa1f3acc6b00000000af43000d9c2194875f48dbe377b839bfa2157758b941b5020e58b55e2ed04fb5de9b4a4dffff001d05540f10
-01000000d04014b56c58d45f823589d9d36bb755c50ee96359ff44449d71cfc4000000009d6e5c4cadaa256c698491f2c3086ceafc5f73eda5e54d4ebd50ac8ed90eefe0c79c4a4dffff001d015a6219
-0100000098fbe05200b867e000286338ee405f70ce4362f54769db2bc9d919db0000000078b787d3d8da61dce5a9fe4d4a9232e804021e439906e6fd52cf8f041f948b3d919d4a4dffff001d05774a61
-01000000c5f311edc79caeab3404ee358871e5f886712e56005f4c67141dadd7000000005545fe6585b08eceabf29cb4ff68ba07020fb36520301d4d5e7f30dd1489aa6e849d4a4dffff001d0505dfe1
-01000000f24700786a174a784f2d99ad24d4c0165e2f64acdf0893cd4839590a0000000022c09454ffd3a434342bed475ee4e9f7a34b99d26b65f2ab92bcf7418e77f732e69d4a4dffff001d04872d33
-010000009849d7f7915299b00804b04d89a946033b4bac82b431a04781ee1c6a000000006801e653da56cf733fbab3ebb4d3f248ae5066f00b0b879a178ce3522c7e1572cb9e4a4dffff001d01e83192
-010000002cc41fc32ae1712dbf174b8d810498ea52c9908a96100cbca447858e00000000a9eefb8c49a77795e353cef1a18ddf9f75556b599049cc5c326bbedbccc3cc5aac9e4a4dffff001d0559b918
-0100000029bd58b2759e2398dafa0ed714764e7ea87a61e9966b4777837ad0520000000073173503f0ea326597487757ead4a2afaded9c36545e6f94578d3dc6e5d58fbdef9f4a4dffff001d01bb0d51
-010000008d7f3d0a93bb78055f440276924456111c24af5ed639ca3b3a2226d600000000fce8d0f71b20ad1d4797818e77da4739eabd906dafb8baa38bed17cc3f8d723906a04a4dffff001d04416634
-01000000e26e977c4cabd28830a8e1f87983e91ecbac81030dbbd7cea6efd4c40000000029045a4c17ed6ba6bfc40396d8b9d2640a705fd487c3c0271eafa3c503d0f54b9ba04a4dffff001d02477ab9
-01000000f3249f94c4a61be9fe426f496ddc9670874206c5034c68fb03a77edb000000008f1c9da6092af60d73b296ebbc796caf1b8a095f7ed33078bae45cbd2925029961a14a4dffff001d0253c63b
-010000006f6cd48debac250a7b42738755888a7571eb9935bae9e94d7cc28b1100000000d42144297dd9954a62226db7fa2de24cba50b4c963ae6226ae5fa652946dd0a7e5a24a4dffff001d003cb819
-010000009ff0cf741383d94f79a6efeff2a317aaf6375ac3d252db55362280e00000000029e2f50ac5d203e020e7b59855380dda3e918c80627117c6249f987b28ac807bd6a24a4dffff001d030ba92c
-01000000f61d5499f92cf040f17a16d02b348dcb3dd041b224625bc99acd35a400000000400de7fdd4b27e6d8d358cbe3b329417d75352a9aaff9af70c1f685cf842560675a34a4dffff001d0271c0e5
-010000000d1e2a2e2670286100f862dbae397fef5d8dede11bbcb013c453e8ec0000000043db438150141c0240a7f3f03cca32f4fd0ebbd6bae6daf898a6c7aac99b8a85c9a34a4dffff001d010d4882
-01000000abcc3483c5e1adeec60646454065ae3a116dc60aea65be6d0e66bc7c000000006c0e3cda9dd0367de3a4e1d356c0ad23cd88f26cdff41b412b0ca1de1d9c738cbda34a4dffff001d00b44c37
-01000000e0d79f654270f553820b56d0332b5ec18a4cb5d969c5d67c8adf9b2a00000000f2cf8413e5df690ebfdc8441586639e39ee7d8571d88e07853117ed693bc0b8d35a44a4dffff001d017fc225
-01000000ee4c6ec5ebb31e14991634916e68379e6f08617bd3e2b0816c0605fc00000000203f6062b808d073f0471cc4bad3fe9cc51cb9c732ab53e46a4127fbf0b960fbbfa34a4dffff001d03592dc6
-010000008000bccda2bdbf0a6293178dd1cdce1a368824e9c99587798b7fc1c600000000d29fc4754ff52a23715d3147c6a0ae31ddf06fa70465f4d09d41b4aa08da707bc8a34a4dffff001d05e36843
-01000000386cd6cb2551941a87716c2c618e1e56e9fe7acb49b0a71f414047eb000000007bd7a97b969168050de5f20cd3d0ea212b138f4b43e3c27755f46aa08f98f1ce06a44a4dffff001d019dfd3f
-0100000053402e2e9f85db9774e0193414436cfbbc70b658c4e54913c67bcad300000000fbcf82e5b9b5c1aff879c25c172d4db531905915b205187bc3ae1425603e7c764da54a4dffff001d0154db1a
-01000000ded3e38a879dcbfde2c9ff5690db8377d0c596e20b8be94dafe611df000000009d8b84155b519e0c1cd97837329fc3505f76944245c1bd686617779dc700c15850a54a4dffff001d00ea1441
-0100000011a98d2176e7952434447a06a9ce9f726651737d3a3e006373183b2400000000a50e90ca36c2cab93fd8acec6eae0755d7d2e710688a26fc16557bb5c038d12c0ca54a4dffff001d044b4279
-010000008cffb590fc8e390cc07b0fc7d7e1f83033a7f09c20ef114f6efd73fc0000000098f65f5151c0fdce2398474d0987d7a531aab1c2659675c07658b07cd954f80b29a64a4dffff001d03e15e65
-010000000a7213bcde17cdc86191ebe8580e3a9e893e3b9a189e2787394c5cac00000000230d4c63ebf11994b50ef9c5f1b75b2b8ce6950f63fad01665fec3ed5ff2bcd243a64a4dffff001d02706123
-010000002c29a0a93ef692c20f7a5d0a917a69be60ec5bd73788f9ae92a2e7f90000000048634496267a248713364570b8c4cc6ad5b1a3f32fb74cc1f11fd22c3b293e88b5a64a4dffff001d010845af
-01000000fd50cc2daafbf969480d2675a4cdc41f397d1d815a2aeaf863236bbc0000000086d723685d916a3b3aec61efe9b88a845d96fb903e78760e0759aa2089de4e2e66a74a4dffff001d0389da36
-01000000e897be2520f0c6faad2d0c4be209e0d4cb2edfacb7579a6aa939a10a00000000ae3f02363ed042360b679fece5726b2499e74f27f1bc596c3beaf701463be4465aa84a4dffff001d04ea7f5c
-01000000a4f61773f2105205cff43c8ccb188a0ebe56f0811834cc0772a5a1e8000000003b776a5a9f039715342ed278feea0e87f1454ffdd086ec1e3663cc738965e9d536a94a4dffff001d04479ccf
-01000000cd182da4f3e6641784b8035ac96d74b182939696dda02368f01889b7000000002fa23a7882a373528b5403d34eeb13a26fbf25d668e7019e7a0403ccb5ded71387a84a4dffff001d033151e9
-01000000913cb00e5db68a01cd2c2c469773d0946e3e1589cd72c56349d0405c00000000e04420559afddb03dcf51c67a8317370080e517e24ea38dbbb5bd529680c1d2c3aa94a4dffff001d01ae2ae9
-01000000f87f4f7f7f99202d77747619865391ed07d87afb9c7c9a48b7f319ab00000000b4e21e67bcdbd54bee76d62b5cfdb6b5cdfc5fd1c6ffe9fd6b1e2f39677aeacd2ea94a4dffff001d03275902
-01000000c7a1220a895e2a83917ab688040dea8a000bbd5f4858e8bda00f3bd100000000fcddd0541ddd056f19fcfac0e637cc8fab7503352757707daf37da8e859434f397a94a4dffff001d02d171f6
-01000000c5711e518c4a53e9a6d684759ecd07d69b5d859e1edffcf4bcd3896800000000e4ce2882f8c5b8e467a080c647ca97b8c11070b7ad10a1eaeef13e1b49d0028cdaaa4a4dffff001d03ac5ea8
-010000000a1bf9a1db633b5c817be9ecef65ea99ed980a58d070cfab68b70d5200000000c9fca844eac0515369a587359fce6a2cec83ebe565dbf46b92928ca831a1abd54ab24a4dffff001d0370f65f
-0100000081f9fcc96f7824b23225d5526b65d3d5826bfa8b65c083028e7b287700000000163cdfb6b5d8589c539ef411a96eb96ee49dcf03ef4538d8f752762893db209515b34a4dffff001d0215c77e
-01000000a563fe8e23fd9acdbd8ce0db616cb72c1b05fc8610c4e89fcd32b21f0000000074fccc385cc517580daf8966fcbae398b81ce1f077bdc5732c529d6c3502e16183b34a4dffff001d033652b3
-01000000de5ca94254b771527679b5dc4862a7eee044409cc33ab2960cbe3920000000005f20491b7a3093fe2b342e816a5b8d409916c2f11a6cb6743dc528e8c7ac51b7ccb44a4dffff001d00d437a6
-01000000f8d57b05a64cb39a5adff645ba434bb707aa118322851cbce137df2800000000d760a34f6e7b07b3718a8355b71b014f07fadb917707e4bb635cc1277cb8ca7f5ab54a4dffff001d00d8ddeb
-01000000a54d55adebdea113e46d6911a15712f7545709577a5ef6684a37974800000000849ecac186963e52f8b855e51f70e9cfc90cd0f7054c23f1bcbc1675206a00bb4db54a4dffff001d01cec36c
-01000000f2f0b39c9e0f8ae81ceaf09ad25ee9166e8f3d33addaca1ca1366c5100000000060e3cb266839d6c8155ebef78939c33b659156bb2cbca1cc95b50e58ad5100b2eb74a4dffff001d02e282eb
-010000004a016d8b02a6e3c33705715c29754230218f04485693994b29d78a2c000000007286500c919f491aa5a0721558e4b8a64230ec2d1d955c45ac871da0e74c898d3eb74a4dffff001d036714f3
-010000002d24b64aca8efd3a0a948e813c5303891d1971e6295be97c1923e05c00000000eca7286e07ea252409b51cb2124e3fcd6adb8e6fdcf87046de18666e36037511e6b74a4dffff001d037e372e
-01000000dc8280b9a38ed7829f3ae49bf8f01642c0b16b90642b2e911c2cb69000000000a10c2661ab1b02ab9f3c5bf928db087c27c06ee7537b04ee66ea4785fb625c6205b84a4dffff001d053fb75f
-01000000280fd86185912d306966b6b7bd90a765e659bad17564825f0c997f2d000000006637b339af8cdf579a250267ce7ce41f19de798c7ee6ff7823312076e0950962c7b84a4dffff001d00c1fc82
-01000000993b4428fc00d1eef46e5fb166b32f32ea75e3e49105a04322845d2800000000fbdd76c6562c86af0e63ea9a6c46a91b8d92c4e7df480977ec0d53b7f3c25b9812b94a4dffff001d0099e992
-01000000c3b9d6eb714b91e367d7a44145f498cdde7f579b68c66bc1b9af7886000000005b0df3f16d5bb399b09989beaf8e0665c695ef49b7aa8473ba8690f0b029ce0094b94a4dffff001d036efa36
-01000000a702519acf76d7519ce42d6c0bfff12644be3694621a942a55e4b36900000000f9357358ee5931b907a8c3df01115891a740ce6f4df224eda4586eaf450d8b9f3bb94a4dffff001d02d9d39c
-01000000931d5230c5a2b7d43d322cebf9026ca68fe1a70afe0d8c8abed78d320000000005634a2446d5fb785d1f1582e6f35418bc6fbfb6abb9507213b010e58dac1c3ce0b94a4dffff001d02e9d793
-010000009c7bf22857a46add066ce2267450ddd5a6f280943e961b1db4d3be0a000000005eef5906ff42a8baf4a8a2d8119f88112d802484361ea778d22e44300f6ab20c55bb4a4dffff001d0179f4e9
-01000000e2a926d9239573962e534a47311e7875482832ecc6306bfaf1137c0500000000fe6ae11390e7bca224e9937759c658c9aadc8971e8ba384caf2a58de311826e7abbb4a4dffff001d01d2102e
-01000000dd3fb5ca9283091e24a2dec99871d9c033f39b1009f5ac592ae2cf190000000086a971609dbe58f45f99ae1a769c07ed6b0575ffe811844b8f6e04edac722bdae9bc4a4dffff001d037251ae
-01000000a7f31bcf8d5a86bda0ddaadc3c8b77ec71af748584b3a5eda6b88c4600000000adc6c0ba4cebd8e2b0154e9f876f1e6ea54e293e6505a5200a4a75d394521a7882bd4a4dffff001d02defce7
-010000003846b6ba73428b23c1aea96cb3a4cf8b72ea4f40268ed68fd16ad9bc0000000050a4b5b4d3fb6c72d198506c83d6e2792262134ac07813baf355921ffee7c6579abd4a4dffff001d04687d8c
-01000000df7e6b1a5947867dda62ed7a79f75d939d4190f3a575b447c31308f9000000002523ea33f4e43dc2dbdb14116d5d087aa3544a7f886a69693caa154ae0abcfdf05be4a4dffff001d030a6d3c
-01000000799f7e9b6d0ef1bcc5d4e6b82936272e3492df8a920b934dc9e1973000000000d0038b40a4b3c20cb7a6b431d6c2edcd235c59dfaca4698dc0f4a057d89eded6ebbd4a4dffff001d01e9924b
-010000005dc85295d33956fc24736fe54dfaa12ca98cae2ba02ef7eb9655a12a00000000b7bae6ad3a263adfc01e5e76acfa7dbdc0e60962230af6fc59003d59b437b28d90be4a4dffff001d032ce3c6
-01000000a3b52bc4a8ade1fb7764462099a412272fa13b3d9de508c356a3d7910000000001eef5a3b0e24e946235bdbdaf78601185042a5974a6f9aa7d8deab62b6bc49c18bf4a4dffff001d05a9f6dc
-010000000e816fbf3db7c990098f50722e36029dda668e9aa386c23a201e9d8e0000000027d9b4ef4291c5332a05c4a2918b5526b96a117c0bb2bc97cd18f5a6eea15caca7bf4a4dffff001d023f105f
-01000000514062fccf6e88a8ad9d0ff0fa2ca4d2716c2b5fcc577f52e4557fab00000000ca12c4c5fa9b8106d21f12f4bb24e1954ee95686b849c643e0504328653198fe1cc04a4dffff001d022e817e
-01000000b8631eb7fbe8abdc32f81b54c6f86c96cdb5d7c270cbc8e8026890e80000000032510d84003ef4d4b634cb4bc914de16f8e9b72b6f1ea20dd9eb847f11351641f7bf4a4dffff001d011d83b5
-01000000bf3ce738c0692a474dadc784640fe4e2f06beef2fffed0bfee65cff100000000a463353790f4669516f33c405164df2ee08f7738bc91ded3ca2a025e18143ac967c04a4dffff001d01fcc651
-01000000fd4bb907a2089b41433dde0fcfa70db3ac3a6f075be657f0e15144d1000000004bc439544765cbaef9a184ce7fb26bd62cf1ab32267eed5fb3bc7050a8f0c427b4c04a4dffff001d05d07be8
-01000000d0d3565bbad3a5fd165a7fbd978fb2ff2974dac1fb4ef21ee0c6282200000000e4e9ef647dfd719c086990944594c3892d0deffc18fc90e092d61a3e586e4cf8c6c14a4dffff001d0188a8b7
-01000000d2d5324fd546db69e8c42e6f6c5f2f686cf29a9fae985224d450ca7b00000000b3c4d587370073598ce1a226be2f70e0ccbe446e80f88f0446dc5b179782186b78c34a4dffff001d027bf975
-0100000074b16276f3e902ba74a5a938a86ad7249db7c620b06023385b515109000000001b94a65422bddf5384bb8da9d866fc7a7e5c5abfbd5867efdc8eada3b78b8e3babc34a4dffff001d02d402ae
-0100000057f6b87254267089a1d84eeb06f20c3b181177372b88cb9152f356dd00000000c70258c4f96177b1cdd9d6fd5ad0e9a65abb44e7fc3dbe507f45e2984ab830d9c9c34a4dffff001d03cfee0e
-0100000078eea9a9282653e1e213c716004ee3c5b7d323c37bdec7a64565831200000000ac37dfa5948ecb63e944a61eb0e83cbf7dff61cd61cf66d21f447d9a97bcbec123c44a4dffff001d05c7a466
-010000006c0d72985fd57581d55754a3dc631a89e6e4e1edbad1696ec271d6c200000000c1d26e829e285126d03a1943bc46d72c7e68f7fe1855393079dcc6406328ebc53ac44a4dffff001d01ec1ff0
-0100000060f628c70ffabdde8c265ff6aa1b49e0f42d250a0645ac0fa2963ffc0000000074f7d49e03dd5ccae2109db1e4ff11507238642d86fc771aaa999ae48b06f3d26fc44a4dffff001d044b6b47
-01000000f2c8d522c94e93a8ff5d947c057e4125a4deb167e5eabed5dfb56736000000005127f86da79df2980cedb16ab9a4b167e6daeadcda0d645f83deb48a3dcc065eb8c44a4dffff001d0561c0ee
-01000000e6c388d72c717914e507f11c58a139137fd483dbd746e9c5f2a1eb0f00000000afa8dd6f0e319d4ddedfa1425f6c03e461dfa005d42d3f355a04cae42626c9b121c64a4dffff001d059f05b2
-010000001b354bd6d10f5a24879851bb2aff42548cb66cebda04e7103bc2521900000000622c689b318941bef087640fddab2c5ef6dd6024f133ac28c1ccfaf30e380bfa4dc64a4dffff001d00484506
-010000003e226e00e126f0a4a35b1c6c09509e0d999122428262a5303e563c6000000000d7432b21fd48689d7e79f9b6f7f624aefe8b72503fca13b814d355618b9023cf23c74a4dffff001d0247f874
-01000000fbb3060018eb1f40d734cc64744134d96536c4a331e00d4c05e2cf9b0000000061b34d561ddfd18ea3381d48a8bbe4627727c6ead00a84030e7f76eeb788148a71c74a4dffff001d012e783d
-01000000fff008ec46c2d35cf469eded16dfadc77ca6e9a9680cea0b0611661b000000001d1e1087d20d41da1f0b4a5423aeb281ecd48cfc434feb45a4c6c31b6b61398124c84a4dffff001d05928767
-0100000093ebaafdaac804feef3ec352e40cc78be60e7ef1edb167891ccd99cc000000006bf225e961b1f1b8e042c45966c2118f20871551e0996eaf51bb628cd9d49b7a45c84a4dffff001d00381daf
-01000000e85fb976eb4817418c0ed2987dba1674c0fd757f70b470f83d01a2d300000000fd6717e5d49bf303d41d861fc50503aa8575eb52243f426de308869a8cd57c57f5c74a4dffff001d033a590f
-010000009cf5f976b9ae634b4c867bf78cb602bee8150ea1838d0ef3d06ce94700000000fe6ce75c462d7d09aa8d917fa90a49bd6a4c41f02457ff40ca47ded089021042b0c84a4dffff001d03a5f6aa
-010000002eff16b6669f88de6f40810c57349804014f734c692a44ee822b7f1200000000c095ce4ab7e0e02110b75a33012da97d75e26b83de5ae0bd392fc3b8191b77e8e8c84a4dffff001d032c2bf6
-0100000001aa2c494f2d4b7ecf367734c734b931d3592b1572dcff557186ece700000000a10e60b120c06cd1be1d2153abb7901e2d9f1a3f43de9e6642ad269be1cae22e44c94a4dffff001d01f2005b
-010000003d04e058642d22428704ad4337f372bb8574cae072c2a4b469b2e1dd00000000bff07e723c3859fe85bb849d860b21a325b1baf1494a3c1e73435dd7992bf8e53dc94a4dffff001d00262757
-01000000272ecd270665dc39e924838516da62f8588270f1e37812aabdb1d48c000000001725d4769aaca3cf86c5b0dd199bf93f2d16dbb13fbd4029633bdd1085283fdd13c94a4dffff001d02f79a8a
-01000000705f1bbf68b4976a9ade4ff01ae933030cfe4cd43e8092c9604442a2000000000cb7f30461a3563992f7b02095263fdceb13984123a28ea68d0989601655e84ab8c94a4dffff001d0017e0d9
-0100000082d6e6bf4ed6c5b989705920effd072fe6b7119ea5b8c8fa6d0bf5c70000000071959f90386cdc263655d36033817a6f69cbc2d99fc56cc81f893b9787907a4fcfc94a4dffff001d000f9093
-01000000374e3a88a3a3eef84b4212e90e863754ac2a6999747c22667c0b29e0000000003a0e3693a8455ac94beb574efd98297948c5b5f69eaf0b813e6d5e57426e39e279ca4a4dffff001d042b079c
-0100000003f06b3017023d1cbddd4cf169c4e74879754683f0d7670f1d1197f70000000098b12eacd55084fe2807a33dc2c89e6fc25f382aba3c6b4c7ee2f74a6999a6bbfbca4a4dffff001d03ba1eb8
-010000009c0730eadadb66fa486e40dbddd14b635ec7939f788fdfd999e043f2000000006b0a86109aea3d5e4b7dc320da600dff19d81dce7b77dab9596204c20c6125b06eca4a4dffff001d01c88a1c
-01000000410f77945e68dba04d76fc931b26ccb571159c9bad438df5f8fc4d190000000004d902fedee34fce75de583a54e1fe7ef26a7946b48b93b9b0834dbf19a0b47f3dcb4a4dffff001d016618bc
-0100000025ec91d09a451f18667262004e0cebb2ad66262407ed0a8f4ddbff580000000092f8e1be93272aae6b36766d721df3d80444582edec0143174c5fafad4cef50c79cd4a4dffff001d031ee0cf
-01000000d8d0cea1249f726362ee78259d97d98efa17ab0efeb1b9d0a0cf0d880000000035c3dc39e544b855457fb0711697a24123fc3ba6c439123714b193b9d1d9ec7514cd4a4dffff001d0526c906
-010000003e824b7a8cb7bea1dddcaee7bbc4720e8c5d2f53c9c28dbaea4662a90000000061ef7a1ca4f6f61cc594d040490d3cb2f11054639a0a964c67cebc6dbc079e36cacc4a4dffff001d03af40bf
-01000000da9201093da940fb6badc420406540a979cd5c06fc2f47db3215130b0000000069577de9d33e6351fb0ac1be26158f94c217d2522c35e9f813e47bf9811fad72dacd4a4dffff001d02f70faa
-010000003dca51f6b97f7c05a44f329c1c9f4d7cf03eeb3b16d94bd56e34b50600000000092122ea597797ea0de7841945f09c221578800d0c44de4961cad7ecfb93c47323ce4a4dffff001d03bd9635
-01000000a560b2ead8a3f50df84385c1d5a51654c22a321268e077dfcb9ef90c0000000091db9cfec3e6c44a790d6295a2effcb8dc94f9f1c0fc4f6d867e90e140c1e9f325cf4a4dffff001d03a86875
-0100000056e6a9a6b93f9ad3ad847ee845ee9c366dc9376489516c31d892ed5e00000000bf2f3b6867855fe1058092fec7c5ea89c15cf8a70d0c565c26362d10129221af47cf4a4dffff001d027a9b69
-01000000d123e40889dc9dd8039943b5b1a0de53026e9ce92cfc69d5f8482fbc0000000022b49f0319707490d002d5b2c04adfc7a6433c2931ed04545e9c33f37a12b5bb924bbe4fffff001d00b7fffa
-0100000065aa216d118366b22580747fb4d876d80ae3be145e318563984e0b040000000000c2b33efaf934623c6bea64570558d6551524e2f45d022b0fe935387279e6a37b51be4fffff001d0511e593
-01000000eced0b25fadf8818fabbf65b9c16f39874336d7faca51b74698ad55500000000ee49643ded3202eb46b451c55a652c6cf38d82da93de97a2f2bc0e8a28c1be7ba951be4fffff001d01f82bc0
-01000000bc9c266783225bfa273dbba2342f54809dcc2b263e1e6bf3269bda300000000001aa244355f8827bdc7eaaa0defe1a928816cf7d919890781c1fe3ee58d985684d53be4fffff001d01a443c5
-010000001b7467dcebcf2baa4814161dd6c7ab966ba082d670a69eaacc1785910000000050098a241f8df957a6bbea8ecc39473091636a4e55d673ae723edb6a3f50b9835853be4fffff001d013788f6
-01000000f5023ad6b3432b6b2d5afe707cfbfa0a30e94000799c8430a97da151000000007a53e7dbfb43a28ee9d5956be8da4190e5be6f16da4a5636f6139742754ec0cedc54be4fffff001d04474930
-010000002077ea8e53ba9a132d83b91e40fb1f4c724217b8197c4533a5bee9e90000000096a376627bd7b42278fb33609713b83665f195d100316b9e1651638cd4d7d47cfd84bf4fffff001d027c40c5
-010000001936a4ef861f194c15f171e843866f33ec3b3cf09394bc323753beb8000000002e3288941ec156d0fdc90d314d85a71a418d272704e12f2a99576fe3201e2d1b3887bf4fffff001d027aefaf
-010000006e5c2e805629d476b92e0a8d74c3ee0dea0c24e9f35ab4afc6ac77b400000000d26cbed9a7c1e51fe657c6b3cdf202926e0b6e371ebf41ccdcbc0909470d56256e88bf4fffff001d05a2db35
-01000000e5f26b5abf56353520e1f9baa35e9cdeb57f257f59ff6a4ee42c3795000000007becb215d446a70b351fdb14659d105b3c258802fa4314b536c4e5249adaab2a9c88bf4fffff001d04e36b51
-010000003cf3550994f31a27c040b1340c7ae9ccd36d554a1bfa797cf46504c00000000005f56011e8d4bf55bca3dd8c9799e0d83304e43ae8b66ee58c688bb9d7f7fefeb088bf4fffff001d0314c7c0
-01000000ad48a4d4922e3834375f8c50e8cb1842688829c8952204f66b89a7e9000000004579dc3ff13abb920007843862e9091b0e142564cd0a75f5fc3272982b816d4ee988bf4fffff001d00becf18
-0100000098eff668afac04d3d8531d9bc31aafcd48f7ba68b080b40641dfddc200000000a91184d97bec523016c15dfc3473e7407278b70638f4fd6c9dc1ba210454f7fb1189bf4fffff001d042a1349
-01000000ed2b2b04575642de5fc665cb8e30f3e39dea66299592405204bf6b5d00000000f3af0d684b2c16f307b6ddf9a02b58b9079e858dd2d093aa29288856b83b82183789bf4fffff001d002cfc38
-01000000a398a8e978de6f1e7b9b84523d45e5f2021feb29f6d39890a2f48afd00000000f4a78ab4703ca95ed478e78e526f1a8198c3cbfb8a9ee6455338d517aa18173f3e89bf4fffff001d008b40b4
-0100000036bef7eedabe3b05e1e049efcf66823190285d64d11ccfd2eccb5e3200000000243f2ed308bd48cd3dd25d4cc649dea0d0518d6e12612e03c8a0888aa284bf2d6189bf4fffff001d0498f47c
-010000008d84b4fadc45563b60c0f50797ffaf71046f287482ab9fe629f64e4e000000003ae5c2515afb4117d032de958e0ba535e484575b80ff6d6e2e0a23e6dc95e0ea7889bf4fffff001d0518a2da
-0100000020ddc91a15f8c9ec5161bf1709ad7f37c33ecce9809b353dfd3df2a400000000f2b6d372af2c7164d36dc1c369090f4f9179b0870676ab6ec2641b0922b1fd179289bf4fffff001d04bbff73
-010000009701e67638ec4e8b47c547ac3125ac6c1892a98d77a580ab88f069d5000000007c740055656afd61883f9c1c102fec710315e6e4d58904accd184cba85c9f958cd8bbf4fffff001d03f8f01b
-01000000fa9f56e3e4fe1352905b3a1f12567caa3f9f4251f0bda94fb07f1684000000009ff7fbae47f6afb47a1723662d196155b5f4bc1c62e882a93f54ba2d9a10913b508cbf4fffff001d02d1c97b
-0100000002ae1c66166259ef43d290c6a60cf8eb5783e6c91293a3566946673a00000000846d597237ea76576bc49381badb59bd509cfda3095c2c1ce5c75788b96aa144718cbf4fffff001d0139c1f5
-010000001ed0a06499985c4cfb05371eec681819d8e193b66011f57b66792565000000008980b714aeb09568fd34128f4c7ff84d3e09223dcb2b290c5948816cc636d69fa58cbf4fffff001d0122c5f4
-010000008c045f9e0e200a8eea9c0957b12e045e927dc768a8a5fc2d8fd8d9ad000000009925a3f617c025b95f6329247379b7ef7bd081e52838676671c7360eec07255a098dbf4fffff001d0099c40f
-01000000a6adbd81b12cff9948911af583db14484c4c0d30e91b1af2e7fd4d4f00000000a70e4b2057854c71170f8468b799f03d0344905213872216f4210f7bfcf76980198dbf4fffff001d002b7c3a
-0100000059e1e5ae6727e02c2acf95bc5f24d8274e42495c790125ba52a581170000000043412a5a9f1749688460eee46b62851641fd9b17f9ed5131b3f50e4f160eadc45cb3bf4fffff001d03a966ba
-01000000c704e90a0c4cb992d6973d636a7094ef2790a60231db345a926b6cb6000000006f98c89001a2e89ea35aaf00b85d965af5598b61bc48d9d9847609331995383effb4bf4fffff001d02ee5af9
-010000005468467a64f255415f3ad770f0d5393275f2813fd0e1e915a2b8c28b000000000566f29ed6b8cdf85a4b197dcbb0135dfb7b671f83ca67970bffea903309ab7445b5bf4fffff001d032ac068
-0100000021ad75b801d48a30fa5b4e6b1e43106a294a5e2763307a992fbd5282000000002c20851e58dc1a2ceb7c7771822ed41c7d0994731d01829628c3e938f4155a276eb5bf4fffff001d01a1420f
-0100000002954bf32d68d54adac42cb5190efc06f18ead35208dc14a8face6f1000000009002c5c2dfd0259960507e69399c688f0d74bbcd52c810cd2d2507a829133f4941bdbf4fffff001d01724be9
-01000000add5df18f427437ace8b40064b3806583217a3f724672cf72cf8c18300000000bc652800c84513b2de38e0e97be92a582a628e1e49a9fe8d49aea5623251eda54abdbf4fffff001d045ec8ea
-010000003b0c953fed585c1ac952df84e4c3953ba551da457c700035f6f3fc0c00000000831c01723b0fa955a6fbd51d9ddc5c77964814868f96f52ea3eaf3b66098e6df9dbdbf4fffff001d00cb77db
-01000000f6667e8c4557c28f88b86a6892d03509a5afc9a89088a5bb8638eafa00000000ff61d87fbc86dac7f80962702153a2a6d9a84dac13c265106b883ed7ef68fc91cebdbf4fffff001d00e07f63
-010000002cb99b76cd981a422d02d61684f76bacea92669298e552e412ce41df000000005f2a9977b14cf34078500f956be0cc154291ce5a0e34c00a3dbbae97bed5e930f5bdbf4fffff001d008fd760
diff --git a/test/functional/example_test.py b/test/functional/example_test.py
index 39cea2962f..47185cbb9f 100755
--- a/test/functional/example_test.py
+++ b/test/functional/example_test.py
@@ -184,7 +184,7 @@ class ExampleTest(BitcoinTestFramework):
block.solve()
block_message = msg_block(block)
# Send message is used to send a P2P message to the node over our P2PInterface
- peer_messaging.send_message(block_message)
+ peer_messaging.send_without_ping(block_message)
self.tip = block.sha256
blocks.append(self.tip)
self.block_time += 1
@@ -209,7 +209,7 @@ class ExampleTest(BitcoinTestFramework):
getdata_request = msg_getdata()
for block in blocks:
getdata_request.inv.append(CInv(MSG_BLOCK, block))
- peer_receiving.send_message(getdata_request)
+ peer_receiving.send_without_ping(getdata_request)
# wait_until() will loop until a predicate condition is met. Use it to test properties of the
# P2PInterface objects.
diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py
index 2d4e33e5d8..df2fdc9643 100755
--- a/test/functional/feature_assumeutxo.py
+++ b/test/functional/feature_assumeutxo.py
@@ -9,6 +9,7 @@ to a hash that has been compiled into bitcoind.
The assumeutxo value generated and used here is committed to in
`CRegTestParams::m_assumeutxo_data` in `src/kernel/chainparams.cpp`.
"""
+import contextlib
from shutil import rmtree
from dataclasses import dataclass
@@ -16,11 +17,16 @@ from test_framework.blocktools import (
create_block,
create_coinbase
)
+from test_framework.compressor import (
+ compress_amount,
+)
from test_framework.messages import (
CBlockHeader,
from_hex,
msg_headers,
- tx_from_hex
+ tx_from_hex,
+ ser_varint,
+ MAX_MONEY,
)
from test_framework.p2p import (
P2PInterface,
@@ -139,7 +145,14 @@ class AssumeutxoTest(BitcoinTestFramework):
[b"\x81", 34, "3da966ba9826fb6d2604260e01607b55ba44e1a5de298606b08704bc62570ea8", None], # wrong coin code VARINT
[b"\x80", 34, "091e893b3ccb4334378709578025356c8bcb0a623f37c7c4e493133c988648e5", None], # another wrong coin code
[b"\x84\x58", 34, None, "Bad snapshot data after deserializing 0 coins"], # wrong coin case with height 364 and coinbase 0
- [b"\xCA\xD2\x8F\x5A", 39, None, "Bad snapshot data after deserializing 0 coins - bad tx out value"], # Amount exceeds MAX_MONEY
+ [
+ # compressed txout value + scriptpubkey
+ ser_varint(compress_amount(MAX_MONEY + 1)) + ser_varint(0),
+ # txid + coins per txid + vout + coin height
+ 32 + 1 + 1 + 2,
+ None,
+ "Bad snapshot data after deserializing 0 coins - bad tx out value"
+ ], # Amount exceeds MAX_MONEY
]
for content, offset, wrong_hash, custom_message in cases:
@@ -297,7 +310,7 @@ class AssumeutxoTest(BitcoinTestFramework):
msg = msg_headers()
for block_num in range(1, miner.getblockcount()+1):
msg.headers.append(from_hex(CBlockHeader(), miner.getblockheader(miner.getblockhash(block_num), verbose=False)))
- headers_provider_conn.send_message(msg)
+ headers_provider_conn.send_without_ping(msg)
# Ensure headers arrived
default_value = {'status': ''} # No status
@@ -337,6 +350,22 @@ class AssumeutxoTest(BitcoinTestFramework):
assert 'NETWORK' not in node_services
assert 'NETWORK_LIMITED' in node_services
+ @contextlib.contextmanager
+ def assert_disk_cleanup(self, node, assumeutxo_used):
+ """
+ Ensure an assumeutxo node is cleaning up the background chainstate
+ """
+ msg = []
+ if assumeutxo_used:
+ # Check that the snapshot actually existed before restart
+ assert (node.datadir_path / node.chain / "chainstate_snapshot").exists()
+ msg = ["cleaning up unneeded background chainstate"]
+
+ with node.assert_debug_log(msg):
+ yield
+
+ assert not (node.datadir_path / node.chain / "chainstate_snapshot").exists()
+
def run_test(self):
"""
Bring up two (disconnected) nodes, mine some new blocks on the first,
@@ -644,7 +673,8 @@ class AssumeutxoTest(BitcoinTestFramework):
for i in (0, 1):
n = self.nodes[i]
self.log.info(f"Restarting node {i} to ensure (Check|Load)BlockIndex passes")
- self.restart_node(i, extra_args=self.extra_args[i])
+ with self.assert_disk_cleanup(n, i == 1):
+ self.restart_node(i, extra_args=self.extra_args[i])
assert_equal(n.getblockchaininfo()["blocks"], FINAL_HEIGHT)
@@ -721,7 +751,8 @@ class AssumeutxoTest(BitcoinTestFramework):
for i in (0, 2):
n = self.nodes[i]
self.log.info(f"Restarting node {i} to ensure (Check|Load)BlockIndex passes")
- self.restart_node(i, extra_args=self.extra_args[i])
+ with self.assert_disk_cleanup(n, i == 2):
+ self.restart_node(i, extra_args=self.extra_args[i])
assert_equal(n.getblockchaininfo()["blocks"], FINAL_HEIGHT)
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 32ad3ad271..2f67ef8536 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -58,7 +58,7 @@ class BaseNode(P2PInterface):
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
- self.send_message(headers_message)
+ self.send_without_ping(headers_message)
class AssumeValidTest(BitcoinTestFramework):
@@ -80,7 +80,7 @@ class AssumeValidTest(BitcoinTestFramework):
if not p2p_conn.is_connected:
break
try:
- p2p_conn.send_message(msg_block(self.blocks[i]))
+ p2p_conn.send_without_ping(msg_block(self.blocks[i]))
except IOError:
assert not p2p_conn.is_connected
break
@@ -157,7 +157,7 @@ class AssumeValidTest(BitcoinTestFramework):
# Send all blocks to node1. All blocks will be accepted.
for i in range(2202):
- p2p1.send_message(msg_block(self.blocks[i]))
+ p2p1.send_without_ping(msg_block(self.blocks[i]))
# Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync.
p2p1.sync_with_ping(timeout=960)
assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202)
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index e8fc1aca46..c5e3c33b14 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -24,6 +24,9 @@ class ConfArgsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ # Prune to prevent disk space warning on CI systems with limited space,
+ # when using networks other than regtest.
+ self.extra_args = [["-prune=550"]]
self.supports_cli = False
self.wallet_names = []
self.disable_autoconnect = False
@@ -471,32 +474,21 @@ class ConfArgsTest(BitcoinTestFramework):
self.log.info("Test testnet3 deprecation warning")
t3_warning_log = "Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4."
- def warning_msg(node, approx_size):
- return f'Warning: Disk space for "{node.datadir_path / node.chain / "blocks" }" may not accommodate the block files. Approximately {approx_size} GB of data will be stored in this directory.'
-
- # Testnet3 node will log the warning
+ self.log.debug("Testnet3 node will log the deprecation warning")
self.nodes[0].chain = 'testnet3'
self.nodes[0].replace_in_config([('regtest=', 'testnet='), ('[regtest]', '[test]')])
with self.nodes[0].assert_debug_log([t3_warning_log]):
self.start_node(0)
- # Some CI environments will have limited space and some others won't
- # so we need to handle both cases as a valid result.
- self.nodes[0].stderr.seek(0)
- err = self.nodes[0].stdout.read()
- self.nodes[0].stderr.seek(0)
- self.nodes[0].stderr.truncate()
- if err != b'' and err != warning_msg(self.nodes[0], 42):
- raise AssertionError("Unexpected stderr after shutdown of Testnet3 node")
self.stop_node(0)
- # Testnet4 node will not log the warning
+ self.log.debug("Testnet4 node will not log the deprecation warning")
self.nodes[0].chain = 'testnet4'
self.nodes[0].replace_in_config([('testnet=', 'testnet4='), ('[test]', '[testnet4]')])
with self.nodes[0].assert_debug_log([], unexpected_msgs=[t3_warning_log]):
self.start_node(0)
self.stop_node(0)
- # Reset to regtest
+ self.log.debug("Reset to regtest")
self.nodes[0].chain = 'regtest'
self.nodes[0].replace_in_config([('testnet4=', 'regtest='), ('[testnet4]', '[regtest]')])
diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py
index aa4ca4b45a..956c0dbda2 100755
--- a/test/functional/feature_filelock.py
+++ b/test/functional/feature_filelock.py
@@ -59,8 +59,7 @@ class FilelockTest(BitcoinTestFramework):
if self.is_bdb_compiled():
check_wallet_filelock(False)
- if self.is_sqlite_compiled():
- check_wallet_filelock(True)
+ check_wallet_filelock(True)
if __name__ == '__main__':
FilelockTest(__file__).main()
diff --git a/test/functional/feature_framework_unit_tests.py b/test/functional/feature_framework_unit_tests.py
index 14d83f8a70..4ee2143ad6 100755
--- a/test/functional/feature_framework_unit_tests.py
+++ b/test/functional/feature_framework_unit_tests.py
@@ -18,6 +18,7 @@ TEST_FRAMEWORK_MODULES = [
"address",
"crypto.bip324_cipher",
"blocktools",
+ "compressor",
"crypto.chacha20",
"crypto.ellswift",
"key",
diff --git a/test/functional/feature_init.py b/test/functional/feature_init.py
index 4a2f7ecf42..8a936fc0a5 100755
--- a/test/functional/feature_init.py
+++ b/test/functional/feature_init.py
@@ -4,10 +4,13 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Tests related to node initialization."""
from pathlib import Path
+import os
import platform
import shutil
+import signal
+import subprocess
-from test_framework.test_framework import BitcoinTestFramework, SkipTest
+from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import (
BITCOIN_PID_FILENAME_DEFAULT,
ErrorMatch,
@@ -33,20 +36,17 @@ class InitTest(BitcoinTestFramework):
- test terminating initialization after seeing a certain log line.
- test removing certain essential files to test startup error paths.
"""
- # TODO: skip Windows for now since it isn't clear how to SIGTERM.
- #
- # Windows doesn't support `process.terminate()`.
- # and other approaches (like below) don't work:
- #
- # os.kill(node.process.pid, signal.CTRL_C_EVENT)
- if platform.system() == 'Windows':
- raise SkipTest("can't SIGTERM on Windows")
-
self.stop_node(0)
node = self.nodes[0]
def sigterm_node():
- node.process.terminate()
+ if platform.system() == 'Windows':
+ # Don't call Python's terminate() since it calls
+ # TerminateProcess(), which unlike SIGTERM doesn't allow
+ # bitcoind to perform any shutdown logic.
+ os.kill(node.process.pid, signal.CTRL_BREAK_EVENT)
+ else:
+ node.process.terminate()
node.process.wait()
def start_expecting_error(err_fragment):
@@ -86,10 +86,16 @@ class InitTest(BitcoinTestFramework):
if self.is_wallet_compiled():
lines_to_terminate_after.append(b'Verifying wallet')
+ args = ['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1']
for terminate_line in lines_to_terminate_after:
- self.log.info(f"Starting node and will exit after line {terminate_line}")
+ self.log.info(f"Starting node and will terminate after line {terminate_line}")
with node.busy_wait_for_debug_log([terminate_line]):
- node.start(extra_args=['-txindex=1', '-blockfilterindex=1', '-coinstatsindex=1'])
+ if platform.system() == 'Windows':
+ # CREATE_NEW_PROCESS_GROUP is required in order to be able
+ # to terminate the child without terminating the test.
+ node.start(extra_args=args, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
+ else:
+ node.start(extra_args=args)
self.log.debug("Terminating node after terminate line was found")
sigterm_node()
@@ -102,12 +108,22 @@ class InitTest(BitcoinTestFramework):
'blocks/index/*.ldb': 'Error opening block database.',
'chainstate/*.ldb': 'Error opening coins database.',
'blocks/blk*.dat': 'Error loading block database.',
+ 'indexes/txindex/MANIFEST*': 'LevelDB error: Corruption: CURRENT points to a non-existent file',
+ # Removing these files does not result in a startup error:
+ # 'indexes/blockfilter/basic/*.dat', 'indexes/blockfilter/basic/db/*.*', 'indexes/coinstats/db/*.*',
+ # 'indexes/txindex/*.log', 'indexes/txindex/CURRENT', 'indexes/txindex/LOCK'
}
files_to_perturb = {
'blocks/index/*.ldb': 'Error loading block database.',
'chainstate/*.ldb': 'Error opening coins database.',
'blocks/blk*.dat': 'Corrupted block database detected.',
+ 'indexes/blockfilter/basic/db/*.*': 'LevelDB error: Corruption',
+ 'indexes/coinstats/db/*.*': 'LevelDB error: Corruption',
+ 'indexes/txindex/*.log': 'LevelDB error: Corruption',
+ 'indexes/txindex/CURRENT': 'LevelDB error: Corruption',
+ # Perturbing these files does not result in a startup error:
+ # 'indexes/blockfilter/basic/*.dat', 'indexes/txindex/MANIFEST*', 'indexes/txindex/LOCK'
}
for file_patt, err_fragment in files_to_delete.items():
@@ -129,9 +145,10 @@ class InitTest(BitcoinTestFramework):
self.stop_node(0)
self.log.info("Test startup errors after perturbing certain essential files")
+ dirs = ["blocks", "chainstate", "indexes"]
for file_patt, err_fragment in files_to_perturb.items():
- shutil.copytree(node.chain_path / "blocks", node.chain_path / "blocks_bak")
- shutil.copytree(node.chain_path / "chainstate", node.chain_path / "chainstate_bak")
+ for dir in dirs:
+ shutil.copytree(node.chain_path / dir, node.chain_path / f"{dir}_bak")
target_files = list(node.chain_path.glob(file_patt))
for target_file in target_files:
@@ -145,10 +162,9 @@ class InitTest(BitcoinTestFramework):
start_expecting_error(err_fragment)
- shutil.rmtree(node.chain_path / "blocks")
- shutil.rmtree(node.chain_path / "chainstate")
- shutil.move(node.chain_path / "blocks_bak", node.chain_path / "blocks")
- shutil.move(node.chain_path / "chainstate_bak", node.chain_path / "chainstate")
+ for dir in dirs:
+ shutil.rmtree(node.chain_path / dir)
+ shutil.move(node.chain_path / f"{dir}_bak", node.chain_path / dir)
def init_pid_test(self):
BITCOIN_PID_FILENAME_CUSTOM = "my_fancy_bitcoin_pid_file.foobar"
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index ad5a7e4831..1d7a7bfc55 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -124,7 +124,7 @@ class MaxUploadTest(BitcoinTestFramework):
# the test has been running so far).
with self.nodes[0].assert_debug_log(expected_msgs=["historical block serving limit reached, disconnecting peer=0"]):
for _ in range(3):
- p2p_conns[0].send_message(getdata_request)
+ p2p_conns[0].send_without_ping(getdata_request)
p2p_conns[0].wait_for_disconnect()
assert_equal(len(self.nodes[0].getpeerinfo()), 2)
self.log.info("Peer 0 disconnected after downloading old block too many times")
@@ -148,7 +148,7 @@ class MaxUploadTest(BitcoinTestFramework):
# But if p2p_conns[1] tries for an old block, it gets disconnected too.
getdata_request.inv = [CInv(MSG_BLOCK, big_old_block)]
with self.nodes[0].assert_debug_log(expected_msgs=["historical block serving limit reached, disconnecting peer=1"]):
- p2p_conns[1].send_message(getdata_request)
+ p2p_conns[1].send_without_ping(getdata_request)
p2p_conns[1].wait_for_disconnect()
assert_equal(len(self.nodes[0].getpeerinfo()), 1)
@@ -198,7 +198,7 @@ class MaxUploadTest(BitcoinTestFramework):
self.log.info("Peer gets disconnected for a mempool request after limit is reached")
with self.nodes[0].assert_debug_log(expected_msgs=["mempool request with bandwidth limit reached, disconnecting peer=0"]):
- peer.send_message(msg_mempool())
+ peer.send_without_ping(msg_mempool())
peer.wait_for_disconnect()
self.log.info("Test passing an unparsable value to -maxuploadtarget throws an error")
diff --git a/test/functional/feature_signet.py b/test/functional/feature_signet.py
index 63091b3ee8..02e37f0fdd 100755
--- a/test/functional/feature_signet.py
+++ b/test/functional/feature_signet.py
@@ -26,12 +26,14 @@ signet_blocks = [
class SignetParams:
def __init__(self, challenge=None):
+ # Prune to prevent disk space warning on CI systems with limited space,
+ # when using networks other than regtest.
if challenge is None:
self.challenge = SIGNET_DEFAULT_CHALLENGE
- self.shared_args = []
+ self.shared_args = ["-prune=550"]
else:
self.challenge = challenge
- self.shared_args = [f"-signetchallenge={challenge}"]
+ self.shared_args = ["-prune=550", f"-signetchallenge={challenge}"]
class SignetBasicTest(BitcoinTestFramework):
def set_test_params(self):
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py
index dc25ce6c83..af59666222 100755
--- a/test/functional/feature_versionbits_warning.py
+++ b/test/functional/feature_versionbits_warning.py
@@ -47,7 +47,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
for _ in range(numblocks):
block = create_block(tip, create_coinbase(height + 1), block_time, version=version)
block.solve()
- peer.send_message(msg_block(block))
+ peer.send_without_ping(msg_block(block))
block_time += 1
height += 1
tip = block.sha256
diff --git a/test/functional/interface_usdt_coinselection.py b/test/functional/interface_usdt_coinselection.py
index f684848aed..1f4d6d6fbf 100755
--- a/test/functional/interface_usdt_coinselection.py
+++ b/test/functional/interface_usdt_coinselection.py
@@ -49,10 +49,13 @@ BPF_QUEUE(coin_selection_events, struct event_data, 1024);
int trace_selected_coins(struct pt_regs *ctx) {
struct event_data data;
+ void *pwallet_name = NULL, *palgo = NULL;
__builtin_memset(&data, 0, sizeof(data));
data.type = 1;
- bpf_usdt_readarg_p(1, ctx, &data.wallet_name, WALLET_NAME_LENGTH);
- bpf_usdt_readarg_p(2, ctx, &data.algo, ALGO_NAME_LENGTH);
+ bpf_usdt_readarg(1, ctx, &pwallet_name);
+ bpf_probe_read_user_str(&data.wallet_name, WALLET_NAME_LENGTH, pwallet_name);
+ bpf_usdt_readarg(2, ctx, &palgo);
+ bpf_probe_read_user_str(&data.algo, ALGO_NAME_LENGTH, palgo);
bpf_usdt_readarg(3, ctx, &data.target);
bpf_usdt_readarg(4, ctx, &data.waste);
bpf_usdt_readarg(5, ctx, &data.selected_value);
@@ -62,9 +65,11 @@ int trace_selected_coins(struct pt_regs *ctx) {
int trace_normal_create_tx(struct pt_regs *ctx) {
struct event_data data;
+ void *pwallet_name = NULL;
__builtin_memset(&data, 0, sizeof(data));
data.type = 2;
- bpf_usdt_readarg_p(1, ctx, &data.wallet_name, WALLET_NAME_LENGTH);
+ bpf_usdt_readarg(1, ctx, &pwallet_name);
+ bpf_probe_read_user_str(&data.wallet_name, WALLET_NAME_LENGTH, pwallet_name);
bpf_usdt_readarg(2, ctx, &data.success);
bpf_usdt_readarg(3, ctx, &data.fee);
bpf_usdt_readarg(4, ctx, &data.change_pos);
@@ -74,18 +79,22 @@ int trace_normal_create_tx(struct pt_regs *ctx) {
int trace_attempt_aps(struct pt_regs *ctx) {
struct event_data data;
+ void *pwallet_name = NULL;
__builtin_memset(&data, 0, sizeof(data));
data.type = 3;
- bpf_usdt_readarg_p(1, ctx, &data.wallet_name, WALLET_NAME_LENGTH);
+ bpf_usdt_readarg(1, ctx, &pwallet_name);
+ bpf_probe_read_user_str(&data.wallet_name, WALLET_NAME_LENGTH, pwallet_name);
coin_selection_events.push(&data, 0);
return 0;
}
int trace_aps_create_tx(struct pt_regs *ctx) {
struct event_data data;
+ void *pwallet_name = NULL;
__builtin_memset(&data, 0, sizeof(data));
data.type = 4;
- bpf_usdt_readarg_p(1, ctx, &data.wallet_name, WALLET_NAME_LENGTH);
+ bpf_usdt_readarg(1, ctx, &pwallet_name);
+ bpf_probe_read_user_str(&data.wallet_name, WALLET_NAME_LENGTH, pwallet_name);
bpf_usdt_readarg(2, ctx, &data.use_aps);
bpf_usdt_readarg(3, ctx, &data.success);
bpf_usdt_readarg(4, ctx, &data.fee);
diff --git a/test/functional/interface_usdt_mempool.py b/test/functional/interface_usdt_mempool.py
index 44882f642e..7535954172 100755
--- a/test/functional/interface_usdt_mempool.py
+++ b/test/functional/interface_usdt_mempool.py
@@ -75,8 +75,9 @@ BPF_PERF_OUTPUT(replaced_events);
int trace_added(struct pt_regs *ctx) {
struct added_event added = {};
-
- bpf_usdt_readarg_p(1, ctx, &added.hash, HASH_LENGTH);
+ void *phash = NULL;
+ bpf_usdt_readarg(1, ctx, &phash);
+ bpf_probe_read_user(&added.hash, sizeof(added.hash), phash);
bpf_usdt_readarg(2, ctx, &added.vsize);
bpf_usdt_readarg(3, ctx, &added.fee);
@@ -86,9 +87,11 @@ int trace_added(struct pt_regs *ctx) {
int trace_removed(struct pt_regs *ctx) {
struct removed_event removed = {};
-
- bpf_usdt_readarg_p(1, ctx, &removed.hash, HASH_LENGTH);
- bpf_usdt_readarg_p(2, ctx, &removed.reason, MAX_REMOVAL_REASON_LENGTH);
+ void *phash = NULL, *preason = NULL;
+ bpf_usdt_readarg(1, ctx, &phash);
+ bpf_probe_read_user(&removed.hash, sizeof(removed.hash), phash);
+ bpf_usdt_readarg(2, ctx, &preason);
+ bpf_probe_read_user_str(&removed.reason, sizeof(removed.reason), preason);
bpf_usdt_readarg(3, ctx, &removed.vsize);
bpf_usdt_readarg(4, ctx, &removed.fee);
bpf_usdt_readarg(5, ctx, &removed.entry_time);
@@ -99,22 +102,25 @@ int trace_removed(struct pt_regs *ctx) {
int trace_rejected(struct pt_regs *ctx) {
struct rejected_event rejected = {};
-
- bpf_usdt_readarg_p(1, ctx, &rejected.hash, HASH_LENGTH);
- bpf_usdt_readarg_p(2, ctx, &rejected.reason, MAX_REJECT_REASON_LENGTH);
-
+ void *phash = NULL, *preason = NULL;
+ bpf_usdt_readarg(1, ctx, &phash);
+ bpf_probe_read_user(&rejected.hash, sizeof(rejected.hash), phash);
+ bpf_usdt_readarg(2, ctx, &preason);
+ bpf_probe_read_user_str(&rejected.reason, sizeof(rejected.reason), preason);
rejected_events.perf_submit(ctx, &rejected, sizeof(rejected));
return 0;
}
int trace_replaced(struct pt_regs *ctx) {
struct replaced_event replaced = {};
-
- bpf_usdt_readarg_p(1, ctx, &replaced.replaced_hash, HASH_LENGTH);
+ void *preplaced_hash = NULL, *preplacement_hash = NULL;
+ bpf_usdt_readarg(1, ctx, &preplaced_hash);
+ bpf_probe_read_user(&replaced.replaced_hash, sizeof(replaced.replaced_hash), preplaced_hash);
bpf_usdt_readarg(2, ctx, &replaced.replaced_vsize);
bpf_usdt_readarg(3, ctx, &replaced.replaced_fee);
bpf_usdt_readarg(4, ctx, &replaced.replaced_entry_time);
- bpf_usdt_readarg_p(5, ctx, &replaced.replacement_hash, HASH_LENGTH);
+ bpf_usdt_readarg(5, ctx, &preplacement_hash);
+ bpf_probe_read_user(&replaced.replacement_hash, sizeof(replaced.replacement_hash), preplacement_hash);
bpf_usdt_readarg(6, ctx, &replaced.replacement_vsize);
bpf_usdt_readarg(7, ctx, &replaced.replacement_fee);
bpf_usdt_readarg(8, ctx, &replaced.replaced_by_transaction);
@@ -314,10 +320,7 @@ class MempoolTracepointTest(BitcoinTestFramework):
assert_equal(1, len(events))
event = events[0]
assert_equal(bytes(event.hash)[::-1].hex(), tx["tx"].hash)
- # The next test is already known to fail, so disable it to avoid
- # wasting CPU time and developer time. See
- # https://github.com/bitcoin/bitcoin/issues/27380
- #assert_equal(event.reason.decode("UTF-8"), "min relay fee not met")
+ assert_equal(event.reason.decode("UTF-8"), "min relay fee not met")
bpf.cleanup()
self.generate(self.wallet, 1)
diff --git a/test/functional/interface_usdt_net.py b/test/functional/interface_usdt_net.py
index beb2546153..94baacf3dd 100755
--- a/test/functional/interface_usdt_net.py
+++ b/test/functional/interface_usdt_net.py
@@ -17,7 +17,7 @@ except ImportError:
from test_framework.messages import CBlockHeader, MAX_HEADERS_RESULTS, msg_headers, msg_version
from test_framework.p2p import P2PInterface
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
+from test_framework.util import assert_equal, assert_greater_than
# Tor v3 addresses are 62 chars + 6 chars for the port (':12345').
MAX_PEER_ADDR_LENGTH = 68
@@ -91,12 +91,17 @@ struct MisbehavingConnection
BPF_PERF_OUTPUT(inbound_messages);
int trace_inbound_message(struct pt_regs *ctx) {
struct p2p_message msg = {};
+ void *paddr = NULL, *pconn_type = NULL, *pmsg_type = NULL, *pmsg = NULL;
bpf_usdt_readarg(1, ctx, &msg.peer_id);
- bpf_usdt_readarg_p(2, ctx, &msg.peer_addr, MAX_PEER_ADDR_LENGTH);
- bpf_usdt_readarg_p(3, ctx, &msg.peer_conn_type, MAX_PEER_CONN_TYPE_LENGTH);
- bpf_usdt_readarg_p(4, ctx, &msg.msg_type, MAX_MSG_TYPE_LENGTH);
+ bpf_usdt_readarg(2, ctx, &paddr);
+ bpf_probe_read_user_str(&msg.peer_addr, sizeof(msg.peer_addr), paddr);
+ bpf_usdt_readarg(3, ctx, &pconn_type);
+ bpf_probe_read_user_str(&msg.peer_conn_type, sizeof(msg.peer_conn_type), pconn_type);
+ bpf_usdt_readarg(4, ctx, &pmsg_type);
+ bpf_probe_read_user_str(&msg.msg_type, sizeof(msg.msg_type), pmsg_type);
bpf_usdt_readarg(5, ctx, &msg.msg_size);
- bpf_usdt_readarg_p(6, ctx, &msg.msg, _TRACEPOINT_TEST_MIN(msg.msg_size, MAX_MSG_DATA_LENGTH));
+ bpf_usdt_readarg(6, ctx, &pmsg);
+ bpf_probe_read_user(&msg.msg, _TRACEPOINT_TEST_MIN(msg.msg_size, MAX_MSG_DATA_LENGTH), pmsg);
inbound_messages.perf_submit(ctx, &msg, sizeof(msg));
return 0;
}
@@ -104,12 +109,18 @@ int trace_inbound_message(struct pt_regs *ctx) {
BPF_PERF_OUTPUT(outbound_messages);
int trace_outbound_message(struct pt_regs *ctx) {
struct p2p_message msg = {};
+ void *paddr = NULL, *pconn_type = NULL, *pmsg_type = NULL, *pmsg = NULL;
bpf_usdt_readarg(1, ctx, &msg.peer_id);
- bpf_usdt_readarg_p(2, ctx, &msg.peer_addr, MAX_PEER_ADDR_LENGTH);
- bpf_usdt_readarg_p(3, ctx, &msg.peer_conn_type, MAX_PEER_CONN_TYPE_LENGTH);
- bpf_usdt_readarg_p(4, ctx, &msg.msg_type, MAX_MSG_TYPE_LENGTH);
+ bpf_usdt_readarg(1, ctx, &msg.peer_id);
+ bpf_usdt_readarg(2, ctx, &paddr);
+ bpf_probe_read_user_str(&msg.peer_addr, sizeof(msg.peer_addr), paddr);
+ bpf_usdt_readarg(3, ctx, &pconn_type);
+ bpf_probe_read_user_str(&msg.peer_conn_type, sizeof(msg.peer_conn_type), pconn_type);
+ bpf_usdt_readarg(4, ctx, &pmsg_type);
+ bpf_probe_read_user_str(&msg.msg_type, sizeof(msg.msg_type), pmsg_type);
bpf_usdt_readarg(5, ctx, &msg.msg_size);
- bpf_usdt_readarg_p(6, ctx, &msg.msg, _TRACEPOINT_TEST_MIN(msg.msg_size, MAX_MSG_DATA_LENGTH));
+ bpf_usdt_readarg(6, ctx, &pmsg);
+ bpf_probe_read_user(&msg.msg, _TRACEPOINT_TEST_MIN(msg.msg_size, MAX_MSG_DATA_LENGTH), pmsg);
outbound_messages.perf_submit(ctx, &msg, sizeof(msg));
return 0;
};
@@ -353,8 +364,8 @@ class NetTracepointTest(BitcoinTestFramework):
assert_equal(EXPECTED_INBOUND_CONNECTIONS, len(inbound_connections))
for inbound_connection in inbound_connections:
- assert inbound_connection.conn.id > 0
- assert inbound_connection.existing > 0
+ assert_greater_than(inbound_connection.conn.id, 0)
+ assert_greater_than(inbound_connection.existing, 0)
assert_equal(b'inbound', inbound_connection.conn.conn_type)
assert_equal(NETWORK_TYPE_UNROUTABLE, inbound_connection.conn.network)
@@ -394,8 +405,8 @@ class NetTracepointTest(BitcoinTestFramework):
assert_equal(EXPECTED_OUTBOUND_CONNECTIONS, len(outbound_connections))
for outbound_connection in outbound_connections:
- assert outbound_connection.conn.id > 0
- assert outbound_connection.existing > 0
+ assert_greater_than(outbound_connection.conn.id, 0)
+ assert_greater_than(outbound_connection.existing, 0)
assert_equal(EXPECTED_CONNECTION_TYPE, outbound_connection.conn.conn_type.decode('utf-8'))
assert_equal(NETWORK_TYPE_UNROUTABLE, outbound_connection.conn.network)
@@ -431,8 +442,8 @@ class NetTracepointTest(BitcoinTestFramework):
assert_equal(EXPECTED_EVICTED_CONNECTIONS, len(evicted_connections))
for evicted_connection in evicted_connections:
- assert evicted_connection.conn.id > 0
- assert evicted_connection.time_established > 0
+ assert_greater_than(evicted_connection.conn.id, 0)
+ assert_greater_than(evicted_connection.time_established, 0)
assert_equal("inbound", evicted_connection.conn.conn_type.decode('utf-8'))
assert_equal(NETWORK_TYPE_UNROUTABLE, evicted_connection.conn.network)
@@ -462,15 +473,15 @@ class NetTracepointTest(BitcoinTestFramework):
for _ in range(EXPECTED_MISBEHAVING_CONNECTIONS):
testnode = P2PInterface()
self.nodes[0].add_p2p_connection(testnode)
- testnode.send_message(msg)
+ testnode.send_without_ping(msg)
bpf.perf_buffer_poll(timeout=500)
testnode.peer_disconnect()
assert_equal(EXPECTED_MISBEHAVING_CONNECTIONS, len(misbehaving_connections))
for misbehaving_connection in misbehaving_connections:
- assert misbehaving_connection.id > 0
- assert len(misbehaving_connection.message) > 0
- assert misbehaving_connection.message == b"headers message size = 2001"
+ assert_greater_than(misbehaving_connection.id, 0)
+ assert_greater_than(len(misbehaving_connection.message), 0)
+ assert_equal(misbehaving_connection.message, b"headers message size = 2001")
bpf.cleanup()
@@ -505,10 +516,10 @@ class NetTracepointTest(BitcoinTestFramework):
assert_equal(EXPECTED_CLOSED_CONNECTIONS, len(closed_connections))
for closed_connection in closed_connections:
- assert closed_connection.conn.id > 0
+ assert_greater_than(closed_connection.conn.id, 0)
assert_equal("inbound", closed_connection.conn.conn_type.decode('utf-8'))
assert_equal(0, closed_connection.conn.network)
- assert closed_connection.time_established > 0
+ assert_greater_than(closed_connection.time_established, 0)
bpf.cleanup()
diff --git a/test/functional/interface_usdt_utxocache.py b/test/functional/interface_usdt_utxocache.py
index 1617c580f3..12a11409e0 100755
--- a/test/functional/interface_usdt_utxocache.py
+++ b/test/functional/interface_usdt_utxocache.py
@@ -35,7 +35,9 @@ struct utxocache_change
BPF_PERF_OUTPUT(utxocache_add);
int trace_utxocache_add(struct pt_regs *ctx) {
struct utxocache_change add = {};
- bpf_usdt_readarg_p(1, ctx, &add.txid, 32);
+ void *ptxid = NULL;
+ bpf_usdt_readarg(1, ctx, &ptxid);
+ bpf_probe_read_user(&add.txid, sizeof(add.txid), ptxid);
bpf_usdt_readarg(2, ctx, &add.index);
bpf_usdt_readarg(3, ctx, &add.height);
bpf_usdt_readarg(4, ctx, &add.value);
@@ -47,7 +49,9 @@ int trace_utxocache_add(struct pt_regs *ctx) {
BPF_PERF_OUTPUT(utxocache_spent);
int trace_utxocache_spent(struct pt_regs *ctx) {
struct utxocache_change spent = {};
- bpf_usdt_readarg_p(1, ctx, &spent.txid, 32);
+ void *ptxid = NULL;
+ bpf_usdt_readarg(1, ctx, &ptxid);
+ bpf_probe_read_user(&spent.txid, sizeof(spent.txid), ptxid);
bpf_usdt_readarg(2, ctx, &spent.index);
bpf_usdt_readarg(3, ctx, &spent.height);
bpf_usdt_readarg(4, ctx, &spent.value);
@@ -59,7 +63,9 @@ int trace_utxocache_spent(struct pt_regs *ctx) {
BPF_PERF_OUTPUT(utxocache_uncache);
int trace_utxocache_uncache(struct pt_regs *ctx) {
struct utxocache_change uncache = {};
- bpf_usdt_readarg_p(1, ctx, &uncache.txid, 32);
+ void *ptxid = NULL;
+ bpf_usdt_readarg(1, ctx, &ptxid);
+ bpf_probe_read_user(&uncache.txid, sizeof(uncache.txid), ptxid);
bpf_usdt_readarg(2, ctx, &uncache.index);
bpf_usdt_readarg(3, ctx, &uncache.height);
bpf_usdt_readarg(4, ctx, &uncache.value);
diff --git a/test/functional/interface_usdt_validation.py b/test/functional/interface_usdt_validation.py
index 8a98a452de..9b2e708d95 100755
--- a/test/functional/interface_usdt_validation.py
+++ b/test/functional/interface_usdt_validation.py
@@ -39,7 +39,9 @@ struct connected_block
BPF_PERF_OUTPUT(block_connected);
int trace_block_connected(struct pt_regs *ctx) {
struct connected_block block = {};
- bpf_usdt_readarg_p(1, ctx, &block.hash, 32);
+ void *phash = NULL;
+ bpf_usdt_readarg(1, ctx, &phash);
+ bpf_probe_read_user(&block.hash, sizeof(block.hash), phash);
bpf_usdt_readarg(2, ctx, &block.height);
bpf_usdt_readarg(3, ctx, &block.transactions);
bpf_usdt_readarg(4, ctx, &block.inputs);
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 27ecc3b4a8..9014ab260e 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -45,6 +45,7 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
+ sync_txindex,
)
from test_framework.wallet import MiniWallet
from test_framework.wallet_util import generate_keypair
@@ -270,6 +271,7 @@ class MempoolAcceptanceTest(BitcoinTestFramework):
self.log.info('A coinbase transaction')
# Pick the input of the first tx we created, so it has to be a coinbase tx
+ sync_txindex(self, node)
raw_tx_coinbase_spent = node.getrawtransaction(txid=node.decoderawtransaction(hexstring=raw_tx_in_block)['vin'][0]['txid'])
tx = tx_from_hex(raw_tx_coinbase_spent)
self.check_mempool_result(
diff --git a/test/functional/mempool_ephemeral_dust.py b/test/functional/mempool_ephemeral_dust.py
index e614a9e607..004db3656e 100755
--- a/test/functional/mempool_ephemeral_dust.py
+++ b/test/functional/mempool_ephemeral_dust.py
@@ -233,8 +233,8 @@ class EphemeralDustTest(BitcoinTestFramework):
unspent_sweep_tx = self.wallet.create_self_transfer_multi(fee_per_output=2000, utxos_to_spend=[dusty_tx["new_utxos"][0]], version=3)
assert_greater_than(unspent_sweep_tx["fee"], sweep_tx["fee"])
res = self.nodes[0].submitpackage([dusty_tx["hex"], unspent_sweep_tx["hex"]])
- assert_equal(res["tx-results"][unspent_sweep_tx["wtxid"]]["error"], f"missing-ephemeral-spends, tx {unspent_sweep_tx['txid']} did not spend parent's ephemeral dust")
- assert_raises_rpc_error(-26, f"missing-ephemeral-spends, tx {unspent_sweep_tx['txid']} did not spend parent's ephemeral dust", self.nodes[0].sendrawtransaction, unspent_sweep_tx["hex"])
+ assert_equal(res["tx-results"][unspent_sweep_tx["wtxid"]]["error"], f"missing-ephemeral-spends, tx {unspent_sweep_tx['txid']} (wtxid={unspent_sweep_tx['wtxid']}) did not spend parent's ephemeral dust")
+ assert_raises_rpc_error(-26, f"missing-ephemeral-spends, tx {unspent_sweep_tx['txid']} (wtxid={unspent_sweep_tx['wtxid']}) did not spend parent's ephemeral dust", self.nodes[0].sendrawtransaction, unspent_sweep_tx["hex"])
assert_mempool_contents(self, self.nodes[0], expected=[dusty_tx["tx"], sweep_tx["tx"]])
# Spend works with dust spent
@@ -405,7 +405,7 @@ class EphemeralDustTest(BitcoinTestFramework):
res = self.nodes[0].submitpackage([dusty_tx["hex"] for dusty_tx in dusty_txs] + [insufficient_sweep_tx["hex"]])
assert_equal(res['package_msg'], "transaction failed")
- assert_equal(res['tx-results'][insufficient_sweep_tx['wtxid']]['error'], f"missing-ephemeral-spends, tx {insufficient_sweep_tx['txid']} did not spend parent's ephemeral dust")
+ assert_equal(res['tx-results'][insufficient_sweep_tx['wtxid']]['error'], f"missing-ephemeral-spends, tx {insufficient_sweep_tx['txid']} (wtxid={insufficient_sweep_tx['wtxid']}) did not spend parent's ephemeral dust")
# Everything got in except for insufficient spend
assert_mempool_contents(self, self.nodes[0], expected=[dusty_tx["tx"] for dusty_tx in dusty_txs])
@@ -418,7 +418,7 @@ class EphemeralDustTest(BitcoinTestFramework):
res = self.nodes[0].submitpackage([dusty_tx["hex"] for dusty_tx in dusty_txs] + [insufficient_sweep_tx["hex"]])
assert_equal(res['package_msg'], "transaction failed")
- assert_equal(res['tx-results'][insufficient_sweep_tx["wtxid"]]["error"], f"missing-ephemeral-spends, tx {insufficient_sweep_tx['txid']} did not spend parent's ephemeral dust")
+ assert_equal(res['tx-results'][insufficient_sweep_tx["wtxid"]]["error"], f"missing-ephemeral-spends, tx {insufficient_sweep_tx['txid']} (wtxid={insufficient_sweep_tx['wtxid']}) did not spend parent's ephemeral dust")
assert_mempool_contents(self, self.nodes[0], expected=[dusty_tx["tx"] for dusty_tx in dusty_txs] + [sweep_all_but_one_tx["tx"]])
# Cycle out the partial sweep to avoid triggering package RBF behavior which limits package to no in-mempool ancestors
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index c64c203e50..bf0a97df0d 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -59,7 +59,7 @@ class MempoolPersistTest(BitcoinTestFramework):
def run_test(self):
self.mini_wallet = MiniWallet(self.nodes[2])
- if self.is_sqlite_compiled():
+ if self.is_wallet_compiled():
self.nodes[2].createwallet(
wallet_name="watch",
descriptors=True,
@@ -73,7 +73,7 @@ class MempoolPersistTest(BitcoinTestFramework):
tx_creation_time_lower = int(time.time())
for _ in range(5):
last_txid = self.mini_wallet.send_self_transfer(from_node=self.nodes[2])["txid"]
- if self.is_sqlite_compiled():
+ if self.is_wallet_compiled():
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
node2_balance = wallet_watch.getbalance()
self.sync_all()
@@ -137,7 +137,7 @@ class MempoolPersistTest(BitcoinTestFramework):
assert_equal(entry_prioritised_before_restart['fees']['base'] + Decimal('0.00009999'), entry_prioritised_before_restart['fees']['modified'])
# Verify accounting of mempool transactions after restart is correct
- if self.is_sqlite_compiled():
+ if self.is_wallet_compiled():
self.nodes[2].loadwallet("watch")
wallet_watch = self.nodes[2].get_wallet_rpc("watch")
self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 56a9e6a84e..71af7f1e7c 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -76,9 +76,9 @@ class AddrReceiver(P2PInterface):
def on_version(self, message):
self.send_version()
- self.send_message(msg_verack())
+ self.send_without_ping(msg_verack())
if (self.send_getaddr):
- self.send_message(msg_getaddr())
+ self.send_without_ping(msg_getaddr())
def getaddr_received(self):
return self.message_count['getaddr'] > 0
@@ -142,7 +142,7 @@ class AddrTest(BitcoinTestFramework):
msg = self.setup_addr_msg(1010)
with self.nodes[0].assert_debug_log(['addr message size = 1010']):
- addr_source.send_message(msg)
+ addr_source.send_without_ping(msg)
addr_source.wait_for_disconnect()
self.nodes[0].disconnect_p2ps()
diff --git a/test/functional/p2p_addrfetch.py b/test/functional/p2p_addrfetch.py
index 69cc106341..1243f951dc 100755
--- a/test/functional/p2p_addrfetch.py
+++ b/test/functional/p2p_addrfetch.py
@@ -62,7 +62,7 @@ class P2PAddrFetch(BitcoinTestFramework):
self.log.info("Check that answering with larger addr messages leads to disconnect")
msg.addrs = [ADDR] * 2
- peer.send_message(msg)
+ peer.send_without_ping(msg)
peer.wait_for_disconnect(timeout=5)
self.log.info("Check timeout for addr-fetch peer that does not send addrs")
diff --git a/test/functional/p2p_addrv2_relay.py b/test/functional/p2p_addrv2_relay.py
index 8012137971..3a14d89239 100755
--- a/test/functional/p2p_addrv2_relay.py
+++ b/test/functional/p2p_addrv2_relay.py
@@ -79,7 +79,7 @@ class AddrTest(BitcoinTestFramework):
self.log.info('Check disconnection when sending sendaddrv2 after verack')
conn = self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(['sendaddrv2 received after verack, disconnecting peer=0']):
- conn.send_message(msg_sendaddrv2())
+ conn.send_without_ping(msg_sendaddrv2())
conn.wait_for_disconnect()
self.log.info('Create connection that sends addrv2 messages')
@@ -104,7 +104,7 @@ class AddrTest(BitcoinTestFramework):
self.log.info('Send too-large addrv2 message')
msg.addrs = ADDRS * 101
with self.nodes[0].assert_debug_log(['addrv2 message size = 1010']):
- addr_source.send_message(msg)
+ addr_source.send_without_ping(msg)
addr_source.wait_for_disconnect()
diff --git a/test/functional/p2p_blockfilters.py b/test/functional/p2p_blockfilters.py
index 88d5aa1408..0a4b7f0296 100755
--- a/test/functional/p2p_blockfilters.py
+++ b/test/functional/p2p_blockfilters.py
@@ -212,7 +212,7 @@ class CompactFiltersTest(BitcoinTestFramework):
for request in requests:
peer_1 = self.nodes[1].add_p2p_connection(P2PInterface())
with self.nodes[1].assert_debug_log(expected_msgs=["requested unsupported block filter type"]):
- peer_1.send_message(request)
+ peer_1.send_without_ping(request)
peer_1.wait_for_disconnect()
self.log.info("Check that invalid requests result in disconnection.")
@@ -259,7 +259,7 @@ class CompactFiltersTest(BitcoinTestFramework):
for request, expected_log_msg in requests:
peer_0 = self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(expected_msgs=[expected_log_msg]):
- peer_0.send_message(request)
+ peer_0.send_without_ping(request)
peer_0.wait_for_disconnect()
self.log.info("Test -peerblockfilters without -blockfilterindex raises an error")
diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py
index 6737cc687e..fca8e3266c 100755
--- a/test/functional/p2p_blocksonly.py
+++ b/test/functional/p2p_blocksonly.py
@@ -34,7 +34,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
self.log.info('Check that tx invs also violate the protocol')
self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(['transaction (0000000000000000000000000000000000000000000000000000000000001234) inv sent in violation of protocol, disconnecting peer']):
- self.nodes[0].p2ps[0].send_message(msg_inv([CInv(t=MSG_WTX, h=0x1234)]))
+ self.nodes[0].p2ps[0].send_without_ping(msg_inv([CInv(t=MSG_WTX, h=0x1234)]))
self.nodes[0].p2ps[0].wait_for_disconnect()
del self.nodes[0].p2ps[0]
@@ -68,7 +68,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
# But if, for some reason, first_peer decides to relay transactions to us anyway, we should relay them to
# second_peer since we gave relay permission to first_peer.
# See https://github.com/bitcoin/bitcoin/issues/19943 for details.
- first_peer.send_message(msg_tx(tx))
+ first_peer.send_without_ping(msg_tx(tx))
self.log.info('Check that the peer with relay-permission is still connected after sending the transaction')
assert_equal(first_peer.is_connected, True)
second_peer.wait_for_tx(txid)
@@ -107,7 +107,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
def check_p2p_inv_violation(self, peer):
self.log.info("Check that tx-invs from P2P are rejected and result in disconnect")
with self.nodes[0].assert_debug_log(["inv sent in violation of protocol, disconnecting peer"]):
- peer.send_message(msg_inv([CInv(t=MSG_WTX, h=0x12345)]))
+ peer.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=0x12345)]))
peer.wait_for_disconnect()
self.nodes[0].disconnect_p2ps()
@@ -116,7 +116,7 @@ class P2PBlocksOnly(BitcoinTestFramework):
spendtx = self.miniwallet.create_self_transfer()
with self.nodes[0].assert_debug_log(['transaction sent in violation of protocol, disconnecting peer=0']):
- self.nodes[0].p2ps[0].send_message(msg_tx(spendtx['tx']))
+ self.nodes[0].p2ps[0].send_without_ping(msg_tx(spendtx['tx']))
self.nodes[0].p2ps[0].wait_for_disconnect()
assert_equal(self.nodes[0].getmempoolinfo()['size'], 0)
self.nodes[0].disconnect_p2ps()
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index ca36b2fbc0..a0bd063663 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -113,12 +113,12 @@ class TestP2PConn(P2PInterface):
msg = msg_getheaders()
msg.locator.vHave = locator
msg.hashstop = hashstop
- self.send_message(msg)
+ self.send_without_ping(msg)
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
- self.send_message(headers_message)
+ self.send_without_ping(headers_message)
def request_headers_and_sync(self, locator, hashstop=0):
self.clear_block_announcement()
@@ -138,7 +138,7 @@ class TestP2PConn(P2PInterface):
This is used when we want to send a message into the node that we expect
will get us disconnected, eg an invalid block."""
- self.send_message(message)
+ self.send_without_ping(message)
self.wait_for_disconnect(timeout=timeout)
class CompactBlocksTest(BitcoinTestFramework):
@@ -325,7 +325,7 @@ class CompactBlocksTest(BitcoinTestFramework):
# Now fetch the compact block using a normal non-announce getdata
test_node.clear_block_announcement()
inv = CInv(MSG_CMPCT_BLOCK, block_hash)
- test_node.send_message(msg_getdata([inv]))
+ test_node.send_without_ping(msg_getdata([inv]))
test_node.wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30)
@@ -386,7 +386,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block = self.build_block_on_tip(node)
if announce == "inv":
- test_node.send_message(msg_inv([CInv(MSG_BLOCK, block.sha256)]))
+ test_node.send_without_ping(msg_inv([CInv(MSG_BLOCK, block.sha256)]))
test_node.wait_for_getheaders(timeout=30)
test_node.send_header_for_blocks([block])
else:
@@ -497,7 +497,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block = self.build_block_with_transactions(node, utxo, 10)
self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
for tx in block.vtx[1:]:
- test_node.send_message(msg_tx(tx))
+ test_node.send_without_ping(msg_tx(tx))
test_node.sync_with_ping()
# Make sure all transactions were accepted.
mempool = node.getrawmempool()
@@ -525,7 +525,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.utxos.append([block.vtx[-1].sha256, 0, block.vtx[-1].vout[0].nValue])
# Relay the first 5 transactions from the block in advance
for tx in block.vtx[1:6]:
- test_node.send_message(msg_tx(tx))
+ test_node.send_without_ping(msg_tx(tx))
test_node.sync_with_ping()
# Make sure all transactions were accepted.
mempool = node.getrawmempool()
@@ -581,7 +581,7 @@ class CompactBlocksTest(BitcoinTestFramework):
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [])
num_to_request = random.randint(1, len(block.vtx))
msg.block_txn_request.from_absolute(sorted(random.sample(range(len(block.vtx)), num_to_request)))
- test_node.send_message(msg)
+ test_node.send_without_ping(msg)
test_node.wait_until(lambda: "blocktxn" in test_node.last_message, timeout=10)
[tx.calc_sha256() for tx in block.vtx]
@@ -616,7 +616,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block = from_hex(CBlock(), node.getblock(block_hash, False))
msg.block_txn_request = BlockTransactionsRequest(int(block_hash, 16), [len(block.vtx)])
with node.assert_debug_log(['getblocktxn with out-of-bounds tx indices']):
- bad_peer.send_message(msg)
+ bad_peer.send_without_ping(msg)
bad_peer.wait_for_disconnect()
def test_low_work_compactblocks(self, test_node):
@@ -651,7 +651,7 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.wait_until(test_node.received_block_announcement, timeout=30)
test_node.clear_block_announcement()
- test_node.send_message(msg_getdata([CInv(MSG_CMPCT_BLOCK, int(new_blocks[0], 16))]))
+ test_node.send_without_ping(msg_getdata([CInv(MSG_CMPCT_BLOCK, int(new_blocks[0], 16))]))
test_node.wait_until(lambda: "cmpctblock" in test_node.last_message, timeout=30)
test_node.clear_block_announcement()
@@ -660,7 +660,7 @@ class CompactBlocksTest(BitcoinTestFramework):
test_node.clear_block_announcement()
with p2p_lock:
test_node.last_message.pop("block", None)
- test_node.send_message(msg_getdata([CInv(MSG_CMPCT_BLOCK, int(new_blocks[0], 16))]))
+ test_node.send_without_ping(msg_getdata([CInv(MSG_CMPCT_BLOCK, int(new_blocks[0], 16))]))
test_node.wait_until(lambda: "block" in test_node.last_message, timeout=30)
with p2p_lock:
test_node.last_message["block"].block.calc_sha256()
@@ -768,7 +768,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block, cmpct_block = announce_cmpct_block(node, stalling_peer)
for tx in block.vtx[1:]:
- delivery_peer.send_message(msg_tx(tx))
+ delivery_peer.send_without_ping(msg_tx(tx))
delivery_peer.sync_with_ping()
mempool = node.getrawmempool()
for tx in block.vtx[1:]:
@@ -783,7 +783,7 @@ class CompactBlocksTest(BitcoinTestFramework):
block, cmpct_block = announce_cmpct_block(node, stalling_peer)
for tx in block.vtx[1:]:
- delivery_peer.send_message(msg_tx(tx))
+ delivery_peer.send_without_ping(msg_tx(tx))
delivery_peer.sync_with_ping()
cmpct_block.prefilled_txn[0].tx.wit.vtxinwit = [CTxInWitness()]
diff --git a/test/functional/p2p_compactblocks_blocksonly.py b/test/functional/p2p_compactblocks_blocksonly.py
index b92efc875c..954175b772 100755
--- a/test/functional/p2p_compactblocks_blocksonly.py
+++ b/test/functional/p2p_compactblocks_blocksonly.py
@@ -93,19 +93,16 @@ class P2PCompactBlocksBlocksOnly(BitcoinTestFramework):
block1 = self.build_block_on_tip()
- p2p_conn_blocksonly.send_message(msg_headers(headers=[CBlockHeader(block1)]))
- p2p_conn_blocksonly.sync_with_ping()
+ p2p_conn_blocksonly.send_and_ping(msg_headers(headers=[CBlockHeader(block1)]))
assert_equal(p2p_conn_blocksonly.last_message['getdata'].inv, [CInv(MSG_BLOCK | MSG_WITNESS_FLAG, block1.sha256)])
- p2p_conn_high_bw.send_message(msg_headers(headers=[CBlockHeader(block1)]))
- p2p_conn_high_bw.sync_with_ping()
+ p2p_conn_high_bw.send_and_ping(msg_headers(headers=[CBlockHeader(block1)]))
assert_equal(p2p_conn_high_bw.last_message['getdata'].inv, [CInv(MSG_CMPCT_BLOCK, block1.sha256)])
self.log.info("Test that getdata(CMPCT) is still sent on BIP152 low bandwidth connections"
" when no -blocksonly nodes are involved")
p2p_conn_low_bw.send_and_ping(msg_headers(headers=[CBlockHeader(block1)]))
- p2p_conn_low_bw.sync_with_ping()
assert_equal(p2p_conn_low_bw.last_message['getdata'].inv, [CInv(MSG_CMPCT_BLOCK, block1.sha256)])
self.log.info("Test that -blocksonly nodes still serve compact blocks")
@@ -115,7 +112,7 @@ class P2PCompactBlocksBlocksOnly(BitcoinTestFramework):
return False
return p2p_conn_blocksonly.last_message['cmpctblock'].header_and_shortids.header.rehash() == block.sha256
- p2p_conn_blocksonly.send_message(msg_getdata([CInv(MSG_CMPCT_BLOCK, block0.sha256)]))
+ p2p_conn_blocksonly.send_without_ping(msg_getdata([CInv(MSG_CMPCT_BLOCK, block0.sha256)]))
p2p_conn_blocksonly.wait_until(lambda: test_for_cmpctblock(block0))
# Request BIP152 high bandwidth mode from the -blocksonly node.
diff --git a/test/functional/p2p_dos_header_tree.py b/test/functional/p2p_dos_header_tree.py
deleted file mode 100755
index fbb5d716f5..0000000000
--- a/test/functional/p2p_dos_header_tree.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2019-2022 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test that we reject low difficulty headers to prevent our block tree from filling up with useless bloat"""
-
-from test_framework.messages import (
- CBlockHeader,
- from_hex,
-)
-from test_framework.p2p import (
- P2PInterface,
- msg_headers,
-)
-from test_framework.test_framework import BitcoinTestFramework
-
-import os
-
-
-class RejectLowDifficultyHeadersTest(BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = True
- self.chain = 'testnet3' # Use testnet chain because it has an early checkpoint
- self.num_nodes = 2
- self.extra_args = [["-minimumchainwork=0x0", '-prune=550']] * self.num_nodes
-
- def add_options(self, parser):
- parser.add_argument(
- '--datafile',
- default='data/blockheader_testnet3.hex',
- help='Test data file (default: %(default)s)',
- )
-
- def run_test(self):
- self.log.info("Read headers data")
- self.headers_file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.options.datafile)
- with open(self.headers_file_path, encoding='utf-8') as headers_data:
- h_lines = [l.strip() for l in headers_data.readlines()]
-
- # The headers data is taken from testnet3 for early blocks from genesis until the first checkpoint. There are
- # two headers with valid POW at height 1 and 2, forking off from genesis. They are indicated by the FORK_PREFIX.
- FORK_PREFIX = 'fork:'
- self.headers = [l for l in h_lines if not l.startswith(FORK_PREFIX)]
- self.headers_fork = [l[len(FORK_PREFIX):] for l in h_lines if l.startswith(FORK_PREFIX)]
-
- self.headers = [from_hex(CBlockHeader(), h) for h in self.headers]
- self.headers_fork = [from_hex(CBlockHeader(), h) for h in self.headers_fork]
-
- self.log.info("Feed all non-fork headers, including and up to the first checkpoint")
- peer_checkpoint = self.nodes[0].add_p2p_connection(P2PInterface())
- peer_checkpoint.send_and_ping(msg_headers(self.headers))
- assert {
- 'height': 546,
- 'hash': '000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70',
- 'branchlen': 546,
- 'status': 'headers-only',
- } in self.nodes[0].getchaintips()
-
- self.log.info("Feed all fork headers (fails due to checkpoint)")
- with self.nodes[0].assert_debug_log(['bad-fork-prior-to-checkpoint']):
- peer_checkpoint.send_message(msg_headers(self.headers_fork))
- peer_checkpoint.wait_for_disconnect()
-
- self.log.info("Feed all fork headers (succeeds without checkpoint)")
- # On node 0 it succeeds because checkpoints are disabled
- self.restart_node(0, extra_args=['-nocheckpoints', "-minimumchainwork=0x0", '-prune=550'])
- peer_no_checkpoint = self.nodes[0].add_p2p_connection(P2PInterface())
- peer_no_checkpoint.send_and_ping(msg_headers(self.headers_fork))
- assert {
- "height": 2,
- "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
- "branchlen": 2,
- "status": "headers-only",
- } in self.nodes[0].getchaintips()
-
- # On node 1 it succeeds because no checkpoint has been reached yet by a chain tip
- peer_before_checkpoint = self.nodes[1].add_p2p_connection(P2PInterface())
- peer_before_checkpoint.send_and_ping(msg_headers(self.headers_fork))
- assert {
- "height": 2,
- "hash": "00000000b0494bd6c3d5ff79c497cfce40831871cbf39b1bc28bd1dac817dc39",
- "branchlen": 2,
- "status": "headers-only",
- } in self.nodes[1].getchaintips()
-
-
-if __name__ == '__main__':
- RejectLowDifficultyHeadersTest(__file__).main()
diff --git a/test/functional/p2p_eviction.py b/test/functional/p2p_eviction.py
index 0d2bdcc429..9809faa682 100755
--- a/test/functional/p2p_eviction.py
+++ b/test/functional/p2p_eviction.py
@@ -34,13 +34,13 @@ from test_framework.wallet import MiniWallet
class SlowP2PDataStore(P2PDataStore):
def on_ping(self, message):
time.sleep(0.1)
- self.send_message(msg_pong(message.nonce))
+ self.send_without_ping(msg_pong(message.nonce))
class SlowP2PInterface(P2PInterface):
def on_ping(self, message):
time.sleep(0.1)
- self.send_message(msg_pong(message.nonce))
+ self.send_without_ping(msg_pong(message.nonce))
class P2PEvict(BitcoinTestFramework):
@@ -82,7 +82,7 @@ class P2PEvict(BitcoinTestFramework):
txpeer.sync_with_ping()
tx = self.wallet.create_self_transfer()['tx']
- txpeer.send_message(msg_tx(tx))
+ txpeer.send_without_ping(msg_tx(tx))
protected_peers.add(current_peer)
self.log.info("Create 8 peers and protect them from eviction by having faster pings")
diff --git a/test/functional/p2p_filter.py b/test/functional/p2p_filter.py
index e4aaf507cf..e3612f9852 100755
--- a/test/functional/p2p_filter.py
+++ b/test/functional/p2p_filter.py
@@ -62,7 +62,7 @@ class P2PBloomFilter(P2PInterface):
else:
want.inv.append(i)
if len(want.inv):
- self.send_message(want)
+ self.send_without_ping(want)
def on_merkleblock(self, message):
self._merkleblock_received = True
@@ -146,11 +146,11 @@ class FilterTest(BitcoinTestFramework):
self.log.info("Send a mempool msg after connecting and check that the relevant tx is announced")
self.nodes[0].add_p2p_connection(filter_peer)
filter_peer.send_and_ping(filter_peer.watch_filter_init)
- filter_peer.send_message(msg_mempool())
+ filter_peer.send_without_ping(msg_mempool())
filter_peer.wait_for_tx(rel_txid)
self.log.info("Request the irrelevant transaction even though it was not announced")
- filter_peer.send_message(msg_getdata([CInv(t=MSG_WTX, h=int(irr_wtxid, 16))]))
+ filter_peer.send_without_ping(msg_getdata([CInv(t=MSG_WTX, h=int(irr_wtxid, 16))]))
self.log.info("We should get it anyway because it was in the mempool on connection to peer")
filter_peer.wait_for_tx(irr_txid)
@@ -242,7 +242,7 @@ class FilterTest(BitcoinTestFramework):
version_without_fRelay.strSubVer = P2P_SUBVERSION
version_without_fRelay.nServices = P2P_SERVICES
version_without_fRelay.relay = 0
- filter_peer_without_nrelay.send_message(version_without_fRelay)
+ filter_peer_without_nrelay.send_without_ping(version_without_fRelay)
filter_peer_without_nrelay.wait_for_verack()
assert not self.nodes[0].getpeerinfo()[0]['relaytxes']
self.test_frelay_false(filter_peer_without_nrelay)
diff --git a/test/functional/p2p_fingerprint.py b/test/functional/p2p_fingerprint.py
index f49be62056..412de0149f 100755
--- a/test/functional/p2p_fingerprint.py
+++ b/test/functional/p2p_fingerprint.py
@@ -50,13 +50,13 @@ class P2PFingerprintTest(BitcoinTestFramework):
def send_block_request(self, block_hash, node):
msg = msg_getdata()
msg.inv.append(CInv(MSG_BLOCK, block_hash))
- node.send_message(msg)
+ node.send_without_ping(msg)
# Send a getheaders request for a given single block hash
def send_header_request(self, block_hash, node):
msg = msg_getheaders()
msg.hashstop = block_hash
- node.send_message(msg)
+ node.send_without_ping(msg)
# Checks that stale blocks timestamped more than a month ago are not served
# by the node while recent stale blocks and old active chain blocks are.
@@ -78,7 +78,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
new_blocks = self.build_chain(5, block_hash, height, block_time)
# Force reorg to a longer chain
- node0.send_message(msg_headers(new_blocks))
+ node0.send_without_ping(msg_headers(new_blocks))
node0.wait_for_getdata([x.sha256 for x in new_blocks])
for block in new_blocks:
node0.send_and_ping(msg_block(block))
diff --git a/test/functional/p2p_ibd_stalling.py b/test/functional/p2p_ibd_stalling.py
index 4348bf7ee9..1ae508085d 100755
--- a/test/functional/p2p_ibd_stalling.py
+++ b/test/functional/p2p_ibd_stalling.py
@@ -38,7 +38,7 @@ class P2PStaller(P2PDataStore):
self.getdata_requests.append(inv.hash)
if (inv.type & MSG_TYPE_MASK) == MSG_BLOCK:
if (inv.hash != self.stall_block):
- self.send_message(msg_block(self.block_store[inv.hash]))
+ self.send_without_ping(msg_block(self.block_store[inv.hash]))
def on_getheaders(self, message):
pass
@@ -78,7 +78,7 @@ class P2PIBDStallingTest(BitcoinTestFramework):
for id in range(NUM_PEERS):
peers.append(node.add_outbound_p2p_connection(P2PStaller(stall_block), p2p_idx=id, connection_type="outbound-full-relay"))
peers[-1].block_store = block_dict
- peers[-1].send_message(headers_message)
+ peers[-1].send_without_ping(headers_message)
# Need to wait until 1023 blocks are received - the magic total bytes number is a workaround in lack of an rpc
# returning the number of downloaded (but not connected) blocks.
@@ -96,7 +96,7 @@ class P2PIBDStallingTest(BitcoinTestFramework):
headers_message.headers = [CBlockHeader(b) for b in blocks]
with node.assert_debug_log(expected_msgs=['Stall started']):
for p in peers:
- p.send_message(headers_message)
+ p.send_without_ping(headers_message)
self.all_sync_send_with_ping(peers)
self.log.info("Check that the stalling peer is disconnected after 2 seconds")
@@ -139,7 +139,7 @@ class P2PIBDStallingTest(BitcoinTestFramework):
with node.assert_debug_log(expected_msgs=['Decreased stalling timeout to 2 seconds']):
for p in peers:
if p.is_connected and (stall_block in p.getdata_requests):
- p.send_message(msg_block(block_dict[stall_block]))
+ p.send_without_ping(msg_block(block_dict[stall_block]))
self.log.info("Check that all outstanding blocks get connected")
self.wait_until(lambda: node.getblockcount() == NUM_BLOCKS)
diff --git a/test/functional/p2p_initial_headers_sync.py b/test/functional/p2p_initial_headers_sync.py
index 5c17b75677..595a5202f5 100755
--- a/test/functional/p2p_initial_headers_sync.py
+++ b/test/functional/p2p_initial_headers_sync.py
@@ -45,7 +45,7 @@ class HeadersSyncTest(BitcoinTestFramework):
# An empty reply will clear the outstanding getheaders request,
# allowing additional getheaders requests to be sent to this peer in
# the future.
- peer1.send_message(msg_headers())
+ peer1.send_without_ping(msg_headers())
self.log.info("Connecting two more peers to node0")
# Connect 2 more peers; they should not receive a getheaders yet
@@ -66,7 +66,7 @@ class HeadersSyncTest(BitcoinTestFramework):
self.log.info("Check that peer1 receives a getheaders in response")
peer1.wait_for_getheaders(block_hash=best_block_hash)
- peer1.send_message(msg_headers()) # Send empty response, see above
+ peer1.send_without_ping(msg_headers()) # Send empty response, see above
self.log.info("Check that exactly 1 of {peer2, peer3} received a getheaders in response")
count = 0
@@ -76,7 +76,7 @@ class HeadersSyncTest(BitcoinTestFramework):
if "getheaders" in p.last_message:
count += 1
peer_receiving_getheaders = p
- p.send_message(msg_headers()) # Send empty response, see above
+ p.send_without_ping(msg_headers()) # Send empty response, see above
assert_equal(count, 1)
diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py
index bde01d5c95..d36f4c6a02 100755
--- a/test/functional/p2p_invalid_locator.py
+++ b/test/functional/p2p_invalid_locator.py
@@ -24,14 +24,14 @@ class InvalidLocatorTest(BitcoinTestFramework):
self.log.info('Wait for disconnect when sending {} hashes in locator'.format(MAX_LOCATOR_SZ + 1))
exceed_max_peer = node.add_p2p_connection(P2PInterface())
msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ + 1), -1)]
- exceed_max_peer.send_message(msg)
+ exceed_max_peer.send_without_ping(msg)
exceed_max_peer.wait_for_disconnect()
node.disconnect_p2ps()
self.log.info('Wait for response when sending {} hashes in locator'.format(MAX_LOCATOR_SZ))
within_max_peer = node.add_p2p_connection(P2PInterface())
msg.locator.vHave = [int(node.getblockhash(i - 1), 16) for i in range(block_count, block_count - (MAX_LOCATOR_SZ), -1)]
- within_max_peer.send_message(msg)
+ within_max_peer.send_without_ping(msg)
if type(msg) is msg_getheaders:
within_max_peer.wait_for_header(node.getbestblockhash())
else:
diff --git a/test/functional/p2p_invalid_messages.py b/test/functional/p2p_invalid_messages.py
index 507393fb70..c8228df802 100755
--- a/test/functional/p2p_invalid_messages.py
+++ b/test/functional/p2p_invalid_messages.py
@@ -261,7 +261,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
self.log.info("Test {} message of size {} is logged as misbehaving".format(msg_type, size))
with self.nodes[0].assert_debug_log(['Misbehaving', '{} message size = {}'.format(msg_type, size)]):
conn = self.nodes[0].add_p2p_connection(P2PInterface())
- conn.send_message(msg)
+ conn.send_without_ping(msg)
conn.wait_for_disconnect()
self.nodes[0].disconnect_p2ps()
@@ -304,7 +304,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
blockheader.nNonce += 1
blockheader.rehash()
with self.nodes[0].assert_debug_log(['Misbehaving', 'header with invalid proof of work']):
- peer.send_message(msg_headers([blockheader]))
+ peer.send_without_ping(msg_headers([blockheader]))
peer.wait_for_disconnect()
def test_noncontinuous_headers_msg(self):
@@ -323,7 +323,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
# delete arbitrary block header somewhere in the middle to break link
del block_headers[random.randrange(1, len(block_headers)-1)]
with self.nodes[0].assert_debug_log(expected_msgs=MISBEHAVING_NONCONTINUOUS_HEADERS_MSGS):
- peer.send_message(msg_headers(block_headers))
+ peer.send_without_ping(msg_headers(block_headers))
peer.wait_for_disconnect()
self.nodes[0].disconnect_p2ps()
@@ -338,7 +338,7 @@ class InvalidMessagesTest(BitcoinTestFramework):
self.log.info("(a) Send 80 messages, each of maximum valid data size (4MB)")
for _ in range(80):
- conn.send_message(msg_at_size)
+ conn.send_without_ping(msg_at_size)
# Check that, even though the node is being hammered by nonsense from one
# connection, it can still service other peers in a timely way.
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 7848cdaadb..4b74c55ae8 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -84,8 +84,8 @@ class NoVerackIdlePeer(LazyPeer):
# list!
def on_version(self, message):
self.version_received = True
- self.send_message(msg_ping())
- self.send_message(msg_getaddr())
+ self.send_without_ping(msg_ping())
+ self.send_without_ping(msg_getaddr())
class P2PVersionStore(P2PInterface):
@@ -121,7 +121,7 @@ class P2PLeakTest(BitcoinTestFramework):
# Pre-wtxidRelay peer that sends a version but not a verack and does not support feature negotiation
# messages which start at nVersion == 70016
pre_wtxidrelay_peer = self.nodes[0].add_p2p_connection(NoVerackIdlePeer(), send_version=False, wait_for_verack=False)
- pre_wtxidrelay_peer.send_message(self.create_old_version(70015))
+ pre_wtxidrelay_peer.send_without_ping(self.create_old_version(70015))
# Wait until the peer gets the verack in response to the version. Though, don't wait for the node to receive the
# verack, since the peer never sent one
@@ -173,7 +173,7 @@ class P2PLeakTest(BitcoinTestFramework):
self.log.info('Check that old peers are disconnected')
p2p_old_peer = self.nodes[0].add_p2p_connection(P2PInterface(), send_version=False, wait_for_verack=False)
with self.nodes[0].assert_debug_log(["using obsolete version 31799, disconnecting peer=5"]):
- p2p_old_peer.send_message(self.create_old_version(31799))
+ p2p_old_peer.send_without_ping(self.create_old_version(31799))
p2p_old_peer.wait_for_disconnect()
diff --git a/test/functional/p2p_mutated_blocks.py b/test/functional/p2p_mutated_blocks.py
index 4a790168da..6d909ded05 100755
--- a/test/functional/p2p_mutated_blocks.py
+++ b/test/functional/p2p_mutated_blocks.py
@@ -60,7 +60,7 @@ class MutatedBlocksTest(BitcoinTestFramework):
# Announce the new block via a compact block through the honest relayer
cmpctblock = HeaderAndShortIDs()
cmpctblock.initialize_from_block(block, use_witness=True)
- honest_relayer.send_message(msg_cmpctblock(cmpctblock.to_p2p()))
+ honest_relayer.send_without_ping(msg_cmpctblock(cmpctblock.to_p2p()))
# Wait for a `getblocktxn` that attempts to fetch the self-transfer
def self_transfer_requested():
@@ -80,7 +80,7 @@ class MutatedBlocksTest(BitcoinTestFramework):
# Attempt to clear the honest relayer's download request by sending the
# mutated block (as the attacker).
with self.nodes[0].assert_debug_log(expected_msgs=["Block mutated: bad-txnmrklroot, hashMerkleRoot mismatch"]):
- attacker.send_message(msg_block(mutated_block))
+ attacker.send_without_ping(msg_block(mutated_block))
# Attacker should get disconnected for sending a mutated block
attacker.wait_for_disconnect(timeout=5)
@@ -107,7 +107,7 @@ class MutatedBlocksTest(BitcoinTestFramework):
# Check that non-connecting block causes disconnect
assert_equal(len(self.nodes[0].getpeerinfo()), 2)
with self.nodes[0].assert_debug_log(expected_msgs=["AcceptBlock FAILED (prev-blk-not-found)"]):
- attacker.send_message(msg_block(block_missing_prev))
+ attacker.send_without_ping(msg_block(block_missing_prev))
attacker.wait_for_disconnect(timeout=5)
diff --git a/test/functional/p2p_nobloomfilter_messages.py b/test/functional/p2p_nobloomfilter_messages.py
index dd2dc9ae69..835230fa7e 100755
--- a/test/functional/p2p_nobloomfilter_messages.py
+++ b/test/functional/p2p_nobloomfilter_messages.py
@@ -26,7 +26,7 @@ class P2PNoBloomFilterMessages(BitcoinTestFramework):
def test_message_causes_disconnect(self, message):
"""Add a p2p connection that sends a message and check that it disconnects."""
peer = self.nodes[0].add_p2p_connection(P2PInterface())
- peer.send_message(message)
+ peer.send_without_ping(message)
peer.wait_for_disconnect()
assert_equal(self.nodes[0].getconnectioncount(), 0)
diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py
index 7788be6adb..73f52b0e49 100755
--- a/test/functional/p2p_node_network_limited.py
+++ b/test/functional/p2p_node_network_limited.py
@@ -40,7 +40,7 @@ class P2PIgnoreInv(P2PInterface):
def send_getdata_for_block(self, blockhash):
getdata_request = msg_getdata()
getdata_request.inv.append(CInv(MSG_BLOCK, int(blockhash, 16)))
- self.send_message(getdata_request)
+ self.send_without_ping(getdata_request)
class NodeNetworkLimitedTest(BitcoinTestFramework):
def set_test_params(self):
diff --git a/test/functional/p2p_opportunistic_1p1c.py b/test/functional/p2p_opportunistic_1p1c.py
index 5cf616b3ef..addb5027f3 100755
--- a/test/functional/p2p_opportunistic_1p1c.py
+++ b/test/functional/p2p_opportunistic_1p1c.py
@@ -249,7 +249,7 @@ class PackageRelayTest(BitcoinTestFramework):
assert tx_orphan_bad_wit.rehash() not in node_mempool
# 5. Have the other peer send the tx too, so that tx_orphan_bad_wit package is attempted.
- bad_orphan_sender.send_message(msg_tx(low_fee_parent["tx"]))
+ bad_orphan_sender.send_without_ping(msg_tx(low_fee_parent["tx"]))
bad_orphan_sender.wait_for_disconnect()
# The peer that didn't provide the orphan should not be disconnected.
diff --git a/test/functional/p2p_orphan_handling.py b/test/functional/p2p_orphan_handling.py
index 755cb8f3e9..e839b2d987 100755
--- a/test/functional/p2p_orphan_handling.py
+++ b/test/functional/p2p_orphan_handling.py
@@ -312,7 +312,7 @@ class OrphanHandlingTest(BitcoinTestFramework):
# Even though the peer would send a notfound for the "old" confirmed transaction, the node
# doesn't give up on the orphan. Once all of the missing parents are received, it should be
# submitted to mempool.
- peer.send_message(msg_notfound(vec=[CInv(MSG_WITNESS_TX, int(txid_conf_old, 16))]))
+ peer.send_without_ping(msg_notfound(vec=[CInv(MSG_WITNESS_TX, int(txid_conf_old, 16))]))
# Sync with ping to ensure orphans are reconsidered
peer.send_and_ping(msg_tx(missing_tx["tx"]))
assert_equal(node.getmempoolentry(orphan["txid"])["ancestorcount"], 3)
@@ -611,7 +611,7 @@ class OrphanHandlingTest(BitcoinTestFramework):
tx_child_1 = self.wallet.create_self_transfer(utxo_to_spend=tx_parent_1["new_utxo"])
parent_orphans.append(tx_parent_1["tx"])
orphans.append(tx_child_1["tx"])
- peer_1.send_message(msg_tx(tx_child_1["tx"]))
+ peer_1.send_without_ping(msg_tx(tx_child_1["tx"]))
peer_1.sync_with_ping()
orphanage = node.getorphantxs()
@@ -771,7 +771,7 @@ class OrphanHandlingTest(BitcoinTestFramework):
node.bumpmocktime(NONPREF_PEER_TX_DELAY + TXID_RELAY_DELAY)
peer1.wait_for_getdata([int(parent_missing["txid"], 16)])
- # Replace parent_peekaboo_AB so that is is a newly missing parent.
+ # Replace parent_peekaboo_AB so that is a newly missing parent.
# Then, replace the replacement so that it can be resubmitted.
node.sendrawtransaction(tx_replacer_BC["hex"])
assert tx_replacer_BC["txid"] in node.getrawmempool()
@@ -788,6 +788,8 @@ class OrphanHandlingTest(BitcoinTestFramework):
# Disconnect peer1. peer2 should become the new candidate for orphan resolution.
peer1.peer_disconnect()
+ self.wait_until(lambda: node.num_test_p2p_connections() == 1)
+ peer2.sync_with_ping() # Sync with the 'net' thread which completes the disconnection fully
node.bumpmocktime(TXREQUEST_TIME_SKIP)
self.wait_until(lambda: len(node.getorphantxs(verbosity=2)[0]["from"]) == 1)
# Both parents should be requested, now that they are both missing.
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 9caf5a19aa..0f04a87707 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -174,9 +174,9 @@ class TestP2PConn(P2PInterface):
self.last_message.pop("getdata", None)
if use_wtxid:
wtxid = tx.calc_sha256(True)
- self.send_message(msg_inv(inv=[CInv(MSG_WTX, wtxid)]))
+ self.send_without_ping(msg_inv(inv=[CInv(MSG_WTX, wtxid)]))
else:
- self.send_message(msg_inv(inv=[CInv(MSG_TX, tx.sha256)]))
+ self.send_without_ping(msg_inv(inv=[CInv(MSG_TX, tx.sha256)]))
if success:
if use_wtxid:
@@ -192,17 +192,17 @@ class TestP2PConn(P2PInterface):
msg = msg_headers()
msg.headers = [CBlockHeader(block)]
if use_header:
- self.send_message(msg)
+ self.send_without_ping(msg)
else:
- self.send_message(msg_inv(inv=[CInv(MSG_BLOCK, block.sha256)]))
+ self.send_without_ping(msg_inv(inv=[CInv(MSG_BLOCK, block.sha256)]))
self.wait_for_getheaders(block_hash=block.hashPrevBlock, timeout=timeout)
- self.send_message(msg)
+ self.send_without_ping(msg)
self.wait_for_getdata([block.sha256], timeout=timeout)
def request_block(self, blockhash, inv_type, timeout=60):
with p2p_lock:
self.last_message.pop("block", None)
- self.send_message(msg_getdata(inv=[CInv(inv_type, blockhash)]))
+ self.send_without_ping(msg_getdata(inv=[CInv(inv_type, blockhash)]))
self.wait_for_block(blockhash, timeout=timeout)
return self.last_message["block"].block
@@ -373,7 +373,7 @@ class SegWitTest(BitcoinTestFramework):
# Send an empty headers message, to clear out any prior getheaders
# messages that our peer may be waiting for us on.
- self.test_node.send_message(msg_headers())
+ self.test_node.send_without_ping(msg_headers())
self.test_node.announce_block_and_wait_for_getdata(block1, use_header=False)
assert self.test_node.last_message["getdata"].inv[0].type == blocktype
@@ -444,7 +444,7 @@ class SegWitTest(BitcoinTestFramework):
# to announce this block.
msg = msg_headers()
msg.headers = [CBlockHeader(block4)]
- self.old_node.send_message(msg)
+ self.old_node.send_without_ping(msg)
self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
assert block4.sha256 not in self.old_node.getdataset
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index db706556d8..7dc91305f3 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -115,28 +115,28 @@ class BaseNode(P2PInterface):
msg = msg_getdata()
for x in block_hashes:
msg.inv.append(CInv(MSG_BLOCK, x))
- self.send_message(msg)
+ self.send_without_ping(msg)
def send_get_headers(self, locator, hashstop):
msg = msg_getheaders()
msg.locator.vHave = locator
msg.hashstop = hashstop
- self.send_message(msg)
+ self.send_without_ping(msg)
def send_block_inv(self, blockhash):
msg = msg_inv()
msg.inv = [CInv(MSG_BLOCK, blockhash)]
- self.send_message(msg)
+ self.send_without_ping(msg)
def send_header_for_blocks(self, new_blocks):
headers_message = msg_headers()
headers_message.headers = [CBlockHeader(b) for b in new_blocks]
- self.send_message(headers_message)
+ self.send_without_ping(headers_message)
def send_getblocks(self, locator):
getblocks_message = msg_getblocks()
getblocks_message.locator.vHave = locator
- self.send_message(getblocks_message)
+ self.send_without_ping(getblocks_message)
def wait_for_block_announcement(self, block_hash, timeout=60):
test_function = lambda: self.last_blockhash_announced == block_hash
@@ -252,7 +252,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.sync_with_ping()
assert_equal(test_node.block_announced, False)
inv_node.clear_block_announcements()
- test_node.send_message(msg_block(block))
+ test_node.send_without_ping(msg_block(block))
inv_node.check_last_inv_announcement(inv=[int(block.hash, 16)])
def test_nonnull_locators(self, test_node, inv_node):
@@ -298,7 +298,7 @@ class SendHeadersTest(BitcoinTestFramework):
# PART 2
# 2. Send a sendheaders message and test that headers announcements
# commence and keep working.
- test_node.send_message(msg_sendheaders())
+ test_node.send_without_ping(msg_sendheaders())
prev_tip = int(self.nodes[0].getbestblockhash(), 16)
test_node.send_get_headers(locator=[prev_tip], hashstop=0)
test_node.sync_with_ping()
@@ -348,7 +348,7 @@ class SendHeadersTest(BitcoinTestFramework):
# getdata requests (the check is further down)
inv_node.send_header_for_blocks(blocks)
inv_node.sync_with_ping()
- [test_node.send_message(msg_block(x)) for x in blocks]
+ [test_node.send_without_ping(msg_block(x)) for x in blocks]
test_node.sync_with_ping()
inv_node.sync_with_ping()
# This block should not be announced to the inv node (since it also
@@ -444,7 +444,7 @@ class SendHeadersTest(BitcoinTestFramework):
tip = blocks[-1].sha256
block_time += 1
height += 1
- inv_node.send_message(msg_block(blocks[-1]))
+ inv_node.send_without_ping(msg_block(blocks[-1]))
inv_node.sync_with_ping() # Make sure blocks are processed
test_node.last_message.pop("getdata", None)
@@ -467,7 +467,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.sync_with_ping()
test_node.wait_for_getdata([x.sha256 for x in blocks], timeout=DIRECT_FETCH_RESPONSE_TIME)
- [test_node.send_message(msg_block(x)) for x in blocks]
+ [test_node.send_without_ping(msg_block(x)) for x in blocks]
test_node.sync_with_ping()
@@ -514,7 +514,7 @@ class SendHeadersTest(BitcoinTestFramework):
self.log.info("Part 4: success!")
# Now deliver all those blocks we announced.
- [test_node.send_message(msg_block(x)) for x in blocks]
+ [test_node.send_without_ping(msg_block(x)) for x in blocks]
self.log.info("Part 5: Testing handling of unconnecting headers")
# First we test that receipt of an unconnecting header doesn't prevent
@@ -537,7 +537,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getheaders(block_hash=expected_hash)
test_node.send_header_for_blocks(blocks)
test_node.wait_for_getdata([x.sha256 for x in blocks])
- [test_node.send_message(msg_block(x)) for x in blocks]
+ [test_node.send_without_ping(msg_block(x)) for x in blocks]
test_node.sync_with_ping()
assert_equal(int(self.nodes[0].getbestblockhash(), 16), blocks[1].sha256)
expected_hash = blocks[1].sha256
diff --git a/test/functional/p2p_sendtxrcncl.py b/test/functional/p2p_sendtxrcncl.py
index 3f1fca5c78..43c171f26f 100755
--- a/test/functional/p2p_sendtxrcncl.py
+++ b/test/functional/p2p_sendtxrcncl.py
@@ -31,7 +31,7 @@ class PeerNoVerack(P2PInterface):
# comment in add_p2p_connection).
self.send_version()
if message.nVersion >= 70016 and self.wtxidrelay:
- self.send_message(msg_wtxidrelay())
+ self.send_without_ping(msg_wtxidrelay())
class SendTxrcnclReceiver(P2PInterface):
def __init__(self):
@@ -92,7 +92,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
pre_wtxid_version_msg.strSubVer = P2P_SUBVERSION
pre_wtxid_version_msg.nServices = P2P_SERVICES
pre_wtxid_version_msg.relay = 1
- peer.send_message(pre_wtxid_version_msg)
+ peer.send_without_ping(pre_wtxid_version_msg)
peer.wait_for_verack()
assert not peer.sendtxrcncl_msg_received
self.nodes[0].disconnect_p2ps()
@@ -104,7 +104,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
no_txrelay_version_msg.strSubVer = P2P_SUBVERSION
no_txrelay_version_msg.nServices = P2P_SERVICES
no_txrelay_version_msg.relay = 0
- peer.send_message(no_txrelay_version_msg)
+ peer.send_without_ping(no_txrelay_version_msg)
peer.wait_for_verack()
assert not peer.sendtxrcncl_msg_received
self.nodes[0].disconnect_p2ps()
@@ -117,7 +117,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
no_txrelay_version_msg.strSubVer = P2P_SUBVERSION
no_txrelay_version_msg.nServices = P2P_SERVICES
no_txrelay_version_msg.relay = 0
- peer.send_message(no_txrelay_version_msg)
+ peer.send_without_ping(no_txrelay_version_msg)
peer.wait_for_verack()
assert peer.nServices & NODE_BLOOM != 0
assert not peer.sendtxrcncl_msg_received
@@ -166,17 +166,17 @@ class SendTxRcnclTest(BitcoinTestFramework):
self.log.info('valid SENDTXRCNCL received')
peer = self.nodes[0].add_p2p_connection(PeerNoVerack(), send_version=True, wait_for_verack=False)
with self.nodes[0].assert_debug_log(["received: sendtxrcncl"]):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
self.log.info('second SENDTXRCNCL triggers a disconnect')
with self.nodes[0].assert_debug_log(["(sendtxrcncl received from already registered peer), disconnecting peer=0"]):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
peer.wait_for_disconnect()
self.restart_node(0, [])
self.log.info('SENDTXRCNCL if no txreconciliation supported is ignored')
peer = self.nodes[0].add_p2p_connection(PeerNoVerack(), send_version=True, wait_for_verack=False)
with self.nodes[0].assert_debug_log(['ignored, as our node does not have txreconciliation enabled']):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
self.nodes[0].disconnect_p2ps()
self.restart_node(0, ["-txreconciliation"])
@@ -186,7 +186,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
sendtxrcncl_low_version.version = 0
peer = self.nodes[0].add_p2p_connection(PeerNoVerack(), send_version=True, wait_for_verack=False)
with self.nodes[0].assert_debug_log(["txreconciliation protocol violation"]):
- peer.send_message(sendtxrcncl_low_version)
+ peer.send_without_ping(sendtxrcncl_low_version)
peer.wait_for_disconnect()
self.log.info('SENDTXRCNCL with version=2 is valid')
@@ -194,7 +194,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
sendtxrcncl_higher_version.version = 2
peer = self.nodes[0].add_p2p_connection(PeerNoVerack(), send_version=True, wait_for_verack=False)
with self.nodes[0].assert_debug_log(['Register peer=1']):
- peer.send_message(sendtxrcncl_higher_version)
+ peer.send_without_ping(sendtxrcncl_higher_version)
self.nodes[0].disconnect_p2ps()
self.log.info('unexpected SENDTXRCNCL is ignored')
@@ -204,22 +204,22 @@ class SendTxRcnclTest(BitcoinTestFramework):
old_version_msg.strSubVer = P2P_SUBVERSION
old_version_msg.nServices = P2P_SERVICES
old_version_msg.relay = 1
- peer.send_message(old_version_msg)
+ peer.send_without_ping(old_version_msg)
with self.nodes[0].assert_debug_log(['Ignore unexpected txreconciliation signal']):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
self.nodes[0].disconnect_p2ps()
self.log.info('sending SENDTXRCNCL after sending VERACK triggers a disconnect')
peer = self.nodes[0].add_p2p_connection(P2PInterface())
with self.nodes[0].assert_debug_log(["sendtxrcncl received after verack"]):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
peer.wait_for_disconnect()
self.log.info('SENDTXRCNCL without WTXIDRELAY is ignored (recon state is erased after VERACK)')
peer = self.nodes[0].add_p2p_connection(PeerNoVerack(wtxidrelay=False), send_version=True, wait_for_verack=False)
with self.nodes[0].assert_debug_log(['Forget txreconciliation state of peer']):
- peer.send_message(create_sendtxrcncl_msg())
- peer.send_message(msg_verack())
+ peer.send_without_ping(create_sendtxrcncl_msg())
+ peer.send_without_ping(msg_verack())
self.nodes[0].disconnect_p2ps()
# Now, *receiving* from *outbound*.
@@ -227,7 +227,7 @@ class SendTxRcnclTest(BitcoinTestFramework):
peer = self.nodes[0].add_outbound_p2p_connection(
PeerNoVerack(), wait_for_verack=False, p2p_idx=0, connection_type="block-relay-only")
with self.nodes[0].assert_debug_log(["we indicated no tx relay, disconnecting peer=5"]):
- peer.send_message(create_sendtxrcncl_msg())
+ peer.send_without_ping(create_sendtxrcncl_msg())
peer.wait_for_disconnect()
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index ce01547887..73a6a866e8 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -67,10 +67,10 @@ class TimeoutsTest(BitcoinTestFramework):
assert no_send_node.is_connected
with self.nodes[0].assert_debug_log(['Unsupported message "ping" prior to verack from peer=0']):
- no_verack_node.send_message(msg_ping())
+ no_verack_node.send_without_ping(msg_ping())
with self.nodes[0].assert_debug_log(['non-version message before version handshake. Message "ping" from peer=1']):
- no_version_node.send_message(msg_ping())
+ no_version_node.send_without_ping(msg_ping())
self.mock_forward(1)
assert "version" in no_verack_node.last_message
@@ -79,8 +79,8 @@ class TimeoutsTest(BitcoinTestFramework):
assert no_version_node.is_connected
assert no_send_node.is_connected
- no_verack_node.send_message(msg_ping())
- no_version_node.send_message(msg_ping())
+ no_verack_node.send_without_ping(msg_ping())
+ no_version_node.send_without_ping(msg_ping())
if self.options.v2transport:
expected_timeout_logs = [
diff --git a/test/functional/p2p_tx_download.py b/test/functional/p2p_tx_download.py
index a5e3905990..2b75c1193d 100755
--- a/test/functional/p2p_tx_download.py
+++ b/test/functional/p2p_tx_download.py
@@ -143,13 +143,13 @@ class TxDownloadTest(BitcoinTestFramework):
mock_time = int(time.time() + 1)
self.nodes[0].setmocktime(mock_time)
for i in range(MAX_PEER_TX_REQUEST_IN_FLIGHT):
- p.send_message(msg_inv([CInv(t=MSG_WTX, h=txids[i])]))
+ p.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=txids[i])]))
p.sync_with_ping()
mock_time += NONPREF_PEER_TX_DELAY
self.nodes[0].setmocktime(mock_time)
p.wait_until(lambda: p.tx_getdata_count >= MAX_PEER_TX_REQUEST_IN_FLIGHT)
for i in range(MAX_PEER_TX_REQUEST_IN_FLIGHT, len(txids)):
- p.send_message(msg_inv([CInv(t=MSG_WTX, h=txids[i])]))
+ p.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=txids[i])]))
p.sync_with_ping()
self.log.info("No more than {} requests should be seen within {} seconds after announcement".format(MAX_PEER_TX_REQUEST_IN_FLIGHT, NONPREF_PEER_TX_DELAY + OVERLOADED_PEER_TX_DELAY - 1))
self.nodes[0].setmocktime(mock_time + NONPREF_PEER_TX_DELAY + OVERLOADED_PEER_TX_DELAY - 1)
@@ -166,7 +166,7 @@ class TxDownloadTest(BitcoinTestFramework):
peer1 = self.nodes[0].add_p2p_connection(TestP2PConn())
peer2 = self.nodes[0].add_p2p_connection(TestP2PConn())
for p in [peer1, peer2]:
- p.send_message(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
+ p.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
# One of the peers is asked for the tx
peer2.wait_until(lambda: sum(p.tx_getdata_count for p in [peer1, peer2]) == 1)
with p2p_lock:
@@ -182,7 +182,7 @@ class TxDownloadTest(BitcoinTestFramework):
peer1 = self.nodes[0].add_p2p_connection(TestP2PConn())
peer2 = self.nodes[0].add_p2p_connection(TestP2PConn())
for p in [peer1, peer2]:
- p.send_message(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
+ p.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
# One of the peers is asked for the tx
peer2.wait_until(lambda: sum(p.tx_getdata_count for p in [peer1, peer2]) == 1)
with p2p_lock:
@@ -198,7 +198,7 @@ class TxDownloadTest(BitcoinTestFramework):
peer1 = self.nodes[0].add_p2p_connection(TestP2PConn())
peer2 = self.nodes[0].add_p2p_connection(TestP2PConn())
for p in [peer1, peer2]:
- p.send_message(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
+ p.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=WTXID)]))
# One of the peers is asked for the tx
peer2.wait_until(lambda: sum(p.tx_getdata_count for p in [peer1, peer2]) == 1)
with p2p_lock:
@@ -229,8 +229,7 @@ class TxDownloadTest(BitcoinTestFramework):
else:
peer = self.nodes[0].add_p2p_connection(TestP2PConn())
- peer.send_message(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
- peer.sync_with_ping()
+ peer.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
if connection_type != ConnectionType.INBOUND:
peer.wait_until(lambda: peer.tx_getdata_count >= 1, timeout=1)
else:
@@ -250,8 +249,7 @@ class TxDownloadTest(BitcoinTestFramework):
# of which is preferred and one which is not
unresponsive_peer = self.nodes[0].add_outbound_p2p_connection(
TestP2PConn(), wait_for_verack=True, p2p_idx=0, connection_type="outbound-full-relay")
- unresponsive_peer.send_message(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
- unresponsive_peer.sync_with_ping()
+ unresponsive_peer.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
unresponsive_peer.wait_until(lambda: unresponsive_peer.tx_getdata_count >= 1, timeout=1)
# A bunch of incoming (non-preferred) connections that advertise the same tx
@@ -259,8 +257,7 @@ class TxDownloadTest(BitcoinTestFramework):
NUM_INBOUND = 10
for _ in range(NUM_INBOUND):
non_pref_peers.append(self.nodes[0].add_p2p_connection(TestP2PConn()))
- non_pref_peers[-1].send_message(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
- non_pref_peers[-1].sync_with_ping()
+ non_pref_peers[-1].send_and_ping(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
# Check that no request made due to in-flight
self.nodes[0].bumpmocktime(NONPREF_PEER_TX_DELAY)
@@ -272,8 +269,7 @@ class TxDownloadTest(BitcoinTestFramework):
# upon advertisement
pref_peer = self.nodes[0].add_outbound_p2p_connection(
TestP2PConn(), wait_for_verack=True, p2p_idx=1, connection_type="outbound-full-relay")
- pref_peer.send_message(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
- pref_peer.sync_with_ping()
+ pref_peer.send_and_ping(msg_inv([CInv(t=MSG_WTX, h=0xff00ff00)]))
assert_equal(len(self.nodes[0].getpeerinfo()), NUM_INBOUND + 2)
@@ -302,8 +298,7 @@ class TxDownloadTest(BitcoinTestFramework):
# Add a second wtxid-relay connection otherwise TXID_RELAY_DELAY is waived in
# lack of wtxid-relay peers
self.nodes[0].add_p2p_connection(TestP2PConn(wtxidrelay=True))
- peer.send_message(msg_inv([CInv(t=MSG_TX, h=0xff11ff11)]))
- peer.sync_with_ping()
+ peer.send_and_ping(msg_inv([CInv(t=MSG_TX, h=0xff11ff11)]))
with p2p_lock:
assert_equal(peer.tx_getdata_count, 0 if glob_wtxid else 1)
self.nodes[0].setmocktime(mock_time + TXID_RELAY_DELAY)
@@ -313,19 +308,19 @@ class TxDownloadTest(BitcoinTestFramework):
self.log.info('Test how large inv batches are handled with relay permission')
self.restart_node(0, extra_args=['-whitelist=relay@127.0.0.1'])
peer = self.nodes[0].add_p2p_connection(TestP2PConn())
- peer.send_message(msg_inv([CInv(t=MSG_WTX, h=wtxid) for wtxid in range(MAX_PEER_TX_ANNOUNCEMENTS + 1)]))
+ peer.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=wtxid) for wtxid in range(MAX_PEER_TX_ANNOUNCEMENTS + 1)]))
peer.wait_until(lambda: peer.tx_getdata_count == MAX_PEER_TX_ANNOUNCEMENTS + 1)
self.log.info('Test how large inv batches are handled without relay permission')
self.restart_node(0)
peer = self.nodes[0].add_p2p_connection(TestP2PConn())
- peer.send_message(msg_inv([CInv(t=MSG_WTX, h=wtxid) for wtxid in range(MAX_PEER_TX_ANNOUNCEMENTS + 1)]))
+ peer.send_without_ping(msg_inv([CInv(t=MSG_WTX, h=wtxid) for wtxid in range(MAX_PEER_TX_ANNOUNCEMENTS + 1)]))
peer.wait_until(lambda: peer.tx_getdata_count == MAX_PEER_TX_ANNOUNCEMENTS)
peer.sync_with_ping()
def test_spurious_notfound(self):
self.log.info('Check that spurious notfound is ignored')
- self.nodes[0].p2ps[0].send_message(msg_notfound(vec=[CInv(MSG_TX, 1)]))
+ self.nodes[0].p2ps[0].send_without_ping(msg_notfound(vec=[CInv(MSG_TX, 1)]))
def test_rejects_filter_reset(self):
self.log.info('Check that rejected tx is not requested again')
diff --git a/test/functional/p2p_tx_privacy.py b/test/functional/p2p_tx_privacy.py
index afe9df8a0f..688f27f582 100755
--- a/test/functional/p2p_tx_privacy.py
+++ b/test/functional/p2p_tx_privacy.py
@@ -39,7 +39,7 @@ class P2PTxSpy(P2PInterface):
self.all_invs = []
def on_version(self, message):
- self.send_message(msg_wtxidrelay())
+ self.send_without_ping(msg_wtxidrelay())
def on_inv(self, message):
self.all_invs += message.inv
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 1430131a97..34c2654b9b 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -170,7 +170,7 @@ class AcceptBlockTest(BitcoinTestFramework):
tip = next_block
# Now send the block at height 5 and check that it wasn't accepted (missing header)
- test_node.send_message(msg_block(all_blocks[1]))
+ test_node.send_without_ping(msg_block(all_blocks[1]))
test_node.wait_for_disconnect()
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblock, all_blocks[1].hash)
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getblockheader, all_blocks[1].hash)
@@ -179,13 +179,13 @@ class AcceptBlockTest(BitcoinTestFramework):
# The block at height 5 should be accepted if we provide the missing header, though
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(all_blocks[0]))
- test_node.send_message(headers_message)
+ test_node.send_without_ping(headers_message)
test_node.send_and_ping(msg_block(all_blocks[1]))
self.nodes[0].getblock(all_blocks[1].hash)
# Now send the blocks in all_blocks
for i in range(288):
- test_node.send_message(msg_block(all_blocks[i]))
+ test_node.send_without_ping(msg_block(all_blocks[i]))
test_node.sync_with_ping()
# Blocks 1-287 should be accepted, block 288 should be ignored because it's too far ahead
@@ -215,7 +215,7 @@ class AcceptBlockTest(BitcoinTestFramework):
with p2p_lock:
# Clear state so we can check the getdata request
test_node.last_message.pop("getdata", None)
- test_node.send_message(msg_inv([CInv(MSG_BLOCK, block_h3.sha256)]))
+ test_node.send_without_ping(msg_inv([CInv(MSG_BLOCK, block_h3.sha256)]))
test_node.sync_with_ping()
with p2p_lock:
@@ -262,13 +262,13 @@ class AcceptBlockTest(BitcoinTestFramework):
assert tip_entry_found
assert_raises_rpc_error(-1, "Block not available (not fully downloaded)", self.nodes[0].getblock, block_292.hash)
- test_node.send_message(msg_block(block_289f))
+ test_node.send_without_ping(msg_block(block_289f))
test_node.send_and_ping(msg_block(block_290f))
self.nodes[0].getblock(block_289f.hash)
self.nodes[0].getblock(block_290f.hash)
- test_node.send_message(msg_block(block_291))
+ test_node.send_without_ping(msg_block(block_291))
# At this point we've sent an obviously-bogus block, wait for full processing
# and assume disconnection
@@ -287,7 +287,7 @@ class AcceptBlockTest(BitcoinTestFramework):
block_293.solve()
headers_message = msg_headers()
headers_message.headers.append(CBlockHeader(block_293))
- test_node.send_message(headers_message)
+ test_node.send_without_ping(headers_message)
test_node.wait_for_disconnect()
# 9. Connect node1 to node0 and ensure it is able to sync
diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py
index 4a415d57f5..f4036abdad 100755
--- a/test/functional/rpc_deprecated.py
+++ b/test/functional/rpc_deprecated.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017-2021 The Bitcoin Core developers
+# Copyright (c) 2017-2025 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of RPC calls."""
@@ -7,23 +7,23 @@ from test_framework.test_framework import BitcoinTestFramework
class DeprecatedRpcTest(BitcoinTestFramework):
def set_test_params(self):
- self.num_nodes = 2
+ self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [[], ['-deprecatedrpc=bumpfee']]
+ self.extra_args = [[]]
def run_test(self):
- # This test should be used to verify correct behaviour of deprecated
- # RPC methods with and without the -deprecatedrpc flags. For example:
+ # This test should be used to verify the errors of the currently
+ # deprecated RPC methods (without the -deprecatedrpc flag) until
+ # such RPCs are fully removed. For example:
#
- # In set_test_params:
- # self.extra_args = [[], ["-deprecatedrpc=generate"]]
- #
- # In run_test:
# self.log.info("Test generate RPC")
# assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1)
- # self.generate(self.nodes[1], 1)
+ #
+ # Please ensure that for all the RPC methods tested here, there is
+ # at least one other functional test that still tests the RPCs
+ # functionality using the respective -deprecatedrpc flag.
- self.log.info("No tested deprecated RPC methods")
+ self.log.info("Currently no tests for deprecated RPC methods")
if __name__ == '__main__':
DeprecatedRpcTest(__file__).main()
diff --git a/test/functional/rpc_getdescriptorinfo.py b/test/functional/rpc_getdescriptorinfo.py
index e4e6d6f0f3..65aa6dd47c 100755
--- a/test/functional/rpc_getdescriptorinfo.py
+++ b/test/functional/rpc_getdescriptorinfo.py
@@ -11,6 +11,7 @@ from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
)
+from test_framework.wallet_util import generate_keypair
class DescriptorTest(BitcoinTestFramework):
@@ -36,6 +37,12 @@ class DescriptorTest(BitcoinTestFramework):
assert_raises_rpc_error(-1, 'getdescriptorinfo', self.nodes[0].getdescriptorinfo)
assert_raises_rpc_error(-3, 'JSON value of type number is not of expected type string', self.nodes[0].getdescriptorinfo, 1)
assert_raises_rpc_error(-5, "'' is not a valid descriptor function", self.nodes[0].getdescriptorinfo, "")
+ assert_raises_rpc_error(-5, "pk(): Key ' 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798' is invalid due to whitespace", self.nodes[0].getdescriptorinfo, "pk( 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)")
+ assert_raises_rpc_error(-5, "pk(): Key '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 ' is invalid due to whitespace", self.nodes[0].getdescriptorinfo, "pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 )")
+ assert_raises_rpc_error(-5, "Multi: Key ' 03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7' is invalid due to whitespace", self.nodes[0].getdescriptorinfo, "wsh(multi(2, 03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7,03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))")
+ assert_raises_rpc_error(-5, "Multi: Key ' 03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb' is invalid due to whitespace", self.nodes[0].getdescriptorinfo, "wsh(multi(2,03a0434d9e47f3c86235477c7b1ae6ae5d3442d49b1943c2b752a68e2a47e247c7, 03774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb,03d01115d548e7561b15c38f004d734633687cf4419620095bc5b0f47070afe85a))")
+ priv_key = generate_keypair(wif=True)[0]
+ assert_raises_rpc_error(-5, f"pk(): Key ' {priv_key}' is invalid due to whitespace", self.nodes[0].getdescriptorinfo, f"pk( {priv_key})")
# P2PK output with the specified public key.
self.test_desc('pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)', isrange=False, issolvable=True, hasprivatekeys=False)
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 8042bdf071..04e68a97af 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -999,7 +999,7 @@ class PSBTTest(BitcoinTestFramework):
{'hex': '0200000001dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd0000000000000000000100000000000000000000000000', 'complete': True})
self.log.info("Test we don't crash when making a 0-value funded transaction at 0 fee without forcing an input selection")
- assert_raises_rpc_error(-4, "Transaction requires one destination of non-0 value, a non-0 feerate, or a pre-selected input", self.nodes[0].walletcreatefundedpsbt, [], [{"data": "deadbeef"}], 0, {"fee_rate": "0"})
+ assert_raises_rpc_error(-4, "Transaction requires one destination of non-zero value, a non-zero feerate, or a pre-selected input", self.nodes[0].walletcreatefundedpsbt, [], [{"data": "deadbeef"}], 0, {"fee_rate": "0"})
self.log.info("Test descriptorprocesspsbt updates and signs a psbt with descriptors")
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 18b1fc1896..3c3eb9fcb6 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -34,6 +34,7 @@ from test_framework.util import (
assert_equal,
assert_greater_than,
assert_raises_rpc_error,
+ sync_txindex,
)
from test_framework.wallet import (
getnewdestination,
@@ -70,7 +71,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.num_nodes = 3
self.extra_args = [
["-txindex"],
- ["-txindex"],
+ [],
["-fastprune", "-prune=1"],
]
# whitelist peers to speed up tx relay / mempool sync
@@ -109,6 +110,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.log.info(f"Test getrawtransaction {'with' if n == 0 else 'without'} -txindex")
if n == 0:
+ sync_txindex(self, self.nodes[n])
# With -txindex.
# 1. valid parameters - only supply txid
assert_equal(self.nodes[n].getrawtransaction(txId), tx['hex'])
diff --git a/test/functional/rpc_txoutproof.py b/test/functional/rpc_txoutproof.py
index 90572245d6..d430f47f66 100755
--- a/test/functional/rpc_txoutproof.py
+++ b/test/functional/rpc_txoutproof.py
@@ -12,6 +12,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
+ sync_txindex,
)
from test_framework.wallet import MiniWallet
@@ -77,6 +78,7 @@ class MerkleBlockTest(BitcoinTestFramework):
assert_equal(sorted(self.nodes[0].verifytxoutproof(self.nodes[0].gettxoutproof([txid1, txid2]))), sorted(txlist))
assert_equal(sorted(self.nodes[0].verifytxoutproof(self.nodes[0].gettxoutproof([txid2, txid1]))), sorted(txlist))
# We can always get a proof if we have a -txindex
+ sync_txindex(self, self.nodes[1])
assert_equal(self.nodes[0].verifytxoutproof(self.nodes[1].gettxoutproof([txid_spent])), [txid_spent])
# We can't get a proof if we specify transactions from different blocks
assert_raises_rpc_error(-5, "Not all transactions found in specified or retrieved block", self.nodes[0].gettxoutproof, [txid1, txid3])
diff --git a/test/functional/test-shell.md b/test/functional/test-shell.md
index d79c4a0ab6..0a05658e2f 100644
--- a/test/functional/test-shell.md
+++ b/test/functional/test-shell.md
@@ -24,13 +24,16 @@ user inputs. Such environments include the Python3 command line interpreter or
## 2. Importing `TestShell` from the Bitcoin Core repository
-We can import the `TestShell` by adding the path of the Bitcoin Core
+We can import the `TestShell` by adding the path of the configured Bitcoin Core
`test_framework` module to the beginning of the PATH variable, and then
-importing the `TestShell` class from the `test_shell` sub-package.
+importing the `TestShell` class from the `test_shell` sub-package. Since
+the build system creates a copy of the `test_framework` module into a new `build/`
+directory along with the required configuration file, the path to the build copy
+must be used.
```
>>> import sys
->>> sys.path.insert(0, "/path/to/bitcoin/test/functional")
+>>> sys.path.insert(0, "/path/to/bitcoin/build/test/functional")
>>> from test_framework.test_shell import TestShell
```
@@ -155,7 +158,7 @@ To prevent the logs from being removed after a shutdown, simply set the
The following utility consolidates logs from the bitcoind nodes and the
underlying `BitcoinTestFramework`:
-* `/path/to/bitcoin/test/functional/combine_logs.py
+* `/path/to/bitcoin/build/test/functional/combine_logs.py
'/path/to/bitcoin_func_test_XXXXXXX'`
## 6. Custom `TestShell` parameters
@@ -170,9 +173,9 @@ can be called after the TestShell is shut down.
| Test parameter key | Default Value | Description |
|---|---|---|
| `bind_to_localhost_only` | `True` | Binds bitcoind P2P services to `127.0.0.1` if set to `True`.|
-| `cachedir` | `"/path/to/bitcoin/test/cache"` | Sets the bitcoind datadir directory. |
+| `cachedir` | `"/path/to/bitcoin/build/test/cache"` | Sets the bitcoind datadir directory. |
| `chain` | `"regtest"` | Sets the chain-type for the underlying test bitcoind processes. |
-| `configfile` | `"/path/to/bitcoin/test/config.ini"` | Sets the location of the test framework config file. |
+| `configfile` | `"/path/to/bitcoin/build/test/config.ini"` | Sets the location of the test framework config file. |
| `coveragedir` | `None` | Records bitcoind RPC test coverage into this directory if set. |
| `loglevel` | `INFO` | Logs events at this level and higher. Can be set to `DEBUG`, `INFO`, `WARNING`, `ERROR` or `CRITICAL`. |
| `nocleanup` | `False` | Cleans up temporary test directory if set to `True` during `shutdown`. |
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 37fd5ae568..e24e5f7312 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -105,14 +105,19 @@ class AuthServiceProxy():
self.__conn.request(method, path, postdata, headers)
return self._get_response()
+ def _json_dumps(self, obj):
+ return json.dumps(obj, default=serialization_fallback, ensure_ascii=self.ensure_ascii)
+
def get_request(self, *args, **argsn):
AuthServiceProxy.__id_count += 1
- log.debug("-{}-> {} {}".format(
+ log.debug("-{}-> {} {} {}".format(
AuthServiceProxy.__id_count,
self._service_name,
- json.dumps(args or argsn, default=serialization_fallback, ensure_ascii=self.ensure_ascii),
+ self._json_dumps(args),
+ self._json_dumps(argsn),
))
+
if args and argsn:
params = dict(args=args, **argsn)
else:
@@ -123,7 +128,7 @@ class AuthServiceProxy():
'id': AuthServiceProxy.__id_count}
def __call__(self, *args, **argsn):
- postdata = json.dumps(self.get_request(*args, **argsn), default=serialization_fallback, ensure_ascii=self.ensure_ascii)
+ postdata = self._json_dumps(self.get_request(*args, **argsn))
response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
# For backwards compatibility tests, accept JSON RPC 1.1 responses
if 'jsonrpc' not in response:
@@ -150,7 +155,7 @@ class AuthServiceProxy():
return response['result']
def batch(self, rpc_call_list):
- postdata = json.dumps(list(rpc_call_list), default=serialization_fallback, ensure_ascii=self.ensure_ascii)
+ postdata = self._json_dumps(list(rpc_call_list))
log.debug("--> " + postdata)
response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
if status != HTTPStatus.OK:
@@ -197,7 +202,7 @@ class AuthServiceProxy():
response = json.loads(responsedata, parse_float=decimal.Decimal)
elapsed = time.time() - req_start_time
if "error" in response and response["error"] is None:
- log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, json.dumps(response["result"], default=serialization_fallback, ensure_ascii=self.ensure_ascii)))
+ log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, self._json_dumps(response["result"])))
else:
log.debug("<-- [%.6f] %s" % (elapsed, responsedata))
return response, http_response.status
diff --git a/test/functional/test_framework/compressor.py b/test/functional/test_framework/compressor.py
new file mode 100644
index 0000000000..1c30d749df
--- /dev/null
+++ b/test/functional/test_framework/compressor.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright (c) 2025-present The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Routines for compressing transaction output amounts and scripts."""
+import unittest
+
+from .messages import COIN
+
+
+def compress_amount(n):
+ if n == 0:
+ return 0
+ e = 0
+ while ((n % 10) == 0) and (e < 9):
+ n //= 10
+ e += 1
+ if e < 9:
+ d = n % 10
+ assert (d >= 1 and d <= 9)
+ n //= 10
+ return 1 + (n*9 + d - 1)*10 + e
+ else:
+ return 1 + (n - 1)*10 + 9
+
+
+def decompress_amount(x):
+ if x == 0:
+ return 0
+ x -= 1
+ e = x % 10
+ x //= 10
+ n = 0
+ if e < 9:
+ d = (x % 9) + 1
+ x //= 9
+ n = x * 10 + d
+ else:
+ n = x + 1
+ while e > 0:
+ n *= 10
+ e -= 1
+ return n
+
+
+class TestFrameworkCompressor(unittest.TestCase):
+ def test_amount_compress_decompress(self):
+ def check_amount(amount, expected_compressed):
+ self.assertEqual(compress_amount(amount), expected_compressed)
+ self.assertEqual(decompress_amount(expected_compressed), amount)
+
+ # test cases from compress_tests.cpp:compress_amounts
+ check_amount(0, 0x0)
+ check_amount(1, 0x1)
+ check_amount(1000000, 0x7)
+ check_amount(COIN, 0x9)
+ check_amount(50*COIN, 0x32)
+ check_amount(21000000*COIN, 0x1406f40)
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 9ebb683a9d..1ba48f9a48 100755
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -120,6 +120,26 @@ def deser_compact_size(f):
return nit
+def ser_varint(l):
+ r = b""
+ while True:
+ r = bytes([(l & 0x7f) | (0x80 if len(r) > 0 else 0x00)]) + r
+ if l <= 0x7f:
+ return r
+ l = (l >> 7) - 1
+
+
+def deser_varint(f):
+ n = 0
+ while True:
+ dat = f.read(1)[0]
+ n = (n << 7) | (dat & 0x7f)
+ if (dat & 0x80) > 0:
+ n += 1
+ else:
+ return n
+
+
def deser_string(f):
nit = deser_compact_size(f)
return f.read(nit)
@@ -1913,3 +1933,20 @@ class TestFrameworkScript(unittest.TestCase):
check_addrv2("2bqghnldu6mcug4pikzprwhtjjnsyederctvci6klcwzepnjd46ikjyd.onion", CAddress.NET_TORV3)
check_addrv2("255fhcp6ajvftnyo7bwz3an3t4a4brhopm3bamyh2iu5r3gnr2rq.b32.i2p", CAddress.NET_I2P)
check_addrv2("fc32:17ea:e415:c3bf:9808:149d:b5a2:c9aa", CAddress.NET_CJDNS)
+
+ def test_varint_encode_decode(self):
+ def check_varint(num, expected_encoding_hex):
+ expected_encoding = bytes.fromhex(expected_encoding_hex)
+ self.assertEqual(ser_varint(num), expected_encoding)
+ self.assertEqual(deser_varint(BytesIO(expected_encoding)), num)
+
+ # test cases from serialize_tests.cpp:varint_bitpatterns
+ check_varint(0, "00")
+ check_varint(0x7f, "7f")
+ check_varint(0x80, "8000")
+ check_varint(0x1234, "a334")
+ check_varint(0xffff, "82fe7f")
+ check_varint(0x123456, "c7e756")
+ check_varint(0x80123456, "86ffc7e756")
+ check_varint(0xffffffff, "8efefefe7f")
+ check_varint(0xffffffffffffffff, "80fefefefefefefefe7f")
diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py
index 207d19137b..bac57f3886 100755
--- a/test/functional/test_framework/p2p.py
+++ b/test/functional/test_framework/p2p.py
@@ -378,11 +378,17 @@ class P2PConnection(asyncio.Protocol):
# Socket write methods
- def send_message(self, message, is_decoy=False):
+ def send_without_ping(self, message, is_decoy=False):
"""Send a P2P message over the socket.
This method takes a P2P payload, builds the P2P header and adds
- the message to the send buffer to be sent over the socket."""
+ the message to the send buffer to be sent over the socket.
+
+ When a message does not lead to a disconnect, send_and_ping is usually
+ preferred to send a message. This can help to reduce intermittent test
+ failures due to a missing sync. Also, it includes a call to
+ sync_with_ping, allowing for concise test code.
+ """
with self._send_lock:
tmsg = self.build_message(message, is_decoy)
self._log_message("send", message)
@@ -558,10 +564,10 @@ class P2PInterface(P2PConnection):
if i.type != 0:
want.inv.append(i)
if len(want.inv):
- self.send_message(want)
+ self.send_without_ping(want)
def on_ping(self, message):
- self.send_message(msg_pong(message.nonce))
+ self.send_without_ping(msg_pong(message.nonce))
def on_verack(self, message):
pass
@@ -574,14 +580,14 @@ class P2PInterface(P2PConnection):
self.send_version()
self.reconnect = False
if message.nVersion >= 70016 and self.wtxidrelay:
- self.send_message(msg_wtxidrelay())
+ self.send_without_ping(msg_wtxidrelay())
if self.support_addrv2:
- self.send_message(msg_sendaddrv2())
- self.send_message(msg_verack())
+ self.send_without_ping(msg_sendaddrv2())
+ self.send_without_ping(msg_verack())
self.nServices = message.nServices
self.relay = message.relay
if self.p2p_connected_to_node:
- self.send_message(msg_getaddr())
+ self.send_without_ping(msg_getaddr())
# Connection helper methods
@@ -688,11 +694,11 @@ class P2PInterface(P2PConnection):
def send_version(self):
if self.on_connection_send_msg:
- self.send_message(self.on_connection_send_msg)
+ self.send_without_ping(self.on_connection_send_msg)
self.on_connection_send_msg = None # Never used again
def send_and_ping(self, message, *, timeout=60):
- self.send_message(message)
+ self.send_without_ping(message)
self.sync_with_ping(timeout=timeout)
def sync_with_ping(self, *, timeout=60):
@@ -700,8 +706,8 @@ class P2PInterface(P2PConnection):
# Sending two pings back-to-back, requires that the node calls
# `ProcessMessage` twice, and thus ensures `SendMessages` must have
# been called at least once
- self.send_message(msg_ping(nonce=0))
- self.send_message(msg_ping(nonce=self.ping_counter))
+ self.send_without_ping(msg_ping(nonce=0))
+ self.send_without_ping(msg_ping(nonce=self.ping_counter))
def test_function():
return self.last_message.get("pong") and self.last_message["pong"].nonce == self.ping_counter
@@ -814,9 +820,9 @@ class P2PDataStore(P2PInterface):
self.getdata_requests.append(inv.hash)
invtype = inv.type & MSG_TYPE_MASK
if (invtype == MSG_TX or invtype == MSG_WTX) and inv.hash in self.tx_store.keys():
- self.send_message(msg_tx(self.tx_store[inv.hash]))
+ self.send_without_ping(msg_tx(self.tx_store[inv.hash]))
elif invtype == MSG_BLOCK and inv.hash in self.block_store.keys():
- self.send_message(msg_block(self.block_store[inv.hash]))
+ self.send_without_ping(msg_block(self.block_store[inv.hash]))
else:
logger.debug('getdata message type {} received.'.format(hex(inv.type)))
@@ -849,7 +855,7 @@ class P2PDataStore(P2PInterface):
response = msg_headers(headers_list)
if response is not None:
- self.send_message(response)
+ self.send_without_ping(response)
def send_blocks_and_test(self, blocks, node, *, success=True, force_send=False, reject_reason=None, expect_disconnect=False, timeout=60, is_decoy=False):
"""Send blocks to test node and test whether the tip advances.
@@ -874,9 +880,9 @@ class P2PDataStore(P2PInterface):
force_send = True
if force_send:
for b in blocks:
- self.send_message(msg_block(block=b), is_decoy)
+ self.send_without_ping(msg_block(block=b), is_decoy)
else:
- self.send_message(msg_headers([CBlockHeader(block) for block in blocks]))
+ self.send_without_ping(msg_headers([CBlockHeader(block) for block in blocks]))
self.wait_until(
lambda: blocks[-1].sha256 in self.getdata_requests,
timeout=timeout,
@@ -909,7 +915,7 @@ class P2PDataStore(P2PInterface):
reject_reason = [reject_reason] if reject_reason else []
with node.assert_debug_log(expected_msgs=reject_reason):
for tx in txs:
- self.send_message(msg_tx(tx))
+ self.send_without_ping(msg_tx(tx))
if expect_disconnect:
self.wait_for_disconnect()
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 921f12d9fb..c4b10af16c 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -18,6 +18,7 @@ import subprocess
import sys
import tempfile
import time
+import types
from .address import create_deterministic_address_bcrt1_p2tr_op_true
from .authproxy import JSONRPCException
@@ -56,6 +57,48 @@ class SkipTest(Exception):
self.message = message
+class Binaries:
+ """Helper class to provide information about bitcoin binaries
+
+ Attributes:
+ paths: Object returned from get_binary_paths() containing information
+ which binaries and command lines to use from environment variables and
+ the config file.
+ bin_dir: An optional string containing a directory path to look for
+ binaries, which takes precedence over the paths above, if specified.
+ This is used by tests calling binaries from previous releases.
+ """
+ def __init__(self, paths, bin_dir):
+ self.paths = paths
+ self.bin_dir = bin_dir
+
+ def daemon_argv(self):
+ "Return argv array that should be used to invoke bitcoind"
+ return self._argv(self.paths.bitcoind)
+
+ def rpc_argv(self):
+ "Return argv array that should be used to invoke bitcoin-cli"
+ return self._argv(self.paths.bitcoincli)
+
+ def util_argv(self):
+ "Return argv array that should be used to invoke bitcoin-util"
+ return self._argv(self.paths.bitcoinutil)
+
+ def wallet_argv(self):
+ "Return argv array that should be used to invoke bitcoin-wallet"
+ return self._argv(self.paths.bitcoinwallet)
+
+ def _argv(self, bin_path):
+ """Return argv array that should be used to invoke the command.
+ Normally this will return binary paths directly from the paths object,
+ but when bin_dir is set (by tests calling binaries from previous
+ releases) it will return paths relative to bin_dir instead."""
+ if self.bin_dir is not None:
+ return [os.path.join(self.bin_dir, os.path.basename(bin_path))]
+ else:
+ return [bin_path]
+
+
class BitcoinTestMetaClass(type):
"""Metaclass for BitcoinTestFramework.
@@ -220,6 +263,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
config = configparser.ConfigParser()
config.read_file(open(self.options.configfile))
self.config = config
+ self.binary_paths = self.get_binary_paths()
if self.options.v1transport:
self.options.v2transport=False
@@ -229,23 +273,20 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# So set it to None to force -disablewallet, because the wallet is not needed.
self.options.descriptors = None
elif self.options.descriptors is None:
- # Some wallet is either required or optionally used by the test.
- # Prefer SQLite unless it isn't available
- if self.is_sqlite_compiled():
+ if self.is_wallet_compiled():
self.options.descriptors = True
- elif self.is_bdb_compiled():
- self.options.descriptors = False
else:
- # If neither are compiled, tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter
+ # Tests requiring a wallet will be skipped and the value of self.options.descriptors won't matter
# It still needs to exist and be None in order for tests to work however.
# So set it to None, which will also set -disablewallet.
self.options.descriptors = None
PortSeed.n = self.options.port_seed
- def set_binary_paths(self):
- """Update self.options with the paths of all binaries from environment variables or their default values"""
+ def get_binary_paths(self):
+ """Get paths of all binaries from environment variables or their default values"""
+ paths = types.SimpleNamespace()
binaries = {
"bitcoind": ("bitcoind", "BITCOIND"),
"bitcoin-cli": ("bitcoincli", "BITCOINCLI"),
@@ -255,10 +296,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
for binary, [attribute_name, env_variable_name] in binaries.items():
default_filename = os.path.join(
self.config["environment"]["BUILDDIR"],
- "src",
+ "bin",
binary + self.config["environment"]["EXEEXT"],
)
- setattr(self.options, attribute_name, os.getenv(env_variable_name, default=default_filename))
+ setattr(paths, attribute_name, os.getenv(env_variable_name, default=default_filename))
+ return paths
+
+ def get_binaries(self, bin_dir=None):
+ return Binaries(self.binary_paths, bin_dir)
def setup(self):
"""Call this method to start up the test framework object with options set."""
@@ -269,11 +314,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
config = self.config
- self.set_binary_paths()
-
os.environ['PATH'] = os.pathsep.join([
- os.path.join(config['environment']['BUILDDIR'], 'src'),
- os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'), os.environ['PATH']
+ os.path.join(config['environment']['BUILDDIR'], 'bin'),
+ os.environ['PATH']
])
# Set up temp directory and start logging
@@ -477,14 +520,14 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
group.add_argument("--legacy-wallet", action='store_const', const=False, **kwargs,
help="Run test using legacy wallets", dest='descriptors')
- def add_nodes(self, num_nodes: int, extra_args=None, *, rpchost=None, binary=None, binary_cli=None, versions=None):
+ def add_nodes(self, num_nodes: int, extra_args=None, *, rpchost=None, versions=None):
"""Instantiate TestNode objects.
Should only be called once after the nodes have been specified in
set_test_params()."""
- def get_bin_from_version(version, bin_name, bin_default):
+ def bin_dir_from_version(version):
if not version:
- return bin_default
+ return None
if version > 219999:
# Starting at client version 220000 the first two digits represent
# the major version, e.g. v22.0 instead of v0.22.0.
@@ -502,7 +545,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
),
),
'bin',
- bin_name,
)
if self.bind_to_localhost_only:
@@ -517,13 +559,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
extra_args[i] = extra_args[i] + ["-whitelist=noban,in,out@127.0.0.1"]
if versions is None:
versions = [None] * num_nodes
- if binary is None:
- binary = [get_bin_from_version(v, 'bitcoind', self.options.bitcoind) for v in versions]
- if binary_cli is None:
- binary_cli = [get_bin_from_version(v, 'bitcoin-cli', self.options.bitcoincli) for v in versions]
+ bin_dirs = [bin_dir_from_version(v) for v in versions]
# Fail test if any of the needed release binaries is missing
bins_missing = False
- for bin_path in binary + binary_cli:
+ for bin_path in (argv[0] for bin_dir in bin_dirs
+ for binaries in (self.get_binaries(bin_dir),)
+ for argv in (binaries.daemon_argv(), binaries.rpc_argv())):
if shutil.which(bin_path) is None:
self.log.error(f"Binary not found: {bin_path}")
bins_missing = True
@@ -533,8 +574,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert_equal(len(extra_confs), num_nodes)
assert_equal(len(extra_args), num_nodes)
assert_equal(len(versions), num_nodes)
- assert_equal(len(binary), num_nodes)
- assert_equal(len(binary_cli), num_nodes)
+ assert_equal(len(bin_dirs), num_nodes)
for i in range(num_nodes):
args = list(extra_args[i])
test_node_i = TestNode(
@@ -544,8 +584,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
rpchost=rpchost,
timewait=self.rpc_timeout,
timeout_factor=self.options.timeout_factor,
- bitcoind=binary[i],
- bitcoin_cli=binary_cli[i],
+ binaries=self.get_binaries(bin_dirs[i]),
version=versions[i],
coverage_dir=self.options.coveragedir,
cwd=self.options.tmpdir,
@@ -856,8 +895,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
rpchost=None,
timewait=self.rpc_timeout,
timeout_factor=self.options.timeout_factor,
- bitcoind=self.options.bitcoind,
- bitcoin_cli=self.options.bitcoincli,
+ binaries=self.get_binaries(),
coverage_dir=None,
cwd=self.options.tmpdir,
descriptors=self.options.descriptors,
@@ -966,16 +1004,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self._requires_wallet = True
if not self.is_wallet_compiled():
raise SkipTest("wallet has not been compiled.")
- if self.options.descriptors:
- self.skip_if_no_sqlite()
- else:
+ if not self.options.descriptors:
self.skip_if_no_bdb()
- def skip_if_no_sqlite(self):
- """Skip the running test if sqlite has not been compiled."""
- if not self.is_sqlite_compiled():
- raise SkipTest("sqlite has not been compiled.")
-
def skip_if_no_bdb(self):
"""Skip the running test if BDB has not been compiled."""
if not self.is_bdb_compiled():
@@ -1030,7 +1061,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"""Checks whether wallet support for the specified type
(legacy or descriptor wallet) was compiled."""
if self.options.descriptors:
- return self.is_sqlite_compiled()
+ return self.is_wallet_compiled()
else:
return self.is_bdb_compiled()
@@ -1050,10 +1081,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
"""Checks whether the USDT tracepoints were compiled."""
return self.config["components"].getboolean("ENABLE_USDT_TRACEPOINTS")
- def is_sqlite_compiled(self):
- """Checks whether the wallet module was compiled with Sqlite support."""
- return self.config["components"].getboolean("USE_SQLITE")
-
def is_bdb_compiled(self):
"""Checks whether the wallet module was compiled with BDB support."""
return self.config["components"].getboolean("USE_BDB")
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index f7d6ba78d2..7ab6dd0f30 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -76,7 +76,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
- def __init__(self, i, datadir_path, *, chain, rpchost, timewait, timeout_factor, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None, descriptors=False, v2transport=False):
+ def __init__(self, i, datadir_path, *, chain, rpchost, timewait, timeout_factor, binaries, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False, use_valgrind=False, version=None, descriptors=False, v2transport=False):
"""
Kwargs:
start_perf (bool): If True, begin profiling the node with `perf` as soon as
@@ -92,7 +92,7 @@ class TestNode():
self.chain = chain
self.rpchost = rpchost
self.rpc_timeout = timewait
- self.binary = bitcoind
+ self.binaries = binaries
self.coverage_dir = coverage_dir
self.cwd = cwd
self.descriptors = descriptors
@@ -109,8 +109,7 @@ class TestNode():
# Configuration for logging is set as command-line args rather than in the bitcoin.conf file.
# This means that starting a bitcoind using the temp dir to debug a failed test won't
# spam debug.log.
- self.args = [
- self.binary,
+ self.args = self.binaries.daemon_argv() + [
f"-datadir={self.datadir_path}",
"-logtimemicros",
"-debug",
@@ -149,7 +148,7 @@ class TestNode():
self.args.append("-v2transport=0")
# if v2transport is requested via global flag but not supported for node version, ignore it
- self.cli = TestNodeCLI(bitcoin_cli, self.datadir_path)
+ self.cli = TestNodeCLI(binaries, self.datadir_path)
self.use_cli = use_cli
self.start_perf = start_perf
@@ -443,6 +442,11 @@ class TestNode():
kwargs["expected_ret_code"] = 1 if expect_error else 0 # Whether node shutdown return EXIT_FAILURE or EXIT_SUCCESS
self.wait_until(lambda: self.is_node_stopped(**kwargs), timeout=timeout)
+ def kill_process(self):
+ self.process.kill()
+ self.wait_until_stopped(expected_ret_code=1 if platform.system() == "Windows" else -9)
+ assert self.is_node_stopped()
+
def replace_in_config(self, replacements):
"""
Perform replacements in the configuration file.
@@ -822,7 +826,8 @@ class TestNode():
def disconnect_p2ps(self):
"""Close all p2p connections to the node.
- Use only after each p2p has sent a version message to ensure the wait works."""
+ The state of the peers (such as txrequests) may not be fully cleared
+ yet, even after this method returns."""
for p in self.p2ps:
p.peer_disconnect()
del self.p2ps[:]
@@ -865,16 +870,16 @@ def arg_to_cli(arg):
class TestNodeCLI():
"""Interface to bitcoin-cli for an individual node"""
- def __init__(self, binary, datadir):
+ def __init__(self, binaries, datadir):
self.options = []
- self.binary = binary
+ self.binaries = binaries
self.datadir = datadir
self.input = None
self.log = logging.getLogger('TestFramework.bitcoincli')
def __call__(self, *options, input=None):
# TestNodeCLI is callable with bitcoin-cli command-line options
- cli = TestNodeCLI(self.binary, self.datadir)
+ cli = TestNodeCLI(self.binaries, self.datadir)
cli.options = [str(o) for o in options]
cli.input = input
return cli
@@ -895,7 +900,7 @@ class TestNodeCLI():
"""Run bitcoin-cli command. Deserializes returned string as python object."""
pos_args = [arg_to_cli(arg) for arg in args]
named_args = [str(key) + "=" + arg_to_cli(value) for (key, value) in kwargs.items()]
- p_args = [self.binary, f"-datadir={self.datadir}"] + self.options
+ p_args = self.binaries.rpc_argv() + [f"-datadir={self.datadir}"] + self.options
if named_args:
p_args += ["-named"]
if clicommand is not None:
@@ -911,7 +916,7 @@ class TestNodeCLI():
code, message = match.groups()
raise JSONRPCException(dict(code=int(code), message=message))
# Ignore cli_stdout, raise with cli_stderr
- raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr)
+ raise subprocess.CalledProcessError(returncode, p_args, output=cli_stderr)
try:
return json.loads(cli_stdout, parse_float=decimal.Decimal)
except (json.JSONDecodeError, decimal.InvalidOperation):
diff --git a/test/functional/test_framework/test_shell.py b/test/functional/test_framework/test_shell.py
index e232430507..3f237c7ea2 100644
--- a/test/functional/test_framework/test_shell.py
+++ b/test/functional/test_framework/test_shell.py
@@ -61,7 +61,8 @@ class TestShell:
print("Shutdown TestShell before resetting!")
else:
self.num_nodes = None
- super().__init__()
+ dummy_testshell_file = pathlib.Path(__file__).absolute().parent.parent / "testshell_dummy.py"
+ super().__init__(dummy_testshell_file)
instance = None
@@ -74,8 +75,8 @@ class TestShell:
# cache. Since TestShell is meant for interactive use, there is no concrete
# test; passing a dummy name is fine though, as only the containing directory
# is relevant for successful initialization.
- tests_directory = pathlib.Path(__file__).resolve().parent.parent
- TestShell.instance = TestShell.__TestShell(tests_directory / "testshell_dummy.py")
+ dummy_testshell_file = pathlib.Path(__file__).absolute().parent.parent / "testshell_dummy.py"
+ TestShell.instance = TestShell.__TestShell(dummy_testshell_file)
TestShell.instance.running = False
return TestShell.instance
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 14930ef671..ceca0d3b19 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -592,3 +592,10 @@ def find_vout_for_address(node, txid, addr):
if addr == tx["vout"][i]["scriptPubKey"]["address"]:
return i
raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
+
+
+def sync_txindex(test_framework, node):
+ test_framework.log.debug("Waiting for node txindex to sync")
+ sync_start = int(time.time())
+ test_framework.wait_until(lambda: node.getindexinfo("txindex")["txindex"]["synced"])
+ test_framework.log.debug(f"Synced in {time.time() - sync_start} seconds")
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index a332818e5d..4b8c9172b4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -275,6 +275,7 @@ BASE_SCRIPTS = [
'mempool_truc.py',
'wallet_txn_doublespend.py --legacy-wallet',
'wallet_multisig_descriptor_psbt.py --descriptors',
+ 'wallet_miniscript_decaying_multisig_descriptor_psbt.py --descriptors',
'wallet_txn_doublespend.py --descriptors',
'wallet_backwards_compatibility.py --legacy-wallet',
'wallet_backwards_compatibility.py --descriptors',
@@ -364,7 +365,6 @@ BASE_SCRIPTS = [
'feature_filelock.py',
'feature_loadblock.py',
'wallet_assumeutxo.py --descriptors',
- 'p2p_dos_header_tree.py',
'p2p_add_connections.py',
'feature_bind_port_discover.py',
'p2p_unrequested_blocks.py',
diff --git a/test/functional/tool_signet_miner.py b/test/functional/tool_signet_miner.py
index 0084158554..11b6af4e9d 100755
--- a/test/functional/tool_signet_miner.py
+++ b/test/functional/tool_signet_miner.py
@@ -5,6 +5,7 @@
"""Test signet miner tool"""
import os.path
+import shlex
import subprocess
import sys
import time
@@ -49,13 +50,15 @@ class SignetMinerTest(BitcoinTestFramework):
# generate block with signet miner tool
base_dir = self.config["environment"]["SRCDIR"]
signet_miner_path = os.path.join(base_dir, "contrib", "signet", "miner")
+ rpc_argv = node.binaries.rpc_argv() + [f"-datadir={node.cli.datadir}"]
+ util_argv = node.binaries.util_argv() + ["grind"]
subprocess.run([
sys.executable,
signet_miner_path,
- f'--cli={node.cli.binary} -datadir={node.cli.datadir}',
+ f'--cli={shlex.join(rpc_argv)}',
'generate',
f'--address={node.getnewaddress()}',
- f'--grind-cmd={self.options.bitcoinutil} grind',
+ f'--grind-cmd={shlex.join(util_argv)}',
f'--nbits={DIFF_1_N_BITS:08x}',
f'--set-block-time={int(time.time())}',
'--poolnum=99',
diff --git a/test/functional/tool_wallet.py b/test/functional/tool_wallet.py
index b0b9adab87..387ba276dd 100755
--- a/test/functional/tool_wallet.py
+++ b/test/functional/tool_wallet.py
@@ -5,7 +5,6 @@
"""Test bitcoin-wallet."""
import os
-import platform
import random
import stat
import string
@@ -49,7 +48,7 @@ class ToolWalletTest(BitcoinTestFramework):
if "dump" in args and self.options.bdbro:
default_args.append("-withinternalbdb")
- return subprocess.Popen([self.options.bitcoinwallet] + default_args + list(args), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
+ return subprocess.Popen(self.get_binaries().wallet_argv() + default_args + list(args), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
def assert_raises_tool_error(self, error, *args):
p = self.bitcoin_wallet_process(*args)
@@ -367,8 +366,7 @@ class ToolWalletTest(BitcoinTestFramework):
self.do_tool_createfromdump("load", "wallet.dump")
if self.is_bdb_compiled():
self.do_tool_createfromdump("load-bdb", "wallet.dump", "bdb")
- if self.is_sqlite_compiled():
- self.do_tool_createfromdump("load-sqlite", "wallet.dump", "sqlite")
+ self.do_tool_createfromdump("load-sqlite", "wallet.dump", "sqlite")
self.log.info('Checking createfromdump handling of magic and versions')
bad_ver_wallet_dump = self.nodes[0].datadir_path / "wallet-bad_ver1.dump"
@@ -537,9 +535,7 @@ class ToolWalletTest(BitcoinTestFramework):
# Next cause a bunch of writes by filling the keypool
wallet.keypoolrefill(wallet.getwalletinfo()["keypoolsize"] + 100)
# Lastly kill bitcoind so that the LSNs don't get reset
- self.nodes[0].process.kill()
- self.nodes[0].wait_until_stopped(expected_ret_code=1 if platform.system() == "Windows" else -9)
- assert self.nodes[0].is_node_stopped()
+ self.nodes[0].kill_process()
wallet_dump = self.nodes[0].datadir_path / "unclean_lsn.dump"
self.assert_raises_tool_error("LSNs are not reset, this database is not completely flushed. Please reopen then close the database with a version that has BDB support", "-wallet=unclean_lsn", f"-dumpfile={wallet_dump}", "dump")
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index ce0f4d099b..2bbfaee3db 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -45,6 +45,10 @@ class AbandonConflictTest(BitcoinTestFramework):
txB = alice.sendtoaddress(alice.getnewaddress(), Decimal("10"))
txC = alice.sendtoaddress(alice.getnewaddress(), Decimal("10"))
self.sync_mempools()
+
+ # Can not abandon transaction in mempool
+ assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: alice.abandontransaction(txid=txA))
+
self.generate(self.nodes[1], 1)
# Can not abandon non-wallet transaction
diff --git a/test/functional/wallet_avoid_mixing_output_types.py b/test/functional/wallet_avoid_mixing_output_types.py
index 146b3df3f4..08584abfbc 100755
--- a/test/functional/wallet_avoid_mixing_output_types.py
+++ b/test/functional/wallet_avoid_mixing_output_types.py
@@ -117,7 +117,6 @@ class AddressInputTypeGrouping(BitcoinTestFramework):
self.extra_args = [
[
"-addresstype=bech32",
- "-txindex",
],
[
"-addresstype=p2sh-segwit",
@@ -127,7 +126,6 @@ class AddressInputTypeGrouping(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def make_payment(self, A, B, v, addr_type):
fee_rate = random.randint(1, 20)
diff --git a/test/functional/wallet_crosschain.py b/test/functional/wallet_crosschain.py
index 97db84c3e4..a496694d12 100755
--- a/test/functional/wallet_crosschain.py
+++ b/test/functional/wallet_crosschain.py
@@ -11,7 +11,7 @@ class WalletCrossChain(BitcoinTestFramework):
self.add_wallet_options(parser)
def set_test_params(self):
- self.num_nodes = 3
+ self.num_nodes = 2
self.setup_clean_chain = True
def skip_test_if_missing_module(self):
@@ -20,16 +20,11 @@ class WalletCrossChain(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes)
- # Switch node 1 to testnet before starting it.
- self.nodes[1].chain = 'testnet3'
- self.nodes[1].extra_args = ['-maxconnections=0', '-prune=550'] # disable testnet sync
- self.nodes[1].replace_in_config([('regtest=', 'testnet='), ('[regtest]', '[test]')])
-
- # Switch node 2 to testnet4 before starting it.
- self.nodes[2].chain = 'testnet4'
- self.nodes[2].extra_args = ['-maxconnections=0', '-prune=550'] # disable testnet4 sync
- self.nodes[2].replace_in_config([('regtest=', 'testnet4='), ('[regtest]', '[testnet4]')])
-
+ # Switch node 1 to any network different from regtest before starting it.
+ self.nodes[1].chain = 'signet'
+ # Disable network sync and prevent disk space warning on low resource CI
+ self.nodes[1].extra_args = ['-maxconnections=0', '-prune=550']
+ self.nodes[1].replace_in_config([('regtest=', 'signet='), ('[regtest]', '[signet]')])
self.start_nodes()
def run_test(self):
@@ -45,40 +40,19 @@ class WalletCrossChain(BitcoinTestFramework):
self.nodes[1].createwallet(node1_wallet)
self.nodes[1].backupwallet(node1_wallet_backup)
self.nodes[1].unloadwallet(node1_wallet)
- node2_wallet = self.nodes[2].datadir_path / 'node2_wallet'
- node2_wallet_backup = self.nodes[0].datadir_path / 'node2_wallet.bak'
- self.nodes[2].createwallet(node2_wallet)
- self.nodes[2].backupwallet(node2_wallet_backup)
- self.nodes[2].unloadwallet(node2_wallet)
self.log.info("Loading/restoring wallets into nodes with a different genesis block")
if self.options.descriptors:
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].loadwallet, node1_wallet)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].loadwallet, node2_wallet)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].loadwallet, node0_wallet)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].loadwallet, node0_wallet)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].loadwallet, node2_wallet)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].loadwallet, node1_wallet)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].restorewallet, 'w', node1_wallet_backup)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[0].restorewallet, 'w', node2_wallet_backup)
assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].restorewallet, 'w', node0_wallet_backup)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].restorewallet, 'w', node0_wallet_backup)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[1].restorewallet, 'w', node2_wallet_backup)
- assert_raises_rpc_error(-18, 'Wallet file verification failed.', self.nodes[2].restorewallet, 'w', node1_wallet_backup)
else:
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].loadwallet, node1_wallet)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].loadwallet, node2_wallet)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].loadwallet, node0_wallet)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].loadwallet, node0_wallet)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].loadwallet, node2_wallet)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].loadwallet, node1_wallet)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].restorewallet, 'w', node1_wallet_backup)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[0].restorewallet, 'w', node2_wallet_backup)
assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].restorewallet, 'w', node0_wallet_backup)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].restorewallet, 'w', node0_wallet_backup)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[1].restorewallet, 'w', node2_wallet_backup)
- assert_raises_rpc_error(-4, 'Wallet files should not be reused across chains.', self.nodes[2].restorewallet, 'w', node1_wallet_backup)
if not self.options.descriptors:
self.log.info("Override cross-chain wallet load protection")
diff --git a/test/functional/wallet_descriptor.py b/test/functional/wallet_descriptor.py
index 5e0ee97892..0071d671c2 100755
--- a/test/functional/wallet_descriptor.py
+++ b/test/functional/wallet_descriptor.py
@@ -33,7 +33,6 @@ class WalletDescriptorTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
self.skip_if_no_py_sqlite3()
def test_concurrent_writes(self):
diff --git a/test/functional/wallet_encryption.py b/test/functional/wallet_encryption.py
index 5e131405f1..4171951cf8 100755
--- a/test/functional/wallet_encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -112,7 +112,7 @@ class WalletEncryptionTest(BitcoinTestFramework):
def do_wallet_tool(*args):
proc = subprocess.Popen(
- [self.options.bitcoinwallet, f"-datadir={self.nodes[0].datadir_path}", f"-chain={self.chain}"] + list(args),
+ self.get_binaries().wallet_argv() + [f"-datadir={self.nodes[0].datadir_path}", f"-chain={self.chain}"] + list(args),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
diff --git a/test/functional/wallet_fast_rescan.py b/test/functional/wallet_fast_rescan.py
index 6cee0d3660..1a9c319cb1 100755
--- a/test/functional/wallet_fast_rescan.py
+++ b/test/functional/wallet_fast_rescan.py
@@ -28,7 +28,6 @@ class WalletFastRescanTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def get_wallet_txids(self, node: TestNode, wallet_name: str) -> list[str]:
w = node.get_wallet_rpc(wallet_name)
diff --git a/test/functional/wallet_importdescriptors.py b/test/functional/wallet_importdescriptors.py
index 03e26465f1..bd50b8cdc0 100755
--- a/test/functional/wallet_importdescriptors.py
+++ b/test/functional/wallet_importdescriptors.py
@@ -24,7 +24,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.descriptors import descsum_create
from test_framework.util import (
assert_equal,
- assert_greater_than,
assert_raises_rpc_error,
)
from test_framework.wallet_util import (
@@ -48,7 +47,6 @@ class ImportDescriptorsTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def test_importdesc(self, req, success, error_code=None, error_message=None, warnings=None, wallet=None):
"""Run importdescriptors and assert success"""
@@ -130,6 +128,20 @@ class ImportDescriptorsTest(BitcoinTestFramework):
assert_equal(info["ismine"], True)
assert_equal(info["ischange"], True)
+ self.log.info("Should not import a descriptor with an invalid public key due to whitespace")
+ self.test_importdesc({"desc": descsum_create("pkh( " + key.pubkey + ")"),
+ "timestamp": "now",
+ "internal": True},
+ error_code=-5,
+ error_message=f"pkh(): Key ' {key.pubkey}' is invalid due to whitespace",
+ success=False)
+ self.test_importdesc({"desc": descsum_create("pkh(" + key.pubkey + " )"),
+ "timestamp": "now",
+ "internal": True},
+ error_code=-5,
+ error_message=f"pkh(): Key '{key.pubkey} ' is invalid due to whitespace",
+ success=False)
+
# # Test importing of a P2SH-P2WPKH descriptor
key = get_generate_key()
self.log.info("Should not import a p2sh-p2wpkh descriptor without checksum")
@@ -706,13 +718,6 @@ class ImportDescriptorsTest(BitcoinTestFramework):
except JSONRPCException as e:
assert e.error["code"] == -4 and "Error: the wallet is currently being used to rescan the blockchain for related transactions. Please call `abortrescan` before changing the passphrase." in e.error["message"]
- wallet_info = self.nodes[0].cli("-rpcwallet=encrypted_wallet").getwalletinfo()
- try:
- duration = wallet_info["scanning"]["duration"]
- assert_greater_than(duration, 0)
- except Exception:
- assert "scanning" not in wallet_info
-
assert_equal(importing.result(), [{"success": True}])
assert_equal(temp_wallet.getbalance(), encrypted_wallet.getbalance())
diff --git a/test/functional/wallet_listdescriptors.py b/test/functional/wallet_listdescriptors.py
index c9d6c1f190..35be527b32 100755
--- a/test/functional/wallet_listdescriptors.py
+++ b/test/functional/wallet_listdescriptors.py
@@ -26,7 +26,6 @@ class ListDescriptorsTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
# do not create any wallet by default
def init_wallet(self, *, node):
diff --git a/test/functional/wallet_miniscript.py b/test/functional/wallet_miniscript.py
index 064eac499b..748faf14e2 100755
--- a/test/functional/wallet_miniscript.py
+++ b/test/functional/wallet_miniscript.py
@@ -212,7 +212,6 @@ class WalletMiniscriptTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def watchonly_test(self, desc):
self.log.info(f"Importing descriptor '{desc}'")
diff --git a/test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py b/test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py
new file mode 100755
index 0000000000..1c8c4de492
--- /dev/null
+++ b/test/functional/wallet_miniscript_decaying_multisig_descriptor_psbt.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python3
+# Copyright (c) 2024 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test a miniscript multisig that starts as 4-of-4 and "decays" to 3-of-4, 2-of-4, and finally 1-of-4 at each future halvening block height.
+
+Spending policy: `thresh(4,pk(key_1),pk(key_2),pk(key_3),pk(key_4),after(t1),after(t2),after(t3))`
+This is similar to `test/functional/wallet_multisig_descriptor_psbt.py`.
+"""
+
+import random
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_approx,
+ assert_equal,
+ assert_raises_rpc_error,
+)
+
+
+class WalletMiniscriptDecayingMultisigDescriptorPSBTTest(BitcoinTestFramework):
+ def add_options(self, parser):
+ self.add_wallet_options(parser, legacy=False)
+
+ def set_test_params(self):
+ self.num_nodes = 1
+ self.setup_clean_chain = True
+ self.wallet_names = []
+ self.extra_args = [["-keypool=100"]]
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ @staticmethod
+ def _get_xpub(wallet, internal):
+ """Extract the wallet's xpubs using `listdescriptors` and pick the one from the `pkh` descriptor since it's least likely to be accidentally reused (legacy addresses)."""
+ pkh_descriptor = next(filter(lambda d: d["desc"].startswith("pkh(") and d["internal"] == internal, wallet.listdescriptors()["descriptors"]))
+ # keep all key origin information (master key fingerprint and all derivation steps) for proper support of hardware devices
+ # see section 'Key origin identification' in 'doc/descriptors.md' for more details...
+ return pkh_descriptor["desc"].split("pkh(")[1].split(")")[0]
+
+ def create_multisig(self, external_xpubs, internal_xpubs):
+ """The multisig is created by importing the following descriptors. The resulting wallet is watch-only and every signer can do this."""
+ self.node.createwallet(wallet_name=f"{self.name}", blank=True, descriptors=True, disable_private_keys=True)
+ multisig = self.node.get_wallet_rpc(f"{self.name}")
+ # spending policy: `thresh(4,pk(key_1),pk(key_2),pk(key_3),pk(key_4),after(t1),after(t2),after(t3))`
+ # IMPORTANT: when backing up your descriptor, the order of key_1...key_4 must be correct!
+ external = multisig.getdescriptorinfo(f"wsh(thresh({self.N},pk({'),s:pk('.join(external_xpubs)}),sln:after({'),sln:after('.join(map(str, self.locktimes))})))")
+ internal = multisig.getdescriptorinfo(f"wsh(thresh({self.N},pk({'),s:pk('.join(internal_xpubs)}),sln:after({'),sln:after('.join(map(str, self.locktimes))})))")
+ result = multisig.importdescriptors([
+ { # receiving addresses (internal: False)
+ "desc": external["descriptor"],
+ "active": True,
+ "internal": False,
+ "timestamp": "now",
+ },
+ { # change addresses (internal: True)
+ "desc": internal["descriptor"],
+ "active": True,
+ "internal": True,
+ "timestamp": "now",
+ },
+ ])
+ assert all(r["success"] for r in result)
+ return multisig
+
+ def run_test(self):
+ self.node = self.nodes[0]
+ self.M = 4 # starts as 4-of-4
+ self.N = 4
+
+ self.locktimes = [104, 106, 108]
+ assert_equal(len(self.locktimes), self.N - 1)
+
+ self.name = f"{self.M}_of_{self.N}_decaying_multisig"
+ self.log.info(f"Testing a miniscript multisig which starts as 4-of-4 and 'decays' to 3-of-4 at block height {self.locktimes[0]}, 2-of-4 at {self.locktimes[1]}, and finally 1-of-4 at {self.locktimes[2]}...")
+
+ self.log.info("Create the signer wallets and get their xpubs...")
+ signers = [self.node.get_wallet_rpc(self.node.createwallet(wallet_name=f"signer_{i}", descriptors=True)["name"]) for i in range(self.N)]
+ external_xpubs, internal_xpubs = [[self._get_xpub(signer, internal) for signer in signers] for internal in [False, True]]
+
+ self.log.info("Create the watch-only decaying multisig using signers' xpubs...")
+ multisig = self.create_multisig(external_xpubs, internal_xpubs)
+
+ self.log.info("Get a mature utxo to send to the multisig...")
+ coordinator_wallet = self.node.get_wallet_rpc(self.node.createwallet(wallet_name="coordinator", descriptors=True)["name"])
+ self.generatetoaddress(self.node, 101, coordinator_wallet.getnewaddress())
+
+ self.log.info("Send funds to the multisig's receiving address...")
+ deposit_amount = 6.15
+ coordinator_wallet.sendtoaddress(multisig.getnewaddress(), deposit_amount)
+ self.generate(self.node, 1)
+ assert_approx(multisig.getbalance(), deposit_amount, vspan=0.001)
+
+ self.log.info("Send transactions from the multisig as required signers decay...")
+ amount = 1.5
+ receiver = signers[0]
+ sent = 0
+ for locktime in [0] + self.locktimes:
+ self.log.info(f"At block height >= {locktime} this multisig is {self.M}-of-{self.N}")
+ current_height = self.node.getblock(self.node.getbestblockhash())['height']
+
+ # in this test each signer signs the same psbt "in series" one after the other.
+ # Another option is for each signer to sign the original psbt, and then combine
+ # and finalize these. In some cases this may be more optimal for coordination.
+ psbt = multisig.walletcreatefundedpsbt(inputs=[], outputs={receiver.getnewaddress(): amount}, feeRate=0.00010, locktime=locktime)
+ # the random sample asserts that any of the signing keys can sign for the 3-of-4,
+ # 2-of-4, and 1-of-4. While this is basic behavior of the miniscript thresh primitive,
+ # it is a critical property of this wallet.
+ for i, m in enumerate(random.sample(range(self.M), self.M)):
+ psbt = signers[m].walletprocesspsbt(psbt["psbt"])
+ assert_equal(psbt["complete"], i == self.M - 1)
+
+ if self.M < self.N:
+ self.log.info(f"Check that the time-locked transaction is too immature to spend with {self.M}-of-{self.N} at block height {current_height}...")
+ assert_equal(current_height >= locktime, False)
+ assert_raises_rpc_error(-26, "non-final", multisig.sendrawtransaction, psbt["hex"])
+
+ self.log.info(f"Generate blocks to reach the time-lock block height {locktime} and broadcast the transaction...")
+ self.generate(self.node, locktime - current_height)
+ else:
+ self.log.info("All the signers are required to spend before the first locktime")
+
+ multisig.sendrawtransaction(psbt["hex"])
+ sent += amount
+
+ self.log.info("Check that balances are correct after the transaction has been included in a block...")
+ self.generate(self.node, 1)
+ assert_approx(multisig.getbalance(), deposit_amount - sent, vspan=0.001)
+ assert_equal(receiver.getbalance(), sent)
+
+ self.M -= 1 # decay the number of required signers for the next locktime..
+
+
+if __name__ == "__main__":
+ WalletMiniscriptDecayingMultisigDescriptorPSBTTest(__file__).main()
diff --git a/test/functional/wallet_multisig_descriptor_psbt.py b/test/functional/wallet_multisig_descriptor_psbt.py
index a69185b3a5..23a9a4cc75 100755
--- a/test/functional/wallet_multisig_descriptor_psbt.py
+++ b/test/functional/wallet_multisig_descriptor_psbt.py
@@ -26,7 +26,6 @@ class WalletMultisigDescriptorPSBTTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
@staticmethod
def _get_xpub(wallet, internal):
diff --git a/test/functional/wallet_reorgsrestore.py b/test/functional/wallet_reorgsrestore.py
index 77cf34898b..9c69c33680 100755
--- a/test/functional/wallet_reorgsrestore.py
+++ b/test/functional/wallet_reorgsrestore.py
@@ -19,6 +19,8 @@ import shutil
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
+ assert_greater_than,
+ assert_raises_rpc_error
)
class ReorgsRestoreTest(BitcoinTestFramework):
@@ -31,6 +33,113 @@ class ReorgsRestoreTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
+ def test_coinbase_automatic_abandon_during_startup(self):
+ ##########################################################################################################
+ # Verify the wallet marks coinbase transactions, and their descendants, as abandoned during startup when #
+ # the block is no longer part of the best chain. #
+ ##########################################################################################################
+ self.log.info("Test automatic coinbase abandonment during startup")
+ # Test setup: Sync nodes for the coming test, ensuring both are at the same block, then disconnect them to
+ # generate two competing chains. After disconnection, verify no other peer connection exists.
+ self.connect_nodes(1, 0)
+ self.sync_blocks(self.nodes[:2])
+ self.disconnect_nodes(1, 0)
+ assert all(len(node.getpeerinfo()) == 0 for node in self.nodes[:2])
+
+ # Create a new block in node0, coinbase going to wallet0
+ self.nodes[0].createwallet(wallet_name="w0", load_on_startup=True)
+ wallet0 = self.nodes[0].get_wallet_rpc("w0")
+ self.generatetoaddress(self.nodes[0], 1, wallet0.getnewaddress(), sync_fun=self.no_op)
+ node0_coinbase_tx_hash = wallet0.getblock(wallet0.getbestblockhash(), verbose=1)['tx'][0]
+
+ # Mine 100 blocks on top to mature the coinbase and create a descendant
+ self.generate(self.nodes[0], 101, sync_fun=self.no_op)
+ # Make descendant, send-to-self
+ descendant_tx_id = wallet0.sendtoaddress(wallet0.getnewaddress(), 1)
+
+ # Verify balance
+ wallet0.syncwithvalidationinterfacequeue()
+ assert(wallet0.getbalances()['mine']['trusted'] > 0)
+
+ # Now create a fork in node1. This will be used to replace node0's chain later.
+ self.nodes[1].createwallet(wallet_name="w1", load_on_startup=True)
+ wallet1 = self.nodes[1].get_wallet_rpc("w1")
+ self.generatetoaddress(self.nodes[1], 1, wallet1.getnewaddress(), sync_fun=self.no_op)
+ wallet1.syncwithvalidationinterfacequeue()
+
+ # Verify both nodes are on a different chain
+ block0_best_hash, block1_best_hash = wallet0.getbestblockhash(), wallet1.getbestblockhash()
+ assert(block0_best_hash != block1_best_hash)
+
+ # Stop both nodes and replace node0 chain entirely for the node1 chain
+ self.stop_nodes()
+ for path in ["chainstate", "blocks"]:
+ shutil.rmtree(self.nodes[0].chain_path / path)
+ shutil.copytree(self.nodes[1].chain_path / path, self.nodes[0].chain_path / path)
+
+ # Start node0 and verify that now it has node1 chain and no info about its previous best block
+ self.start_node(0)
+ wallet0 = self.nodes[0].get_wallet_rpc("w0")
+ assert_equal(wallet0.getbestblockhash(), block1_best_hash)
+ assert_raises_rpc_error(-5, "Block not found", wallet0.getblock, block0_best_hash)
+
+ # Verify the coinbase tx was marked as abandoned and balance correctly computed
+ tx_info = wallet0.gettransaction(node0_coinbase_tx_hash)['details'][0]
+ assert_equal(tx_info['abandoned'], True)
+ assert_equal(tx_info['category'], 'orphan')
+ assert(wallet0.getbalances()['mine']['trusted'] == 0)
+ # Verify the coinbase descendant was also marked as abandoned
+ assert_equal(wallet0.gettransaction(descendant_tx_id)['details'][0]['abandoned'], True)
+
+ def test_reorg_handling_during_unclean_shutdown(self):
+ self.log.info("Test that wallet doesn't crash due to a duplicate block disconnection event after an unclean shutdown")
+ node = self.nodes[0]
+ # Receive coinbase reward on a new wallet
+ node.createwallet(wallet_name="reorg_crash", load_on_startup=True)
+ wallet = node.get_wallet_rpc("reorg_crash")
+ self.generatetoaddress(node, 1, wallet.getnewaddress(), sync_fun=self.no_op)
+
+ # Restart to ensure node and wallet are flushed
+ self.restart_node(0)
+ wallet = node.get_wallet_rpc("reorg_crash")
+ assert_greater_than(wallet.getwalletinfo()['immature_balance'], 0)
+
+ # Disconnect tip and sync wallet state
+ tip = wallet.getbestblockhash()
+ wallet.invalidateblock(tip)
+ wallet.syncwithvalidationinterfacequeue()
+
+ # Tip was disconnected, ensure coinbase has been abandoned
+ assert_equal(wallet.getwalletinfo()['immature_balance'], 0)
+ coinbase_tx_id = wallet.getblock(tip, verbose=1)["tx"][0]
+ assert_equal(wallet.gettransaction(coinbase_tx_id)['details'][0]['abandoned'], True)
+
+ # Abort process abruptly to mimic an unclean shutdown (no chain state flush to disk)
+ node.kill_process()
+
+ # Restart the node and confirm that it has not persisted the last chain state changes to disk
+ self.start_node(0)
+ assert_equal(node.getbestblockhash(), tip)
+
+ # Due to an existing bug, the wallet incorrectly keeps the transaction in an abandoned state, even though that's
+ # no longer the case (after the unclean shutdown, the node's chain returned to the pre-invalidation tip).
+ # This issue blocks any future spending and results in an incorrect balance display.
+ wallet = node.get_wallet_rpc("reorg_crash")
+ assert_equal(wallet.getwalletinfo()['immature_balance'], 0) # FIXME: #31824.
+
+ # Previously, a bug caused the node to crash if two block disconnection events occurred consecutively.
+ # Ensure this is no longer the case by simulating a new reorg.
+ node.invalidateblock(tip)
+ assert(node.getbestblockhash() != tip)
+ # Ensure wallet state is consistent now
+ assert_equal(wallet.gettransaction(coinbase_tx_id)['details'][0]['abandoned'], True)
+ assert_equal(wallet.getwalletinfo()['immature_balance'], 0)
+
+ # And finally, verify the state if the block ends up being into the best chain again
+ node.reconsiderblock(tip)
+ assert_equal(wallet.gettransaction(coinbase_tx_id)['details'][0]['abandoned'], False)
+ assert_greater_than(wallet.getwalletinfo()['immature_balance'], 0)
+
def run_test(self):
# Send a tx from which to conflict outputs later
txid_conflict_from = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
@@ -100,5 +209,12 @@ class ReorgsRestoreTest(BitcoinTestFramework):
assert_equal(conflicted_after_reorg["confirmations"], 1)
assert conflicting["blockhash"] != conflicted_after_reorg["blockhash"]
+ # Verify we mark coinbase txs, and their descendants, as abandoned during startup
+ self.test_coinbase_automatic_abandon_during_startup()
+
+ # Verify reorg behavior during an unclean shutdown
+ self.test_reorg_handling_during_unclean_shutdown()
+
+
if __name__ == '__main__':
ReorgsRestoreTest(__file__).main()
diff --git a/test/functional/wallet_rescan_unconfirmed.py b/test/functional/wallet_rescan_unconfirmed.py
index 69ad522b5d..23c58b92f4 100755
--- a/test/functional/wallet_rescan_unconfirmed.py
+++ b/test/functional/wallet_rescan_unconfirmed.py
@@ -24,7 +24,6 @@ class WalletRescanUnconfirmed(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def run_test(self):
self.log.info("Create wallets and mine initial chain")
diff --git a/test/functional/wallet_taproot.py b/test/functional/wallet_taproot.py
index a88d84f4c6..cc9683fcde 100755
--- a/test/functional/wallet_taproot.py
+++ b/test/functional/wallet_taproot.py
@@ -198,7 +198,6 @@ class WalletTaprootTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- self.skip_if_no_sqlite()
def setup_network(self):
self.setup_nodes()
diff --git a/test/functional/wallet_upgradewallet.py b/test/functional/wallet_upgradewallet.py
index c909336a25..e1bb098ec7 100755
--- a/test/functional/wallet_upgradewallet.py
+++ b/test/functional/wallet_upgradewallet.py
@@ -343,16 +343,15 @@ class UpgradeWalletTest(BitcoinTestFramework):
v16_3_kvs = dump_bdb_kv(v16_3_wallet)
assert b'\x0adefaultkey' not in v16_3_kvs
- if self.is_sqlite_compiled():
- self.log.info("Checking that descriptor wallets do nothing, successfully")
- self.nodes[0].createwallet(wallet_name="desc_upgrade", descriptors=True)
- desc_wallet = self.nodes[0].get_wallet_rpc("desc_upgrade")
- self.test_upgradewallet(desc_wallet, previous_version=169900, expected_version=169900)
-
- self.log.info("Checking that descriptor wallets without privkeys do nothing, successfully")
- self.nodes[0].createwallet(wallet_name="desc_upgrade_nopriv", descriptors=True, disable_private_keys=True)
- desc_wallet = self.nodes[0].get_wallet_rpc("desc_upgrade_nopriv")
- self.test_upgradewallet(desc_wallet, previous_version=169900, expected_version=169900)
+ self.log.info("Checking that descriptor wallets do nothing, successfully")
+ self.nodes[0].createwallet(wallet_name="desc_upgrade", descriptors=True)
+ desc_wallet = self.nodes[0].get_wallet_rpc("desc_upgrade")
+ self.test_upgradewallet(desc_wallet, previous_version=169900, expected_version=169900)
+
+ self.log.info("Checking that descriptor wallets without privkeys do nothing, successfully")
+ self.nodes[0].createwallet(wallet_name="desc_upgrade_nopriv", descriptors=True, disable_private_keys=True)
+ desc_wallet = self.nodes[0].get_wallet_rpc("desc_upgrade_nopriv")
+ self.test_upgradewallet(desc_wallet, previous_version=169900, expected_version=169900)
if self.is_bdb_compiled():
self.log.info("Upgrading a wallet with private keys disabled")
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index e87977edfc..12661b4da5 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -109,7 +109,7 @@ def main():
logging.error("Must have fuzz executable built")
sys.exit(1)
- fuzz_bin=os.getenv("BITCOINFUZZ", default=os.path.join(config["environment"]["BUILDDIR"], 'src', 'test', 'fuzz', 'fuzz'))
+ fuzz_bin=os.getenv("BITCOINFUZZ", default=os.path.join(config["environment"]["BUILDDIR"], 'bin', 'fuzz'))
# Build list of tests
test_list_all = parse_test_list(
diff --git a/test/lint/README.md b/test/lint/README.md
index 8c1f0fedf0..a1e1a35a67 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -96,7 +96,7 @@ maintained:
* for `src/leveldb`: https://github.com/bitcoin-core/leveldb-subtree.git (branch bitcoin-fork)
* for `src/crypto/ctaes`: https://github.com/bitcoin-core/ctaes.git (branch master)
* for `src/crc32c`: https://github.com/bitcoin-core/crc32c-subtree.git (branch bitcoin-fork)
-* for `src/minisketch`: https://github.com/sipa/minisketch.git (branch master)
+* for `src/minisketch`: https://github.com/bitcoin-core/minisketch.git (branch master)
To do so, add the upstream repository as remote:
diff --git a/test/util/test_runner.py b/test/util/test_runner.py
index cac184ca30..d6faf18c5c 100755
--- a/test/util/test_runner.py
+++ b/test/util/test_runner.py
@@ -73,7 +73,7 @@ def bctest(testDir, testObj, buildenv):
are not as expected. Error is caught by bctester() and reported.
"""
# Get the exec names and arguments
- execprog = os.path.join(buildenv["BUILDDIR"], "src", testObj["exec"] + buildenv["EXEEXT"])
+ execprog = os.path.join(buildenv["BUILDDIR"], "bin", testObj["exec"] + buildenv["EXEEXT"])
if testObj["exec"] == "./bitcoin-util":
execprog = os.getenv("BITCOINUTIL", default=execprog)
elif testObj["exec"] == "./bitcoin-tx":