aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/README.md2
-rwxr-xr-xtest/functional/combine_logs.py2
-rw-r--r--test/functional/data/rpc_getblockstats.json204
-rwxr-xr-xtest/functional/feature_assumevalid.py4
-rwxr-xr-xtest/functional/feature_bip68_sequence.py8
-rwxr-xr-xtest/functional/feature_block.py3
-rwxr-xr-xtest/functional/feature_help.py11
-rwxr-xr-xtest/functional/feature_includeconf.py80
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py2
-rwxr-xr-xtest/functional/feature_notifications.py6
-rwxr-xr-xtest/functional/feature_nulldummy.py2
-rwxr-xr-xtest/functional/feature_proxy.py6
-rwxr-xr-xtest/functional/feature_pruning.py7
-rwxr-xr-xtest/functional/feature_rbf.py46
-rwxr-xr-xtest/functional/feature_segwit.py37
-rwxr-xr-xtest/functional/p2p_compactblocks.py7
-rwxr-xr-xtest/functional/p2p_feefilter.py2
-rwxr-xr-xtest/functional/p2p_invalid_tx.py22
-rwxr-xr-xtest/functional/p2p_leak.py6
-rwxr-xr-xtest/functional/p2p_segwit.py185
-rwxr-xr-xtest/functional/p2p_sendheaders.py112
-rwxr-xr-xtest/functional/p2p_timeouts.py18
-rwxr-xr-xtest/functional/rpc_blockchain.py1
-rwxr-xr-xtest/functional/rpc_deprecated.py5
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py20
-rwxr-xr-xtest/functional/rpc_getblockstats.py180
-rwxr-xr-xtest/functional/test_framework/mininode.py68
-rwxr-xr-xtest/functional/test_framework/test_framework.py22
-rwxr-xr-xtest/functional/test_framework/test_node.py41
-rw-r--r--test/functional/test_framework/util.py25
-rwxr-xr-xtest/functional/test_runner.py17
-rwxr-xr-xtest/functional/wallet_basic.py32
-rwxr-xr-xtest/functional/wallet_bumpfee.py2
-rwxr-xr-xtest/functional/wallet_dump.py6
-rwxr-xr-xtest/functional/wallet_hd.py40
-rwxr-xr-xtest/functional/wallet_import_rescan.py44
-rwxr-xr-xtest/functional/wallet_keypool.py8
-rwxr-xr-xtest/functional/wallet_keypool_topup.py2
-rwxr-xr-xtest/functional/wallet_labels.py81
-rwxr-xr-xtest/functional/wallet_listreceivedby.py19
-rwxr-xr-xtest/functional/wallet_listsinceblock.py1
-rwxr-xr-xtest/functional/wallet_listtransactions.py26
-rwxr-xr-xtest/functional/wallet_multiwallet.py93
-rwxr-xr-xtest/functional/wallet_txn_clone.py51
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py41
45 files changed, 1138 insertions, 459 deletions
diff --git a/test/functional/README.md b/test/functional/README.md
index 21050cc2fa..fdd7c339c5 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -20,6 +20,8 @@ don't have test cases for.
- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/)
- Use a python linter like flake8 before submitting PRs to catch common style
nits (eg trailing whitespace, unused imports, etc)
+- See [the python lint script](/test/lint/lint-python.sh) that checks for violations that
+ could lead to bugs and issues in the test code.
- Avoid wildcard imports where possible
- Use a module-level docstring to describe what the test is testing, and how it
is testing it.
diff --git a/test/functional/combine_logs.py b/test/functional/combine_logs.py
index d1bf9206b2..91b6415a7c 100755
--- a/test/functional/combine_logs.py
+++ b/test/functional/combine_logs.py
@@ -63,7 +63,7 @@ def get_log_events(source, logfile):
Log events may be split over multiple lines. We use the timestamp
regex match as the marker for a new log event."""
try:
- with open(logfile, 'r') as infile:
+ with open(logfile, 'r', encoding='utf-8') as infile:
event = ''
timestamp = ''
for line in infile:
diff --git a/test/functional/data/rpc_getblockstats.json b/test/functional/data/rpc_getblockstats.json
new file mode 100644
index 0000000000..750abc5c42
--- /dev/null
+++ b/test/functional/data/rpc_getblockstats.json
@@ -0,0 +1,204 @@
+{
+ "blocks": [
+ "0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",
+ "0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f1cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f194ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002014341131c18d3b3aa30056a0f7a97c9ac852d3fd0ec9c76f7a25e83c01e7f821bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601491a4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002078616da95299bd42cd8f813c8043816ec5741de466be3162e16bfff471808461f671e694afaf534d37df484f1990fc19a65fc26964b38141b7f8ecf61b8a50241a4ae75affff7f200500000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a08613f37d305835a3a1553e77a479eba0f34c06c52e429ece54f5973cd77a7086a1efcaf75f1cd5be2c9deb6a7850225757a2cfc3031a91cc1330b3af4acc891b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203b304fa1ce0505c2366982939ac148d9124c5ac747cc9aea133cea9916484966305de0e8d049f2be65c68d64d2c45746def5a9b4fcb8e298692b53b83b4690241b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fbdf49978ec4f0b23704b6772a614336872587e29c463f375836ffd775248837fed9f3fdfc33f076c6663ae78070fad7263c1e24161f3ee1a4857b8931815e2c1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020c37548b9ca256b9ff17187d4d4309cf3143845b0a5811d3ca5427b2fddf000731a10985dfd473561c070c3527c3fe3941834cf51b3dfbacb501b44c69c9745ce1b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020383dd3766c0675440f26370ad62d687e335ea3a650dec9b02fe544107cc1823a13b98696d41562945457d655f4c6921f736068f7a72afd1ad6b335f2857d16631c4ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207476dd96d81f53e63934ce28c9e89022e0f24d040ec3c838443e925fc3a2f230a94d0cbcefb4a151191dd7664153944d9eee3b7b46d4ba997f397ed2b72c3afe1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209e425c73eea16cce98c0d47d6070aca29f0524eab4b97af84c386aa5322dd43055002f097e929bc6ad88ce869968e1b049aab7f6e45a5b869cf4349afd5d43e01c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202090e16a514fad40386413a100bbaa4fc14086a8d3501ac64c91fdef922e834a369e409444d0ec496eb0dd9a47f1fe81a7ab974bab28c50a912b994acf13b5f91c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020777b767e42624c52775b331f19e81ba03be2f51a0608166cd5388c1a47d5e776473570bb9bba553a7db4a9a3083533027c54af1fea3ef6ef67757ef2255d64631c4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002076bb2bf3251a51ec367a42f8584043171a5d53157394cd776ebd017e2982127653d953aca3e2217f56533c043c07b9a926a30672ebce2562f1d06a6dc5044e7b1c4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020e6d7f02292655b73fc1f1958b09633ba07265d71d2a2784060b354cbbf1900202e9c9b02b63170002a94a0c9d8d787e2faa4c074a1ebdeb2855555347321dd101d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020d61f077b0ed326e17f0a3d5af3fa876b72b434a252c9c3248d20130ed744287fcb10da470222dd29c7a07e2da7eb25d6499ed3919676df89cc630bd1b23fbb411d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205efa9741cf51533ed6e07a97c71768372f53ca9c6df83894d64fe94c718eee23a207441e79ecdcf99ef3326385f5f675e2dea84c85ab8973219c63f92847ed5b1d4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020368386b0a0f46b2a2c4648eb9cb5dd1380c4f22e437e0bd49420670993361e5b9026632c2ddbb4b31b3c3118c51e43ea4d78e05c0aca0956278ead26a263d1521d4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401110101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dd0a1594bbff6345a3e34f326e5ee605c855f5e0a5c363fc39615a8b1539b736200b51297dbee4aadf9b536cd2afe7617651e0a1d0f0610f436518a2a4dc54621d4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401120101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020f302a1092709dc27a32d7229d391b90824a75828692c4bb2ca8f0ca5c88b3613c2e18797ffe8b367336338f90b2cf8c3f66277eb1e1ddbe18c052977294f10691d4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401130101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203dcc77aac703a8cd0e799384b74383c1d5f236426f77d516694607fc88fe85581276a20ceb98d02e6355c9dba4312e2fdc9832f4302cc307e1263f2df0aadd6a1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401140101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dfe109704a0b2801aee4232c31fb744145a7c80dd91a7727e16d4057719d5c3730f8296243521d82d96ed75c5af800a722fc9dde2e02af95c8c9822190ba07b21e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000201ef9ef2699bc36fd646bb9ba8629644bc98396122f6753710caf0315d7539f751382d3d85f17eb8b42cf17e54baa327886dcf6fa63207e097df8f9b84cc5422f1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401160101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020834c91f23cd91b727be08b892f1c1a2f33c1e66d66f35607925fa1be4bca2c25b4145a73b1c71b945f5bb9ede3d8d95c9a3b12a0a81b7b14f440ec5146dd4ec71e4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401170101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205743202bf1e543a9be2a59b62be6a5a494511fab96968007b8d7199ea60a524697227ba473ceaf48d4f48ee17f8ee6cd2f1f5ddff03a641642ece240e7872f8f1e4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401180101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207469f5c1841bf57275d82db23e5a8f0e8512af1eb10119c238519cdd6cdced34fd96dc659a874b3f5d30fbe6ea421a6b9791dfce8450f8851e4b90d80f0f794e1e4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401190101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020b6338f55fcc473b744d53d675b4a83dcd80ddec9d02ad3323cf1ff50ac0412239d986ec20885d772fdc67803273aaec43871426ac93d3815846a8cd13dea5af11f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a19d9edf2d22415cf226b4e1416c8a3097e0af222efac2bfeab15fa1f07b3f24c18580c4004de6d6244a30ce431c4be3ca44731509fc6b11710c792efed5e9191f4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000208f9f29a27424ec01ce77485617088506ca8faeef69300f0a474ad63ca5d32972d6049609fa3588d6ffab4d9d89a90636ac94c0ca1995f7768163abeb25dbf2bc1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fbd87d530a9ec3835ab579337fd16e512cec6c4779ab4d84e7256b3333dece28de1065c8c3d3d166e057139ac59af6f4f2c0d241b6269bbea6f61c5eff3dba431f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dc6ef4f436baab2d6880f242a2588313a2739ac694e30319344045ee318c9524d0ec7fbcaca30ce85392cb03b64015ece769afb50fd07db05c15ec49abf7d71c1f4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020386bf4cbb3708ae6345b9f2459bdd99d07422b05f9b005d2d4d1d3bf87d47359ebb22b3a15c8e94ddd8129527873b9bebfa10c54d11196961376efbcaad3c4681f4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020600e892f12ad82a23ce12684d3ffa0887eab5e3e97804fa651050b23366cc55ef2468e65c3d3cf49650657eb47d0b0b7949c71dcc0922eb824523157b7eff478204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401200101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002068e4aec52a3f4e44279e3a65cd476237bdfcc2328390bb31b8a903f89ddfa70e8d669f61b469acb31b1d4ecdc238e6616a83a30644a5d06fc2ca1aad6449d09b204ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401210101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020cf2428ae9a5014b910275807f54a8bbbeec47d462f9d284ada60329b4955ff10cf83c44ddde39a709aef54fb302c7f1cb36db8fe7c3befce20dcc3729767518c204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401220101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205801eef8cca082407ce4798648c4d3ba0fc4dd2d4459eccfe5300c7960760d16cb3dd78a2f22fb88717a175e45c53d34f970b94ef9f7cd1b6c279294d427d163204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401230101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002088320983a4bcb95b9f342994c6943c227f3102d3b16282f048ceb8e15748662a52d1207591a0a364bc9245a76e36530f147ec4d1b4e1917676b4071f542c3b19204ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401240101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020acd85b6d8087d3b6bd2a208a2e39b75da459c0e0eb14088075a23a2e043e8a4ed5a1754491f8180d293b42e6c04ec3f82e29c1f2600dc8607616f69a4a464e6e204ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401250101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204873bcb379f78da4497ce1e22f6bfb63537b89c8c522257a7b7bef74e515ed1b6b235faab048fa73a76c68fdbdde6a4ee7ebe0a3b7b23df24ce75dbd2cf49c33214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401260101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a87f6d13bae8e2e07996c3316e8e0da6aec7d1aee6b80aa5883018e4d136db3e9a498ff7d322ad93863e0a5318af7e7d0ed683fd2e4ecf523f2b7369106dbe4a214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401270101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020d9b0618450a51c08f43187c479e20d351f0466464409bb3071dc0af7c51d65498a198cef23dddd2c4b93d9d3288ae922584e221a9ef1ded3dba5a2ad494d9237214ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401280101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020167dff31847b8dcad472bb6bb7d0af53b245f0f1d4c9f83d4ce14a0f05d42d7f0f2638ffc0e6896230f28df1865ef133dccb1f027545c6a1177dffd1fecf8a01214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401290101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000208236c04424573692504e777e179b9247e54622b118239311413812f13cefbf6e39a639143f599dc76208b2014de12a364716df2918af9186453e3676dca743d7214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fab7b55aeb59f63315dbc10784c55e55635a7600cc4f3b94a00003007e7fc90b4af016248e9908882f8a7f0bd8743c8da82da119446e8b02e4d3b8d1d938a3aa214ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020794b4160d8fd4ebe7611d0fc9d3e04f3038a485669f74075aa153852ed181121c577f4c0b7151f6d78a16e3c21ab291b53ced8a5c4f05a22caf24a25ed029d56224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204a8acdb549d2ed922360ae0e81de6c913c3fd84b0de51abacbf97162a99f7c26c656b252d3259c33ffc7e5d403843accc6ace9b7e60e911e2347a6a0b0abd122224ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020dee6d00c7058b3422e4273c98c16181e04ea93116496a8442de546c2ee9fd86b550013f39e004b3829dc3717b17fcfedc87de9450315fcca540963119cb264c1224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202ebca471f5fb2226a790233c3d0bc323f73d935872f3e15b66bd5fdcb822101d7b68788ed61d3fb8cb746f627e09db2fc09d8a07672747709d92ae400e053e78224ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ee500470fc1c71a82f2cbb9f8d5723bcdf57b8051fc458a8dbd8d0dbf60d0e40d1a0be0e50f3312d4830e3900186e5a6760d44006c164b4f0758218ef2b2de8e224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401300101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205057e8d8a7451d79325851dc8e0f4dfdb1dfaaab637509d9e61f0e064af5ee5c185221c53c0cf43261b3c238c0e8117da5d6ac60085615f7a3d8027726cb2143224ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401310101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000200907f01d9c5c872296796ca77feb62eb414cc080e13a93e59e181528bc19c336eaabacb1ebcbd20b26f6bacdc712ffe17d4c8131e7f99b9cac309c0683737c04234ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401320101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209bd6a4ec962d9e6199c0a2f39481a7ecc322fedbd2320cbe7dc984c6ab958421fe7a5c7f2513a3c3de9ddf7b211f5bfe85675b31183c4bb98ae79ab28cd055ac234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401330101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202b8a6381b7c9476fd77be379a929863db6b7edd9858d6eca0f68a430dc87cc3a9c6c8b34bfadfdacbe95cb1d4ae5ce4e4f4ccf0300171d7a91cdc97f620c7b37234ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401340101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203d3e9a0b4decf12b4402a2178b60599311c8a9c7d50ece365a61ca29530da7056754ddf7d77a11cc8ce680a74fae01d851bda024fc9c51712c55b4a190caef24234ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401350101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002067fa05082d4f7a29a3985f30798940cd854c76a2b20e9560b2047f7753193f71ac61b8df17a8a63f099c8f55869301fc2a0aa37355a4a2f89078135ee72a1362234ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401360101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020249684272865fec3ad62ecb73dfd930500e32e475306c9e5d4b6d545e3687b0a48deaeebfafa213f0a560994b3f4000d5e2b93951d7e5be40073503877292dc7234ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401370101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204671db1df91098669bb03c3e8504d432da99853601366c7de7585bb8f23a6e1e2996a16c11a0f9ae87d937f566c8bbd919040528c1bf8dae4e22a8f0ac5f935a244ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401380101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203046500cabfee552ed114c505279cd75c28faa811adcb5010c53c14df5de3216d265321a4168c70fff1c85fd83bd976cc03c8c1fb6567398cc24053e343ad137244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401390101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020591533cf8dd1fa1872c7e6d62ef714b28886f38f7921ee614e13b748eaf923282a96287277f18b1113a9c3ac384fd7b43bccd0e45114908ca5396a76cbd736fd244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205286b5747d0244a55e1dce435fdbb9f300d7138fff3b16767bc09196eb00256c6795e3f372a2d5d137244a4fd72fd799e8de913f868f22269eaa628d7d2970a1244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000209649b55f6a5ff0d5db73aeb7089fcce605fb9dd23971e577b73747ffab586f4edf84581240223e2d8912a6eca049e06aa46ddbf271af08e9ac9605505311418b244ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fe7ff82c11ad3a3db3dc11a03a67e0b86b727d232c80f37209b028bc2689296c0da76fb756e1c9833f38b198cfe843ab820fbc0c38e30f8f858f6ffdbd64e834244ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020c02e6109b6aaf6643cac109ad5b5be7f7ec47c7993335bdceea6e0e490ae9067eb1fcee49ecc40a61477f934e3b9821f2cc7ada429fcca2cd645866742854c40254ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020956c46fce0adfc8a30d91c7b7f328f17c2a90771083884c4fdb7f24640598f6fa69c4e5971bd3b6cdc7e3ee98e03a969b28c3220fdc685cc2eb77293763ca4ba254ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203eec7d0ea9c539f47e684eec9dba900e27c805b8200f237924c7df8065957726c83caf659fa341bf45f733a92cf76daf2cfb6bccbf969a2753f5f7d9cda4bd1e254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401400101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000203c022b42283bf651ee4d536fe71b7e5382e9783d4a85f8bc159f00b97f16d82d312ac4f89f1b1496de576811f2ff17de44b512db0beddae59e030e2ce3eba4df254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401410101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205da9709dea4bea4f3229d0eed439a4820a0e817f9fbbcd8bb355cd8052702973403358080a2881b823a740f58b6b0c922b42189e06326478cc33390f2c704743254ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401420101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020447c49f664916cc13a839e27f7cbe0b09dea990dec71dd479b537ecfb771c7159ae6241727c2645ce00817909ba97d43447fe2e146bce55b7dccd5bcd27d2e3d254ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401430101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ae3b214b1495953eea3b99af7ade4b8d22d615d598dd6c790c6576d6453ef35d37fbd3446f8431f00052f278c3e0359beba54a2f5064bc6be4990478fcf4e086264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401440101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204cc68f9f571f59145e1f7505550d56da13a797fbc7e5a178dd7f6f9241d91f007f2400f7aa1b32b30bf869e4da86f75eaf2baae182efc45c42c6245f06aba675264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401450101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002096d55714a83c3d030cc72141eac3577b8a394b8366b2c93354fcecdafeab025022f5e26de7e4eba3f8e4a09f243b55ea6f08bfd013e2051cf1d5df20dcb3331b264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401460101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202ccf49665bd46e4915dcc9221f5fc72124bb73fb11fed8869dc5862a47950c0d654693a1d86098212d68fa9a27f9df0faafea4aecebd8b203f2ab8f3f0b86196264ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401470101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000205d0be5aea546eab7734cbee757ea5f4983ab3a3f202323c1c88590bdbc8b561974cb0de6549bfdec92322ad53d8a4192433edab0e33a10e7561d2e27c7759f8a264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401480101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020fc3d70d4f690d7d7da90b1c832a51c2a92940cdd9fccda6a909c7256ad567160550e1089b48fe75f0f1e6f712cc2a1d4aad384a4ceacf1c71576420fe8e7de46264ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401490101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020995ab1f2293e3aa1e7bef418919bdce60032e89e60223b8c12b17488c50af83b3a360b4f89551aa0ced646a6210b0c3d3f7d0464faa248b9d252c89615babc9f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020e02dd5e1201ebe7ef453e77df3021cffde1b5447b9eced017963489e005ac247e1f2b80e91180cd9744c3e126eb8a0fb34ced45587da6b0fa9fd1c6946f049bf274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002081b265800d61feb37525c58aacc7e6d32cfc6b6579784f9952dca51c3addeb37da900ae4ec1b2075056001a361c0fc8f9ac1ca018bde2a2bd8fc587424dfe18f274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000207daba0dc6fccc067a19dec46770d1443fc715b50540242ff26073a6748bcd9583804c315b783d4f9aac4dc8f109fa60bcbf1c3cf98a7e1e593fcb969e88aafae274ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204a35ab2d9c4656c4992d2445ee566e4f5cd0468358292c94839de2b270ba0628de9148db03da59ca2eb727a4f7a03f2b9ee1e4045f37bdaa4b75a89de56b63ee274ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020215ed7b31d118a45a06407133e41f3f9d25c913ff98f3e798144f981d9145305266efc9274f7c836aa0f8b831732aec2c1d85c5bb9176af4c889a707cca380fc274ae75affff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020425321a1f12ed4613b63b3cc5b4c7674242c3de67ea86984f2d9bb2766f6220a5c460ce6840832b7ef05f206c5d255bc2d8ea83753a7f5ef5c0bf3dbcbc7c74a284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401500101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204e088cfd312091bf589f0fc24131dba20ed83f716530a7b033356e9ec803be23a73c4af5b64fc631d20aa1f646c7c61c4cc5d4be6e2fa29570030d72219726a0284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401510101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204287a2bf40300e39b45d6667d6e17abba37d98c41efc7023fd21b643fb2f6b76d915d10e1f9e224d3bfdf5203da57173f0b8d8eedc92ed9ff23372927e86073b284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401520101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002083137929ca902f409a1f35385b4d31e0f5163d488d71b00ade724d7831986a280a187c13fe0db45aed5fa4f5089d544a617da9f4f80fe6ce1d0711b228f3a6bd284ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401530101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020b38c074d78cbcc8bbbf20c48e30639c2dcf444488efee59f5aa01c48322a30418009c11df7e14de6a6d0d72cc22f20ff5fdba3a7dbe409409ff92b1302340fb8284ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401540101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020a6865148220c7f5ac3259f57fa381676d6be5fdab56eed8e060808fcce4118492476fe6d5ecc681e7a18c20a04239143de1c2cddefbb08f15153b8e9b0c22f62284ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401550101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ae146263f4087106b8c51ffb5cdddb03a4e593ea1a22a8f6580eaa374185126db2187dbe694a1b17b7c5664115307965407274c25bf6ae02049817685f923256294ae75affff7f200600000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401560101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020718abe22705f33134812b56d04c129d453da890e27caf6e77d2bfb3f9be460083634f35fc8ea4a29b0f30d6c6b4926455a31de62d2f763bc95c8cd1a7a425599294ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401570101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002084537c50520f4e6b0173926320c3193f6b4259c9a724fe202337d3d5cf7da70b1104e1d6f25c411165a856a0bfdd5ddbe168238425c05271962aa6e5ebb676fb294ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401580101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204bae65b948c9790468cfc8fbf78a81e7aec5407dbab18c18ef1ab37a13f0c257792cd1246dac5ce265a8439e539db1aebe4776535d422315bac8e57a51605aa6294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401590101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000201e68985b2a15920524c3c2da77354c0ccfb202c3ab4005128eb2743aa33f0a5b0527a624a6d1f808c896d8cd1552c251a4ae5310e6c62493977b0965d17f580d294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015a0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ab1d90854505caa1ee748c1987f4cb6674844b84d17224bc3983fdd6e44a930b2edf3e5a90be7a9080ad15014ce796b38b6c19ddd3754443243fc277bcd2368a294ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015b0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002062242f316efa083c17e2173d9f9831afc1465f3fe84431d8e52fec71ae358b243e29246e0db770708987f2cff380920321636926d9c66c2c808d2d5f0ed27d672a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015c0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020258c1a9b0ca17819d8d7fea5178e9c72c2e7c6769696f70098e0d5d2a9dc0e5cf039f5f686d727c6158ef5405ee8794ec2f89c641093a1dff0f5240263a441bc2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015d0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020434ce26cddae99571a1d663419d715f88e6ff0e413c45f21c44b1991d041fd2745534db221054e2233052aaffe7d7232a91b3f0918c14eac74b2f704b37bfb8e2a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015e0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ec94475f112ea37dddd84f066e61446b431d28d2d9b6fbb336d16295e7eece52f1dc01abb3b27e71d8a25c3ed2d6fbbc5900bf954738ed63d57689ba5e68f6532a4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015f0101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000206188cca18a2be3b7f0b500a724f1b73312873488f04c5082abd81ca0b2250a75ec0efb2fa994ad23e1f39416e69976e66fc4ef9f101bd4f60fcee1f8c45a2b802a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401600101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000202384b91bd0bfb1385ef42bda9b2fa43930aa8889214bb14f63c61a74f380dc7f9d547f2925ad39b9161fa55b9cd258463fd058234778a7c7b3061113d64179812a4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401610101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204c266a3008c3bd95ae4bc8228bf878595cabf76cc2ef3fed32936777fe37833a1a13ea016868b2352a8d6d1eb35d0aee784cef06ed50655b8d84c089324351df2b4ae75affff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401620101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "00000020ab2c78d1249de8482cf26bfb1616ac04f7b8404eafcae3e0654f398943fd41571b4d7549862be0b06ed1408ddc3e7c01b07af24c203a18fe9744e214b14d2d652b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0000002031aa0fc5e0242a9c9d91024b6b7e67544da72c4773537f881ee5caacd45a3c38c650ff5fa0ffd080b3e5f9752527b718e8c6b731467028e14b0b009d4e7406ee2b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000200418c57609fc6ea3f24f569dc3afe163538a6aab940fe8c3d73c72cd781221380482c6f8ef2c19429da2f7a842bb811496aa86247c55f7ecb3337718b694d9472b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a01000000232103836d350d84c3782a7579c5f542c7e70fe628d3062c6bac563d2264c21e56f70eac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
+ "000000204f36abaf10d6a8b3113103f3413475db0640c89a39f02a718e8bd2190fe87f1d6ffaf2b9fdbed67ebae4b36c97f9582814c99c90d0b5123f14da4861bf3e4f742b4ae75affff7f200100000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff02b000062a01000000232102f6869601b2b9980b07fc047e309c1fc1433e08c5bf0498115c5c0e117ef59bfdac0000000000000000266a24aa21a9ed5896cd6a40cd126b09e317cbd179f39e2bcef2f9d423751d980258396416e671012000000000000000000000000000000000000000000000000000000000000000000000000002000000011cd16b94f20a8a3dda91027c888025f2ec1a07ddcb2786bdff5916e66c00406f0000000048473044022046d00465c4508cfd02fcb878b19d120e28be28e40658b1f15458828891ed1541022036aac054f36a42666dfb7b42a20506315a0b72232ce7704406e23c7a9515178701feffffff0200286bee0000000017a91481ddd4a9708ba8088cdcfeab9583ede8d83a298c8750bb9a3b0000000017a91484e16967722289584257803688aae36cd64480688765000000",
+ "00000020cc7c39992f2dae21e0ebd958f6ba77a6d0bcc568e044b9b61ca4d77536a4214e7b4ade79dd733ea72d97993aaac27f2263b91b1500467350ff35ea40c2850d392b4ae75affff7f200100000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff0230d0062a01000000232102f58ba54b2d51c4e2a6096f9d266261b45f1026a86ba88c29ed8070dfe3f5ec6bac0000000000000000266a24aa21a9edb824d92cb231c2366f0726aedf8bfc2705239a40ae6b10a106534e8b5395a09d01200000000000000000000000000000000000000000000000000000000000000000000000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab8001000000171600144f8a6c8d4c6c309b1e2b725b7496859e172ea367feffffff02781ef5050000000017a9149f00bafb542049fe32d532b0ea7494ebb7ae41398750daa4350000000017a9147794e6dc43de332ca7a095e582478c331446686d8702483045022100bd85ed3954f1151c2fde32c4021a32c96d7defa4a57c14b1a056be9b361a8e49022054947bf6fdb535c46cbee62efc1262cc0389a6eaa19afbcfa98fb1fb30c3ef230121031b2371df07fb88dddf590b246dc74defc265fdbfe258e4b168250859b806f5ce660000000200000001bf83574fb606f25c59200c844443201faf923ef5284fd4401f3104a323c601490000000049483045022100d1c4b09b488f6375ee4540a531a13b5549e88e2459bd88c84867e293c54862740220222e8af70c8d8b1139c2a7b616d9132bde94244edca7eee3c7a783b12839dadc01feffffff0250196bee0000000017a91490e5e33cfedf18d5cf911d6f853770c62e1f5d028700ca9a3b0000000017a91422311ee58518edf3a2289012461dc66bc8739d2687660000000200000000010196bac2a0f6212b8e5710f8c7214dd32c393d38d20b7703cf0b7b25276bb6ab800000000017160014b81faaafa52f7723f539f8d595147b1a112b38ecfeffffff0208bd9a3b0000000017a9146b2e611708a94d9c674dd08c7c4c1fbb97bcdba987005ed0b20000000017a914933a20f07bab1d8f341f391819466a271f0cfd648702483045022100dfa8b0052c7825e6abcea05d10fc82550a8d6538681ffc8188d48ba789e4d9b40220697371cdf527a6ecd1887f87da3c87dca3419e4a1aa2683e5c4e035199084d100121021cc37c2ec090f30ea0b49508ae8a7d65d9759903932666da56671c1faa445d5d53000000"
+ ],
+ "mocktime": 1525107225,
+ "stats": [
+ {
+ "avgfee": 0,
+ "avgfeerate": 0,
+ "avgtxsize": 0,
+ "blockhash": "1d7fe80f19d28b8e712af0399ac84006db753441f3033111b3a8d610afab364f",
+ "height": 101,
+ "ins": 0,
+ "maxfee": 0,
+ "maxfeerate": 0,
+ "maxtxsize": 0,
+ "medianfee": 0,
+ "medianfeerate": 0,
+ "mediantime": 1525107242,
+ "mediantxsize": 0,
+ "minfee": 0,
+ "minfeerate": 0,
+ "mintxsize": 0,
+ "outs": 2,
+ "subsidy": 5000000000,
+ "swtotal_size": 0,
+ "swtotal_weight": 0,
+ "swtxs": 0,
+ "time": 1525107243,
+ "total_out": 0,
+ "total_size": 0,
+ "total_weight": 0,
+ "totalfee": 0,
+ "txs": 1,
+ "utxo_increase": 2,
+ "utxo_size_inc": 173
+ },
+ {
+ "avgfee": 3760,
+ "avgfeerate": 20,
+ "avgtxsize": 187,
+ "blockhash": "4e21a43675d7a41cb6b944e068c5bcd0a677baf658d9ebe021ae2d2f99397ccc",
+ "height": 102,
+ "ins": 1,
+ "maxfee": 3760,
+ "maxfeerate": 20,
+ "maxtxsize": 187,
+ "medianfee": 3760,
+ "medianfeerate": 20,
+ "mediantime": 1525107242,
+ "mediantxsize": 187,
+ "minfee": 3760,
+ "minfeerate": 20,
+ "mintxsize": 187,
+ "outs": 4,
+ "subsidy": 5000000000,
+ "swtotal_size": 0,
+ "swtotal_weight": 0,
+ "swtxs": 0,
+ "time": 1525107243,
+ "total_out": 4999996240,
+ "total_size": 187,
+ "total_weight": 748,
+ "totalfee": 3760,
+ "txs": 2,
+ "utxo_increase": 3,
+ "utxo_size_inc": 234
+ },
+ {
+ "avgfee": 18960,
+ "avgfeerate": 109,
+ "avgtxsize": 228,
+ "blockhash": "22d9b8b9c2a37c81515f3fc84f7241f6c07dbcea85ef16b00bcc33ae400a030f",
+ "height": 103,
+ "ins": 3,
+ "maxfee": 49800,
+ "maxfeerate": 300,
+ "maxtxsize": 248,
+ "medianfee": 3760,
+ "medianfeerate": 20,
+ "mediantime": 1525107243,
+ "mediantxsize": 248,
+ "minfee": 3320,
+ "minfeerate": 20,
+ "mintxsize": 188,
+ "outs": 8,
+ "subsidy": 5000000000,
+ "swtotal_size": 496,
+ "swtotal_weight": 1324,
+ "swtxs": 2,
+ "time": 1525107243,
+ "total_out": 9999939360,
+ "total_size": 684,
+ "total_weight": 2076,
+ "totalfee": 56880,
+ "txs": 4,
+ "utxo_increase": 5,
+ "utxo_size_inc": 380
+ }
+ ]
+} \ No newline at end of file
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 5a09142412..a925c70783 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -68,12 +68,12 @@ class AssumeValidTest(BitcoinTestFramework):
def send_blocks_until_disconnected(self, p2p_conn):
"""Keep sending blocks to the node until we're disconnected."""
for i in range(len(self.blocks)):
- if p2p_conn.state != "connected":
+ if not p2p_conn.is_connected:
break
try:
p2p_conn.send_message(msg_block(self.blocks[i]))
except IOError as e:
- assert str(e) == 'Not connected, no pushbuf'
+ assert not p2p_conn.is_connected
break
def assert_blockchain_height(self, node, height):
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index eee38ce648..d8521550b5 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -67,7 +67,7 @@ class BIP68Test(BitcoinTestFramework):
# If sequence locks were used, this would require 1 block for the
# input to mature.
sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
- tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
+ tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
tx1.vout = [CTxOut(value, CScript([b'a']))]
tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))["hex"]
@@ -80,7 +80,7 @@ class BIP68Test(BitcoinTestFramework):
tx2.nVersion = 2
sequence_value = sequence_value & 0x7fffffff
tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
- tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))]
+ tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a' * 35]))]
tx2.rehash()
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2))
@@ -222,7 +222,7 @@ class BIP68Test(BitcoinTestFramework):
tx = CTransaction()
tx.nVersion = 2
tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
- tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))]
+ tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a' * 35]))]
tx.rehash()
if (orig_tx.hash in node.getrawmempool()):
@@ -350,7 +350,7 @@ class BIP68Test(BitcoinTestFramework):
tx3 = CTransaction()
tx3.nVersion = 2
tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
- tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
+ tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a' * 35]))]
tx3.rehash()
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3))
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 17d3ddae4a..f943fdf176 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -32,6 +32,7 @@ from test_framework.script import (
OP_ELSE,
OP_ENDIF,
OP_EQUAL,
+ OP_DROP,
OP_FALSE,
OP_HASH160,
OP_IF,
@@ -1215,7 +1216,7 @@ class FullBlockTest(BitcoinTestFramework):
block.vtx.extend(tx_list)
# this is a little handier to use than the version in blocktools.py
- def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE])):
+ def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])):
return create_transaction(spend_tx, n, b"", value, script)
# sign a transaction, using the key we know about
diff --git a/test/functional/feature_help.py b/test/functional/feature_help.py
index fd4a72f628..d38275a9ca 100755
--- a/test/functional/feature_help.py
+++ b/test/functional/feature_help.py
@@ -36,6 +36,17 @@ class HelpTest(BitcoinTestFramework):
output = self.nodes[0].process.stdout.read()
assert b'version' in output
self.log.info("Version text received: {} (...)".format(output[0:60]))
+
+ # Test that arguments not in the help results in an error
+ self.log.info("Start bitcoind with -fakearg to make sure it does not start")
+ self.nodes[0].start(extra_args=['-fakearg'], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+ # Node should exit immediately and output an error to stderr
+ ret_code = self.nodes[0].process.wait(timeout=1)
+ assert_equal(ret_code, 1)
+ output = self.nodes[0].process.stderr.read()
+ assert b'Error parsing command line arguments' in output
+ self.log.info("Error message received: {} (...)".format(output[0:60]))
+
# Clean up TestNode state
self.nodes[0].running = False
self.nodes[0].process = None
diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py
new file mode 100755
index 0000000000..9a7a0ca103
--- /dev/null
+++ b/test/functional/feature_includeconf.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Tests the includeconf argument
+
+Verify that:
+
+1. adding includeconf to the configuration file causes the includeconf
+ file to be loaded in the correct order.
+2. includeconf cannot be used as a command line argument.
+3. includeconf cannot be used recursively (ie includeconf can only
+ be used from the base config file).
+4. multiple includeconf arguments can be specified in the main config
+ file.
+"""
+import os
+
+from test_framework.test_framework import BitcoinTestFramework
+
+class IncludeConfTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def setup_chain(self):
+ super().setup_chain()
+ # Create additional config files
+ # - tmpdir/node0/relative.conf
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ f.write("uacomment=relative\n")
+ # - tmpdir/node0/relative2.conf
+ with open(os.path.join(self.options.tmpdir, "node0", "relative2.conf"), "w", encoding="utf8") as f:
+ f.write("uacomment=relative2\n")
+ with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
+ f.write("uacomment=main\nincludeconf=relative.conf\n")
+
+ def run_test(self):
+ self.log.info("-includeconf works from config file. subversion should end with 'main; relative)/'")
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative)/")
+
+ self.log.info("-includeconf cannot be used as command-line arg")
+ self.stop_node(0)
+ self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf")
+
+ self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f:
+ f.write("includeconf=relative2.conf\n")
+ self.start_node(0)
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative)/")
+ self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf")
+
+ self.log.info("-includeconf cannot contain invalid arg")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ f.write("foo=bar\n")
+ self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Invalid configuration value foo")
+
+ self.log.info("-includeconf cannot be invalid path")
+ os.remove(os.path.join(self.options.tmpdir, "node0", "relative.conf"))
+ self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Failed to include configuration file relative.conf")
+
+ self.log.info("multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ # Restore initial file contents
+ f.write("uacomment=relative\n")
+
+ with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
+ f.write("includeconf=relative2.conf\n")
+
+ self.start_node(0)
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative; relative2)/")
+
+if __name__ == '__main__':
+ IncludeConfTest().main()
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 072ba6c7c7..0946f27b90 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -100,7 +100,7 @@ class MaxUploadTest(BitcoinTestFramework):
assert_equal(p2p_conns[0].block_receive_map[big_old_block], i+1)
assert_equal(len(self.nodes[0].getpeerinfo()), 3)
- # At most a couple more tries should succeed (depending on how long
+ # At most a couple more tries should succeed (depending on how long
# the test has been running so far).
for i in range(3):
p2p_conns[0].send_message(getdata_request)
diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py
index 8964c8d64b..6d51f31e35 100755
--- a/test/functional/feature_notifications.py
+++ b/test/functional/feature_notifications.py
@@ -36,7 +36,7 @@ class NotificationsTest(BitcoinTestFramework):
wait_until(lambda: os.path.isfile(self.block_filename) and os.stat(self.block_filename).st_size >= (block_count * 65), timeout=10)
# file content should equal the generated blocks hashes
- with open(self.block_filename, 'r') as f:
+ with open(self.block_filename, 'r', encoding="utf-8") as f:
assert_equal(sorted(blocks), sorted(l.strip() for l in f.read().splitlines()))
self.log.info("test -walletnotify")
@@ -45,7 +45,7 @@ class NotificationsTest(BitcoinTestFramework):
# file content should equal the generated transaction hashes
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
- with open(self.tx_filename, 'r') as f:
+ with open(self.tx_filename, 'r', encoding="ascii") as f:
assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
os.remove(self.tx_filename)
@@ -58,7 +58,7 @@ class NotificationsTest(BitcoinTestFramework):
# file content should equal the generated transaction hashes
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
- with open(self.tx_filename, 'r') as f:
+ with open(self.tx_filename, 'r', encoding="ascii") as f:
assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
# Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
diff --git a/test/functional/feature_nulldummy.py b/test/functional/feature_nulldummy.py
index 7db6a03b45..6577d83f5c 100755
--- a/test/functional/feature_nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -42,7 +42,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
# normal segwit activation here (and don't use the default always-on behaviour).
- self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]]
+ self.extra_args = [['-whitelist=127.0.0.1', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]]
def run_test(self):
self.address = self.nodes[0].getnewaddress()
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index 60859de7a5..2d10c547e2 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -79,9 +79,9 @@ class ProxyTest(BitcoinTestFramework):
# Note: proxies are not used to connect to local nodes
# this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost
args = [
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
- ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
+ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
+ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
+ ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
[]
]
if self.have_ipv6:
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index 11a52b9ee2..d400507a66 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -260,10 +260,17 @@ class PruneTest(BitcoinTestFramework):
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
assert_raises_rpc_error(-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500))
+ # Save block transaction count before pruning, assert value
+ block1_details = node.getblock(node.getblockhash(1))
+ assert_equal(block1_details["nTx"], len(block1_details["tx"]))
+
# mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight)
node.generate(6)
assert_equal(node.getblockchaininfo()["blocks"], 1001)
+ # Pruned block should still know the number of transactions
+ assert_equal(node.getblockheader(node.getblockhash(1))["nTx"], block1_details["nTx"])
+
# negative heights should raise an exception
assert_raises_rpc_error(-8, "Negative", node.pruneblockchain, -10)
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index d6ab5ecc37..c087960782 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -123,7 +123,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -132,7 +132,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Should fail because we haven't changed the fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
+ tx1b.vout = [CTxOut(1 * COIN, CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# This will raise an exception due to insufficient fee
@@ -143,7 +143,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Extra 0.1 BTC fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# Replacement still disabled even with "enough fee"
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
@@ -175,7 +175,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
remaining_value -= 1*COIN
tx = CTransaction()
tx.vin = [CTxIn(prevout, nSequence=0)]
- tx.vout = [CTxOut(remaining_value, CScript([1]))]
+ tx.vout = [CTxOut(remaining_value, CScript([1, OP_DROP] * 15 + [1]))]
tx_hex = txToHex(tx)
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
chain_txids.append(txid)
@@ -185,7 +185,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# child fees - 40 BTC - so this attempt is rejected.
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception due to insufficient fee
@@ -194,7 +194,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Accepted with sufficient fee
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(1 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
@@ -247,7 +247,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Attempt double-spend, will fail because too little fee paid
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - fee * n, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception due to insufficient fee
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
@@ -255,7 +255,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# 1 BTC fee is enough
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
@@ -275,7 +275,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
@@ -290,7 +290,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -311,7 +311,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
- tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
+ tx1a.vout = [CTxOut(int(1.1 * COIN), CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -330,7 +330,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Spend tx1a's output to test the indirect case.
tx1b = CTransaction()
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1b.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1b_hex = txToHex(tx1b)
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
tx1b_txid = int(tx1b_txid, 16)
@@ -351,7 +351,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1 = CTransaction()
tx1.vin = [CTxIn(confirmed_utxo)]
- tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1_hex = txToHex(tx1)
self.nodes[0].sendrawtransaction(tx1_hex, True)
@@ -390,7 +390,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
for i in range(MAX_REPLACEMENT_LIMIT+1):
tx_i = CTransaction()
tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
- tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
+ tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))]
tx_i_hex = txToHex(tx_i)
self.nodes[0].sendrawtransaction(tx_i_hex, True)
@@ -423,14 +423,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Create a non-opting in transaction
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
# Shouldn't be able to double-spend
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# This will raise an exception
@@ -441,14 +441,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Create a different non-opting in transaction
tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
- tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx2a_hex = txToHex(tx2a)
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
# Still shouldn't be able to double-spend
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx2b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx2b_hex = txToHex(tx2b)
# This will raise an exception
@@ -471,12 +471,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx3b = CTransaction()
tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
+ tx3b.vout = [CTxOut(int(0.5 * COIN), CScript([b'e' * 35]))]
tx3b_hex = txToHex(tx3b)
tx3c = CTransaction()
tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
- tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
+ tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f' * 35]))]
tx3c_hex = txToHex(tx3c)
self.nodes[0].sendrawtransaction(tx3b_hex, True)
@@ -493,7 +493,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -519,14 +519,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx2a_hex = txToHex(tx2a)
self.nodes[0].sendrawtransaction(tx2a_hex, True)
# Lower fee, but we'll prioritise it
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
+ tx2b.vout = [CTxOut(int(1.01 * COIN), CScript([b'a' * 35]))]
tx2b.rehash()
tx2b_hex = txToHex(tx2b)
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index a47c42829a..b10306b283 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -16,7 +16,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex
from test_framework.address import script_to_p2sh, key_to_p2pkh
-from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE
+from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE, OP_DROP
from io import BytesIO
NODE_0 = 0
@@ -42,9 +42,9 @@ class SegWitTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
- self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
- ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
- ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]]
+ self.extra_args = [["-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
+ ["-blockversion=4", "-promiscuousmempoolflags=517", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
+ ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]]
def setup_network(self):
super().setup_network()
@@ -129,21 +129,6 @@ class SegWitTest(BitcoinTestFramework):
self.nodes[0].generate(260) #block 423
sync_blocks(self.nodes)
- self.log.info("Verify default node can't accept any witness format txs before fork")
- # unsigned, no scriptsig
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False)
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False)
- # unsigned with redeem script
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0]))
- self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0]))
- # signed
- self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V0][0], True)
- self.fail_accept(self.nodes[0], "no-witness-yet", wit_ids[NODE_0][WIT_V1][0], True)
- self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V0][0], True)
- self.fail_accept(self.nodes[0], "no-witness-yet", p2sh_ids[NODE_0][WIT_V1][0], True)
-
self.log.info("Verify witness txs are skipped for mining before the fork")
self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][0], True) #block 424
self.skip_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][0], True) #block 425
@@ -164,6 +149,16 @@ class SegWitTest(BitcoinTestFramework):
segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
assert_equal(len(segwit_tx_list), 5)
+ self.log.info("Verify default node can't accept txs with missing witness")
+ # unsigned, no scriptsig
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V0][0], False)
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", wit_ids[NODE_0][WIT_V1][0], False)
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False)
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False)
+ # unsigned with redeem script
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V0][0], False, witness_script(False, self.pubkey[0]))
+ self.fail_accept(self.nodes[0], "mandatory-script-verify-flag", p2sh_ids[NODE_0][WIT_V1][0], False, witness_script(True, self.pubkey[0]))
+
self.log.info("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag")
assert(self.nodes[2].getblock(block[0], False) != self.nodes[0].getblock(block[0], False))
assert(self.nodes[1].getblock(block[0], False) == self.nodes[2].getblock(block[0], False))
@@ -212,7 +207,7 @@ class SegWitTest(BitcoinTestFramework):
# Now create tx2, which will spend from txid1.
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b''))
- tx.vout.append(CTxOut(int(49.99*COIN), CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex']
txid2 = self.nodes[0].sendrawtransaction(tx2_hex)
tx = FromHex(CTransaction(), tx2_hex)
@@ -221,7 +216,7 @@ class SegWitTest(BitcoinTestFramework):
# Now create tx3, which will spend from txid2
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b""))
- tx.vout.append(CTxOut(int(49.95*COIN), CScript([OP_TRUE]))) # Huge fee
+ tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee
tx.calc_sha256()
txid3 = self.nodes[0].sendrawtransaction(ToHex(tx))
assert(tx.wit.is_null())
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 1657d97281..37849e9213 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -12,7 +12,8 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
-from test_framework.script import CScript, OP_TRUE
+from test_framework.script import CScript, OP_TRUE, OP_DROP
+
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses.
class TestP2PConn(P2PInterface):
@@ -86,7 +87,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)
- wait_until(lambda: self.state != "connected", timeout=timeout, lock=mininode_lock)
+ wait_until(lambda: not self.is_connected, timeout=timeout, lock=mininode_lock)
class CompactBlocksTest(BitcoinTestFramework):
def set_test_params(self):
@@ -423,7 +424,7 @@ class CompactBlocksTest(BitcoinTestFramework):
for i in range(num_transactions):
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(utxo[0], utxo[1]), b''))
- tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.rehash()
utxo = [tx.sha256, 0, tx.vout[0].nValue]
block.vtx.append(tx)
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index 7c954cdca2..c304bbba85 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -69,7 +69,7 @@ class FeeFilterTest(BitcoinTestFramework):
# Change tx fee rate to 10 sat/byte and test they are no longer received
node1.settxfee(Decimal("0.00010000"))
[node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
- sync_mempools(self.nodes) # must be sure node 0 has received all txs
+ sync_mempools(self.nodes) # must be sure node 0 has received all txs
# Send one transaction from node0 that should be received, so that we
# we can sync the test on receipt (if node1's txs were relayed, they'd
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 8a0961be1f..3fed872ccc 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -70,7 +70,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
# Transaction will be rejected with code 16 (REJECT_INVALID)
# and we get disconnected immediately
self.log.info('Test a transaction that is rejected')
- tx1 = create_transaction(block1.vtx[0], 0, b'\x64', 50 * COIN - 12000)
+ tx1 = create_transaction(block1.vtx[0], 0, b'\x64' * 35, 50 * COIN - 12000)
node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
# Make two p2p connections to provide the node with orphans
@@ -79,34 +79,35 @@ class InvalidTxRequestTest(BitcoinTestFramework):
self.reconnect_p2p(num_connections=2)
self.log.info('Test orphan transaction handling ... ')
- # Create a root transaction that we withold until all dependend transactions
+ # Create a root transaction that we withhold until all dependend transactions
# are sent out and in the orphan cache
+ SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
tx_withhold = CTransaction()
tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
- tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=b'\x51'))
+ tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
tx_withhold.calc_sha256()
# Our first orphan tx with some outputs to create further orphan txs
tx_orphan_1 = CTransaction()
tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
- tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51')] * 3
+ tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
tx_orphan_1.calc_sha256()
# A valid transaction with low fee
tx_orphan_2_no_fee = CTransaction()
tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
- tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=b'\x51'))
+ tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
# A valid transaction with sufficient fee
tx_orphan_2_valid = CTransaction()
tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
- tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=b'\x51'))
+ tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
tx_orphan_2_valid.calc_sha256()
# An invalid transaction with negative fee
tx_orphan_2_invalid = CTransaction()
tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
- tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=b'\x51'))
+ tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
self.log.info('Send the orphans ... ')
# Send valid orphan txs from p2ps[0]
@@ -136,6 +137,13 @@ class InvalidTxRequestTest(BitcoinTestFramework):
wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
assert_equal(expected_mempool, set(node.getrawmempool()))
+ # restart node with sending BIP61 messages disabled, check that it disconnects without sending the reject message
+ self.log.info('Test a transaction that is rejected, with BIP61 disabled')
+ self.restart_node(0, ['-enablebip61=0','-persistmempool=0'])
+ self.reconnect_p2p(num_connections=1)
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+ # send_txs_and_test will have waited for disconnect, so we can safely check that no reject has been received
+ assert_equal(node.p2p.reject_code_received, None)
if __name__ == '__main__':
InvalidTxRequestTest().main()
diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py
index 198dcc1490..dca5ea39de 100755
--- a/test/functional/p2p_leak.py
+++ b/test/functional/p2p_leak.py
@@ -118,11 +118,11 @@ class P2PLeakTest(BitcoinTestFramework):
time.sleep(5)
#This node should have been banned
- assert no_version_bannode.state != "connected"
+ assert not no_version_bannode.is_connected
# These nodes should have been disconnected
- assert unsupported_service_bit5_node.state != "connected"
- assert unsupported_service_bit7_node.state != "connected"
+ assert not unsupported_service_bit5_node.is_connected
+ assert not unsupported_service_bit7_node.is_connected
self.nodes[0].disconnect_p2ps()
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 4fecd4ffee..940d085e89 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -73,11 +73,15 @@ class TestP2PConn(P2PInterface):
for inv in message.inv:
self.getdataset.add(inv.hash)
- def announce_tx_and_wait_for_getdata(self, tx, timeout=60):
+ def announce_tx_and_wait_for_getdata(self, tx, timeout=60, success=True):
with mininode_lock:
self.last_message.pop("getdata", None)
self.send_message(msg_inv(inv=[CInv(1, tx.sha256)]))
- self.wait_for_getdata(timeout)
+ if success:
+ self.wait_for_getdata(timeout)
+ else:
+ time.sleep(timeout)
+ assert not self.last_message.get("getdata")
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
with mininode_lock:
@@ -173,7 +177,7 @@ class SegWitTest(BitcoinTestFramework):
# Create a transaction that spends the coinbase
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(txid, 0), b""))
- tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.calc_sha256()
# Check that serializing it with or without witness is the same
@@ -226,55 +230,9 @@ class SegWitTest(BitcoinTestFramework):
sync_blocks(self.nodes)
- # Create a p2sh output -- this is so we can pass the standardness
- # rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped
- # in P2SH).
- p2sh_program = CScript([OP_TRUE])
- p2sh_pubkey = hash160(p2sh_program)
- scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
-
- # Now check that unnecessary witnesses can't be used to blind a node
- # to a transaction, eg by violating standardness checks.
- tx2 = CTransaction()
- tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), b""))
- tx2.vout.append(CTxOut(tx.vout[0].nValue-1000, scriptPubKey))
- tx2.rehash()
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, False, True)
- self.nodes[0].generate(1)
- sync_blocks(self.nodes)
-
- # We'll add an unnecessary witness to this transaction that would cause
- # it to be non-standard, to test that violating policy with a witness before
- # segwit activation doesn't blind a node to a transaction. Transactions
- # rejected for having a witness before segwit activation shouldn't be added
- # to the rejection cache.
- tx3 = CTransaction()
- tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program])))
- tx3.vout.append(CTxOut(tx2.vout[0].nValue-1000, scriptPubKey))
- tx3.wit.vtxinwit.append(CTxInWitness())
- tx3.wit.vtxinwit[0].scriptWitness.stack = [b'a'*400000]
- tx3.rehash()
- # Note that this should be rejected for the premature witness reason,
- # rather than a policy check, since segwit hasn't activated yet.
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'no-witness-yet')
-
- # If we send without witness, it should be accepted.
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, False, True)
-
- # Now create a new anyone-can-spend utxo for the next test.
- tx4 = CTransaction()
- tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program])))
- tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE])))
- tx4.rehash()
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, False, True)
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, False, True)
-
- self.nodes[0].generate(1)
- sync_blocks(self.nodes)
-
# Update our utxo list; we spent the first entry.
self.utxo.pop(0)
- self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue))
+ self.utxo.append(UTXO(tx.sha256, 0, tx.vout[0].nValue))
# ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was
# backdated so that it applies to all blocks, going back to the genesis
@@ -893,7 +851,7 @@ class SegWitTest(BitcoinTestFramework):
assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -908,12 +866,7 @@ class SegWitTest(BitcoinTestFramework):
# Since we haven't delivered the tx yet, inv'ing the same tx from
# a witness transaction ought not result in a getdata.
- try:
- self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2)
- self.log.error("Error: duplicate tx getdata!")
- assert(False)
- except AssertionError:
- pass
+ self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2, success=False)
# Delivering this transaction with witness should fail (no matter who
# its from)
@@ -945,7 +898,7 @@ class SegWitTest(BitcoinTestFramework):
assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -989,7 +942,7 @@ class SegWitTest(BitcoinTestFramework):
test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'tx-size')
# Remove witness stuffing, instead add extra witness push on stack
- tx3.vout[0] = CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))
+ tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))
tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ]
tx3.rehash()
@@ -1120,7 +1073,7 @@ class SegWitTest(BitcoinTestFramework):
self.old_node.announce_tx_and_wait_for_getdata(block4.vtx[0])
assert(block4.sha256 not in self.old_node.getdataset)
- # V0 segwit outputs should be standard after activation, but not before.
+ # V0 segwit outputs and inputs are always standard. V0 segwit inputs may only be mined after activation, but not before.
def test_standardness_v0(self, segwit_activated):
self.log.info("Testing standardness of v0 outputs (%s activation)" % ("after" if segwit_activated else "before"))
assert(len(self.utxo))
@@ -1149,45 +1102,46 @@ class SegWitTest(BitcoinTestFramework):
tx.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
tx.vout = [CTxOut(p2sh_tx.vout[0].nValue-10000, scriptPubKey)]
tx.vout.append(CTxOut(8000, scriptPubKey)) # Might burn this later
+ tx.vin[0].nSequence = BIP125_SEQUENCE_NUMBER # Just to have the option to bump this tx from the mempool
tx.rehash()
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=segwit_activated)
+ # This is always accepted, since the mempool policy is to consider segwit as always active
+ # and thus allow segwit outputs
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx, with_witness=True, accepted=True)
# Now create something that looks like a P2PKH output. This won't be spendable.
scriptPubKey = CScript([OP_0, hash160(witness_hash)])
tx2 = CTransaction()
- if segwit_activated:
- # if tx was accepted, then we spend the second output.
- tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")]
- tx2.vout = [CTxOut(7000, scriptPubKey)]
- tx2.wit.vtxinwit.append(CTxInWitness())
- tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
- else:
- # if tx wasn't accepted, we just re-spend the p2sh output we started with.
- tx2.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
- tx2.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, scriptPubKey)]
+ # tx was accepted, so we spend the second output.
+ tx2.vin = [CTxIn(COutPoint(tx.sha256, 1), b"")]
+ tx2.vout = [CTxOut(7000, scriptPubKey)]
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx2.rehash()
- test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=segwit_activated)
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, with_witness=True, accepted=True)
# Now update self.utxo for later tests.
tx3 = CTransaction()
- if segwit_activated:
- # tx and tx2 were both accepted. Don't bother trying to reclaim the
- # P2PKH output; just send tx's first output back to an anyone-can-spend.
- sync_mempools([self.nodes[0], self.nodes[1]])
- tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
- tx3.vout = [CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))]
- tx3.wit.vtxinwit.append(CTxInWitness())
- tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
- tx3.rehash()
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
- else:
- # tx and tx2 didn't go anywhere; just clean up the p2sh_tx output.
- tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
- tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)]
+ # tx and tx2 were both accepted. Don't bother trying to reclaim the
+ # P2PKH output; just send tx's first output back to an anyone-can-spend.
+ sync_mempools([self.nodes[0], self.nodes[1]])
+ tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
+ tx3.vout = [CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))]
+ tx3.wit.vtxinwit.append(CTxInWitness())
+ tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
+ tx3.rehash()
+ if not segwit_activated:
+ # Just check mempool acceptance, but don't add the transaction to the mempool, since witness is disallowed
+ # in blocks and the tx is impossible to mine right now.
+ assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
+ # Create the same output as tx3, but by replacing tx
+ tx3_out = tx3.vout[0]
+ tx3 = tx
+ tx3.vout = [tx3_out]
tx3.rehash()
- test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
+ assert_equal(self.nodes[0].testmempoolaccept([bytes_to_hex_str(tx3.serialize_with_witness())]), [{'txid': tx3.hash, 'allowed': True}])
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
self.nodes[0].generate(1)
sync_blocks(self.nodes)
@@ -1659,7 +1613,7 @@ class SegWitTest(BitcoinTestFramework):
tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ]
total_value += tx.vout[i].nValue
- tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE])))
tx2.rehash()
@@ -1856,6 +1810,60 @@ class SegWitTest(BitcoinTestFramework):
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
self.utxo.append(UTXO(tx5.sha256, 0, tx5.vout[0].nValue))
+ def test_non_standard_witness_blinding(self):
+ self.log.info("Testing behavior of unnecessary witnesses in transactions does not blind the node for the transaction")
+ assert (len(self.utxo) > 0)
+
+ # Create a p2sh output -- this is so we can pass the standardness
+ # rules (an anyone-can-spend OP_TRUE would be rejected, if not wrapped
+ # in P2SH).
+ p2sh_program = CScript([OP_TRUE])
+ p2sh_pubkey = hash160(p2sh_program)
+ scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+
+ # Now check that unnecessary witnesses can't be used to blind a node
+ # to a transaction, eg by violating standardness checks.
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, scriptPubKey))
+ tx.rehash()
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx, False, True)
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+
+ # We'll add an unnecessary witness to this transaction that would cause
+ # it to be non-standard, to test that violating policy with a witness
+ # doesn't blind a node to a transaction. Transactions
+ # rejected for having a witness shouldn't be added
+ # to the rejection cache.
+ tx2 = CTransaction()
+ tx2.vin.append(CTxIn(COutPoint(tx.sha256, 0), CScript([p2sh_program])))
+ tx2.vout.append(CTxOut(tx.vout[0].nValue - 1000, scriptPubKey))
+ tx2.wit.vtxinwit.append(CTxInWitness())
+ tx2.wit.vtxinwit[0].scriptWitness.stack = [b'a' * 400]
+ tx2.rehash()
+ # This will be rejected due to a policy check:
+ # No witness is allowed, since it is not a witness program but a p2sh program
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, True, False, b'bad-witness-nonstandard')
+
+ # If we send without witness, it should be accepted.
+ test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx2, False, True)
+
+ # Now create a new anyone-can-spend utxo for the next test.
+ tx3 = CTransaction()
+ tx3.vin.append(CTxIn(COutPoint(tx2.sha256, 0), CScript([p2sh_program])))
+ tx3.vout.append(CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
+ tx3.rehash()
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx2, False, True)
+ test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, False, True)
+
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+
+ # Update our utxo list; we spent the first entry.
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(tx3.sha256, 0, tx3.vout[0].nValue))
+
def test_non_standard_witness(self):
self.log.info("Testing detection of non-standard P2WSH witness")
pad = chr(1).encode('latin-1')
@@ -2024,6 +2032,7 @@ class SegWitTest(BitcoinTestFramework):
self.test_premature_coinbase_witness_spend()
self.test_uncompressed_pubkey()
self.test_signature_version_1()
+ self.test_non_standard_witness_blinding()
self.test_non_standard_witness()
sync_blocks(self.nodes)
self.test_upgrade_after_activation(node_id=2)
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index 4c7d5e65c5..7ee8168e2f 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -116,6 +116,7 @@ class BaseNode(P2PInterface):
self.block_announced = False
self.last_blockhash_announced = None
+ self.recent_headers_announced = []
def send_get_data(self, block_hashes):
"""Request data for a list of block hashes."""
@@ -163,40 +164,45 @@ class BaseNode(P2PInterface):
def on_headers(self, message):
if len(message.headers):
self.block_announced = True
- message.headers[-1].calc_sha256()
+ for x in message.headers:
+ x.calc_sha256()
+ # append because headers may be announced over multiple messages.
+ self.recent_headers_announced.append(x.sha256)
self.last_blockhash_announced = message.headers[-1].sha256
- def clear_last_announcement(self):
+ def clear_block_announcements(self):
with mininode_lock:
self.block_announced = False
self.last_message.pop("inv", None)
self.last_message.pop("headers", None)
+ self.recent_headers_announced = []
- def check_last_announcement(self, headers=None, inv=None):
- """Test whether the last announcement received had the right header or the right inv.
- inv and headers should be lists of block hashes."""
+ def check_last_headers_announcement(self, headers):
+ """Test whether the last headers announcements received are right.
+ Headers may be announced across more than one message."""
+ test_function = lambda: (len(self.recent_headers_announced) >= len(headers))
+ wait_until(test_function, timeout=60, lock=mininode_lock)
+ with mininode_lock:
+ assert_equal(self.recent_headers_announced, headers)
+ self.block_announced = False
+ self.last_message.pop("headers", None)
+ self.recent_headers_announced = []
+
+ def check_last_inv_announcement(self, inv):
+ """Test whether the last announcement received had the right inv.
+ inv should be a list of block hashes."""
test_function = lambda: self.block_announced
wait_until(test_function, timeout=60, lock=mininode_lock)
with mininode_lock:
- self.block_announced = False
-
compare_inv = []
if "inv" in self.last_message:
compare_inv = [x.hash for x in self.last_message["inv"].inv]
- if inv is not None:
- assert_equal(compare_inv, inv)
-
- compare_headers = []
- if "headers" in self.last_message:
- compare_headers = [x.sha256 for x in self.last_message["headers"].headers]
- if headers is not None:
- assert_equal(compare_headers, headers)
-
+ assert_equal(compare_inv, inv)
+ self.block_announced = False
self.last_message.pop("inv", None)
- self.last_message.pop("headers", None)
class SendHeadersTest(BitcoinTestFramework):
def set_test_params(self):
@@ -206,8 +212,8 @@ class SendHeadersTest(BitcoinTestFramework):
def mine_blocks(self, count):
"""Mine count blocks and return the new tip."""
- # Clear out last block announcement from each p2p listener
- [x.clear_last_announcement() for x in self.nodes[0].p2ps]
+ # Clear out block announcements from each p2p listener
+ [x.clear_block_announcements() for x in self.nodes[0].p2ps]
self.nodes[0].generate(count)
return int(self.nodes[0].getbestblockhash(), 16)
@@ -222,7 +228,7 @@ class SendHeadersTest(BitcoinTestFramework):
sync_blocks(self.nodes, wait=0.1)
for x in self.nodes[0].p2ps:
x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16))
- x.clear_last_announcement()
+ x.clear_block_announcements()
tip_height = self.nodes[1].getblockcount()
hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1))
@@ -255,25 +261,25 @@ class SendHeadersTest(BitcoinTestFramework):
tip = self.nodes[0].getblockheader(self.nodes[0].generate(1)[0])
tip_hash = int(tip["hash"], 16)
- inv_node.check_last_announcement(inv=[tip_hash], headers=[])
- test_node.check_last_announcement(inv=[tip_hash], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip_hash])
+ test_node.check_last_inv_announcement(inv=[tip_hash])
self.log.info("Verify getheaders with null locator and valid hashstop returns headers.")
- test_node.clear_last_announcement()
+ test_node.clear_block_announcements()
test_node.send_get_headers(locator=[], hashstop=tip_hash)
- test_node.check_last_announcement(headers=[tip_hash])
+ test_node.check_last_headers_announcement(headers=[tip_hash])
self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.")
block = create_block(int(tip["hash"], 16), create_coinbase(tip["height"] + 1), tip["mediantime"] + 1)
block.solve()
test_node.send_header_for_blocks([block])
- test_node.clear_last_announcement()
+ test_node.clear_block_announcements()
test_node.send_get_headers(locator=[], hashstop=int(block.hash, 16))
test_node.sync_with_ping()
assert_equal(test_node.block_announced, False)
- inv_node.clear_last_announcement()
+ inv_node.clear_block_announcements()
test_node.send_message(msg_block(block))
- inv_node.check_last_announcement(inv=[int(block.hash, 16)], headers=[])
+ inv_node.check_last_inv_announcement(inv=[int(block.hash, 16)])
def test_nonnull_locators(self, test_node, inv_node):
tip = int(self.nodes[0].getbestblockhash(), 16)
@@ -282,10 +288,11 @@ class SendHeadersTest(BitcoinTestFramework):
# 1. Mine a block; expect inv announcements each time
self.log.info("Part 1: headers don't start before sendheaders message...")
for i in range(4):
+ self.log.debug("Part 1.{}: starting...".format(i))
old_tip = tip
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
# Try a few different responses; none should affect next announcement
if i == 0:
# first request the block
@@ -296,7 +303,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.send_get_headers(locator=[old_tip], hashstop=tip)
test_node.send_get_data([tip])
test_node.wait_for_block(tip)
- test_node.clear_last_announcement() # since we requested headers...
+ test_node.clear_block_announcements() # since we requested headers...
elif i == 2:
# this time announce own block via headers
height = self.nodes[0].getblockcount()
@@ -308,8 +315,8 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed
- inv_node.clear_last_announcement()
- test_node.clear_last_announcement()
+ inv_node.clear_block_announcements()
+ test_node.clear_block_announcements()
self.log.info("Part 1: success!")
self.log.info("Part 2: announce blocks with headers after sendheaders message...")
@@ -323,17 +330,19 @@ class SendHeadersTest(BitcoinTestFramework):
# Now that we've synced headers, headers announcements should work
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
height = self.nodes[0].getblockcount() + 1
block_time += 10 # Advance far enough ahead
for i in range(10):
+ self.log.debug("Part 2.{}: starting...".format(i))
# Mine i blocks, and alternate announcing either via
# inv (of tip) or via headers. After each, new blocks
# mined by the node should successfully be announced
# with block header, even though the blocks are never requested
for j in range(2):
+ self.log.debug("Part 2.{}.{}: starting...".format(i, j))
blocks = []
for b in range(i + 1):
blocks.append(create_block(tip, create_coinbase(height), block_time))
@@ -368,8 +377,8 @@ class SendHeadersTest(BitcoinTestFramework):
assert "inv" not in inv_node.last_message
assert "headers" not in inv_node.last_message
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
height += 1
block_time += 1
@@ -380,19 +389,20 @@ class SendHeadersTest(BitcoinTestFramework):
# PART 3. Headers announcements can stop after large reorg, and resume after
# getheaders or inv from peer.
for j in range(2):
+ self.log.debug("Part 3.{}: starting...".format(j))
# First try mining a reorg that can propagate with header announcement
new_block_hashes = self.mine_reorg(length=7)
tip = new_block_hashes[-1]
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=new_block_hashes)
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=new_block_hashes)
block_time += 8
# Mine a too-large reorg, which should be announced with a single inv
new_block_hashes = self.mine_reorg(length=8)
tip = new_block_hashes[-1]
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
block_time += 9
@@ -401,28 +411,33 @@ class SendHeadersTest(BitcoinTestFramework):
# Use getblocks/getdata
test_node.send_getblocks(locator=[fork_point])
- test_node.check_last_announcement(inv=new_block_hashes, headers=[])
+ test_node.check_last_inv_announcement(inv=new_block_hashes)
test_node.send_get_data(new_block_hashes)
test_node.wait_for_block(new_block_hashes[-1])
for i in range(3):
+ self.log.debug("Part 3.{}.{}: starting...".format(j, i))
+
# Mine another block, still should get only an inv
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
if i == 0:
- self.log.debug("Just get the data -- shouldn't cause headers announcements to resume")
+ # Just get the data -- shouldn't cause headers announcements to resume
test_node.send_get_data([tip])
test_node.wait_for_block(tip)
elif i == 1:
- self.log.debug("Send a getheaders message that shouldn't trigger headers announcements to resume (best header sent will be too old)")
+ # Send a getheaders message that shouldn't trigger headers announcements
+ # to resume (best header sent will be too old)
test_node.send_get_headers(locator=[fork_point], hashstop=new_block_hashes[1])
test_node.send_get_data([tip])
test_node.wait_for_block(tip)
elif i == 2:
+ # This time, try sending either a getheaders to trigger resumption
+ # of headers announcements, or mine a new block and inv it, also
+ # triggering resumption of headers announcements.
test_node.send_get_data([tip])
test_node.wait_for_block(tip)
- self.log.debug("This time, try sending either a getheaders to trigger resumption of headers announcements, or mine a new block and inv it, also triggering resumption of headers announcements.")
if j == 0:
test_node.send_get_headers(locator=[tip], hashstop=0)
test_node.sync_with_ping()
@@ -431,8 +446,8 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.sync_with_ping()
# New blocks should now be announced with header
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
self.log.info("Part 3: success!")
@@ -526,6 +541,7 @@ class SendHeadersTest(BitcoinTestFramework):
# First we test that receipt of an unconnecting header doesn't prevent
# chain sync.
for i in range(10):
+ self.log.debug("Part 5.{}: starting...".format(i))
test_node.last_message.pop("getdata", None)
blocks = []
# Create two more blocks.
diff --git a/test/functional/p2p_timeouts.py b/test/functional/p2p_timeouts.py
index 6a21b693b4..e958536cf9 100755
--- a/test/functional/p2p_timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -47,9 +47,9 @@ class TimeoutsTest(BitcoinTestFramework):
sleep(1)
- assert no_verack_node.connected
- assert no_version_node.connected
- assert no_send_node.connected
+ assert no_verack_node.is_connected
+ 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())
@@ -58,18 +58,18 @@ class TimeoutsTest(BitcoinTestFramework):
assert "version" in no_verack_node.last_message
- assert no_verack_node.connected
- assert no_version_node.connected
- assert no_send_node.connected
+ assert no_verack_node.is_connected
+ 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())
sleep(31)
- assert not no_verack_node.connected
- assert not no_version_node.connected
- assert not no_send_node.connected
+ assert not no_verack_node.is_connected
+ assert not no_version_node.is_connected
+ assert not no_send_node.is_connected
if __name__ == '__main__':
TimeoutsTest().main()
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index 17e24453e5..7acc59c2c6 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -217,6 +217,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(header['confirmations'], 1)
assert_equal(header['previousblockhash'], secondbesthash)
assert_is_hex_string(header['chainwork'])
+ assert_equal(header['nTx'], 1)
assert_is_hash_string(header['hash'])
assert_is_hash_string(header['previousblockhash'])
assert_is_hash_string(header['merkleroot'])
diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py
index 2e0500e7c4..bc27c183b1 100755
--- a/test/functional/rpc_deprecated.py
+++ b/test/functional/rpc_deprecated.py
@@ -40,7 +40,6 @@ class DeprecatedRpcTest(BitcoinTestFramework):
#
# The following 'label' RPC methods are usable both with and without the
# -deprecatedrpc=accounts switch enabled.
- # - getlabeladdress
# - getaddressesbylabel
# - getreceivedbylabel
# - listlabels
@@ -69,10 +68,6 @@ class DeprecatedRpcTest(BitcoinTestFramework):
assert_raises_rpc_error(-32, "getaccountaddress is deprecated", self.nodes[0].getaccountaddress, "label0")
self.nodes[1].getaccountaddress("label1")
- self.log.info("- getlabeladdress")
- self.nodes[0].getlabeladdress("label0")
- self.nodes[1].getlabeladdress("label1")
-
self.log.info("- getaddressesbyaccount")
assert_raises_rpc_error(-32, "getaddressesbyaccount is deprecated", self.nodes[0].getaddressesbyaccount, "label0")
self.nodes[1].getaddressesbyaccount("label1")
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 0f09c3c552..1e91cf598c 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -4,8 +4,18 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the fundrawtransaction RPC."""
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ assert_fee_amount,
+ assert_greater_than,
+ assert_greater_than_or_equal,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ count_bytes,
+ find_vout_for_address,
+)
def get_unspent(listunspent, amount):
@@ -57,6 +67,11 @@ class RawTransactionsTest(BitcoinTestFramework):
watchonly_amount = Decimal(200)
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
+
+ # Lock UTXO so nodes[0] doesn't accidentally spend it
+ watchonly_vout = find_vout_for_address(self.nodes[0], watchonly_txid, watchonly_address)
+ self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
+
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
@@ -475,6 +490,9 @@ class RawTransactionsTest(BitcoinTestFramework):
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
+ # Again lock the watchonly UTXO or nodes[0] may spend it, because
+ # lockunspent is memory-only and thus lost on restart
+ self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
self.sync_all()
# drain the keypool
diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py
new file mode 100755
index 0000000000..f573faaf17
--- /dev/null
+++ b/test/functional/rpc_getblockstats.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017-2017 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 getblockstats rpc call
+#
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
+import json
+import os
+import time
+
+TESTSDIR = os.path.dirname(os.path.realpath(__file__))
+
+class GetblockstatsTest(BitcoinTestFramework):
+
+ start_height = 101
+ max_stat_pos = 2
+ STATS_NEED_TXINDEX = [
+ 'avgfee',
+ 'avgfeerate',
+ 'maxfee',
+ 'maxfeerate',
+ 'medianfee',
+ 'medianfeerate',
+ 'minfee',
+ 'minfeerate',
+ 'totalfee',
+ 'utxo_size_inc',
+ ]
+
+ def add_options(self, parser):
+ parser.add_option('--gen-test-data', dest='gen_test_data',
+ default=False, action='store_true',
+ help='Generate test data')
+ parser.add_option('--test-data', dest='test_data',
+ default='data/rpc_getblockstats.json',
+ action='store', metavar='FILE',
+ help='Test data file')
+
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.extra_args = [['-txindex'], ['-paytxfee=0.003']]
+ self.setup_clean_chain = True
+
+ def get_stats(self):
+ return [self.nodes[0].getblockstats(hash_or_height=self.start_height + i) for i in range(self.max_stat_pos+1)]
+
+ def generate_test_data(self, filename):
+ mocktime = time.time()
+ self.nodes[0].generate(101)
+
+ self.nodes[0].sendtoaddress(address=self.nodes[1].getnewaddress(), amount=10, subtractfeefromamount=True)
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=True)
+ self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=10, subtractfeefromamount=False)
+ self.nodes[1].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=1, subtractfeefromamount=True)
+ self.sync_all()
+ self.nodes[0].generate(1)
+
+ self.expected_stats = self.get_stats()
+
+ blocks = []
+ tip = self.nodes[0].getbestblockhash()
+ blockhash = None
+ height = 0
+ while tip != blockhash:
+ blockhash = self.nodes[0].getblockhash(height)
+ blocks.append(self.nodes[0].getblock(blockhash, 0))
+ height += 1
+
+ to_dump = {
+ 'blocks': blocks,
+ 'mocktime': int(mocktime),
+ 'stats': self.expected_stats,
+ }
+ with open(filename, 'w', encoding="utf8") as f:
+ json.dump(to_dump, f, sort_keys=True, indent=2)
+
+ def load_test_data(self, filename):
+ with open(filename, 'r', encoding="utf8") as f:
+ d = json.load(f)
+ blocks = d['blocks']
+ mocktime = d['mocktime']
+ self.expected_stats = d['stats']
+
+ # Set the timestamps from the file so that the nodes can get out of Initial Block Download
+ self.nodes[0].setmocktime(mocktime)
+ self.nodes[1].setmocktime(mocktime)
+
+ for b in blocks:
+ self.nodes[0].submitblock(b)
+
+ def run_test(self):
+ test_data = os.path.join(TESTSDIR, self.options.test_data)
+ if self.options.gen_test_data:
+ self.generate_test_data(test_data)
+ else:
+ self.load_test_data(test_data)
+
+ self.sync_all()
+ stats = self.get_stats()
+ expected_stats_noindex = []
+ for stat_row in stats:
+ expected_stats_noindex.append({k: v for k, v in stat_row.items() if k not in self.STATS_NEED_TXINDEX})
+
+ # Make sure all valid statistics are included but nothing else is
+ expected_keys = self.expected_stats[0].keys()
+ assert_equal(set(stats[0].keys()), set(expected_keys))
+
+ assert_equal(stats[0]['height'], self.start_height)
+ assert_equal(stats[self.max_stat_pos]['height'], self.start_height + self.max_stat_pos)
+
+ for i in range(self.max_stat_pos+1):
+ self.log.info('Checking block %d\n' % (i))
+ assert_equal(stats[i], self.expected_stats[i])
+
+ # Check selecting block by hash too
+ blockhash = self.expected_stats[i]['blockhash']
+ stats_by_hash = self.nodes[0].getblockstats(hash_or_height=blockhash)
+ assert_equal(stats_by_hash, self.expected_stats[i])
+
+ # Check with the node that has no txindex
+ stats_no_txindex = self.nodes[1].getblockstats(hash_or_height=blockhash, stats=list(expected_stats_noindex[i].keys()))
+ assert_equal(stats_no_txindex, expected_stats_noindex[i])
+
+ # Make sure each stat can be queried on its own
+ for stat in expected_keys:
+ for i in range(self.max_stat_pos+1):
+ result = self.nodes[0].getblockstats(hash_or_height=self.start_height + i, stats=[stat])
+ assert_equal(list(result.keys()), [stat])
+ if result[stat] != self.expected_stats[i][stat]:
+ self.log.info('result[%s] (%d) failed, %r != %r' % (
+ stat, i, result[stat], self.expected_stats[i][stat]))
+ assert_equal(result[stat], self.expected_stats[i][stat])
+
+ # Make sure only the selected statistics are included (more than one)
+ some_stats = {'minfee', 'maxfee'}
+ stats = self.nodes[0].getblockstats(hash_or_height=1, stats=list(some_stats))
+ assert_equal(set(stats.keys()), some_stats)
+
+ # Test invalid parameters raise the proper json exceptions
+ tip = self.start_height + self.max_stat_pos
+ assert_raises_rpc_error(-8, 'Target block height %d after current tip %d' % (tip+1, tip),
+ self.nodes[0].getblockstats, hash_or_height=tip+1)
+ assert_raises_rpc_error(-8, 'Target block height %d is negative' % (-1),
+ self.nodes[0].getblockstats, hash_or_height=-1)
+
+ # Make sure not valid stats aren't allowed
+ inv_sel_stat = 'asdfghjkl'
+ inv_stats = [
+ [inv_sel_stat],
+ ['minfee' , inv_sel_stat],
+ [inv_sel_stat, 'minfee'],
+ ['minfee', inv_sel_stat, 'maxfee'],
+ ]
+ for inv_stat in inv_stats:
+ assert_raises_rpc_error(-8, 'Invalid selected statistic %s' % inv_sel_stat,
+ self.nodes[0].getblockstats, hash_or_height=1, stats=inv_stat)
+
+ # Make sure we aren't always returning inv_sel_stat as the culprit stat
+ assert_raises_rpc_error(-8, 'Invalid selected statistic aaa%s' % inv_sel_stat,
+ self.nodes[0].getblockstats, hash_or_height=1, stats=['minfee' , 'aaa%s' % inv_sel_stat])
+
+ assert_raises_rpc_error(-8, 'One or more of the selected stats requires -txindex enabled',
+ self.nodes[1].getblockstats, hash_or_height=self.start_height + self.max_stat_pos)
+
+ # Mainchain's genesis block shouldn't be found on regtest
+ assert_raises_rpc_error(-5, 'Block not found', self.nodes[0].getblockstats,
+ hash_or_height='000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f')
+
+if __name__ == '__main__':
+ GetblockstatsTest().main()
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 7c2125a177..5859f108a4 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -77,6 +77,12 @@ class P2PConnection(asyncore.dispatcher):
super().__init__(map=mininode_socket_map)
+ self._conn_open = False
+
+ @property
+ def is_connected(self):
+ return self._conn_open
+
def peer_connect(self, dstaddr, dstport, net="regtest"):
self.dstaddr = dstaddr
self.dstport = dstport
@@ -84,7 +90,7 @@ class P2PConnection(asyncore.dispatcher):
self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
self.sendbuf = b""
self.recvbuf = b""
- self.state = "connecting"
+ self._asyncore_pre_connection = True
self.network = net
self.disconnect = False
@@ -97,22 +103,23 @@ class P2PConnection(asyncore.dispatcher):
def peer_disconnect(self):
# Connection could have already been closed by other end.
- if self.state == "connected":
- self.disconnect_node()
+ if self.is_connected:
+ self.disconnect = True # Signal asyncore to disconnect
# Connection and disconnection methods
def handle_connect(self):
"""asyncore callback when a connection is opened."""
- if self.state != "connected":
+ if not self.is_connected:
logger.debug("Connected & Listening: %s:%d" % (self.dstaddr, self.dstport))
- self.state = "connected"
+ self._conn_open = True
+ self._asyncore_pre_connection = False
self.on_open()
def handle_close(self):
"""asyncore callback when a connection is closed."""
logger.debug("Closing connection to: %s:%d" % (self.dstaddr, self.dstport))
- self.state = "closed"
+ self._conn_open = False
self.recvbuf = b""
self.sendbuf = b""
try:
@@ -121,13 +128,6 @@ class P2PConnection(asyncore.dispatcher):
pass
self.on_close()
- def disconnect_node(self):
- """Disconnect the p2p connection.
-
- Called by the test logic thread. Causes the p2p connection
- to be disconnected on the next iteration of the asyncore loop."""
- self.disconnect = True
-
# Socket read methods
def handle_read(self):
@@ -182,9 +182,8 @@ class P2PConnection(asyncore.dispatcher):
def writable(self):
"""asyncore method to determine whether the handle_write() callback should be called on the next loop."""
with mininode_lock:
- pre_connection = self.state == "connecting"
length = len(self.sendbuf)
- return (length > 0 or pre_connection)
+ return length > 0 or self._asyncore_pre_connection
def handle_write(self):
"""asyncore callback when data should be written to the socket."""
@@ -192,7 +191,7 @@ class P2PConnection(asyncore.dispatcher):
# asyncore does not expose socket connection, only the first read/write
# event, thus we must check connection manually here to know when we
# actually connect
- if self.state == "connecting":
+ if self._asyncore_pre_connection:
self.handle_connect()
if not self.writable():
return
@@ -204,26 +203,17 @@ class P2PConnection(asyncore.dispatcher):
return
self.sendbuf = self.sendbuf[sent:]
- def send_message(self, message, pushbuf=False):
+ def send_message(self, message):
"""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."""
- if self.state != "connected" and not pushbuf:
- raise IOError('Not connected, no pushbuf')
+ if not self.is_connected:
+ raise IOError('Not connected')
self._log_message("send", message)
- command = message.command
- data = message.serialize()
- tmsg = MAGIC_BYTES[self.network]
- tmsg += command
- tmsg += b"\x00" * (12 - len(command))
- tmsg += struct.pack("<I", len(data))
- th = sha256(data)
- h = sha256(th)
- tmsg += h[:4]
- tmsg += data
+ tmsg = self._build_message(message)
with mininode_lock:
- if (len(self.sendbuf) == 0 and not pushbuf):
+ if len(self.sendbuf) == 0:
try:
sent = self.send(tmsg)
self.sendbuf = tmsg[sent:]
@@ -234,6 +224,20 @@ class P2PConnection(asyncore.dispatcher):
# Class utility methods
+ def _build_message(self, message):
+ """Build a serialized P2P message"""
+ command = message.command
+ data = message.serialize()
+ tmsg = MAGIC_BYTES[self.network]
+ tmsg += command
+ tmsg += b"\x00" * (12 - len(command))
+ tmsg += struct.pack("<I", len(data))
+ th = sha256(data)
+ h = sha256(th)
+ tmsg += h[:4]
+ tmsg += data
+ return tmsg
+
def _log_message(self, direction, msg):
"""Logs a message being sent or received over the connection."""
if direction == "send":
@@ -280,7 +284,7 @@ class P2PInterface(P2PConnection):
vt.addrTo.port = self.dstport
vt.addrFrom.ip = "0.0.0.0"
vt.addrFrom.port = 0
- self.send_message(vt, True)
+ self.sendbuf = self._build_message(vt) # Will be sent right after handle_connect
# Message receiving methods
@@ -348,7 +352,7 @@ class P2PInterface(P2PConnection):
# Connection helper methods
def wait_for_disconnect(self, timeout=60):
- test_function = lambda: self.state != "connected"
+ test_function = lambda: not self.is_connected
wait_until(test_function, timeout=timeout, lock=mininode_lock)
# Message receiving helper methods
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 472664a314..5c2555c1ff 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -98,8 +98,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="Leave bitcoinds and test.* datadir on exit or error")
parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true",
help="Don't stop bitcoinds after the test execution")
- parser.add_option("--srcdir", dest="srcdir", default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../../src"),
- help="Source directory containing bitcoind/bitcoin-cli (default: %default)")
parser.add_option("--cachedir", dest="cachedir", default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"),
help="Directory for caching pregenerated datadirs (default: %default)")
parser.add_option("--tmpdir", dest="tmpdir", help="Root directory for datadirs")
@@ -123,10 +121,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
PortSeed.n = self.options.port_seed
- os.environ['PATH'] = self.options.srcdir + os.pathsep + \
- self.options.srcdir + os.path.sep + "qt" + os.pathsep + \
- os.environ['PATH']
-
check_json_precision()
self.options.cachedir = os.path.abspath(self.options.cachedir)
@@ -136,6 +130,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/bitcoind' + config["environment"]["EXEEXT"])
self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/bitcoin-cli' + config["environment"]["EXEEXT"])
+ os.environ['PATH'] = os.pathsep.join([
+ os.path.join(config['environment']['BUILDDIR'], 'src'),
+ os.path.join(config['environment']['BUILDDIR'], 'src', 'qt'),
+ os.environ['PATH']
+ ])
+
# Set up temp directory and start logging
if self.options.tmpdir:
self.options.tmpdir = os.path.abspath(self.options.tmpdir)
@@ -258,7 +258,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
assert_equal(len(extra_args), num_nodes)
assert_equal(len(binary), num_nodes)
for i in range(num_nodes):
- self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=timewait, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
+ self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=timewait, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
def start_node(self, i, *args, **kwargs):
"""Start a bitcoind"""
@@ -291,9 +291,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
for node in self.nodes:
coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc)
- def stop_node(self, i):
+ def stop_node(self, i, expected_stderr=''):
"""Stop a bitcoind test node"""
- self.nodes[i].stop_node()
+ self.nodes[i].stop_node(expected_stderr)
self.nodes[i].wait_until_stopped()
def stop_nodes(self):
@@ -359,7 +359,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.log = logging.getLogger('TestFramework')
self.log.setLevel(logging.DEBUG)
# Create file handler to log all messages
- fh = logging.FileHandler(self.options.tmpdir + '/test_framework.log')
+ fh = logging.FileHandler(self.options.tmpdir + '/test_framework.log', encoding='utf-8')
fh.setLevel(logging.DEBUG)
# Create console handler to log messages to stderr. By default this logs only error messages, but can be configured with --loglevel.
ch = logging.StreamHandler(sys.stdout)
@@ -409,7 +409,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
args = [self.options.bitcoind, "-datadir=" + datadir]
if i > 0:
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
- self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=None, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, stderr=None, mocktime=self.mocktime, coverage_dir=None))
+ self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=None, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
self.nodes[i].args = args
self.start_node(i)
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 5a6a659392..0353fc0712 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -10,6 +10,7 @@ from enum import Enum
import http.client
import json
import logging
+import os
import re
import subprocess
import tempfile
@@ -55,9 +56,11 @@ 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, rpchost, timewait, bitcoind, bitcoin_cli, stderr, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
+ def __init__(self, i, datadir, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
self.index = i
self.datadir = datadir
+ self.stdout_dir = os.path.join(self.datadir, "stdout")
+ self.stderr_dir = os.path.join(self.datadir, "stderr")
self.rpchost = rpchost
if timewait:
self.rpc_timeout = timewait
@@ -65,7 +68,6 @@ class TestNode():
# Wait for up to 60 seconds for the RPC server to respond
self.rpc_timeout = 60
self.binary = bitcoind
- self.stderr = stderr
self.coverage_dir = coverage_dir
if extra_conf != None:
append_config(datadir, extra_conf)
@@ -81,8 +83,7 @@ class TestNode():
"-debugexclude=libevent",
"-debugexclude=leveldb",
"-mocktime=" + str(mocktime),
- "-uacomment=testnode%d" % i,
- "-noprinttoconsole"
+ "-uacomment=testnode%d" % i
]
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
@@ -124,17 +125,29 @@ class TestNode():
assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
return getattr(self.rpc, name)
- def start(self, extra_args=None, stderr=None, *args, **kwargs):
+ def start(self, extra_args=None, stdout=None, stderr=None, *args, **kwargs):
"""Start the node."""
if extra_args is None:
extra_args = self.extra_args
+
+ # Add a new stdout and stderr file each time bitcoind is started
if stderr is None:
- stderr = self.stderr
+ stderr = tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False)
+ if stdout is None:
+ stdout = tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False)
+ self.stderr = stderr
+ self.stdout = stdout
+
# Delete any existing cookie file -- if such a file exists (eg due to
# unclean shutdown), it will get overwritten anyway by bitcoind, and
# potentially interfere with our attempt to authenticate
delete_cookie_file(self.datadir)
- self.process = subprocess.Popen(self.args + extra_args, stderr=stderr, *args, **kwargs)
+
+ # add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal
+ subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1")
+
+ self.process = subprocess.Popen(self.args + extra_args, env=subp_env, stdout=stdout, stderr=stderr, *args, **kwargs)
+
self.running = True
self.log.debug("bitcoind started, waiting for RPC to come up")
@@ -174,7 +187,7 @@ class TestNode():
wallet_path = "wallet/%s" % wallet_name
return self.rpc / wallet_path
- def stop_node(self):
+ def stop_node(self, expected_stderr=''):
"""Stop the node."""
if not self.running:
return
@@ -183,6 +196,13 @@ class TestNode():
self.stop()
except http.client.CannotSendRequest:
self.log.exception("Unable to stop node.")
+
+ # Check that stderr is as expected
+ self.stderr.seek(0)
+ stderr = self.stderr.read().decode('utf-8').strip()
+ if stderr != expected_stderr:
+ raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr))
+
del self.p2ps[:]
def is_node_stopped(self):
@@ -217,9 +237,10 @@ class TestNode():
Will throw if bitcoind starts without an error.
Will throw if an expected_msg is provided and it does not match bitcoind's stdout."""
- with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr:
+ with tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False) as log_stderr, \
+ tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout:
try:
- self.start(extra_args, stderr=log_stderr, *args, **kwargs)
+ self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs)
self.wait_for_rpc_connection()
self.stop_node()
self.wait_until_stopped()
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 4ec3175cd6..5e0b61b5e7 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -301,6 +301,9 @@ def initialize_datadir(dirname, n):
f.write("keypool=1\n")
f.write("discover=0\n")
f.write("listenonion=0\n")
+ f.write("printtoconsole=0\n")
+ os.makedirs(os.path.join(datadir, 'stderr'), exist_ok=True)
+ os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
return datadir
def get_datadir_path(dirname, n):
@@ -324,7 +327,7 @@ def get_auth_cookie(datadir):
assert password is None # Ensure that there is only one rpcpassword line
password = line.split("=")[1].strip("\n")
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
- with open(os.path.join(datadir, "regtest", ".cookie"), 'r') as f:
+ with open(os.path.join(datadir, "regtest", ".cookie"), 'r', encoding="ascii") as f:
userpass = f.read()
split_userpass = userpass.split(':')
user = split_userpass[0]
@@ -349,7 +352,14 @@ def set_node_times(nodes, t):
def disconnect_nodes(from_connection, node_num):
for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]:
- from_connection.disconnectnode(nodeid=peer_id)
+ try:
+ from_connection.disconnectnode(nodeid=peer_id)
+ except JSONRPCException as e:
+ # If this node is disconnected between calculating the peer id
+ # and issuing the disconnect, don't worry about it.
+ # This avoids a race condition if we're mass-disconnecting peers.
+ if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED
+ raise
# wait to disconnect
wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == [], timeout=5)
@@ -556,3 +566,14 @@ def mine_large_block(node, utxos=None):
fee = 100 * node.getnetworkinfo()["relayfee"]
create_lots_of_big_transactions(node, txouts, utxos, num, fee=fee)
node.generate(1)
+
+def find_vout_for_address(node, txid, addr):
+ """
+ Locate the vout index of the given transaction sending to the
+ given address. Raises runtime error exception if not found.
+ """
+ tx = node.getrawtransaction(txid, True)
+ for i in range(len(tx["vout"])):
+ if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
+ return i
+ raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index ff4b480165..36101d9f57 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -135,9 +135,11 @@ BASE_SCRIPTS = [
'wallet_resendwallettransactions.py',
'wallet_fallbackfee.py',
'feature_minchainwork.py',
+ 'rpc_getblockstats.py',
'p2p_fingerprint.py',
'feature_uacomment.py',
'p2p_unrequested_blocks.py',
+ 'feature_includeconf.py',
'feature_logging.py',
'p2p_node_network_limited.py',
'feature_blocksdir.py',
@@ -211,7 +213,7 @@ def main():
# Read config generated by configure.
config = configparser.ConfigParser()
configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini"
- config.read_file(open(configfile))
+ config.read_file(open(configfile, encoding="utf8"))
passon_args.append("--configfile=%s" % configfile)
@@ -313,8 +315,7 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
tests_dir = src_dir + '/test/functional/'
- flags = ["--srcdir={}/src".format(build_dir)] + args
- flags.append("--cachedir=%s" % cache_dir)
+ flags = ['--cachedir={}'.format(cache_dir)] + args
if enable_coverage:
coverage = RPCCoverage()
@@ -418,10 +419,6 @@ class TestHandler:
self.test_list = test_list
self.flags = flags
self.num_running = 0
- # In case there is a graveyard of zombie bitcoinds, we can apply a
- # pseudorandom offset to hopefully jump over them.
- # (625 is PORT_RANGE/MAX_NODES)
- self.portseed_offset = int(time.time() * 1000) % 625
self.jobs = []
def get_next(self):
@@ -429,7 +426,7 @@ class TestHandler:
# Add tests
self.num_running += 1
test = self.test_list.pop(0)
- portseed = len(self.test_list) + self.portseed_offset
+ portseed = len(self.test_list)
portseed_arg = ["--portseed={}".format(portseed)]
log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16)
log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16)
@@ -593,7 +590,7 @@ class RPCCoverage():
if not os.path.isfile(coverage_ref_filename):
raise RuntimeError("No coverage reference found")
- with open(coverage_ref_filename, 'r') as coverage_ref_file:
+ with open(coverage_ref_filename, 'r', encoding="utf8") as coverage_ref_file:
all_cmds.update([line.strip() for line in coverage_ref_file.readlines()])
for root, dirs, files in os.walk(self.dir):
@@ -602,7 +599,7 @@ class RPCCoverage():
coverage_filenames.add(os.path.join(root, filename))
for filename in coverage_filenames:
- with open(filename, 'r') as coverage_file:
+ with open(filename, 'r', encoding="utf8") as coverage_file:
covered_cmds.update([line.strip() for line in coverage_file.readlines()])
return all_cmds - covered_cmds
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 0673b6d55e..d6a64eaefb 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -22,10 +22,9 @@ class WalletTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
self.setup_clean_chain = True
- self.extra_args = [['-deprecatedrpc=accounts']] * 4
def setup_network(self):
- self.add_nodes(4, self.extra_args)
+ self.add_nodes(4)
self.start_node(0)
self.start_node(1)
self.start_node(2)
@@ -160,7 +159,7 @@ class WalletTest(BitcoinTestFramework):
inputs = []
outputs = {}
inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
- outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] - 3
+ outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))
@@ -174,7 +173,6 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[2].getbalance(), 94)
- assert_equal(self.nodes[2].getbalance("from1"), 94 - 21)
# Verify that a spent output cannot be locked anymore
spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
@@ -199,7 +197,7 @@ class WalletTest(BitcoinTestFramework):
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
# Sendmany 10 BTC
- txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [])
+ txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
node_0_bal += Decimal('10')
@@ -207,7 +205,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), node_0_bal)
# Sendmany 10 BTC with subtract fee from amount
- txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [address])
+ txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
node_2_bal -= Decimal('10')
@@ -374,14 +372,14 @@ class WalletTest(BitcoinTestFramework):
# - True: unicode escaped as \u....
# - False: unicode directly as UTF-8
for mode in [True, False]:
- self.nodes[0].ensure_ascii = mode
+ self.nodes[0].rpc.ensure_ascii = mode
# unicode check: Basic Multilingual Plane, Supplementary Plane respectively
- for s in [u'рыба', u'𝅘𝅥𝅯']:
- addr = self.nodes[0].getaccountaddress(s)
- label = self.nodes[0].getaccount(addr)
- assert_equal(label, s)
- assert(s in self.nodes[0].listaccounts().keys())
- self.nodes[0].ensure_ascii = True # restore to default
+ for label in [u'рыба', u'𝅘𝅥𝅯']:
+ addr = self.nodes[0].getnewaddress()
+ self.nodes[0].setlabel(addr, label)
+ assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label)
+ assert(label in self.nodes[0].listlabels())
+ self.nodes[0].rpc.ensure_ascii = True # restore to default
# maintenance tests
maintenance = [
@@ -397,9 +395,9 @@ class WalletTest(BitcoinTestFramework):
self.log.info("check " + m)
self.stop_nodes()
# set lower ancestor limit for later
- self.start_node(0, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
- self.start_node(1, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
- self.start_node(2, [m, "-deprecatedrpc=accounts", "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(1, [m, "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(2, [m, "-limitancestorcount=" + str(chainlimit)])
if m == '-reindex':
# reindex will leave rpc warm up "early"; Wait for it to finish
wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
@@ -447,7 +445,7 @@ class WalletTest(BitcoinTestFramework):
# Try with walletrejectlongchains
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
self.stop_node(0)
- self.start_node(0, extra_args=["-deprecatedrpc=accounts", "-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
+ self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
# wait for loadmempool
timeout = 10
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index fcc11abce0..f07041706a 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -31,7 +31,7 @@ class BumpFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
- self.extra_args = [["-prematurewitness", "-walletprematurewitness", "-deprecatedrpc=addwitnessaddress", "-walletrbf={}".format(i)]
+ self.extra_args = [["-deprecatedrpc=addwitnessaddress", "-walletrbf={}".format(i)]
for i in range(self.num_nodes)]
def run_test(self):
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 997f67ec7e..ba420ab2a6 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -36,10 +36,10 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
addr_keypath = comment.split(" addr=")[1]
addr = addr_keypath.split(" ")[0]
keypath = None
- if keytype == "inactivehdmaster=1":
+ if keytype == "inactivehdseed=1":
# ensure the old master is still available
assert(hd_master_addr_old == addr)
- elif keytype == "hdmaster=1":
+ elif keytype == "hdseed=1":
# ensure we have generated a new hd master key
assert(hd_master_addr_old != addr)
hd_master_addr_ret = addr
@@ -136,7 +136,7 @@ class WalletDumpTest(BitcoinTestFramework):
assert_equal(found_addr, test_addr_count)
assert_equal(found_script_addr, 2)
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
- assert_equal(found_addr_rsv, 90*2)
+ assert_equal(found_addr_rsv, 90*2)
assert_equal(witness_addr_ret, witness_addr)
# Overwriting should fail
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 8c754807e6..86abe0ca99 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -11,6 +11,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
connect_nodes_bi,
+ assert_raises_rpc_error
)
@@ -28,7 +29,8 @@ class WalletHDTest(BitcoinTestFramework):
connect_nodes_bi(self.nodes, 0, 1)
# Make sure we use hd, keep masterkeyid
- masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid'])
assert_equal(len(masterkeyid), 40)
# create an internal key
@@ -53,6 +55,7 @@ class WalletHDTest(BitcoinTestFramework):
hd_add = self.nodes[1].getnewaddress()
hd_info = self.nodes[1].getaddressinfo(hd_add)
assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'")
+ assert_equal(hd_info["hdseedid"], masterkeyid)
assert_equal(hd_info["hdmasterkeyid"], masterkeyid)
self.nodes[0].sendtoaddress(hd_add, 1)
self.nodes[0].generate(1)
@@ -82,6 +85,7 @@ class WalletHDTest(BitcoinTestFramework):
hd_add_2 = self.nodes[1].getnewaddress()
hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2)
assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'")
+ assert_equal(hd_info_2["hdseedid"], masterkeyid)
assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid)
assert_equal(hd_add, hd_add_2)
connect_nodes_bi(self.nodes, 0, 1)
@@ -120,5 +124,39 @@ class WalletHDTest(BitcoinTestFramework):
assert_equal(keypath[0:7], "m/0'/1'")
+ # Generate a new HD seed on node 1 and make sure it is set
+ orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ self.nodes[1].sethdseed()
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool
+ self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key
+
+ # Set a new HD seed on node 1 without flushing the keypool
+ new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
+ orig_masterkeyid = new_masterkeyid
+ self.nodes[1].sethdseed(False, new_seed)
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid'])
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool
+
+ # Check that the next address is from the new seed
+ self.nodes[1].keypoolrefill(1)
+ next_addr = self.nodes[1].getnewaddress()
+ assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid'])
+ assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool
+ assert next_addr != addr
+
+ # Sethdseed parameter validity
+ assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed, False, new_seed, 0)
+ assert_raises_rpc_error(-5, "Invalid private key", self.nodes[1].sethdseed, False, "not_wif")
+ assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool")
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
+
if __name__ == '__main__':
WalletHDTest().main ()
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index baf933f079..4c0ffb938b 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -42,16 +42,15 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
def do_import(self, timestamp):
"""Call one key import RPC."""
+ rescan = self.rescan == Rescan.yes
if self.call == Call.single:
if self.data == Data.address:
- response = self.try_rpc(self.node.importaddress, self.address["address"], self.label,
- self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importaddress, address=self.address["address"], rescan=rescan)
elif self.data == Data.pub:
- response = self.try_rpc(self.node.importpubkey, self.address["pubkey"], self.label,
- self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importpubkey, pubkey=self.address["pubkey"], rescan=rescan)
elif self.data == Data.priv:
- response = self.try_rpc(self.node.importprivkey, self.key, self.label, self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importprivkey, privkey=self.key, rescan=rescan)
assert_equal(response, None)
elif self.call == Call.multi:
@@ -62,30 +61,22 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
"timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0),
"pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [],
"keys": [self.key] if self.data == Data.priv else [],
- "label": self.label,
"watchonly": self.data != Data.priv
}], {"rescan": self.rescan in (Rescan.yes, Rescan.late_timestamp)})
assert_equal(response, [{"success": True}])
def check(self, txid=None, amount=None, confirmations=None):
- """Verify that getbalance/listtransactions return expected values."""
+ """Verify that listreceivedbyaddress returns expected values."""
- balance = self.node.getbalance(self.label, 0, True)
- assert_equal(balance, self.expected_balance)
-
- txs = self.node.listtransactions(self.label, 10000, 0, True)
- assert_equal(len(txs), self.expected_txs)
+ addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address'])
+ if self.expected_txs:
+ assert_equal(len(addresses[0]["txids"]), self.expected_txs)
if txid is not None:
- tx, = [tx for tx in txs if tx["txid"] == txid]
- assert_equal(tx["label"], self.label)
- assert_equal(tx["address"], self.address["address"])
- assert_equal(tx["amount"], amount)
- assert_equal(tx["category"], "receive")
- assert_equal(tx["label"], self.label)
- assert_equal(tx["txid"], txid)
- assert_equal(tx["confirmations"], confirmations)
- assert_equal("trusted" not in tx, True)
+ address, = [ad for ad in addresses if txid in ad["txids"]]
+ assert_equal(address["address"], self.address["address"])
+ assert_equal(address["amount"], self.expected_balance)
+ assert_equal(address["confirmations"], confirmations)
# Verify the transaction is correctly marked watchonly depending on
# whether the transaction pays to an imported public key or
# imported private key. The test setup ensures that transaction
@@ -93,9 +84,9 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
# involvesWatchonly will be true if either the transaction output
# or inputs are watchonly).
if self.data != Data.priv:
- assert_equal(tx["involvesWatchonly"], True)
+ assert_equal(address["involvesWatchonly"], True)
else:
- assert_equal("involvesWatchonly" not in tx, True)
+ assert_equal("involvesWatchonly" not in address, True)
# List of Variants for each way a key or address could be imported.
@@ -119,7 +110,7 @@ class ImportRescanTest(BitcoinTestFramework):
self.num_nodes = 2 + len(IMPORT_NODES)
def setup_network(self):
- extra_args = [["-addresstype=legacy", '-deprecatedrpc=accounts'] for _ in range(self.num_nodes)]
+ extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)]
for i, import_node in enumerate(IMPORT_NODES, 2):
if import_node.prune:
extra_args[i] += ["-prune=1"]
@@ -130,11 +121,10 @@ class ImportRescanTest(BitcoinTestFramework):
connect_nodes(self.nodes[i], 0)
def run_test(self):
- # Create one transaction on node 0 with a unique amount and label for
+ # Create one transaction on node 0 with a unique amount for
# each possible type of wallet import RPC.
for i, variant in enumerate(IMPORT_VARIANTS):
- variant.label = "label {} {}".format(i, variant)
- variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(variant.label))
+ variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())
variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
variant.initial_amount = 10 - (i + 1) / 4.0
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py
index 505014e48f..1285515dfc 100755
--- a/test/functional/wallet_keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -16,7 +16,8 @@ class KeyPoolTest(BitcoinTestFramework):
addr_before_encrypting = nodes[0].getnewaddress()
addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting)
wallet_info_old = nodes[0].getwalletinfo()
- assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid'])
+ assert_equal(wallet_info_old['hdseedid'], wallet_info_old['hdmasterkeyid'])
+ assert(addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid'])
# Encrypt wallet and wait to terminate
nodes[0].node_encrypt_wallet('test')
@@ -26,8 +27,9 @@ class KeyPoolTest(BitcoinTestFramework):
addr = nodes[0].getnewaddress()
addr_data = nodes[0].getaddressinfo(addr)
wallet_info = nodes[0].getwalletinfo()
- assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid'])
- assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid'])
+ assert_equal(wallet_info['hdseedid'], wallet_info['hdmasterkeyid'])
+ assert(addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid'])
+ assert(addr_data['hdseedid'] == wallet_info['hdseedid'])
assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress)
# put six (plus 2) new keys in the keypool (100% external-, +100% internal-keys, 1 in min)
diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py
index ab1493dd04..d657dc30c4 100755
--- a/test/functional/wallet_keypool_topup.py
+++ b/test/functional/wallet_keypool_topup.py
@@ -25,7 +25,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.extra_args = [['-deprecatedrpc=accounts'], ['-deprecatedrpc=accounts', '-keypool=100', '-keypoolmin=20']]
+ self.extra_args = [[], ['-keypool=100']]
def run_test(self):
wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 705dd8985e..f5d7830fca 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -5,7 +5,7 @@
"""Test label RPCs.
RPCs tested are:
- - getlabeladdress
+ - getaccountaddress
- getaddressesbyaccount/getaddressesbylabel
- listaddressgroupings
- setlabel
@@ -92,17 +92,24 @@ class WalletLabelsTest(BitcoinTestFramework):
# recognize the label/address associations.
labels = [Label(name, accounts_api) for name in ("a", "b", "c", "d", "e")]
for label in labels:
- label.add_receive_address(node.getlabeladdress(label=label.name, force=True))
+ if accounts_api:
+ address = node.getaccountaddress(label.name)
+ else:
+ address = node.getnewaddress(label.name)
+ label.add_receive_address(address)
label.verify(node)
# Check all labels are returned by listlabels.
assert_equal(node.listlabels(), [label.name for label in labels])
# Send a transaction to each label, and make sure this forces
- # getlabeladdress to generate a new receiving address.
+ # getaccountaddress to generate a new receiving address.
for label in labels:
- node.sendtoaddress(label.receive_address, amount_to_send)
- label.add_receive_address(node.getlabeladdress(label.name))
+ if accounts_api:
+ node.sendtoaddress(label.receive_address, amount_to_send)
+ label.add_receive_address(node.getaccountaddress(label.name))
+ else:
+ node.sendtoaddress(label.addresses[0], amount_to_send)
label.verify(node)
# Check the amounts received.
@@ -115,10 +122,17 @@ class WalletLabelsTest(BitcoinTestFramework):
# Check that sendfrom label reduces listaccounts balances.
for i, label in enumerate(labels):
to_label = labels[(i + 1) % len(labels)]
- node.sendfrom(label.name, to_label.receive_address, amount_to_send)
+ if accounts_api:
+ node.sendfrom(label.name, to_label.receive_address, amount_to_send)
+ else:
+ node.sendfrom(label.name, to_label.addresses[0], amount_to_send)
node.generate(1)
for label in labels:
- label.add_receive_address(node.getlabeladdress(label.name))
+ if accounts_api:
+ address = node.getaccountaddress(label.name)
+ else:
+ address = node.getnewaddress(label.name)
+ label.add_receive_address(address)
label.verify(node)
assert_equal(node.getreceivedbylabel(label.name), 2)
if accounts_api:
@@ -134,12 +148,12 @@ class WalletLabelsTest(BitcoinTestFramework):
# Check that setlabel can assign a label to a new unused address.
for label in labels:
- address = node.getlabeladdress(label="", force=True)
+ address = node.getnewaddress()
node.setlabel(address, label.name)
label.add_address(address)
label.verify(node)
if accounts_api:
- assert(address not in node.getaddressesbyaccount(""))
+ assert address not in node.getaddressesbyaccount("")
else:
assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "")
@@ -160,19 +174,20 @@ class WalletLabelsTest(BitcoinTestFramework):
# Check that setlabel can change the label of an address from a
# different label.
- change_label(node, labels[0].addresses[0], labels[0], labels[1])
-
- # Check that setlabel can change the label of an address which
- # is the receiving address of a different label.
- change_label(node, labels[0].receive_address, labels[0], labels[1])
+ change_label(node, labels[0].addresses[0], labels[0], labels[1], accounts_api)
# Check that setlabel can set the label of an address already
# in the label. This is a no-op.
- change_label(node, labels[2].addresses[0], labels[2], labels[2])
+ change_label(node, labels[2].addresses[0], labels[2], labels[2], accounts_api)
+
+ if accounts_api:
+ # Check that setaccount can change the label of an address which
+ # is the receiving address of a different label.
+ change_label(node, labels[0].receive_address, labels[0], labels[1], accounts_api)
- # Check that setlabel can set the label of an address which is
- # already the receiving address of the label. This is a no-op.
- change_label(node, labels[2].receive_address, labels[2], labels[2])
+ # Check that setaccount can set the label of an address which is
+ # already the receiving address of the label. This is a no-op.
+ change_label(node, labels[2].receive_address, labels[2], labels[2], accounts_api)
class Label:
def __init__(self, name, accounts_api):
@@ -192,12 +207,14 @@ class Label:
def add_receive_address(self, address):
self.add_address(address)
- self.receive_address = address
+ if self.accounts_api:
+ self.receive_address = address
def verify(self, node):
if self.receive_address is not None:
assert self.receive_address in self.addresses
- assert_equal(node.getlabeladdress(self.name), self.receive_address)
+ if self.accounts_api:
+ assert_equal(node.getaccountaddress(self.name), self.receive_address)
for address in self.addresses:
assert_equal(
@@ -216,22 +233,26 @@ class Label:
assert_equal(set(node.getaddressesbyaccount(self.name)), set(self.addresses))
-def change_label(node, address, old_label, new_label):
+def change_label(node, address, old_label, new_label, accounts_api):
assert_equal(address in old_label.addresses, True)
- node.setlabel(address, new_label.name)
+ if accounts_api:
+ node.setaccount(address, new_label.name)
+ else:
+ node.setlabel(address, new_label.name)
old_label.addresses.remove(address)
new_label.add_address(address)
- # Calling setlabel on an address which was previously the receiving
- # address of a different label should reset the receiving address of
- # the old label, causing getlabeladdress to return a brand new
+ # Calling setaccount on an address which was previously the receiving
+ # address of a different account should reset the receiving address of
+ # the old account, causing getaccountaddress to return a brand new
# address.
- if old_label.name != new_label.name and address == old_label.receive_address:
- new_address = node.getlabeladdress(old_label.name)
- assert_equal(new_address not in old_label.addresses, True)
- assert_equal(new_address not in new_label.addresses, True)
- old_label.add_receive_address(new_address)
+ if accounts_api:
+ if old_label.name != new_label.name and address == old_label.receive_address:
+ new_address = node.getaccountaddress(old_label.name)
+ assert_equal(new_address not in old_label.addresses, True)
+ assert_equal(new_address not in new_label.addresses, True)
+ old_label.add_receive_address(new_address)
old_label.verify(node)
new_label.verify(node)
diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py
index e0e20cc9a3..e9912f994e 100755
--- a/test/functional/wallet_listreceivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -6,19 +6,22 @@
from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import (assert_array_result,
- assert_equal,
- assert_raises_rpc_error,
- )
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ assert_raises_rpc_error,
+ sync_blocks,
+)
+
class ReceivedByTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
- self.extra_args = [['-deprecatedrpc=accounts']] * 2
def run_test(self):
# Generate block to get out of IBD
self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
self.log.info("listreceivedbyaddress Test")
@@ -112,8 +115,9 @@ class ReceivedByTest(BitcoinTestFramework):
self.log.info("listreceivedbylabel + getreceivedbylabel Test")
# set pre-state
+ label = ''
address = self.nodes[1].getnewaddress()
- label = self.nodes[1].getaccount(address)
+ assert_equal(self.nodes[1].getaddressinfo(address)['label'], label)
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
balance_by_label = self.nodes[1].getreceivedbylabel(label)
@@ -141,7 +145,8 @@ class ReceivedByTest(BitcoinTestFramework):
assert_equal(balance, balance_by_label + Decimal("0.1"))
# Create a new label named "mynewlabel" that has a 0 balance
- self.nodes[1].getlabeladdress(label="mynewlabel", force=True)
+ address = self.nodes[1].getnewaddress()
+ self.nodes[1].setlabel(address, "mynewlabel")
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][0]
# Test includeempty of listreceivedbylabel
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 50a3313e2f..63c179411c 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -11,7 +11,6 @@ class ListSinceBlockTest (BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
self.setup_clean_chain = True
- self.extra_args = [['-deprecatedrpc=accounts']] * 4
def run_test(self):
self.nodes[2].generate(101)
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index 883942cc19..7cf2e456cf 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -25,7 +25,6 @@ def tx_from_hex(hexstring):
class ListTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
- self.extra_args = [['-deprecatedrpc=accounts']] * 2
self.enable_mocktime()
def run_test(self):
@@ -34,19 +33,19 @@ class ListTransactionsTest(BitcoinTestFramework):
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
{"txid": txid},
- {"category": "send", "account": "", "amount": Decimal("-0.1"), "confirmations": 0})
+ {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0})
assert_array_result(self.nodes[1].listtransactions(),
{"txid": txid},
- {"category": "receive", "account": "", "amount": Decimal("0.1"), "confirmations": 0})
+ {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0})
# mine a block, confirmations should change:
self.nodes[0].generate(1)
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
{"txid": txid},
- {"category": "send", "account": "", "amount": Decimal("-0.1"), "confirmations": 1})
+ {"category": "send", "amount": Decimal("-0.1"), "confirmations": 1})
assert_array_result(self.nodes[1].listtransactions(),
{"txid": txid},
- {"category": "receive", "account": "", "amount": Decimal("0.1"), "confirmations": 1})
+ {"category": "receive", "amount": Decimal("0.1"), "confirmations": 1})
# send-to-self:
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
@@ -60,8 +59,8 @@ class ListTransactionsTest(BitcoinTestFramework):
# sendmany from node1: twice to self, twice to node2:
send_to = {self.nodes[0].getnewaddress(): 0.11,
self.nodes[1].getnewaddress(): 0.22,
- self.nodes[0].getaccountaddress("from1"): 0.33,
- self.nodes[1].getaccountaddress("toself"): 0.44}
+ self.nodes[0].getnewaddress(): 0.33,
+ self.nodes[1].getnewaddress(): 0.44}
txid = self.nodes[1].sendmany("", send_to)
self.sync_all()
assert_array_result(self.nodes[1].listtransactions(),
@@ -81,13 +80,13 @@ class ListTransactionsTest(BitcoinTestFramework):
{"txid": txid})
assert_array_result(self.nodes[0].listtransactions(),
{"category": "receive", "amount": Decimal("0.33")},
- {"txid": txid, "account": "from1"})
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
{"category": "send", "amount": Decimal("-0.44")},
- {"txid": txid, "account": ""})
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
{"category": "receive", "amount": Decimal("0.44")},
- {"txid": txid, "account": "toself"})
+ {"txid": txid})
pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
multisig = self.nodes[1].createmultisig(1, [pubkey])
@@ -95,10 +94,9 @@ class ListTransactionsTest(BitcoinTestFramework):
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
self.nodes[1].generate(1)
self.sync_all()
- assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
- assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
- {"category": "receive", "amount": Decimal("0.1")},
- {"txid": txid, "account": "watchonly"})
+ assert not [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=False) if "label" in tx and tx["label"] == "watchonly"]
+ txs = [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=True) if "label" in tx and tx['label'] == 'watchonly']
+ assert_array_result(txs, {"category": "receive", "amount": Decimal("0.1")}, {"txid": txid})
self.run_rbf_opt_in_test()
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index e0571ea8f9..3cefd83459 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -88,7 +88,7 @@ class MultiWalletTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist')
# should not initialize if the specified walletdir is not a directory
not_a_dir = wallet_dir('notadir')
- open(not_a_dir, 'a').close()
+ open(not_a_dir, 'a', encoding="utf8").close()
self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
self.log.info("Do not allow -zapwallettxes with multiwallet")
@@ -170,5 +170,96 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(w1.getwalletinfo()['paytxfee'], 0)
assert_equal(w2.getwalletinfo()['paytxfee'], 4.0)
+ self.log.info("Test dynamic wallet loading")
+
+ self.restart_node(0, ['-nowallet'])
+ assert_equal(node.listwallets(), [])
+ assert_raises_rpc_error(-32601, "Method not found", node.getwalletinfo)
+
+ self.log.info("Load first wallet")
+ loadwallet_name = node.loadwallet(wallet_names[0])
+ assert_equal(loadwallet_name['name'], wallet_names[0])
+ assert_equal(node.listwallets(), wallet_names[0:1])
+ node.getwalletinfo()
+ w1 = node.get_wallet_rpc(wallet_names[0])
+ w1.getwalletinfo()
+
+ self.log.info("Load second wallet")
+ loadwallet_name = node.loadwallet(wallet_names[1])
+ assert_equal(loadwallet_name['name'], wallet_names[1])
+ assert_equal(node.listwallets(), wallet_names[0:2])
+ assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo)
+ w2 = node.get_wallet_rpc(wallet_names[1])
+ w2.getwalletinfo()
+
+ self.log.info("Load remaining wallets")
+ for wallet_name in wallet_names[2:]:
+ loadwallet_name = self.nodes[0].loadwallet(wallet_name)
+ assert_equal(loadwallet_name['name'], wallet_name)
+
+ assert_equal(set(self.nodes[0].listwallets()), set(wallet_names))
+
+ # Fail to load if wallet doesn't exist
+ assert_raises_rpc_error(-18, 'Wallet wallets not found.', self.nodes[0].loadwallet, 'wallets')
+
+ # Fail to load duplicate wallets
+ assert_raises_rpc_error(-4, 'Wallet file verification failed: Error loading wallet w1. Duplicate -wallet filename specified.', self.nodes[0].loadwallet, wallet_names[0])
+
+ # Fail to load if one wallet is a copy of another
+ assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
+
+ # Fail to load if wallet file is a symlink
+ assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
+
+ self.log.info("Test dynamic wallet creation.")
+
+ # Fail to create a wallet if it already exists.
+ assert_raises_rpc_error(-4, "Wallet w2 already exists.", self.nodes[0].createwallet, 'w2')
+
+ # Successfully create a wallet with a new name
+ loadwallet_name = self.nodes[0].createwallet('w9')
+ assert_equal(loadwallet_name['name'], 'w9')
+ w9 = node.get_wallet_rpc('w9')
+ assert_equal(w9.getwalletinfo()['walletname'], 'w9')
+
+ assert 'w9' in self.nodes[0].listwallets()
+
+ # Successfully create a wallet using a full path
+ new_wallet_dir = os.path.join(self.options.tmpdir, 'new_walletdir')
+ new_wallet_name = os.path.join(new_wallet_dir, 'w10')
+ loadwallet_name = self.nodes[0].createwallet(new_wallet_name)
+ assert_equal(loadwallet_name['name'], new_wallet_name)
+ w10 = node.get_wallet_rpc(new_wallet_name)
+ assert_equal(w10.getwalletinfo()['walletname'], new_wallet_name)
+
+ assert new_wallet_name in self.nodes[0].listwallets()
+
+ self.log.info("Test dynamic wallet unloading")
+
+ # Test `unloadwallet` errors
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].unloadwallet)
+ assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", self.nodes[0].unloadwallet, "dummy")
+ assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", node.get_wallet_rpc("dummy").unloadwallet)
+ assert_raises_rpc_error(-8, "Cannot unload the requested wallet", w1.unloadwallet, "w2"),
+
+ # Successfully unload the specified wallet name
+ self.nodes[0].unloadwallet("w1")
+ assert 'w1' not in self.nodes[0].listwallets()
+
+ # Successfully unload the wallet referenced by the request endpoint
+ w2.unloadwallet()
+ assert 'w2' not in self.nodes[0].listwallets()
+
+ # Successfully unload all wallets
+ for wallet_name in self.nodes[0].listwallets():
+ self.nodes[0].unloadwallet(wallet_name)
+ assert_equal(self.nodes[0].listwallets(), [])
+ assert_raises_rpc_error(-32601, "Method not found (wallet method is disabled because no wallet is loaded)", self.nodes[0].getwalletinfo)
+
+ # Successfully load a previously unloaded wallet
+ self.nodes[0].loadwallet('w1')
+ assert_equal(self.nodes[0].listwallets(), ['w1'])
+ assert_equal(w1.getwalletinfo()['walletname'], 'w1')
+
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index b4e4cb1686..72ae2d5db7 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -15,7 +15,6 @@ from test_framework.util import (
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
- self.extra_args = [['-deprecatedrpc=accounts']] * 4
def add_options(self, parser):
parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true",
@@ -39,28 +38,27 @@ class TxnMallTest(BitcoinTestFramework):
starting_balance = 1250
for i in range(4):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
+ self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress!
- # Assign coins to foo and bar accounts:
self.nodes[0].settxfee(.001)
- node0_address_foo = self.nodes[0].getnewaddress("foo", output_type)
- fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219)
- fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid)
+ node0_address1 = self.nodes[0].getnewaddress(address_type=output_type)
+ node0_txid1 = self.nodes[0].sendtoaddress(node0_address1, 1219)
+ node0_tx1 = self.nodes[0].gettransaction(node0_txid1)
- node0_address_bar = self.nodes[0].getnewaddress("bar", output_type)
- fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29)
- fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid)
+ node0_address2 = self.nodes[0].getnewaddress(address_type=output_type)
+ node0_txid2 = self.nodes[0].sendtoaddress(node0_address2, 29)
+ node0_tx2 = self.nodes[0].gettransaction(node0_txid2)
- assert_equal(self.nodes[0].getbalance(""),
- starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"])
+ assert_equal(self.nodes[0].getbalance(),
+ starting_balance + node0_tx1["fee"] + node0_tx2["fee"])
# Coins are sent to node1_address
- node1_address = self.nodes[1].getnewaddress("from0")
+ node1_address = self.nodes[1].getnewaddress()
# Send tx1, and another transaction tx2 that won't be cloned
- txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0)
- txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0)
+ txid1 = self.nodes[0].sendtoaddress(node1_address, 40)
+ txid2 = self.nodes[0].sendtoaddress(node1_address, 20)
# Construct a clone of tx1, to be malleated
rawtx1 = self.nodes[0].getrawtransaction(txid1, 1)
@@ -96,28 +94,22 @@ class TxnMallTest(BitcoinTestFramework):
# Node0's balance should be starting balance, plus 50BTC for another
# matured block, minus tx1 and tx2 amounts, and minus transaction fees:
- expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"]
+ expected = starting_balance + node0_tx1["fee"] + node0_tx2["fee"]
if self.options.mine_block:
expected += 50
expected += tx1["amount"] + tx1["fee"]
expected += tx2["amount"] + tx2["fee"]
assert_equal(self.nodes[0].getbalance(), expected)
- # foo and bar accounts should be debited:
- assert_equal(self.nodes[0].getbalance("foo", 0), 1219 + tx1["amount"] + tx1["fee"])
- assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
-
if self.options.mine_block:
assert_equal(tx1["confirmations"], 1)
assert_equal(tx2["confirmations"], 1)
- # Node1's "from0" balance should be both transaction amounts:
- assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"]))
else:
assert_equal(tx1["confirmations"], 0)
assert_equal(tx2["confirmations"], 0)
# Send clone and its parent to miner
- self.nodes[2].sendrawtransaction(fund_foo_tx["hex"])
+ self.nodes[2].sendrawtransaction(node0_tx1["hex"])
txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"])
if self.options.segwit:
assert_equal(txid1, txid1_clone)
@@ -128,7 +120,7 @@ class TxnMallTest(BitcoinTestFramework):
# Reconnect the split network, and sync chain:
connect_nodes(self.nodes[1], 2)
- self.nodes[2].sendrawtransaction(fund_bar_tx["hex"])
+ self.nodes[2].sendrawtransaction(node0_tx2["hex"])
self.nodes[2].sendrawtransaction(tx2["hex"])
self.nodes[2].generate(1) # Mine another block to make sure we sync
sync_blocks(self.nodes)
@@ -149,19 +141,6 @@ class TxnMallTest(BitcoinTestFramework):
if (self.options.mine_block):
expected -= 50
assert_equal(self.nodes[0].getbalance(), expected)
- assert_equal(self.nodes[0].getbalance("*", 0), expected)
-
- # Check node0's individual account balances.
- # "foo" should have been debited by the equivalent clone of tx1
- assert_equal(self.nodes[0].getbalance("foo"), 1219 + tx1["amount"] + tx1["fee"])
- # "bar" should have been debited by (possibly unconfirmed) tx2
- assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
- # "" should have starting balance, less funding txes, plus subsidies
- assert_equal(self.nodes[0].getbalance("", 0),
- starting_balance - 1219 + fund_foo_tx["fee"] - 29 + fund_bar_tx["fee"] + 100)
-
- # Node1's "from0" account balance
- assert_equal(self.nodes[1].getbalance("from0", 0), -(tx1["amount"] + tx2["amount"]))
if __name__ == '__main__':
TxnMallTest().main()
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index d8d91132d1..7ee60d5611 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -17,7 +17,6 @@ from test_framework.util import (
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 4
- self.extra_args = [['-deprecatedrpc=accounts']] * 4
def add_options(self, parser):
parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true",
@@ -36,20 +35,20 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(self.nodes[i].getbalance(), starting_balance)
self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
- # Assign coins to foo and bar accounts:
- node0_address_foo = self.nodes[0].getnewaddress("foo")
- fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219)
+ # Assign coins to foo and bar addresses:
+ node0_address_foo = self.nodes[0].getnewaddress()
+ fund_foo_txid = self.nodes[0].sendtoaddress(node0_address_foo, 1219)
fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid)
- node0_address_bar = self.nodes[0].getnewaddress("bar")
- fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29)
+ node0_address_bar = self.nodes[0].getnewaddress()
+ fund_bar_txid = self.nodes[0].sendtoaddress(node0_address_bar, 29)
fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid)
- assert_equal(self.nodes[0].getbalance(""),
- starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"])
+ assert_equal(self.nodes[0].getbalance(),
+ starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"])
# Coins are sent to node1_address
- node1_address = self.nodes[1].getnewaddress("from0")
+ node1_address = self.nodes[1].getnewaddress()
# First: use raw transaction API to send 1240 BTC to node1_address,
# but don't broadcast:
@@ -70,8 +69,8 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(doublespend["complete"], True)
# Create two spends using 1 50 BTC coin each
- txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0)
- txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0)
+ txid1 = self.nodes[0].sendtoaddress(node1_address, 40)
+ txid2 = self.nodes[0].sendtoaddress(node1_address, 20)
# Have node0 mine a block:
if (self.options.mine_block):
@@ -90,15 +89,11 @@ class TxnMallTest(BitcoinTestFramework):
expected += tx2["amount"] + tx2["fee"]
assert_equal(self.nodes[0].getbalance(), expected)
- # foo and bar accounts should be debited:
- assert_equal(self.nodes[0].getbalance("foo", 0), 1219 + tx1["amount"] + tx1["fee"])
- assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
-
if self.options.mine_block:
assert_equal(tx1["confirmations"], 1)
assert_equal(tx2["confirmations"], 1)
- # Node1's "from0" balance should be both transaction amounts:
- assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"]))
+ # Node1's balance should be both transaction amounts:
+ assert_equal(self.nodes[1].getbalance(), starting_balance - tx1["amount"] - tx2["amount"])
else:
assert_equal(tx1["confirmations"], 0)
assert_equal(tx2["confirmations"], 0)
@@ -129,17 +124,9 @@ class TxnMallTest(BitcoinTestFramework):
# negative):
expected = starting_balance + 100 - 1240 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee
assert_equal(self.nodes[0].getbalance(), expected)
- assert_equal(self.nodes[0].getbalance("*"), expected)
-
- # Final "" balance is starting_balance - amount moved to accounts - doublespend + subsidies +
- # fees (which are negative)
- assert_equal(self.nodes[0].getbalance("foo"), 1219)
- assert_equal(self.nodes[0].getbalance("bar"), 29)
- assert_equal(self.nodes[0].getbalance(""),
- starting_balance - 1219 - 29 - 1240 + 100 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee)
- # Node1's "from0" account balance should be just the doublespend:
- assert_equal(self.nodes[1].getbalance("from0"), 1240)
+ # Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend:
+ assert_equal(self.nodes[1].getbalance(), 1250 + 1240)
if __name__ == '__main__':
TxnMallTest().main()