mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-13 12:33:42 +02:00
MERGE-FIX: Copy bitcoin_functional from upstream
This commit is contained in:
parent
9f4f2e7519
commit
449ac89f39
78 changed files with 1699 additions and 806 deletions
|
|
@ -60,6 +60,11 @@ don't have test cases for.
|
|||
- When calling RPCs with lots of arguments, consider using named keyword
|
||||
arguments instead of positional arguments to make the intent of the call
|
||||
clear to readers.
|
||||
- Many of the core test framework classes such as `CBlock` and `CTransaction`
|
||||
don't allow new attributes to be added to their objects at runtime like
|
||||
typical Python objects allow. This helps prevent unpredictable side effects
|
||||
from typographical errors or usage of the objects outside of their intended
|
||||
purpose.
|
||||
|
||||
#### RPC and P2P definitions
|
||||
|
||||
|
|
@ -72,7 +77,7 @@ P2P messages. These can be found in the following source files:
|
|||
|
||||
#### Using the P2P interface
|
||||
|
||||
- `mininode.py` contains all the definitions for objects that pass
|
||||
- `messages.py` contains all the definitions for objects that pass
|
||||
over the network (`CBlock`, `CTransaction`, etc, along with the network-level
|
||||
wrappers for them, `msg_block`, `msg_tx`, etc).
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,8 @@ def main():
|
|||
parser = argparse.ArgumentParser(usage='%(prog)s [options] <test temporary directory>', description=__doc__)
|
||||
parser.add_argument('-c', '--color', dest='color', action='store_true', help='outputs the combined log with events colored by source (requires posix terminal colors. Use less -r for viewing)')
|
||||
parser.add_argument('--html', dest='html', action='store_true', help='outputs the combined log as html. Requires jinja2. pip install jinja2')
|
||||
parser.add_argument('--chain', dest='chain', help='selected chain in the tests (default: regtest2)', default='regtest2')
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
|
||||
if args.color and os.name != 'posix':
|
||||
print("Color output requires posix terminal colors.")
|
||||
sys.exit(1)
|
||||
|
||||
if args.html and args.color:
|
||||
print("Only one out of --color or --html should be specified")
|
||||
sys.exit(1)
|
||||
|
|
|
|||
|
|
@ -1,117 +1,117 @@
|
|||
{
|
||||
"blocks": [
|
||||
"0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4adae5494dffff7f20020000000101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000",
|
||||
"0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f69267c77854047f17f73b4f1cffdce0fcd7f9dba5284a8ce1f29b9c8bd82e1824f6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03510101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204368d04dee8ab6fe7ad8e10bae9a8b44d3209ff99e9ac957961377d1f7d15b2a5aea310b010e5bbc71efb61bfb190d20cbb23b5a1e43811e6704f1f942e7bc8c506d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03520101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020bf84c54824e9e19d745726d68d86ae40e20c92c869c7debd01c22ae77406325d2adc7fd006c687e61cbe5664ae530f08c1e05f104aef6f59eee26570490d3a08506d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03530101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020a6d1cbc703ebf125c9bdd5b6e978fae8bd6d07c99bf802feff7af0fcd8eb767b94a2fd82a973246332416a45d6d3dd36d80f1eeb2042c6ad4799b4713a45634e516d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03540101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002088016cd11f0c33dc621c55562c67511bc0231293346b51c7ac601c352a4c971753bfc060d0da761b6217454553394a50ffde3240be1f67e34e11ac24070fdd52516d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03550101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002022385dd3f49f940d9a1f2258735a2ef0ea02a312b2cbe71ed08dde2976103c7fdc0ecbff0653b064dd262af5ac9e68caa7aa3a1d797998e9768e05d76342675d516d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03560101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002010b46e27279b27c6be9d3ae633fa631140a0ee49fddc14d7eea85d0e6ed4637fc70ec23c83712830fe090506ea7d00dfc7d110775993e5a904bdd5d5c3728be0516d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03570101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000201da51b7b9fb7e60441b82e7bd3d40878c0c3fa44d1ba5ed6a45ff912fe3f6c6f38cd0f5aff4163b3a1c7a4c329c3e1dcaa70c16dfe0ab4e2b7e01d0e008bd31f526d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03580101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d4c18e899968abb904dab966357c985d6e4401f161a8ac2885e21d8c5ec1a529cabe196f867faf959fb79dc1d212c360a9b5c27900e0701ac916ad888581e4b0526d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03590101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002065ce0baa3f4dfeb4878072534fb5e097896b50f54862031b30551a572f991f489c7191c7c2734b980fd05802c03611fb1f13f80b3328cb338e939a75f535669c526d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203e6133afe39fa2d85ed2a5bbfe9f10afd9f48e7a0a6001a332967585fc42d151642eaa439a5beae846513c9ae7f2ffeac94ad145ddeb9dfa0134cebfdfbb4ad9526d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020aed13f5d0e5e813c1b3f03ac3b0f03f93d1320c2f65be1689572ae009fea007eae86802f055234f8bac4fb9458ab172b71d16df94f4a714072ca02d19dca2b14526d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002027f3187f5a9f0d8606aa10a933212f6f490797063376d10bcf1fb525e078246b3fcb4623cb74ff5b23da369efba3633d8158c9d45aea66750ece9ad088e0e853526d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020a4c567c91236b8cfa5f0c3c09ac1f5189b0d0a961d7d465db72e9f406052ee6ff507ff7c7e09b1480a1c2a52e116239be50ad2f1e25c127f7e841865f79575e9536d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020881795e44852cbf15376ff4b2b8e4f0c13c990bb1aa989a1cd02de6e72f2a804df5f64756152c471e6d3023f0a5a461d86afdf58721f1dc9d26a2908a88b9e49536d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff035f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020a8bd5b51c0f93fde19d85a00f7dcb91982c87b998e9225ee1cedeb6d010a904a63c5c7c2fa7405fe4eff50aef5ca030be7c8a7e411b9999ea8c2e91435f3e0ce536d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff03600101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002075b17d1cde46881b1f483e452ec1bcaf11bcd85405a62eceeac54c719dfb8d1b34fae8a011c88bd00642c32768ffbdae25032c2044aa196f049d1fd44689a79e536d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401110101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204883916ad172ddcbfaf7899666ff817ce25f805a48a7c48f26a854d563fe4920dade6f2f69feb5642403aa894021373d61f5a0246b1f3dec2c72275b17ee18ad536d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401120101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000209bcbe3afd9a884f4fe4906dcad2892c964df350d6c535eb34367d061386e2e22ea15160f0b27ef65db4289215cc9760e74ba9de0042d4fbbe1c7451a9519063d536d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401130101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000209116c6d7b3c91f143446b59877ba742e307597a41291bc9b423edd177140554ca5043d3e85461cfbd819d0f8c1629ef1fd3c1d419e37fade9b6a89068f18231e546d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401140101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020bbc0d10cc86654955fb50bee7a4dde8b0c559bce754ef989248105a2f7ce7c7cebd0de2adfb5cd226b4d66973cb1b9686d2a04b7551e1fc78ef0e7c389c29071546d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401150101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000207115c8fb00a07785ac61130828b1d11bb6622534c56d53aedc26bea3f50e0753fc8336a1465e1525fd5d65d4ddf0c3b35982cdd69b584e2c55e486d6616bab08546d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401160101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002037e136cc5c4fb689e77f430ee8c46331b6f63d3fc6090de413145f485b56b647a085e8f5b297b0fc202679013dd7d21b5afbeb265f986434ed8e479173c3a281546d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401170101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020db1b7cc33b3a9466a355006c1077e0af75bfe2ae901a36025c2c5e202520e61eb60aee8e7a01a368ff34aeac157e54764dd2e1993e3b295506b19431e19451c8546d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401180101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204b215087f3cd0529726fb2e5bcd2f02886a32340aa6403feea8234ebfccea132573390b52144ae28141a9958385e81cd0ae19e2052a0249ee4a60330fcd19fdc546d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401190101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d3e5e1d18fb40ea9713de365bb0595dc34a35b0805227ea384ec4556bcc95614249f438f29b527ce38f6572b26dbb0a4bee61af7e22afc38cf4ebcf0893fab7f556d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203f53af5e207e7b95e81cf22c640d9d990d3ed6fa74d41c777e4d20cff6dfcd277b95795881bca0d1661b91a32cda4386f7dc082f6aad0d6e0b898dca59eadffb556d505cffff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e51e45c882235d0234cf8c7a9b78ddc5562d6aece4edad32b9ac2ef2efb88f1f8d39b8fb52dda66a93a59358ad76c42257ca7d458404e96a8171299f525f3bd9556d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002072685ab97dba557fedfb563024aec0f5113d3438f7591a8664ea803eb9d21a4ebaf8478612d01af4c8b23421a5f57dea58f41b811cbb1958397f697b5c0c14fd556d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020b7bb1b296112e4a9aa634dd94336edc5d2d45859ef35a7eca51a201effb98f42cbf8270652bba80e41ae5352bba5791d238f372dc3b6afb4a5c46dd01fb0f8f8556d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e3447bf231daa0f65af40d303348a36a42819be85c9c398b70dac23c2cd2082e1cc969275bcdd22a01dfba17bc852578a3850ae42849857bf8d1e8665568e016556d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04011f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020cb52a42d3eedd515a870a4958a467738040680966b82b00d7a3036f67e109226eadf3e2a8513d5a379f595dcc7ae629377475e509b89ad81ee3addf894e736dd566d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401200101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d4e0306f17cc8244c499d545e32819551ea0bdb7deef59e586765ad89980983125923b4d2846c7b8f1d8c3f94252977fa43b4864c765d8cad15621a8154a7365566d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401210101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002006cffe783ef25219d4e31f94026422680419adbe24310964132a459c66915a46649e58b35b75aa2268e7a6beab151839ffdff7ae79b55b38b9034211d0fabfdd566d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401220101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002003703fb77710082f24a5e9a55139016b2ef7fa55c0ff52984a6db9113a5cd25caaa6c4a19c3595470de4f2e32f7f3b352a580c5353f02085af42dc6796bd7bcc566d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401230101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e4f7b8233c6244c39b9802336ce59645c936089d3016c5eac79a25ec7e00b57ccedd0a5ad40703fb5c02749828b3532ff36b4cb554579a30e752fc579990e327566d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401240101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000201ce7ea5233ee6931b812743745329b07dc519641cd30dc30df8cc30fb57edc739f5826011fbf16c064fb5827f4612bd76886efa4c3648b4ee42b16a92b099ef5566d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401250101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002037a33aced942588ceada52d6c43efb9de077e263a6be1ec8948c9b686784ad49b423b08b02540f27bdbbd69f5df825f107f12a39116d29e82a18a0afec6713b9576d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401260101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204560b947007a3a7070ee806f59e0f336053cfb6ff2352309b4e50d655c87a8122169caf51843e1b8bc02e0b8461f281bb77f0498149e9f994fb11b3392b07b52576d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401270101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020cb546aa08b1c59722e884a76c819861069947a01344f6ee61259b143c863930d52af67248ccea109739f4ed3839b2751396a80f748856c0a273d325b81a9f820576d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401280101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020835f06f2e956719c7de6f1ff699deb129c2caf945a0f042b7e6e27a2c770212be68e128e0a95f4362eea17a22f19f5fb22ffee1616e7a57754dc22cbfbf655e5576d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401290101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002093ec8e28cde4ddfc90f5873f727d8d41081f040d83f7ede0dcd3d42b131a6817dbd3303bb66472d5e9f42c42315dbadfde0b68a7e03b34ede93a65301e9013bc576d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020b856fc71d66f0f1dccd11d5f17388c201383ddd39023715e8b29b7deb164f53e2c3cccc10c0e2a0cc5967c91443efb37df89b1316d4885d4843b263a91f132e4576d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002093ee0029697b68c9e751a3d4be505ad06f79bfb3ae713f699ca195ffd49b250f88f8a97e0330097afb7badbc3c0d8d4434c9351ae0ae4e47da6c74e6e3ac7e37586d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204adb37d53bd90c965329c11522e02a8061c4f0c9f71f3fd18af073beef9fef79885e74941698823f7dd7b3207521ebf371bc4be668607b358d350a61ba4924d4586d505cffff7f200400000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e586789a2eaac1af1e881f6ecaccb438bcd2852687c5c5641817d8e315583c674e1384c5d31bd3b1d9945d26d082328f89abe243b7a3b0742118fb97456f4ada586d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e61bab3348402b7d6d46e1a643261535adb310fd0d87c7096e4ab83dba08526e0a71f6f1b8730e3465ebbb10f5b3120c068f2260f08b038d2277f27aa8725e7e586d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04012f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020cab4bad194e7d337d7372b5f1a8f8b529e00f6c855e90b988cc0588599a1d56acc7faefcd3b91c6566bcad9f2c4ba5569f041d3a626a67d519576543f1a02a86586d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401300101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020a17345014289ed1d32e0c67bcb2bfd985d3229fac0420a39d7567bedecbce428b5366a03302e52da050570df5da137f110f9ee812c1354420ba435aa1d920fa5586d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401310101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020326570a2b26e2fe49b31a3751e60702218d5db03d671ffc33ffd97156120ee11aab3a3d536daecc2e3555ade1db1746db324f2fa50b7548483be0c86113f27d1596d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401320101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000201c55691393e2a219410a794620216b2608724b76e8285d4e6051e6a82d716549c1a6555d25b8848387ba9ee42f3fb773cc3a5a67e4ca931714e95f4d805541dd596d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401330101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203f81b09a82990d66ccebb0700d39b9b0ea616fbffb23ea06218113b55564745a3f784790cdafacc2e55f4bfe2a57f6a6674bc30167e8179617dfa50f23fa7c8c596d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401340101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020098a023792b378f73135afb906990121c37252da636d72bb37587134f638164e6ef3a0e811b8bb5c28066381065a4c76c77a3ea272fb4a3af67cc7ca9dd7fd0e596d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401350101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020ff6cc86e00d5fba58b2a377b6aabb1e09df8b721a8c38928df642524313b871e8cc7b1a00cff612d151f3f42f4a117236ff3e9e4064673b8b6e2798500b4a3ec596d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401360101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020998a460dfd6502cd1ee2563442a75196632079f13c3f37745a01dc9f5f477c1bb6fd121b4d197ccc4a997f8fd19955641f11ad6f3d447d99040fa13ba73583b2596d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401370101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002034aad53abf7939b58df544ab0325bdc8637e90fe26a4cc216a5fb92f011f7a236b85d25cae9b9637317f830926408be4c0ee00112b2b076c05a98e0583c2df245a6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401380101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020ee26ae6c5cb5edb54989ddab0d38ed2eb0f1f75488a52116a8b0d3dc2bcd470345c2f16f9ef906fe4580280f5ea2300291879f5437710c23f2c63de6ae2544d35a6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401390101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203c564b3bfac2b77609ddea0c865cf4c86acebcffd7b33d7e855a887a62911834ec324a87a00704cc93fd2c2e007e63831294c382af3fef7bec20f8087fb170125a6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203020d015564406d239bd27eb7f4542d5e1f6c1216b5b24c2ccc9fd39eacc8a53a87c426de000583814d2fc5194def9078547226d1bb0866b61ed17c9f0411d825a6d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020900b6a5442df8403ca4c961b98c7bca53b3df6a94d1fb28a0bbbc89e33e5a52f6cca6a1e971781ad1fac04f5202cc4eff531e896264dc1e75fbf071e2f4e3f0f5a6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000208313878e73fbd7628efa3dd670f8114cdfd8de8ccf30a6ac0f4affd3d67cae50e686a0a9b431c37c7006781c761b05d52954d171c5211effd7e59c98139fc7645a6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002015b83e4d8f01de5794aac4459dba7002b59889345da817979018ca5c26249505019dad51f8b671bc34a97805e43f7ba3e9653188ddf0aade11a0f48477c299035b6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020cc9aa08f9c0caba92e087eda209b58ddce61b08dc66f57f937116f06d4a4bc1ab0f55f7adf6d06f5108c4680e9d76b5ad05089d050f5946c7bf38f1382cddf0a5b6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04013f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020492f97fd7c4ff275b90e8240967c59ba930c5671e48b6f4007109c589764aa3d49a5cbf761e5f5224d6d4ffc345e99118c006c609bb1ba679cf749af29fe2ce75b6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401400101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020751d20f167e444018a7bbbab981c23e698458a6c058b825fce658e0563d5546238c95cf84e756f5b71d7e1b2ab50ef0e45313051269d9f8fc84dae9619b591495b6d505cffff7f200900000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401410101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204c8838d43499a5833e8634b790101c8d6da74ba40e548c82e71bda5b9d737d53e4bdd407fad78536b25728449bf17466113dd96aad49bd0738b82a887632b5ca5b6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401420101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000203982ee52aa49097527b458933d774c7f651d0a3c581c797f49f42f609b95f7448d7327896a7d09ee7035bc470beef5bc6213f6425a212ceae772c8124724cac95b6d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401430101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020cd37f325772b4e179598ae0d4995b26bc75dbe9c70c4ccc810cb1e52c9ea1d39359762ab3f747e113f3bb2b709dd3e7fddefc3977e91e89fe127676a67435e3e5c6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401440101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020702939003631495fa28fe40dfd546e26d3833fc418364a8f94a0bffe26642928c946914899b4150d175248f64d2e2c8b9942d428838d90090ef9ae4bdec5bc1f5c6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401450101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d2faf88500e28f03f8e7454178523ac875d8b7e46293861b392da765eeee9a4c528e9863243e7405499dad45d605342f687835ae56b9a9c0f42df262c3b56d4e5c6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401460101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d0dff532472b32cb018d99d842ab371a439f750bd072bfaf3d5b8c4b6ac1b2642020e9c8c91a6fe9e10a6389817dfc1f8d0515c974dd0339a957d713c0250a0a5c6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401470101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000206701aca3536f416e60f42191d5ed815477084ea9caa4dd00c3b8f6def10ed449a004436149999edf272e12067c1763a72a212991afbe99e76fdb9a1218cd287e5c6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401480101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020ad8ca7ced8f32b099a768b9e1b748543ae0523cea2a0caf9b43eb03093b8703e805b94d7033b90c731371b4a6da15c1f8d4b0dfa2605454bd3e71f9e9405618f5c6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401490101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002090eac7451738d49309c021ec417c46545308d2f327264ac591a07864e692a87298dfac2da63a0f6d3959d26c30ba2b0ca7162bb96443bac0e5555315df09b07e5d6d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020d48402d96141b1f2ad07ab30a001972a65739b4158ab84e47929807c8a6fa032e7eff90136bd1d2a22dcf9c135546ab166059d76e02552102c272471c45a7cb95d6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020eaf4725067ee94a3634ba2aec25ca383bc54b84442686b5fc1163ae50f6eb4573684e5853d2fe00c0eaf8a2ab6bc76847157eed30b9afdfca4abdd1e8744e58b5d6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e3c359035ce47b295300090d498bc744aa549c02d04163a582dfc8c871f47918dc070fbbcd076832685b8ba16f700dbfc9e4b3df91c453e476a70cb54d8fb6245d6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002074ddd2845b805f38d719ed0a5f699c38cbefc1f1ad12f6691739535aec4289662c1c7fe8e60cbb0cfb14f06cd955b38889a8345db9bdc900f30cd51fe90ae4445d6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000200fd8d5ee818727df53fd72fd7ead0b7bd02c3cdbaec8bf98e1c2088835365c7af6324e8bdd755ec6606a9125a6e464d46a32915fdd14e099e1660494090aaae35d6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04014f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020116e84b8b3d7c53bfbfc540f19adb313294fc341d06e6fa32df0c53bc1f9156588042cecee928cf871c8b708d639d6dc51548c4ae0a6cd86022f4b8e2e4587f05e6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401500101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020c2ea6cdf0cfe7217d46e699f10b525e2f14632d02debffaec184891ad887f833f1b305aec70fbad62fcf474d3570ed0341eb707c325c8926bf4a418f0ac8d4a05e6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401510101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000206730c06db8a51b03fc2503685d3c102d98e61c8f81206d63988e73cd7365965dd4296dd739d0e771da9ae9ffb1a62be8de19e2e0cdbe445e2f046e43a5a5b2f75e6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401520101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e9a9c04961a7eb48949184487a23147b57d7e691fc5dbd1ce8166973bf0e11454641d2dc20c63fb9b0490fcb5a1d08c1c82c6e2f784b0dbe9371bb88d51cb66a5e6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401530101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002003c16f410411a9f60475c6ef920077aa76c64f6e54c1f880c5f30645e8a6d46eae982638ce9296f39439c311ee6f3dd534aeaaca1c14deab7424f15f71332b9a5e6d505cffff7f200900000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401540101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000206a67736749a44367f885a2a2518d8c72837b39eceec43d320a27eb497966ad38868a246df81aebc5a046e03412e0efa6b3588d7bc75e8ea6cdcb0a17147d28395e6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401550101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000201d29c55ec28ed455595a9a3905b36b4c0f6ab6eca0cfe1c16702808b2dcde12b47f6b318331a10e3e93d60f866297f2afde490e2b2d566ffe0f110f6c5c9c7bf5f6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401560101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020db18537baf044c29cb5f947280d03ee94d5ba934ac47aa69516c4993f15fee71e3fa3817f700d7324b800d0b33a405aef74ba5ce2004ce18a4c9a8774883e8595f6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401570101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204ce3b6981fef72d76dc76263e001a85ca72e9ad12432c284bb64b03dccdfa121138c735370622f271e7828c30261e297066d08c9e9d5fb937331fcf5454fc07c5f6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401580101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020ad6f6320bc14d9ea794a4dc4aa7cf55bf89965bb15488d280ac35a3b10f35e5da12c51a9d0913a9dcaf0a93c6151afde91e95bc38309c5ed0195b637a21e9a095f6d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401590101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204363923e20712472d54ab5082677ce45f394b22b1139f4ba83d24b68cb8007126a67a787de855bfe06cd865c67f888c7d7bd974a23a176b4cf5daa0940de96645f6d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015a0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020636372fbd7565eb92d1f536edeb7ca0d5dd84d516648d08f2c16e05add8ee071212d733aa80837aa44c8cc1e04534483c1c661f4472dfa706c59ef97ec440b195f6d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015b0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020161ac623003562940f6b68f94c21422280a3c45dd9b980b68b5f1966ab61dc6134c547d8987a68324ec6e006a23eb4b4762878f0996d625312def9be49b26555606d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015c0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002034108cc49dd1b06f8fd7ab64c27465284afa03cae78fa5e3edcc35e9adbf38310691a2303f1cb0e6f6547cef98df37af82578514ae8f5fcb722a5cba575b493a606d505cffff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015d0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204609ca069257105aa0c3dd1b997d6dc9eff98477c1856188b5fb421040db7e755b071f630652076351d891c6895c1020de9f64aa15089c0c88cf96467f63f011606d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015e0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020f9a38a22b10b9667823ab205c7e85eb60c6b7487965006290837779defb96b507a343e21c54ffad5b066b8523ec625ff6297f2945bdaa704a589f538ec6399fa606d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04015f0101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204316ca9b7a3b83dd3030ef42c6dbc580c95168449ca8c3b1a050c8a83acff641a6328a192da69fe826c1eb746866783d3c85b9689d72f5e262306bbd27076fc3606d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401600101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000204fad0ac3f91a76ad02800ecb61b1a25ee88bcc5111a244865a1b7abe03d40974934d9d76039241d7584fd58bc2b143410a1d7a2fb577f597d14845d998f896ef606d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401610101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000002084b341d81ce9638e1a531e156acb711249fea5d467e4b4bd07968dead868f62b1cd74be98d76a2b98c917f0c3661c8502baf77927dfd338699504336e7cc0c1b616d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401620101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020c6a7e682867a85f07fc5c6e5522b84e4946b08bde18b6c795f54298714c0f61cc6fa505f2d5a8ee82218910f1a00e205882b39e4f5661afb1461607384bf2b2b616d505cffff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020f3b58b7787dca4546619bf4d2069c07aaf63e143a1a1dd78025420eaaee4bd482bf67b702348dbcd4517619eaef10551b45260732d4c32d7ab4b11e3d1eabd25616d505cffff7f200200000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"000000206cae3abe4162161567bb27e2a729f1eab9e4c433fbd28cc144a6fab67752256c956d1f38df2ad6a393bbf7973b96b6e4879a8e439aec931e858988ac25d1ee64616d505cffff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a01000000232102eae8289a6f5ff629b8877fba0da555dcff91f134f0359301e0a2d95cdfb0ea26ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"00000020e1a5d2f911c17bca7bbf085e6200319309f360d22df4ffcd3b20f530c16e3d0b4b53556d5844e2b18a55dc2d3c017422651e39fa11d995385b4816a1d7c23cdf616d505cffff7f200000000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff029c00062a01000000232102cf58c61f25feb39fbaeaf07b8c2eb4fa9112f0e48a5f05826f9c20dd0b1b61b9ac0000000000000000266a24aa21a9ed24d639eead21bf766f793804dabcea904ffcbd2e2040c42acb8c0f1c24d602120120000000000000000000000000000000000000000000000000000000000000000000000000020000000169267c77854047f17f73b4f1cffdce0fcd7f9dba5284a8ce1f29b9c8bd82e1820000000048473044022026477966bb300f4de19f0f5dfebe0ea9821fc16ff1d86d6d334b7c633befdb3f022075d7fa864470208963993d4ae53df311eafb0007ad1f076c65da70c13024b07a01fdffffff0264bb9a3b0000000017a914aa3f335b24749a1e8c7238880d7dc6ce8205e3828700286bee0000000017a914fff64215a9ffb080d596e874b1f73ac7269684648765000000",
|
||||
"0000002018155e981a3e2cc1390a0c61d79b5812bca4184f6f8a9b50dd8c3662d8a97951ce5893892031d756196472e93d074d0b93c852e3cc0d622469d6177ee091e668616d505cffff7f200000000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff021cd0062a01000000232103a6a2c3471f77e5a40d6f545e54b7f2147b9b2ec599a2532abc15c745d8f362b4ac0000000000000000266a24aa21a9ed90c1e3c7e323f4fe1a9718fadc7ed1d2bb22d6567907953ff337c705c27ceba60120000000000000000000000000000000000000000000000000000000000000000000000000020000000001011224e2b2d38f665e83037345a3b296f794a402084a85f5720b508d39fc7c765c000000001716001417b5970a703dbe66f7bef82aacc3b70fb6741b98fdffffff0264daa4350000000017a914c8ffd0b7af1d86a9c0bd2bce960c5c4743c2d0f387781ef5050000000017a914c1eda8707c24de3849672f5efb295e0a966adbfd870247304402200c8ee07802f29c9e9181c0ffd14e685669161aa873fe81990d9ce32ee084fa92022064872a944532e87f45b2178e9282b10d9972ce794dc8e289108389ec17ebbf4901210234555d567c1a0b387f518d64b7dfc23da5e6ee1d90d745a9e26687795acb68511b00000002000000015aea310b010e5bbc71efb61bfb190d20cbb23b5a1e43811e6704f1f942e7bc8c000000004847304402200e7f77b8ec16cfbb14f91213405a6018e57279e9469aa920e6a7e9db98b1a5b9022055a635e29a0654bccd1bc09ca299cfea6a08bd79b696a0f7d94fe51e3b65b5d901fdffffff0264196bee0000000017a91478348089b993a376e3bd0f4b429491fdbb2c73b68700ca9a3b0000000017a91468de4c05f3a39609ec6eaa90ce02d42ec29cd09c8766000000020000000001011224e2b2d38f665e83037345a3b296f794a402084a85f5720b508d39fc7c765c010000001716001494ee60544c2282f509f32036753e055d92d447f8fdffffff0208bd9a3b0000000017a9140271287ab0498bfd106b22606f43738588bab93687005ed0b20000000017a9145e5914a69db6c898776095bb77a4dc15539ac0f287024730440220048beffb98b18695b8fd912e0959755707a6139750618ae7aeb9b1dd0ff7d4f502206ed5bbc31abf41b393dbc35ad0f172d3f9ef939b9685fd8b97f61e828b2cdf13012103b53f65bc452a181847cc8c9e45016ce3764299033d352811445b94284a9e9d9366000000"
|
||||
"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": 1548774735,
|
||||
"mocktime": 1525107225,
|
||||
"stats": [
|
||||
{
|
||||
"avgfee": 0,
|
||||
"avgfeerate": 0,
|
||||
"avgtxsize": 0,
|
||||
"blockhash": "0b3d6ec130f5203bcdfff42dd260f309933100625e08bf7bca7bc111f9d2a5e1",
|
||||
"blockhash": "1d7fe80f19d28b8e712af0399ac84006db753441f3033111b3a8d610afab364f",
|
||||
"feerate_percentiles": [
|
||||
0,
|
||||
0,
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
"maxfeerate": 0,
|
||||
"maxtxsize": 0,
|
||||
"medianfee": 0,
|
||||
"mediantime": 1548774752,
|
||||
"mediantime": 1525107242,
|
||||
"mediantxsize": 0,
|
||||
"minfee": 0,
|
||||
"minfeerate": 0,
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
"swtotal_size": 0,
|
||||
"swtotal_weight": 0,
|
||||
"swtxs": 0,
|
||||
"time": 1548774753,
|
||||
"time": 1525107243,
|
||||
"total_out": 0,
|
||||
"total_size": 0,
|
||||
"total_weight": 0,
|
||||
|
|
@ -145,10 +145,11 @@
|
|||
"utxo_size_inc": 173
|
||||
},
|
||||
{
|
||||
"avgfee": 3740,
|
||||
"avgfee": 3760,
|
||||
"avgfeerate": 20,
|
||||
"avgtxsize": 187,
|
||||
"blockhash": "5179a9d862368cdd509b8a6f4f18a4bc12589bd7610c0a39c12c3e1a985e1518",
|
||||
"blockhash": "4e21a43675d7a41cb6b944e068c5bcd0a677baf658d9ebe021ae2d2f99397ccc",
|
||||
"height": 102,
|
||||
"feerate_percentiles": [
|
||||
20,
|
||||
20,
|
||||
|
|
@ -156,15 +157,14 @@
|
|||
20,
|
||||
20
|
||||
],
|
||||
"height": 102,
|
||||
"ins": 1,
|
||||
"maxfee": 3740,
|
||||
"maxfee": 3760,
|
||||
"maxfeerate": 20,
|
||||
"maxtxsize": 187,
|
||||
"medianfee": 3740,
|
||||
"mediantime": 1548774752,
|
||||
"medianfee": 3760,
|
||||
"mediantime": 1525107242,
|
||||
"mediantxsize": 187,
|
||||
"minfee": 3740,
|
||||
"minfee": 3760,
|
||||
"minfeerate": 20,
|
||||
"mintxsize": 187,
|
||||
"outs": 4,
|
||||
|
|
@ -172,48 +172,48 @@
|
|||
"swtotal_size": 0,
|
||||
"swtotal_weight": 0,
|
||||
"swtxs": 0,
|
||||
"time": 1548774753,
|
||||
"total_out": 4999996260,
|
||||
"time": 1525107243,
|
||||
"total_out": 4999996240,
|
||||
"total_size": 187,
|
||||
"total_weight": 748,
|
||||
"totalfee": 3740,
|
||||
"totalfee": 3760,
|
||||
"txs": 2,
|
||||
"utxo_increase": 3,
|
||||
"utxo_size_inc": 234
|
||||
},
|
||||
{
|
||||
"avgfee": 18953,
|
||||
"avgfee": 18960,
|
||||
"avgfeerate": 109,
|
||||
"avgtxsize": 227,
|
||||
"blockhash": "023d532c1219ec366bce7e8dae07143d002edffd8ec081b3a768459ae9c4fab3",
|
||||
"avgtxsize": 228,
|
||||
"blockhash": "22d9b8b9c2a37c81515f3fc84f7241f6c07dbcea85ef16b00bcc33ae400a030f",
|
||||
"feerate_percentiles": [
|
||||
20,
|
||||
20,
|
||||
20,
|
||||
301,
|
||||
301
|
||||
300,
|
||||
300
|
||||
],
|
||||
"height": 103,
|
||||
"ins": 3,
|
||||
"maxfee": 49800,
|
||||
"maxfeerate": 301,
|
||||
"maxtxsize": 247,
|
||||
"medianfee": 3740,
|
||||
"mediantime": 1548774753,
|
||||
"mediantxsize": 247,
|
||||
"maxfeerate": 300,
|
||||
"maxtxsize": 248,
|
||||
"medianfee": 3760,
|
||||
"mediantime": 1525107243,
|
||||
"mediantxsize": 248,
|
||||
"minfee": 3320,
|
||||
"minfeerate": 20,
|
||||
"mintxsize": 187,
|
||||
"mintxsize": 188,
|
||||
"outs": 8,
|
||||
"subsidy": 5000000000,
|
||||
"swtotal_size": 494,
|
||||
"swtotal_weight": 1322,
|
||||
"swtotal_size": 496,
|
||||
"swtotal_weight": 1324,
|
||||
"swtxs": 2,
|
||||
"time": 1548774753,
|
||||
"total_out": 9999939400,
|
||||
"total_size": 681,
|
||||
"total_weight": 2070,
|
||||
"totalfee": 56860,
|
||||
"time": 1525107243,
|
||||
"total_out": 9999939360,
|
||||
"total_size": 684,
|
||||
"total_weight": 2076,
|
||||
"totalfee": 56880,
|
||||
"txs": 4,
|
||||
"utxo_increase": 5,
|
||||
"utxo_size_inc": 380
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
"cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIQIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1PtnuylhxDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA",
|
||||
"cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wCAwABAAAAAAEAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A",
|
||||
"cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAgAAFgAUYunpgv/zTdgjlhAxawkM0qO3R8sAAQAiACCHa62DLx0WgBXtQSMqnqZaGBXZ7xPA74dZ9ktbKyeKZQEBJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A",
|
||||
"cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A"
|
||||
"cHNidP8BAHMCAAAAATAa6YblFqHsisW0vGVz0y+DtGXiOtdhZ9aLOOcwtNvbAAAAAAD/////AnR7AQAAAAAAF6kUA6oXrogrXQ1Usl1jEE5P/s57nqKHYEOZOwAAAAAXqRS5IbG6b3IuS/qDtlV6MTmYakLsg4cAAAAAAAEBHwDKmjsAAAAAFgAU0tlLZK4IWH7vyO6xh8YB6Tn5A3wAAQAWABRi6emC//NN2COWEDFrCQzSo7dHywABACIAIIdrrYMvHRaAFe1BIyqeploYFdnvE8Dvh1n2S1srJ4plIQEAJVEhA7fOI6AcW0vwCmQlN836uzFbZoMyhnR471EwnSvVf4qHUa4A",
|
||||
"cHNidP8BAHMCAAAAAbiWoY6pOQepFsEGhUPXaulX9rvye2NH+NrdlAHg+WgpAQAAAAD/////AkBLTAAAAAAAF6kUqWwXCcLM5BN2zoNqMNT5qMlIi7+HQEtMAAAAAAAXqRSVF/in2XNxAlN1OSxkyp0z+Wtg2YcAAAAAAAEBIBNssgAAAAAAF6kUamsvautR8hRlMRY6OKNTx03DK96HAQcXFgAUo8u1LWpHprjt/uENAwBpGZD0UH0BCGsCRzBEAiAONfH3DYiw67ZbylrsxCF/XXpVwyWBRgofyRbPslzvwgIgIKCsWw5sHSIPh1icNvcVLZLHWj6NA7Dk+4Os2pOnMbQBIQPGStfYHPtyhpV7zIWtn0Q4GXv5gK1zy/tnJ+cBXu4iiwABABYAFMwmJQEz+HDpBEEabxJ5PogPsqZRAAEAFgAUyCrGc3h3FYCmiIspbv2pSTKZ5jU"
|
||||
],
|
||||
"valid" : [
|
||||
"cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA",
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ class ExampleTest(BitcoinTestFramework):
|
|||
|
||||
# self.log.info("I've finished set_test_params") # Oops! Can't run self.log before run_test()
|
||||
|
||||
# Use skip_test_if_missing_module() to skip the test if your test requires certain modules to be present.
|
||||
# This test uses generate which requires wallet to be compiled
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
|
|
@ -162,13 +164,13 @@ class ExampleTest(BitcoinTestFramework):
|
|||
self.tip = int(self.nodes[0].getbestblockhash(), 16)
|
||||
self.block_time = self.nodes[0].getblock(self.nodes[0].getbestblockhash())['time'] + 1
|
||||
|
||||
height = 1
|
||||
height = self.nodes[0].getblockcount()
|
||||
|
||||
for i in range(10):
|
||||
# Use the mininode and blocktools functionality to manually build a block
|
||||
# Calling the generate() rpc is easier, but this allows us to exactly
|
||||
# control the blocks and transactions.
|
||||
block = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
block = create_block(self.tip, create_coinbase(height+1), self.block_time)
|
||||
block.solve()
|
||||
block_message = msg_block(block)
|
||||
# Send message is used to send a P2P message to the node over our P2PInterface
|
||||
|
|
|
|||
|
|
@ -75,9 +75,6 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.extra_args = [[]]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0] # convenience reference to the node
|
||||
|
||||
|
|
@ -827,7 +824,7 @@ class FullBlockTest(BitcoinTestFramework):
|
|||
tx.vin.append(CTxIn(COutPoint(b64a.vtx[1].sha256, 0)))
|
||||
b64a = self.update_block("64a", [tx])
|
||||
assert_equal(len(b64a.serialize()), MAX_BLOCK_BASE_SIZE + 8)
|
||||
self.sync_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize(): iostream error')
|
||||
self.sync_blocks([b64a], success=False, reject_reason='non-canonical ReadCompactSize()')
|
||||
|
||||
# bitcoind doesn't disconnect us for sending a bloated block, but if we subsequently
|
||||
# resend the header message, it won't send us the getdata message again. Just
|
||||
|
|
|
|||
|
|
@ -16,13 +16,10 @@ class BlocksdirTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
self.stop_node(0)
|
||||
shutil.rmtree(self.nodes[0].datadir)
|
||||
initialize_datadir(self.options.tmpdir, 0, self.chain)
|
||||
initialize_datadir(self.options.tmpdir, 0)
|
||||
self.log.info("Starting with nonexistent blocksdir ...")
|
||||
blocksdir_path = os.path.join(self.options.tmpdir, 'blocksdir')
|
||||
self.nodes[0].assert_start_raises_init_error(["-blocksdir=" + blocksdir_path], 'Error: Specified blocks directory "{}" does not exist.'.format(blocksdir_path))
|
||||
|
|
@ -30,9 +27,9 @@ class BlocksdirTest(BitcoinTestFramework):
|
|||
self.log.info("Starting with existing blocksdir ...")
|
||||
self.start_node(0, ["-blocksdir=" + blocksdir_path])
|
||||
self.log.info("mining blocks..")
|
||||
self.nodes[0].generate(10)
|
||||
assert os.path.isfile(os.path.join(blocksdir_path, "regtest2", "blocks", "blk00000.dat"))
|
||||
assert os.path.isdir(os.path.join(self.nodes[0].datadir, "regtest2", "blocks", "index"))
|
||||
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
||||
assert os.path.isfile(os.path.join(blocksdir_path, "regtest", "blocks", "blk00000.dat"))
|
||||
assert os.path.isdir(os.path.join(self.nodes[0].datadir, "regtest", "blocks", "index"))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ CLTV_HEIGHT = 1351
|
|||
|
||||
# Reject codes that we might receive in this test
|
||||
REJECT_INVALID = 16
|
||||
REJECT_OBSOLETE = 17
|
||||
REJECT_NONSTANDARD = 64
|
||||
|
||||
def cltv_invalidate(tx):
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ class ConfArgsTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def test_config_file_parser(self):
|
||||
# Assume node is stopped
|
||||
|
||||
|
|
@ -32,6 +29,10 @@ class ConfArgsTest(BitcoinTestFramework):
|
|||
conf.write('nono\n')
|
||||
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead')
|
||||
|
||||
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
|
||||
conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass')
|
||||
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
|
||||
|
||||
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
|
||||
conf.write('') # clear
|
||||
|
||||
|
|
@ -68,13 +69,18 @@ class ConfArgsTest(BitcoinTestFramework):
|
|||
# Temporarily disabled, because this test would access the user's home dir (~/.bitcoin)
|
||||
#self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
|
||||
#self.stop_node(0)
|
||||
#assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'blocks'))
|
||||
#if self.is_wallet_compiled():
|
||||
#assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1'))
|
||||
|
||||
# Ensure command line argument overrides datadir in conf
|
||||
os.mkdir(new_data_dir_2)
|
||||
self.nodes[0].datadir = new_data_dir_2
|
||||
self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
|
||||
assert os.path.exists(os.path.join(new_data_dir_2, 'regtest2', 'wallets', 'w2'))
|
||||
assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'blocks'))
|
||||
if self.is_wallet_compiled():
|
||||
assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ConfArgsTest().main()
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
|
|||
def setup_network(self):
|
||||
self.add_nodes(self.num_nodes, extra_args=self.extra_args)
|
||||
self.start_nodes()
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
# Leave them unconnected, we'll use submitblock directly in this test
|
||||
|
||||
def restart_node(self, node_index, expected_tip):
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ DERSIG_HEIGHT = 1251
|
|||
|
||||
# Reject codes that we might receive in this test
|
||||
REJECT_INVALID = 16
|
||||
REJECT_OBSOLETE = 17
|
||||
REJECT_NONSTANDARD = 64
|
||||
|
||||
# A canonical signature consists of:
|
||||
|
|
|
|||
|
|
@ -144,6 +144,9 @@ class EstimateFeeTest(BitcoinTestFramework):
|
|||
# (68k weight is room enough for 120 or so transactions)
|
||||
# Node2 is a stingy miner, that
|
||||
# produces too small blocks (room for only 55 or so transactions)
|
||||
self.start_nodes()
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
self.stop_nodes()
|
||||
|
||||
def transact_and_mine(self, numblocks, mining_node):
|
||||
min_fee = Decimal("0.00001")
|
||||
|
|
@ -171,11 +174,6 @@ class EstimateFeeTest(BitcoinTestFramework):
|
|||
newmem.append(utx)
|
||||
self.memutxo = newmem
|
||||
|
||||
def import_deterministic_coinbase_privkeys(self):
|
||||
self.start_nodes()
|
||||
super().import_deterministic_coinbase_privkeys()
|
||||
self.stop_nodes()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("This test is time consuming, please be patient")
|
||||
self.log.info("Splitting inputs so we can generate tx's")
|
||||
|
|
|
|||
36
test/bitcoin_functional/functional/feature_filelock.py
Executable file
36
test/bitcoin_functional/functional/feature_filelock.py
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
#!/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.
|
||||
"""Check that it's not possible to start a second bitcoind instance using the same datadir or wallet."""
|
||||
import os
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.test_node import ErrorMatch
|
||||
|
||||
class FilelockTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 2
|
||||
|
||||
def setup_network(self):
|
||||
self.add_nodes(self.num_nodes, extra_args=None)
|
||||
self.nodes[0].start([])
|
||||
self.nodes[0].wait_for_rpc_connection()
|
||||
|
||||
def run_test(self):
|
||||
datadir = os.path.join(self.nodes[0].datadir, 'regtest')
|
||||
self.log.info("Using datadir {}".format(datadir))
|
||||
|
||||
self.log.info("Check that we can't start a second bitcoind instance using the same datadir")
|
||||
expected_msg = "Error: Cannot obtain a lock on data directory {}. Bitcoin Core is probably already running.".format(datadir)
|
||||
self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg)
|
||||
|
||||
if self.is_wallet_compiled():
|
||||
wallet_dir = os.path.join(datadir, 'wallets')
|
||||
self.log.info("Check that we can't start a second bitcoind instance using the same wallet")
|
||||
expected_msg = "Error: Error initializing wallet database environment"
|
||||
self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX)
|
||||
|
||||
if __name__ == '__main__':
|
||||
FilelockTest().main()
|
||||
|
|
@ -15,11 +15,8 @@ class LoggingTest(BitcoinTestFramework):
|
|||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def relative_log_path(self, name):
|
||||
return os.path.join(self.nodes[0].datadir, "regtest2", name)
|
||||
return os.path.join(self.nodes[0].datadir, "regtest", name)
|
||||
|
||||
def run_test(self):
|
||||
# test default log file name
|
||||
|
|
|
|||
|
|
@ -5,85 +5,84 @@
|
|||
"""Test the -alertnotify, -blocknotify and -walletnotify options."""
|
||||
import os
|
||||
|
||||
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, wait_until, connect_nodes_bi
|
||||
|
||||
|
||||
class NotificationsTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||
self.block_filename = os.path.join(self.options.tmpdir, "blocks.txt")
|
||||
self.tx_filename = os.path.join(self.options.tmpdir, "transactions.txt")
|
||||
self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify")
|
||||
self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify")
|
||||
self.walletnotify_dir = os.path.join(self.options.tmpdir, "walletnotify")
|
||||
os.mkdir(self.alertnotify_dir)
|
||||
os.mkdir(self.blocknotify_dir)
|
||||
os.mkdir(self.walletnotify_dir)
|
||||
|
||||
# -alertnotify and -blocknotify on node0, walletnotify on node1
|
||||
self.extra_args = [["-blockversion=2",
|
||||
"-alertnotify=echo %%s >> %s" % self.alert_filename,
|
||||
"-blocknotify=echo %%s >> %s" % self.block_filename],
|
||||
self.extra_args = [[
|
||||
"-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')),
|
||||
"-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))],
|
||||
["-blockversion=211",
|
||||
"-rescan",
|
||||
"-walletnotify=echo %%s >> %s" % self.tx_filename]]
|
||||
"-walletnotify=echo > {}".format(os.path.join(self.walletnotify_dir, '%s'))]]
|
||||
super().setup_network()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("test -blocknotify")
|
||||
block_count = 10
|
||||
blocks = self.nodes[1].generate(block_count)
|
||||
blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE)
|
||||
|
||||
# wait at most 10 seconds for expected file size before reading the content
|
||||
wait_until(lambda: os.path.isfile(self.block_filename) and os.stat(self.block_filename).st_size >= (block_count * 65), timeout=10)
|
||||
# wait at most 10 seconds for expected number of files before reading the content
|
||||
wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10)
|
||||
|
||||
# file content should equal the generated blocks hashes
|
||||
with open(self.block_filename, 'r', encoding="utf-8") as f:
|
||||
assert_equal(sorted(blocks), sorted(l.strip() for l in f.read().splitlines()))
|
||||
# directory content should equal the generated blocks hashes
|
||||
assert_equal(sorted(blocks), sorted(os.listdir(self.blocknotify_dir)))
|
||||
|
||||
self.log.info("test -walletnotify")
|
||||
# wait at most 10 seconds for expected file size before reading the content
|
||||
wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)
|
||||
if self.is_wallet_compiled():
|
||||
self.log.info("test -walletnotify")
|
||||
# wait at most 10 seconds for expected number of files before reading the content
|
||||
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
||||
|
||||
# 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', encoding="ascii") as f:
|
||||
assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
|
||||
os.remove(self.tx_filename)
|
||||
# directory content should equal the generated transaction hashes
|
||||
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
|
||||
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
||||
self.stop_node(1)
|
||||
for tx_file in os.listdir(self.walletnotify_dir):
|
||||
os.remove(os.path.join(self.walletnotify_dir, tx_file))
|
||||
|
||||
self.log.info("test -walletnotify after rescan")
|
||||
# restart node to rescan to force wallet notifications
|
||||
self.restart_node(1)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
self.log.info("test -walletnotify after rescan")
|
||||
# restart node to rescan to force wallet notifications
|
||||
self.start_node(1)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
|
||||
wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat(self.tx_filename).st_size >= (block_count * 65), timeout=10)
|
||||
wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10)
|
||||
|
||||
# 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', encoding="ascii") as f:
|
||||
assert_equal(sorted(txids_rpc), sorted(l.strip() for l in f.read().splitlines()))
|
||||
# directory content should equal the generated transaction hashes
|
||||
txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count)))
|
||||
assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir)))
|
||||
|
||||
# Mine another 41 up-version blocks. -alertnotify should trigger on the 51st.
|
||||
self.log.info("test -alertnotify")
|
||||
self.nodes[1].generate(41)
|
||||
self.nodes[1].generatetoaddress(41, ADDRESS_BCRT1_UNSPENDABLE)
|
||||
self.sync_all()
|
||||
|
||||
# Give bitcoind 10 seconds to write the alert notification
|
||||
wait_until(lambda: os.path.isfile(self.alert_filename) and os.path.getsize(self.alert_filename), timeout=10)
|
||||
wait_until(lambda: len(os.listdir(self.alertnotify_dir)), timeout=10)
|
||||
|
||||
with open(self.alert_filename, 'r', encoding='utf8') as f:
|
||||
alert_text = f.read()
|
||||
for notify_file in os.listdir(self.alertnotify_dir):
|
||||
os.remove(os.path.join(self.alertnotify_dir, notify_file))
|
||||
|
||||
# Mine more up-version blocks, should not get more alerts:
|
||||
self.nodes[1].generate(2)
|
||||
self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
|
||||
self.sync_all()
|
||||
|
||||
with open(self.alert_filename, 'r', encoding='utf8') as f:
|
||||
alert_text2 = f.read()
|
||||
|
||||
self.log.info("-alertnotify should not continue notifying for more unknown version blocks")
|
||||
assert_equal(alert_text, alert_text2)
|
||||
assert_equal(len(os.listdir(self.alertnotify_dir)), 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
NotificationsTest().main()
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Generate 427 more blocks.
|
|||
[Consensus] Check that the new NULLDUMMY rules are not enforced on the 431st block.
|
||||
[Policy/Consensus] Check that the new NULLDUMMY rules are enforced on the 432nd block.
|
||||
"""
|
||||
import time
|
||||
|
||||
from test_framework.blocktools import create_coinbase, create_block, create_transaction, add_witness_commitment
|
||||
from test_framework.messages import CTransaction
|
||||
|
|
@ -19,8 +20,6 @@ from test_framework.script import CScript
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error, bytes_to_hex_str
|
||||
|
||||
import time
|
||||
|
||||
NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero) (code 64)"
|
||||
|
||||
def trueDummy(tx):
|
||||
|
|
@ -42,7 +41,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', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]]
|
||||
self.extra_args = [['-whitelist=127.0.0.1', '-vbparams=segwit:0:999999999999', '-addresstype=legacy']]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
|
@ -50,14 +49,14 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
|||
def run_test(self):
|
||||
self.address = self.nodes[0].getnewaddress()
|
||||
self.ms_address = self.nodes[0].addmultisigaddress(1, [self.address])['address']
|
||||
self.wit_address = self.nodes[0].addwitnessaddress(self.address)
|
||||
self.wit_address = self.nodes[0].getnewaddress(address_type='p2sh-segwit')
|
||||
self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address']
|
||||
|
||||
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
|
||||
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
|
||||
coinbase_txid = []
|
||||
for i in self.coinbase_blocks:
|
||||
coinbase_txid.append(self.nodes[0].getblock(i)['tx'][0])
|
||||
self.nodes[0].generate(427) # Block 429
|
||||
self.nodes[0].generate(427) # Block 429
|
||||
self.lastblockhash = self.nodes[0].getbestblockhash()
|
||||
self.tip = int("0x" + self.lastblockhash, 0)
|
||||
self.lastblockheight = 429
|
||||
|
|
@ -82,7 +81,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info("Test 4: Non-NULLDUMMY base multisig transaction is invalid after activation")
|
||||
test4tx = create_transaction(self.nodes[0], test2tx.hash, self.address, amount=46)
|
||||
test6txs=[CTransaction(test4tx)]
|
||||
test6txs = [CTransaction(test4tx)]
|
||||
trueDummy(test4tx)
|
||||
assert_raises_rpc_error(-26, NULLDUMMY_ERROR, self.nodes[0].sendrawtransaction, bytes_to_hex_str(test4tx.serialize_with_witness()), True)
|
||||
self.block_submit(self.nodes[0], [test4tx])
|
||||
|
|
@ -99,8 +98,7 @@ class NULLDUMMYTest(BitcoinTestFramework):
|
|||
self.nodes[0].sendrawtransaction(bytes_to_hex_str(i.serialize_with_witness()), True)
|
||||
self.block_submit(self.nodes[0], test6txs, True, True)
|
||||
|
||||
|
||||
def block_submit(self, node, txs, witness = False, accept = False):
|
||||
def block_submit(self, node, txs, witness=False, accept=False):
|
||||
block = create_block(self.tip, create_coinbase(self.lastblockheight + 1), self.lastblocktime + 1)
|
||||
block.nVersion = 4
|
||||
for tx in txs:
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ class PruneTest(BitcoinTestFramework):
|
|||
def setup_nodes(self):
|
||||
self.add_nodes(self.num_nodes, self.extra_args)
|
||||
self.start_nodes()
|
||||
for n in self.nodes:
|
||||
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase', rescan=False)
|
||||
|
||||
def create_big_chain(self):
|
||||
# Start by creating some coinbases we can spend later
|
||||
|
|
|
|||
|
|
@ -18,11 +18,8 @@ class ReindexTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def reindex(self, justchainstate=False):
|
||||
self.nodes[0].generate(3)
|
||||
self.nodes[0].generatetoaddress(3, self.nodes[0].get_deterministic_priv_key().address)
|
||||
blockcount = self.nodes[0].getblockcount()
|
||||
self.stop_nodes()
|
||||
extra_args = [["-reindex-chainstate" if justchainstate else "-reindex"]]
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@
|
|||
"""Test the SegWit changeover logic."""
|
||||
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
|
||||
from test_framework.address import (
|
||||
key_to_p2pkh,
|
||||
key_to_p2sh_p2wpkh,
|
||||
key_to_p2wpkh,
|
||||
program_to_witness,
|
||||
script_to_p2sh,
|
||||
script_to_p2sh_p2wsh,
|
||||
|
|
@ -21,8 +20,6 @@ from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash16
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error, bytes_to_hex_str, connect_nodes, hex_str_to_bytes, sync_blocks, try_rpc
|
||||
|
||||
from io import BytesIO
|
||||
|
||||
NODE_0 = 0
|
||||
NODE_2 = 2
|
||||
WIT_V0 = 0
|
||||
|
|
@ -51,20 +48,17 @@ class SegWitTest(BitcoinTestFramework):
|
|||
"-rpcserialversion=0",
|
||||
"-vbparams=segwit:0:999999999999",
|
||||
"-addresstype=legacy",
|
||||
"-deprecatedrpc=addwitnessaddress",
|
||||
],
|
||||
[
|
||||
"-blockversion=4",
|
||||
"-rpcserialversion=1",
|
||||
"-vbparams=segwit:0:999999999999",
|
||||
"-addresstype=legacy",
|
||||
"-deprecatedrpc=addwitnessaddress",
|
||||
],
|
||||
[
|
||||
"-blockversion=536870915",
|
||||
"-vbparams=segwit:0:999999999999",
|
||||
"-addresstype=legacy",
|
||||
"-deprecatedrpc=addwitnessaddress",
|
||||
],
|
||||
]
|
||||
|
||||
|
|
@ -91,9 +85,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||
def fail_accept(self, node, error_msg, txid, sign, redeem_script=""):
|
||||
assert_raises_rpc_error(-26, error_msg, send_to_witness, use_p2wsh=1, node=node, utxo=getutxo(txid), pubkey=self.pubkey[0], encode_p2sh=False, amount=Decimal("49.998"), sign=sign, insert_redeem_script=redeem_script)
|
||||
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[0].generate(161) #block 161
|
||||
self.nodes[0].generate(161) # block 161
|
||||
|
||||
self.log.info("Verify sigops are counted in GBT with pre-BIP141 rules before the fork")
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
|
|
@ -103,28 +96,24 @@ class SegWitTest(BitcoinTestFramework):
|
|||
assert(tmpl['sigoplimit'] == 20000)
|
||||
assert(tmpl['transactions'][0]['hash'] == txid)
|
||||
assert(tmpl['transactions'][0]['sigops'] == 2)
|
||||
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
||||
tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||
assert(tmpl['sizelimit'] == 1000000)
|
||||
assert('weightlimit' not in tmpl)
|
||||
assert(tmpl['sigoplimit'] == 20000)
|
||||
assert(tmpl['transactions'][0]['hash'] == txid)
|
||||
assert(tmpl['transactions'][0]['sigops'] == 2)
|
||||
self.nodes[0].generate(1) #block 162
|
||||
self.nodes[0].generate(1) # block 162
|
||||
|
||||
balance_presetup = self.nodes[0].getbalance()
|
||||
self.pubkey = []
|
||||
p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
|
||||
wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
|
||||
p2sh_ids = [] # p2sh_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE embedded in p2sh
|
||||
wit_ids = [] # wit_ids[NODE][VER] is an array of txids that spend to a witness version VER pkscript to an address for NODE via bare witness
|
||||
for i in range(3):
|
||||
newaddress = self.nodes[i].getnewaddress()
|
||||
self.pubkey.append(self.nodes[i].getaddressinfo(newaddress)["pubkey"])
|
||||
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
|
||||
p2sh_addr = self.nodes[i].addwitnessaddress(newaddress)
|
||||
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
|
||||
p2sh_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'p2sh-segwit')['address']
|
||||
bip173_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'bech32')['address']
|
||||
assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1]))
|
||||
assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1]))
|
||||
assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))
|
||||
assert_equal(bip173_ms_addr, script_to_p2wsh(multiscript))
|
||||
p2sh_ids.append([])
|
||||
|
|
@ -139,32 +128,32 @@ class SegWitTest(BitcoinTestFramework):
|
|||
wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
|
||||
p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))
|
||||
|
||||
self.nodes[0].generate(1) #block 163
|
||||
self.nodes[0].generate(1) # block 163
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# Make sure all nodes recognize the transactions as theirs
|
||||
assert_equal(self.nodes[0].getbalance(), balance_presetup - 60*50 + 20*Decimal("49.999") + 50)
|
||||
assert_equal(self.nodes[1].getbalance(), 20*Decimal("49.999"))
|
||||
assert_equal(self.nodes[2].getbalance(), 20*Decimal("49.999"))
|
||||
assert_equal(self.nodes[0].getbalance(), balance_presetup - 60 * 50 + 20 * Decimal("49.999") + 50)
|
||||
assert_equal(self.nodes[1].getbalance(), 20 * Decimal("49.999"))
|
||||
assert_equal(self.nodes[2].getbalance(), 20 * Decimal("49.999"))
|
||||
|
||||
self.nodes[0].generate(260) #block 423
|
||||
self.nodes[0].generate(260) # block 423
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
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
|
||||
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426
|
||||
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427
|
||||
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
|
||||
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) # block 426
|
||||
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) # block 427
|
||||
|
||||
self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid")
|
||||
self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False)
|
||||
self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False)
|
||||
|
||||
self.nodes[2].generate(4) # blocks 428-431
|
||||
self.nodes[2].generate(4) # blocks 428-431
|
||||
|
||||
self.log.info("Verify previous witness txs skipped for mining can now be mined")
|
||||
assert_equal(len(self.nodes[2].getrawmempool()), 4)
|
||||
block = self.nodes[2].generate(1) #block 432 (first block with new rules; 432 = 144 * 3)
|
||||
block = self.nodes[2].generate(1) # block 432 (first block with new rules; 432 = 144 * 3)
|
||||
sync_blocks(self.nodes)
|
||||
assert_equal(len(self.nodes[2].getrawmempool()), 0)
|
||||
segwit_tx_list = self.nodes[2].getblock(block[0])["tx"]
|
||||
|
|
@ -181,8 +170,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||
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))
|
||||
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))
|
||||
for i in range(len(segwit_tx_list)):
|
||||
tx = FromHex(CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
|
||||
assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
|
||||
|
|
@ -198,21 +187,21 @@ class SegWitTest(BitcoinTestFramework):
|
|||
self.fail_accept(self.nodes[2], 'non-mandatory-script-verify-flag (Witness program was passed an empty witness) (code 64)', p2sh_ids[NODE_2][WIT_V1][2], sign=False, redeem_script=witness_script(True, self.pubkey[2]))
|
||||
|
||||
self.log.info("Verify default node can now use witness txs")
|
||||
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) #block 432
|
||||
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) #block 433
|
||||
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) #block 434
|
||||
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) #block 435
|
||||
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V0][0], True) # block 432
|
||||
self.success_mine(self.nodes[0], wit_ids[NODE_0][WIT_V1][0], True) # block 433
|
||||
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V0][0], True) # block 434
|
||||
self.success_mine(self.nodes[0], p2sh_ids[NODE_0][WIT_V1][0], True) # block 435
|
||||
|
||||
self.log.info("Verify sigops are counted in GBT with BIP141 rules after the fork")
|
||||
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
|
||||
tmpl = self.nodes[0].getblocktemplate({'rules':['segwit']})
|
||||
tmpl = self.nodes[0].getblocktemplate({'rules': ['segwit']})
|
||||
assert(tmpl['sizelimit'] >= 3999577) # actual maximum size is lower due to minimum mandatory non-witness data
|
||||
assert(tmpl['weightlimit'] == 4000000)
|
||||
assert(tmpl['sigoplimit'] == 80000)
|
||||
assert(tmpl['transactions'][0]['txid'] == txid)
|
||||
assert(tmpl['transactions'][0]['sigops'] == 8)
|
||||
|
||||
self.nodes[0].generate(1) # Mine a block to clear the gbt cache
|
||||
self.nodes[0].generate(1) # Mine a block to clear the gbt cache
|
||||
|
||||
self.log.info("Non-segwit miners are able to use GBT response after activation.")
|
||||
# Create a 3-tx chain: tx1 (non-segwit input, paying to a segwit output) ->
|
||||
|
|
@ -222,7 +211,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996"))
|
||||
hex_tx = self.nodes[0].gettransaction(txid)['hex']
|
||||
tx = FromHex(CTransaction(), hex_tx)
|
||||
assert(tx.wit.is_null()) # This should not be a segwit input
|
||||
assert(tx.wit.is_null()) # This should not be a segwit input
|
||||
assert(txid1 in self.nodes[0].getrawmempool())
|
||||
|
||||
# Now create tx2, which will spend from txid1.
|
||||
|
|
@ -247,13 +236,13 @@ class SegWitTest(BitcoinTestFramework):
|
|||
template = self.nodes[0].getblocktemplate()
|
||||
|
||||
# Check that tx1 is the only transaction of the 3 in the template.
|
||||
template_txids = [ t['txid'] for t in template['transactions'] ]
|
||||
template_txids = [t['txid'] for t in template['transactions']]
|
||||
assert(txid2 not in template_txids and txid3 not in template_txids)
|
||||
assert(txid1 in template_txids)
|
||||
|
||||
# Check that running with segwit support results in all 3 being included.
|
||||
template = self.nodes[0].getblocktemplate({"rules": ["segwit"]})
|
||||
template_txids = [ t['txid'] for t in template['transactions'] ]
|
||||
template_txids = [t['txid'] for t in template['transactions']]
|
||||
assert(txid1 in template_txids)
|
||||
assert(txid2 in template_txids)
|
||||
assert(txid3 in template_txids)
|
||||
|
|
@ -264,17 +253,17 @@ class SegWitTest(BitcoinTestFramework):
|
|||
# Mine a block to clear the gbt cache again.
|
||||
self.nodes[0].generate(1)
|
||||
|
||||
self.log.info("Verify behaviour of importaddress, addwitnessaddress and listunspent")
|
||||
self.log.info("Verify behaviour of importaddress and listunspent")
|
||||
|
||||
# Some public keys to be used later
|
||||
pubkeys = [
|
||||
"0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb
|
||||
"02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97
|
||||
"04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV
|
||||
"02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd
|
||||
"036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66
|
||||
"0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K
|
||||
"0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ
|
||||
"0363D44AABD0F1699138239DF2F042C3282C0671CC7A76826A55C8203D90E39242", # cPiM8Ub4heR9NBYmgVzJQiUH1if44GSBGiqaeJySuL2BKxubvgwb
|
||||
"02D3E626B3E616FC8662B489C123349FECBFC611E778E5BE739B257EAE4721E5BF", # cPpAdHaD6VoYbW78kveN2bsvb45Q7G5PhaPApVUGwvF8VQ9brD97
|
||||
"04A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538A62F5BD8EC85C2477F39650BD391EA6250207065B2A81DA8B009FC891E898F0E", # 91zqCU5B9sdWxzMt1ca3VzbtVm2YM6Hi5Rxn4UDtxEaN9C9nzXV
|
||||
"02A47F2CBCEFFA7B9BCDA184E7D5668D3DA6F9079AD41E422FA5FD7B2D458F2538", # cPQFjcVRpAUBG8BA9hzr2yEzHwKoMgLkJZBBtK9vJnvGJgMjzTbd
|
||||
"036722F784214129FEB9E8129D626324F3F6716555B603FFE8300BBCB882151228", # cQGtcm34xiLjB1v7bkRa4V3aAc9tS2UTuBZ1UnZGeSeNy627fN66
|
||||
"0266A8396EE936BF6D99D17920DB21C6C7B1AB14C639D5CD72B300297E416FD2EC", # cTW5mR5M45vHxXkeChZdtSPozrFwFgmEvTNnanCW6wrqwaCZ1X7K
|
||||
"0450A38BD7F0AC212FEBA77354A9B036A32E0F7C81FC4E0C5ADCA7C549C4505D2522458C2D9AE3CEFD684E039194B72C8A10F9CB9D4764AB26FCC2718D421D3B84", # 92h2XPssjBpsJN5CqSP7v9a7cf2kgDunBC6PDFwJHMACM1rrVBJ
|
||||
]
|
||||
|
||||
# Import a compressed key and an uncompressed key, generate some multisig addresses
|
||||
|
|
@ -282,8 +271,8 @@ class SegWitTest(BitcoinTestFramework):
|
|||
uncompressed_spendable_address = ["mvozP4UwyGD2mGZU4D2eMvMLPB9WkMmMQu"]
|
||||
self.nodes[0].importprivkey("cNC8eQ5dg3mFAVePDX4ddmPYpPbw41r9bm2jd1nLJT77e6RrzTRR")
|
||||
compressed_spendable_address = ["mmWQubrDomqpgSYekvsU7HWEVjLFHAakLe"]
|
||||
assert ((self.nodes[0].getaddressinfo(uncompressed_spendable_address[0])['iscompressed'] == False))
|
||||
assert ((self.nodes[0].getaddressinfo(compressed_spendable_address[0])['iscompressed'] == True))
|
||||
assert not self.nodes[0].getaddressinfo(uncompressed_spendable_address[0])['iscompressed']
|
||||
assert self.nodes[0].getaddressinfo(compressed_spendable_address[0])['iscompressed']
|
||||
|
||||
self.nodes[0].importpubkey(pubkeys[0])
|
||||
compressed_solvable_address = [key_to_p2pkh(pubkeys[0])]
|
||||
|
|
@ -305,7 +294,6 @@ class SegWitTest(BitcoinTestFramework):
|
|||
uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address'])
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address'])
|
||||
compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address'])
|
||||
unknown_address = ["mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx"]
|
||||
|
||||
# Test multisig_without_privkey
|
||||
# We have 2 public keys without private keys, use addmultisigaddress to add to wallet.
|
||||
|
|
@ -386,7 +374,6 @@ class SegWitTest(BitcoinTestFramework):
|
|||
op1 = CScript([OP_1])
|
||||
op0 = CScript([OP_0])
|
||||
# 2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe is the P2SH(P2PKH) version of mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V
|
||||
unsolvable_address = ["mjoE3sSrb8ByYEvgnC3Aox86u1CHnfJA4V", "2N7MGY19ti4KDMSzRfPAssP6Pxyuxoi6jLe", script_to_p2sh(op1), script_to_p2sh(op0)]
|
||||
unsolvable_address_key = hex_str_to_bytes("02341AEC7587A51CDE5279E0630A531AEA2615A9F80B17E8D9376327BAEAA59E3D")
|
||||
unsolvablep2pkh = CScript([OP_DUP, OP_HASH160, hash160(unsolvable_address_key), OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
unsolvablep2wshp2pkh = CScript([OP_0, sha256(unsolvablep2pkh)])
|
||||
|
|
@ -394,9 +381,9 @@ class SegWitTest(BitcoinTestFramework):
|
|||
p2wshop1 = CScript([OP_0, sha256(op1)])
|
||||
unsolvable_after_importaddress.append(unsolvablep2pkh)
|
||||
unsolvable_after_importaddress.append(unsolvablep2wshp2pkh)
|
||||
unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script
|
||||
unsolvable_after_importaddress.append(op1) # OP_1 will be imported as script
|
||||
unsolvable_after_importaddress.append(p2wshop1)
|
||||
unseen_anytime.append(op0) # OP_0 will be imported as P2SH address with no script provided
|
||||
unseen_anytime.append(op0) # OP_0 will be imported as P2SH address with no script provided
|
||||
unsolvable_after_importaddress.append(p2shop0)
|
||||
|
||||
spendable_txid = []
|
||||
|
|
@ -432,27 +419,14 @@ class SegWitTest(BitcoinTestFramework):
|
|||
# exceptions and continue.
|
||||
try_rpc(-4, "The wallet already contains the private key for this address or script", self.nodes[0].importaddress, i, "", False, True)
|
||||
|
||||
self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only
|
||||
self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey
|
||||
self.nodes[0].importaddress(script_to_p2sh(op0)) # import OP_0 as address only
|
||||
self.nodes[0].importaddress(multisig_without_privkey_address) # Test multisig_without_privkey
|
||||
|
||||
spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2))
|
||||
solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1))
|
||||
self.mine_and_test_listunspent(unsolvable_after_importaddress, 1)
|
||||
self.mine_and_test_listunspent(unseen_anytime, 0)
|
||||
|
||||
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
|
||||
# note that no witness address should be returned by unsolvable addresses
|
||||
for i in uncompressed_spendable_address + uncompressed_solvable_address + unknown_address + unsolvable_address:
|
||||
assert_raises_rpc_error(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)
|
||||
|
||||
# addwitnessaddress should return a witness addresses even if keys are not in the wallet
|
||||
self.nodes[0].addwitnessaddress(multisig_without_privkey_address)
|
||||
|
||||
for i in compressed_spendable_address + compressed_solvable_address:
|
||||
witaddress = self.nodes[0].addwitnessaddress(i)
|
||||
# addwitnessaddress should return the same address if it is a known P2SH-witness address
|
||||
assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress))
|
||||
|
||||
spendable_txid.append(self.mine_and_test_listunspent(spendable_anytime + spendable_after_importaddress, 2))
|
||||
solvable_txid.append(self.mine_and_test_listunspent(solvable_anytime + solvable_after_importaddress, 1))
|
||||
self.mine_and_test_listunspent(unsolvable_after_importaddress, 1)
|
||||
|
|
@ -470,8 +444,6 @@ class SegWitTest(BitcoinTestFramework):
|
|||
self.nodes[0].importpubkey(pubkeys[6])
|
||||
uncompressed_solvable_address = [key_to_p2pkh(pubkeys[6])]
|
||||
|
||||
spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress
|
||||
solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable
|
||||
unseen_anytime = [] # These outputs should never be seen
|
||||
solvable_anytime = [] # These outputs should be solvable after importpubkey
|
||||
unseen_anytime = [] # These outputs should never be seen
|
||||
|
|
@ -488,8 +460,6 @@ class SegWitTest(BitcoinTestFramework):
|
|||
v = self.nodes[0].getaddressinfo(i)
|
||||
if (v['isscript']):
|
||||
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
|
||||
# P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after addwitnessaddress
|
||||
spendable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh])
|
||||
premature_witaddress.append(script_to_p2sh(p2wsh))
|
||||
else:
|
||||
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
|
||||
|
|
@ -510,9 +480,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
for i in compressed_solvable_address:
|
||||
v = self.nodes[0].getaddressinfo(i)
|
||||
if (v['isscript']):
|
||||
# P2WSH multisig without private key are seen after addwitnessaddress
|
||||
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
|
||||
solvable_after_addwitnessaddress.extend([p2wsh, p2sh_p2wsh])
|
||||
premature_witaddress.append(script_to_p2sh(p2wsh))
|
||||
else:
|
||||
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
|
||||
|
|
@ -521,29 +489,11 @@ class SegWitTest(BitcoinTestFramework):
|
|||
|
||||
self.mine_and_test_listunspent(spendable_anytime, 2)
|
||||
self.mine_and_test_listunspent(solvable_anytime, 1)
|
||||
self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0)
|
||||
|
||||
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
|
||||
# note that a multisig address returned by addmultisigaddress is not solvable until it is added with importaddress
|
||||
# premature_witaddress are not accepted until the script is added with addwitnessaddress first
|
||||
for i in uncompressed_spendable_address + uncompressed_solvable_address + premature_witaddress:
|
||||
# This will raise an exception
|
||||
assert_raises_rpc_error(-4, "Public key or redeemscript not known to wallet, or the key is uncompressed", self.nodes[0].addwitnessaddress, i)
|
||||
|
||||
# after importaddress it should pass addwitnessaddress
|
||||
v = self.nodes[0].getaddressinfo(compressed_solvable_address[1])
|
||||
self.nodes[0].importaddress(v['hex'],"",False,True)
|
||||
for i in compressed_spendable_address + compressed_solvable_address + premature_witaddress:
|
||||
witaddress = self.nodes[0].addwitnessaddress(i)
|
||||
assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress))
|
||||
|
||||
spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress + spendable_anytime, 2))
|
||||
solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress + solvable_anytime, 1))
|
||||
self.mine_and_test_listunspent(unseen_anytime, 0)
|
||||
|
||||
# Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works
|
||||
v1_addr = program_to_witness(1, [3,5])
|
||||
v1_tx = self.nodes[0].createrawtransaction([getutxo(spendable_txid[0])],{v1_addr: 1})
|
||||
v1_addr = program_to_witness(1, [3, 5])
|
||||
v1_tx = self.nodes[0].createrawtransaction([getutxo(spendable_txid[0])], {v1_addr: 1})
|
||||
v1_decoded = self.nodes[1].decoderawtransaction(v1_tx)
|
||||
assert_equal(v1_decoded['vout'][0]['scriptPubKey']['addresses'][0], v1_addr)
|
||||
assert_equal(v1_decoded['vout'][0]['scriptPubKey']['hex'], "51020305")
|
||||
|
|
@ -586,7 +536,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
def mine_and_test_listunspent(self, script_list, ismine):
|
||||
utxo = find_spendable_utxo(self.nodes[0], 50)
|
||||
tx = CTransaction()
|
||||
tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout'])))
|
||||
tx.vin.append(CTxIn(COutPoint(int('0x' + utxo['txid'], 0), utxo['vout'])))
|
||||
for i in script_list:
|
||||
tx.vout.append(CTxOut(10000000, i))
|
||||
tx.rehash()
|
||||
|
|
@ -599,7 +549,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
for i in self.nodes[0].listunspent():
|
||||
if (i['txid'] == txid):
|
||||
watchcount += 1
|
||||
if (i['spendable'] == True):
|
||||
if i['spendable']:
|
||||
spendcount += 1
|
||||
if (ismine == 2):
|
||||
assert_equal(spendcount, len(script_list))
|
||||
|
|
@ -610,14 +560,14 @@ class SegWitTest(BitcoinTestFramework):
|
|||
assert_equal(watchcount, 0)
|
||||
return txid
|
||||
|
||||
def p2sh_address_to_script(self,v):
|
||||
def p2sh_address_to_script(self, v):
|
||||
bare = CScript(hex_str_to_bytes(v['hex']))
|
||||
p2sh = CScript(hex_str_to_bytes(v['scriptPubKey']))
|
||||
p2wsh = CScript([OP_0, sha256(bare)])
|
||||
p2sh_p2wsh = CScript([OP_HASH160, hash160(p2wsh), OP_EQUAL])
|
||||
return([bare, p2sh, p2wsh, p2sh_p2wsh])
|
||||
|
||||
def p2pkh_address_to_script(self,v):
|
||||
def p2pkh_address_to_script(self, v):
|
||||
pubkey = hex_str_to_bytes(v['pubkey'])
|
||||
p2wpkh = CScript([OP_0, hash160(pubkey)])
|
||||
p2sh_p2wpkh = CScript([OP_HASH160, hash160(p2wpkh), OP_EQUAL])
|
||||
|
|
@ -631,7 +581,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
p2sh_p2wsh_p2pkh = CScript([OP_HASH160, hash160(p2wsh_p2pkh), OP_EQUAL])
|
||||
return [p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh]
|
||||
|
||||
def create_and_mine_tx_from_txids(self, txids, success = True):
|
||||
def create_and_mine_tx_from_txids(self, txids, success=True):
|
||||
tx = CTransaction()
|
||||
for i in txids:
|
||||
txtmp = CTransaction()
|
||||
|
|
@ -639,7 +589,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
f = BytesIO(hex_str_to_bytes(txraw))
|
||||
txtmp.deserialize(f)
|
||||
for j in range(len(txtmp.vout)):
|
||||
tx.vin.append(CTxIn(COutPoint(int('0x'+i,0), j)))
|
||||
tx.vin.append(CTxIn(COutPoint(int('0x' + i, 0), j)))
|
||||
tx.vout.append(CTxOut(0, CScript()))
|
||||
tx.rehash()
|
||||
signresults = self.nodes[0].signrawtransactionwithwallet(bytes_to_hex_str(tx.serialize_without_witness()))['hex']
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class UacommentTest(BitcoinTestFramework):
|
|||
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + 'a' * 256], expected, match=ErrorMatch.FULL_REGEX)
|
||||
|
||||
self.log.info("test -uacomment unsafe characters")
|
||||
for unsafe_char in ['/', ':', '(', ')']:
|
||||
for unsafe_char in ['/', ':', '(', ')', '₿', '🏃']:
|
||||
expected = "Error: User Agent comment \(" + re.escape(unsafe_char) + "\) contains unsafe characters."
|
||||
self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, match=ErrorMatch.FULL_REGEX)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,6 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
|
||||
# Open and close to create zero-length file
|
||||
|
|
@ -68,13 +65,14 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
|||
node = self.nodes[0]
|
||||
node.add_p2p_connection(P2PInterface())
|
||||
|
||||
node_deterministic_address = node.get_deterministic_priv_key().address
|
||||
# Mine one period worth of blocks
|
||||
node.generate(VB_PERIOD)
|
||||
node.generatetoaddress(VB_PERIOD, node_deterministic_address)
|
||||
|
||||
self.log.info("Check that there is no warning if previous VB_BLOCKS have <VB_THRESHOLD blocks with unknown versionbits version.")
|
||||
# Build one period of blocks with < VB_THRESHOLD blocks signaling some unknown bit
|
||||
self.send_blocks_with_version(node.p2p, VB_THRESHOLD - 1, VB_UNKNOWN_VERSION)
|
||||
node.generate(VB_PERIOD - VB_THRESHOLD + 1)
|
||||
node.generatetoaddress(VB_PERIOD - VB_THRESHOLD + 1, node_deterministic_address)
|
||||
|
||||
# Check that we're not getting any versionbit-related errors in get*info()
|
||||
assert(not VB_PATTERN.match(node.getmininginfo()["warnings"]))
|
||||
|
|
@ -83,7 +81,7 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
|||
self.log.info("Check that there is a warning if >50 blocks in the last 100 were an unknown version")
|
||||
# Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit
|
||||
self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION)
|
||||
node.generate(VB_PERIOD - VB_THRESHOLD)
|
||||
node.generatetoaddress(VB_PERIOD - VB_THRESHOLD, node_deterministic_address)
|
||||
|
||||
# Check that get*info() shows the 51/100 unknown block version error.
|
||||
assert(WARN_UNKNOWN_RULES_MINED in node.getmininginfo()["warnings"])
|
||||
|
|
@ -92,16 +90,16 @@ class VersionBitsWarningTest(BitcoinTestFramework):
|
|||
self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.")
|
||||
# Mine a period worth of expected blocks so the generic block-version warning
|
||||
# is cleared. This will move the versionbit state to ACTIVE.
|
||||
node.generate(VB_PERIOD)
|
||||
node.generatetoaddress(VB_PERIOD, node_deterministic_address)
|
||||
|
||||
# Stop-start the node. This is required because bitcoind will only warn once about unknown versions or unknown rules activating.
|
||||
self.restart_node(0)
|
||||
|
||||
# Generating one block guarantees that we'll get out of IBD
|
||||
node.generate(1)
|
||||
node.generatetoaddress(1, node_deterministic_address)
|
||||
wait_until(lambda: not node.getblockchaininfo()['initialblockdownload'], timeout=10, lock=mininode_lock)
|
||||
# Generating one more block will be enough to generate an error.
|
||||
node.generate(1)
|
||||
node.generatetoaddress(1, node_deterministic_address)
|
||||
# Check that get*info() shows the versionbits unknown rules warning
|
||||
assert(WARN_UNKNOWN_RULES_ACTIVE in node.getmininginfo()["warnings"])
|
||||
assert(WARN_UNKNOWN_RULES_ACTIVE in node.getnetworkinfo()["warnings"])
|
||||
|
|
|
|||
|
|
@ -12,26 +12,24 @@ class TestBitcoinCli(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
"""Main test logic"""
|
||||
|
||||
cli_response = self.nodes[0].cli("-version").send_cli()
|
||||
assert("Bitcoin Core RPC client version" in cli_response)
|
||||
|
||||
self.log.info("Compare responses from gewalletinfo RPC and `bitcoin-cli getwalletinfo`")
|
||||
cli_response = self.nodes[0].cli.getwalletinfo()
|
||||
rpc_response = self.nodes[0].getwalletinfo()
|
||||
assert_equal(cli_response, rpc_response)
|
||||
self.log.info("Compare responses from getwalletinfo RPC and `bitcoin-cli getwalletinfo`")
|
||||
if self.is_wallet_compiled():
|
||||
cli_response = self.nodes[0].cli.getwalletinfo()
|
||||
rpc_response = self.nodes[0].getwalletinfo()
|
||||
assert_equal(cli_response, rpc_response)
|
||||
|
||||
self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`")
|
||||
cli_response = self.nodes[0].cli.getblockchaininfo()
|
||||
rpc_response = self.nodes[0].getblockchaininfo()
|
||||
assert_equal(cli_response, rpc_response)
|
||||
|
||||
user, password = get_auth_cookie(self.nodes[0].datadir, self.chain)
|
||||
user, password = get_auth_cookie(self.nodes[0].datadir)
|
||||
|
||||
self.log.info("Test -stdinrpcpass option")
|
||||
assert_equal(0, self.nodes[0].cli('-rpcuser=%s' % user, '-stdinrpcpass', input=password).getblockcount())
|
||||
|
|
@ -52,26 +50,30 @@ class TestBitcoinCli(BitcoinTestFramework):
|
|||
|
||||
self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.")
|
||||
cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
|
||||
wallet_info = self.nodes[0].getwalletinfo()
|
||||
if self.is_wallet_compiled():
|
||||
wallet_info = self.nodes[0].getwalletinfo()
|
||||
network_info = self.nodes[0].getnetworkinfo()
|
||||
blockchain_info = self.nodes[0].getblockchaininfo()
|
||||
|
||||
assert_equal(cli_get_info['version'], network_info['version'])
|
||||
assert_equal(cli_get_info['protocolversion'], network_info['protocolversion'])
|
||||
assert_equal(cli_get_info['walletversion'], wallet_info['walletversion'])
|
||||
assert_equal(cli_get_info['balance'], wallet_info['balance'])
|
||||
if self.is_wallet_compiled():
|
||||
assert_equal(cli_get_info['walletversion'], wallet_info['walletversion'])
|
||||
assert_equal(cli_get_info['balance'], wallet_info['balance'])
|
||||
assert_equal(cli_get_info['blocks'], blockchain_info['blocks'])
|
||||
assert_equal(cli_get_info['timeoffset'], network_info['timeoffset'])
|
||||
assert_equal(cli_get_info['connections'], network_info['connections'])
|
||||
assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy'])
|
||||
assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty'])
|
||||
assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test")
|
||||
assert_equal(cli_get_info['balance'], wallet_info['balance'])
|
||||
assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest'])
|
||||
assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
|
||||
assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
|
||||
assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
|
||||
# unlocked_until is not tested because the wallet is not encrypted
|
||||
if self.is_wallet_compiled():
|
||||
assert_equal(cli_get_info['balance'], wallet_info['balance'])
|
||||
assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest'])
|
||||
assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize'])
|
||||
assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee'])
|
||||
assert_equal(cli_get_info['relayfee'], network_info['relayfee'])
|
||||
# unlocked_until is not tested because the wallet is not encrypted
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
TestBitcoinCli().main()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"""Test the ZMQ notification interface."""
|
||||
import struct
|
||||
|
||||
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.messages import CTransaction
|
||||
from test_framework.util import (
|
||||
|
|
@ -14,6 +15,7 @@ from test_framework.util import (
|
|||
)
|
||||
from io import BytesIO
|
||||
|
||||
ADDRESS = "tcp://127.0.0.1:28332"
|
||||
|
||||
class ZMQSubscriber:
|
||||
def __init__(self, socket, topic):
|
||||
|
|
@ -41,7 +43,6 @@ class ZMQTest (BitcoinTestFramework):
|
|||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_py3_zmq()
|
||||
self.skip_if_no_bitcoind_zmq()
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_nodes(self):
|
||||
import zmq
|
||||
|
|
@ -51,11 +52,10 @@ class ZMQTest (BitcoinTestFramework):
|
|||
# that this test fails if the publishing order changes.
|
||||
# Note that the publishing order is not defined in the documentation and
|
||||
# is subject to change.
|
||||
address = "tcp://127.0.0.1:28332"
|
||||
self.zmq_context = zmq.Context()
|
||||
socket = self.zmq_context.socket(zmq.SUB)
|
||||
socket.set(zmq.RCVTIMEO, 60000)
|
||||
socket.connect(address)
|
||||
socket.connect(ADDRESS)
|
||||
|
||||
# Subscribe to all available topics.
|
||||
self.hashblock = ZMQSubscriber(socket, b"hashblock")
|
||||
|
|
@ -64,11 +64,12 @@ class ZMQTest (BitcoinTestFramework):
|
|||
self.rawtx = ZMQSubscriber(socket, b"rawtx")
|
||||
|
||||
self.extra_args = [
|
||||
["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]],
|
||||
["-zmqpub%s=%s" % (sub.topic.decode(), ADDRESS) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]],
|
||||
[],
|
||||
]
|
||||
self.add_nodes(self.num_nodes, self.extra_args)
|
||||
self.start_nodes()
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
|
||||
def run_test(self):
|
||||
try:
|
||||
|
|
@ -81,7 +82,7 @@ class ZMQTest (BitcoinTestFramework):
|
|||
def _zmq_test(self):
|
||||
num_blocks = 5
|
||||
self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks})
|
||||
genhashes = self.nodes[0].generate(num_blocks)
|
||||
genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE)
|
||||
self.sync_all()
|
||||
|
||||
for x in range(num_blocks):
|
||||
|
|
@ -105,17 +106,29 @@ class ZMQTest (BitcoinTestFramework):
|
|||
block = self.rawblock.receive()
|
||||
assert_equal(genhashes[x], bytes_to_hex_str(hash256(block[:80])))
|
||||
|
||||
self.log.info("Wait for tx from second node")
|
||||
payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
|
||||
self.sync_all()
|
||||
if self.is_wallet_compiled():
|
||||
self.log.info("Wait for tx from second node")
|
||||
payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
|
||||
self.sync_all()
|
||||
|
||||
# Should receive the broadcasted txid.
|
||||
txid = self.hashtx.receive()
|
||||
assert_equal(payment_txid, bytes_to_hex_str(txid))
|
||||
# Should receive the broadcasted txid.
|
||||
txid = self.hashtx.receive()
|
||||
assert_equal(payment_txid, bytes_to_hex_str(txid))
|
||||
|
||||
# Should receive the broadcasted raw transaction.
|
||||
hex = self.rawtx.receive()
|
||||
assert_equal(payment_txid, bytes_to_hex_str(hash256(hex)))
|
||||
# Should receive the broadcasted raw transaction.
|
||||
hex = self.rawtx.receive()
|
||||
assert_equal(payment_txid, bytes_to_hex_str(hash256(hex)))
|
||||
|
||||
|
||||
self.log.info("Test the getzmqnotifications RPC")
|
||||
assert_equal(self.nodes[0].getzmqnotifications(), [
|
||||
{"type": "pubhashblock", "address": ADDRESS, "hwm": 1000},
|
||||
{"type": "pubhashtx", "address": ADDRESS, "hwm": 1000},
|
||||
{"type": "pubrawblock", "address": ADDRESS, "hwm": 1000},
|
||||
{"type": "pubrawtx", "address": ADDRESS, "hwm": 1000},
|
||||
])
|
||||
|
||||
assert_equal(self.nodes[1].getzmqnotifications(), [])
|
||||
|
||||
if __name__ == '__main__':
|
||||
ZMQTest().main()
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ class MempoolPersistTest(BitcoinTestFramework):
|
|||
self.start_node(0)
|
||||
wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
|
||||
|
||||
mempooldat0 = os.path.join(self.nodes[0].datadir, 'regtest2', 'mempool.dat')
|
||||
mempooldat1 = os.path.join(self.nodes[1].datadir, 'regtest2', 'mempool.dat')
|
||||
mempooldat0 = os.path.join(self.nodes[0].datadir, 'regtest', 'mempool.dat')
|
||||
mempooldat1 = os.path.join(self.nodes[1].datadir, 'regtest', 'mempool.dat')
|
||||
self.log.debug("Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it")
|
||||
os.remove(mempooldat0)
|
||||
self.nodes[0].savemempool()
|
||||
|
|
|
|||
|
|
@ -47,12 +47,11 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
|
|||
tx = self.nodes[0].gettransaction(txid)
|
||||
assert(tx["confirmations"] > 0)
|
||||
|
||||
# Use invalidateblock to re-org back; all transactions should
|
||||
# end up unconfirmed and back in the mempool
|
||||
# Use invalidateblock to re-org back
|
||||
for node in self.nodes:
|
||||
node.invalidateblock(blocks[0])
|
||||
|
||||
# mempool should be empty, all txns confirmed
|
||||
# All txns should be back in mempool with 0 confirmations
|
||||
assert_equal(set(self.nodes[0].getrawmempool()), set(spends1_id+spends2_id))
|
||||
for txid in spends1_id+spends2_id:
|
||||
tx = self.nodes[0].gettransaction(txid)
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ class MiningTest(BitcoinTestFramework):
|
|||
self.num_nodes = 2
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
|
|
@ -53,7 +50,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
self.log.info('getmininginfo')
|
||||
mining_info = node.getmininginfo()
|
||||
assert_equal(mining_info['blocks'], 200)
|
||||
assert_equal(mining_info['chain'], 'regtest2')
|
||||
assert_equal(mining_info['chain'], 'regtest')
|
||||
assert_equal(mining_info['currentblocktx'], 0)
|
||||
assert_equal(mining_info['currentblockweight'], 0)
|
||||
assert_equal(mining_info['difficulty'], Decimal('4.656542373906925E-10'))
|
||||
|
|
@ -61,7 +58,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
assert_equal(mining_info['pooledtx'], 0)
|
||||
|
||||
# Mine a block to leave initial block download
|
||||
node.generate(1)
|
||||
node.generatetoaddress(1, node.get_deterministic_priv_key().address)
|
||||
tmpl = node.getblocktemplate()
|
||||
self.log.info("getblocktemplate: Test capability advertised")
|
||||
assert 'proposal' in tmpl['capabilities']
|
||||
|
|
@ -212,7 +209,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
assert chain_tip(block.hash, status='active', branchlen=0) in node.getchaintips()
|
||||
|
||||
# Building a few blocks should give the same results
|
||||
node.generate(10)
|
||||
node.generatetoaddress(10, node.get_deterministic_priv_key().address)
|
||||
assert_raises_rpc_error(-25, 'time-too-old', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block_time).serialize())))
|
||||
assert_raises_rpc_error(-25, 'bad-prevblk', lambda: node.submitheader(hexdata=b2x(CBlockHeader(bad_block2).serialize())))
|
||||
node.submitheader(hexdata=b2x(CBlockHeader(block).serialize()))
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
|
|||
assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0)
|
||||
|
||||
# Test `prioritisetransaction` invalid `txid`
|
||||
assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
|
||||
assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000')", self.nodes[0].prioritisetransaction, txid='Zd1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000', fee_delta=0)
|
||||
|
||||
# Test `prioritisetransaction` invalid `dummy`
|
||||
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
Version 1 compact blocks are pre-segwit (txids)
|
||||
Version 2 compact blocks are post-segwit (wtxids)
|
||||
"""
|
||||
|
||||
from decimal import Decimal
|
||||
import random
|
||||
|
||||
|
|
@ -99,7 +98,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
self.num_nodes = 2
|
||||
# This test was written assuming SegWit is activated using BIP9 at height 432 (3x confirmation window).
|
||||
# TODO: Rewrite this test to support SegWit being always active.
|
||||
self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex", "-deprecatedrpc=addwitnessaddress"]]
|
||||
self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex"]]
|
||||
self.utxos = []
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
|
|
@ -189,7 +188,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
|
||||
# Now try a SENDCMPCT message with too-high version
|
||||
sendcmpct = msg_sendcmpct()
|
||||
sendcmpct.version = preferred_version+1
|
||||
sendcmpct.version = preferred_version + 1
|
||||
sendcmpct.announce = True
|
||||
test_node.send_and_ping(sendcmpct)
|
||||
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" not in p.last_message)
|
||||
|
|
@ -220,7 +219,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
|
||||
|
||||
# Try one more time, after sending a version-1, announce=false message.
|
||||
sendcmpct.version = preferred_version-1
|
||||
sendcmpct.version = preferred_version - 1
|
||||
sendcmpct.announce = False
|
||||
test_node.send_and_ping(sendcmpct)
|
||||
check_announcement_of_new_block(node, test_node, lambda p: "cmpctblock" in p.last_message)
|
||||
|
|
@ -234,7 +233,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
if old_node is not None:
|
||||
# Verify that a peer using an older protocol version can receive
|
||||
# announcements from this node.
|
||||
sendcmpct.version = preferred_version-1
|
||||
sendcmpct.version = preferred_version - 1
|
||||
sendcmpct.announce = True
|
||||
old_node.send_and_ping(sendcmpct)
|
||||
# Header sync
|
||||
|
|
@ -265,9 +264,9 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
if use_witness_address:
|
||||
# Want at least one segwit spend, so move all funds to
|
||||
# a witness address.
|
||||
address = node.addwitnessaddress(address)
|
||||
address = node.getnewaddress(address_type='bech32')
|
||||
value_to_send = node.getbalance()
|
||||
node.sendtoaddress(address, satoshi_round(value_to_send-Decimal(0.1)))
|
||||
node.sendtoaddress(address, satoshi_round(value_to_send - Decimal(0.1)))
|
||||
node.generate(1)
|
||||
|
||||
segwit_tx_generated = False
|
||||
|
|
@ -279,7 +278,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
segwit_tx_generated = True
|
||||
|
||||
if use_witness_address:
|
||||
assert(segwit_tx_generated) # check that our test is not broken
|
||||
assert segwit_tx_generated # check that our test is not broken
|
||||
|
||||
# Wait until we've seen the block announcement for the resulting tip
|
||||
tip = int(node.getbestblockhash(), 16)
|
||||
|
|
@ -293,7 +292,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
block_hash = int(node.generate(1)[0], 16)
|
||||
|
||||
# Store the raw block in our internal format.
|
||||
block = FromHex(CBlock(), node.getblock("%02x" % block_hash, False))
|
||||
block = FromHex(CBlock(), node.getblock("%064x" % block_hash, False))
|
||||
for tx in block.vtx:
|
||||
tx.calc_sha256()
|
||||
block.rehash()
|
||||
|
|
@ -403,8 +402,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
coinbase_hash = block.vtx[0].sha256
|
||||
if version == 2:
|
||||
coinbase_hash = block.vtx[0].calc_sha256(True)
|
||||
comp_block.shortids = [
|
||||
calculate_shortid(k0, k1, coinbase_hash) ]
|
||||
comp_block.shortids = [calculate_shortid(k0, k1, coinbase_hash)]
|
||||
test_node.send_and_ping(msg_cmpctblock(comp_block.to_p2p()))
|
||||
assert_equal(int(node.getbestblockhash(), 16), block.hashPrevBlock)
|
||||
# Expect a getblocktxn message.
|
||||
|
|
@ -443,7 +441,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
# node needs, and that responding to them causes the block to be
|
||||
# reconstructed.
|
||||
def test_getblocktxn_requests(self, node, test_node, version):
|
||||
with_witness = (version==2)
|
||||
with_witness = (version == 2)
|
||||
|
||||
def test_getblocktxn_response(compact_block, peer, expected_result):
|
||||
msg = msg_cmpctblock(compact_block.to_p2p())
|
||||
|
|
@ -470,7 +468,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
|
||||
msg_bt = msg_blocktxn()
|
||||
if with_witness:
|
||||
msg_bt = msg_witness_blocktxn() # serialize with witnesses
|
||||
msg_bt = msg_witness_blocktxn() # serialize with witnesses
|
||||
msg_bt.block_transactions = BlockTransactions(block.sha256, block.vtx[1:])
|
||||
test_tip_after_message(node, test_node, msg_bt, block.sha256)
|
||||
|
||||
|
|
@ -560,7 +558,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
# verifying that the block isn't marked bad permanently. This is good
|
||||
# enough for now.
|
||||
msg = msg_blocktxn()
|
||||
if version==2:
|
||||
if version == 2:
|
||||
msg = msg_witness_blocktxn()
|
||||
msg.block_transactions = BlockTransactions(block.sha256, [block.vtx[5]] + block.vtx[7:])
|
||||
test_node.send_and_ping(msg)
|
||||
|
|
@ -571,11 +569,11 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
# We should receive a getdata request
|
||||
wait_until(lambda: "getdata" in test_node.last_message, timeout=10, lock=mininode_lock)
|
||||
assert_equal(len(test_node.last_message["getdata"].inv), 1)
|
||||
assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2|MSG_WITNESS_FLAG)
|
||||
assert(test_node.last_message["getdata"].inv[0].type == 2 or test_node.last_message["getdata"].inv[0].type == 2 | MSG_WITNESS_FLAG)
|
||||
assert_equal(test_node.last_message["getdata"].inv[0].hash, block.sha256)
|
||||
|
||||
# Deliver the block
|
||||
if version==2:
|
||||
if version == 2:
|
||||
test_node.send_and_ping(msg_witness_block(block))
|
||||
else:
|
||||
test_node.send_and_ping(msg_block(block))
|
||||
|
|
@ -655,7 +653,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
|
||||
# Generate an old compactblock, and verify that it's not accepted.
|
||||
cur_height = node.getblockcount()
|
||||
hashPrevBlock = int(node.getblockhash(cur_height-5), 16)
|
||||
hashPrevBlock = int(node.getblockhash(cur_height - 5), 16)
|
||||
block = self.build_block_on_tip(node)
|
||||
block.hashPrevBlock = hashPrevBlock
|
||||
block.solve()
|
||||
|
|
@ -684,7 +682,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
assert "blocktxn" not in test_node.last_message
|
||||
|
||||
def activate_segwit(self, node):
|
||||
node.generate(144*3)
|
||||
node.generate(144 * 3)
|
||||
assert_equal(get_bip9_status(node, "segwit")["status"], 'active')
|
||||
|
||||
def test_end_to_end_block_relay(self, node, listeners):
|
||||
|
|
@ -780,7 +778,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
delivery_peer.send_message(msg_tx(tx))
|
||||
delivery_peer.sync_with_ping()
|
||||
|
||||
cmpct_block.prefilled_txn[0].tx.wit.vtxinwit = [ CTxInWitness() ]
|
||||
cmpct_block.prefilled_txn[0].tx.wit.vtxinwit = [CTxInWitness()]
|
||||
cmpct_block.prefilled_txn[0].tx.wit.vtxinwit[0].scriptWitness.stack = [ser_uint256(0)]
|
||||
|
||||
cmpct_block.use_witness = True
|
||||
|
|
@ -886,7 +884,7 @@ class CompactBlocksTest(BitcoinTestFramework):
|
|||
self.log.info("Syncing nodes...")
|
||||
assert(self.nodes[0].getbestblockhash() != self.nodes[1].getbestblockhash())
|
||||
while (self.nodes[0].getblockcount() > self.nodes[1].getblockcount()):
|
||||
block_hash = self.nodes[0].getblockhash(self.nodes[1].getblockcount()+1)
|
||||
block_hash = self.nodes[0].getblockhash(self.nodes[1].getblockcount() + 1)
|
||||
self.nodes[1].submitblock(self.nodes[0].getblock(block_hash, False))
|
||||
assert_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash())
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,6 @@ class P2PFingerprintTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
# Build a chain of blocks on top of given one
|
||||
def build_chain(self, nblocks, prev_hash, prev_height, prev_median_time):
|
||||
blocks = []
|
||||
|
|
@ -83,7 +80,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
|
|||
self.nodes[0].setmocktime(int(time.time()) - 60 * 24 * 60 * 60)
|
||||
|
||||
# Generating a chain of 10 blocks
|
||||
block_hashes = self.nodes[0].generate(nblocks=10)
|
||||
block_hashes = self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
||||
|
||||
# Create longer chain starting 2 blocks before current tip
|
||||
height = len(block_hashes) - 2
|
||||
|
|
@ -114,7 +111,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
|
|||
|
||||
# Longest chain is extended so stale is much older than chain tip
|
||||
self.nodes[0].setmocktime(0)
|
||||
tip = self.nodes[0].generate(nblocks=1)[0]
|
||||
tip = self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[0]
|
||||
assert_equal(self.nodes[0].getblockcount(), 14)
|
||||
|
||||
# Send getdata & getheaders to refresh last received getheader message
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.extra_args = [["-whitelist=127.0.0.1"]]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
# Add p2p connection to node0
|
||||
node = self.nodes[0] # convenience reference to the node
|
||||
|
|
@ -48,7 +45,7 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||
node.p2p.send_blocks_and_test([block1], node, success=True)
|
||||
|
||||
self.log.info("Mature the block.")
|
||||
node.generate(100)
|
||||
node.generatetoaddress(100, node.get_deterministic_priv_key().address)
|
||||
|
||||
best_block = node.getblock(node.getbestblockhash())
|
||||
tip = int(node.getbestblockhash(), 16)
|
||||
|
|
@ -80,9 +77,19 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||
block2.vtx.append(tx2)
|
||||
assert_equal(block2.hashMerkleRoot, block2.calc_merkle_root())
|
||||
assert_equal(orig_hash, block2.rehash())
|
||||
assert(block2_orig.vtx != block2.vtx)
|
||||
assert block2_orig.vtx != block2.vtx
|
||||
|
||||
node.p2p.send_blocks_and_test([block2], node, success=False, request_block=False, reject_reason='bad-txns-duplicate')
|
||||
node.p2p.send_blocks_and_test([block2], node, success=False, reject_reason='bad-txns-duplicate')
|
||||
|
||||
# Check transactions for duplicate inputs
|
||||
self.log.info("Test duplicate input block.")
|
||||
|
||||
block2_orig.vtx[2].vin.append(block2_orig.vtx[2].vin[0])
|
||||
block2_orig.vtx[2].rehash()
|
||||
block2_orig.hashMerkleRoot = block2_orig.calc_merkle_root()
|
||||
block2_orig.rehash()
|
||||
block2_orig.solve()
|
||||
node.p2p.send_blocks_and_test([block2_orig], node, success=False, reject_reason='bad-txns-inputs-duplicate')
|
||||
|
||||
self.log.info("Test very broken block.")
|
||||
|
||||
|
|
@ -95,7 +102,8 @@ class InvalidBlockRequestTest(BitcoinTestFramework):
|
|||
block3.rehash()
|
||||
block3.solve()
|
||||
|
||||
node.p2p.send_blocks_and_test([block3], node, success=False, request_block=False, reject_reason='bad-cb-amount')
|
||||
node.p2p.send_blocks_and_test([block3], node, success=False, reject_reason='bad-cb-amount')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
InvalidBlockRequestTest().main()
|
||||
|
|
|
|||
|
|
@ -15,12 +15,9 @@ class InvalidLocatorTest(BitcoinTestFramework):
|
|||
self.num_nodes = 1
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0] # convenience reference to the node
|
||||
node.generate(1) # Get node out of IBD
|
||||
node.generatetoaddress(1, node.get_deterministic_priv_key().address) # Get node out of IBD
|
||||
|
||||
self.log.info('Test max locator size')
|
||||
block_count = node.getblockcount()
|
||||
|
|
|
|||
175
test/bitcoin_functional/functional/p2p_invalid_messages.py
Executable file
175
test/bitcoin_functional/functional/p2p_invalid_messages.py
Executable file
|
|
@ -0,0 +1,175 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-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.
|
||||
"""Test node responses to invalid network messages."""
|
||||
import struct
|
||||
|
||||
from test_framework import messages
|
||||
from test_framework.mininode import P2PDataStore
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
|
||||
class msg_unrecognized:
|
||||
"""Nonsensical message. Modeled after similar types in test_framework.messages."""
|
||||
|
||||
command = b'badmsg'
|
||||
|
||||
def __init__(self, str_data):
|
||||
self.str_data = str_data.encode() if not isinstance(str_data, bytes) else str_data
|
||||
|
||||
def serialize(self):
|
||||
return messages.ser_string(self.str_data)
|
||||
|
||||
def __repr__(self):
|
||||
return "{}(data={})".format(self.command, self.str_data)
|
||||
|
||||
|
||||
class msg_nametoolong(msg_unrecognized):
|
||||
|
||||
command = b'thisnameiswayyyyyyyyytoolong'
|
||||
|
||||
|
||||
class InvalidMessagesTest(BitcoinTestFramework):
|
||||
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def run_test(self):
|
||||
"""
|
||||
0. Send a bunch of large (4MB) messages of an unrecognized type. Check to see
|
||||
that it isn't an effective DoS against the node.
|
||||
|
||||
1. Send an oversized (4MB+) message and check that we're disconnected.
|
||||
|
||||
2. Send a few messages with an incorrect data size in the header, ensure the
|
||||
messages are ignored.
|
||||
|
||||
3. Send an unrecognized message with a command name longer than 12 characters.
|
||||
|
||||
"""
|
||||
node = self.nodes[0]
|
||||
self.node = node
|
||||
node.add_p2p_connection(P2PDataStore())
|
||||
conn2 = node.add_p2p_connection(P2PDataStore())
|
||||
|
||||
msg_limit = 4 * 1000 * 1000 # 4MB, per MAX_PROTOCOL_MESSAGE_LENGTH
|
||||
valid_data_limit = msg_limit - 5 # Account for the 4-byte length prefix
|
||||
|
||||
#
|
||||
# 0.
|
||||
#
|
||||
# Send as large a message as is valid, ensure we aren't disconnected but
|
||||
# also can't exhaust resources.
|
||||
#
|
||||
msg_at_size = msg_unrecognized("b" * valid_data_limit)
|
||||
assert len(msg_at_size.serialize()) == msg_limit
|
||||
|
||||
with node.assert_memory_usage_stable(perc_increase_allowed=0.03):
|
||||
self.log.info(
|
||||
"Sending a bunch of large, junk messages to test "
|
||||
"memory exhaustion. May take a bit...")
|
||||
|
||||
# Run a bunch of times to test for memory exhaustion.
|
||||
for _ in range(80):
|
||||
node.p2p.send_message(msg_at_size)
|
||||
|
||||
# Check that, even though the node is being hammered by nonsense from one
|
||||
# connection, it can still service other peers in a timely way.
|
||||
for _ in range(20):
|
||||
conn2.sync_with_ping(timeout=2)
|
||||
|
||||
# Peer 1, despite serving up a bunch of nonsense, should still be connected.
|
||||
self.log.info("Waiting for node to drop junk messages.")
|
||||
node.p2p.sync_with_ping(timeout=30)
|
||||
assert node.p2p.is_connected
|
||||
|
||||
#
|
||||
# 1.
|
||||
#
|
||||
# Send an oversized message, ensure we're disconnected.
|
||||
#
|
||||
msg_over_size = msg_unrecognized("b" * (valid_data_limit + 1))
|
||||
assert len(msg_over_size.serialize()) == (msg_limit + 1)
|
||||
|
||||
with node.assert_debug_log(["Oversized message from peer=0, disconnecting"]):
|
||||
# An unknown message type (or *any* message type) over
|
||||
# MAX_PROTOCOL_MESSAGE_LENGTH should result in a disconnect.
|
||||
node.p2p.send_message(msg_over_size)
|
||||
node.p2p.wait_for_disconnect(timeout=4)
|
||||
|
||||
node.disconnect_p2ps()
|
||||
conn = node.add_p2p_connection(P2PDataStore())
|
||||
conn.wait_for_verack()
|
||||
|
||||
#
|
||||
# 2.
|
||||
#
|
||||
# Send messages with an incorrect data size in the header.
|
||||
#
|
||||
actual_size = 100
|
||||
msg = msg_unrecognized("b" * actual_size)
|
||||
|
||||
# TODO: handle larger-than cases. I haven't been able to pin down what behavior to expect.
|
||||
for wrong_size in (2, 77, 78, 79):
|
||||
self.log.info("Sending a message with incorrect size of {}".format(wrong_size))
|
||||
|
||||
# Unmodified message should submit okay.
|
||||
node.p2p.send_and_ping(msg)
|
||||
|
||||
# A message lying about its data size results in a disconnect when the incorrect
|
||||
# data size is less than the actual size.
|
||||
#
|
||||
# TODO: why does behavior change at 78 bytes?
|
||||
#
|
||||
node.p2p.send_raw_message(self._tweak_msg_data_size(msg, wrong_size))
|
||||
|
||||
# For some reason unknown to me, we sometimes have to push additional data to the
|
||||
# peer in order for it to realize a disconnect.
|
||||
try:
|
||||
node.p2p.send_message(messages.msg_ping(nonce=123123))
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
node.p2p.wait_for_disconnect(timeout=10)
|
||||
node.disconnect_p2ps()
|
||||
node.add_p2p_connection(P2PDataStore())
|
||||
|
||||
#
|
||||
# 3.
|
||||
#
|
||||
# Send a message with a too-long command name.
|
||||
#
|
||||
node.p2p.send_message(msg_nametoolong("foobar"))
|
||||
node.p2p.wait_for_disconnect(timeout=4)
|
||||
|
||||
# Node is still up.
|
||||
conn = node.add_p2p_connection(P2PDataStore())
|
||||
conn.sync_with_ping()
|
||||
|
||||
|
||||
def _tweak_msg_data_size(self, message, wrong_size):
|
||||
"""
|
||||
Return a raw message based on another message but with an incorrect data size in
|
||||
the message header.
|
||||
"""
|
||||
raw_msg = self.node.p2p.build_message(message)
|
||||
|
||||
bad_size_bytes = struct.pack("<I", wrong_size)
|
||||
num_header_bytes_before_size = 4 + 12
|
||||
|
||||
# Replace the correct data size in the message with an incorrect one.
|
||||
raw_msg_with_wrong_size = (
|
||||
raw_msg[:num_header_bytes_before_size] +
|
||||
bad_size_bytes +
|
||||
raw_msg[(num_header_bytes_before_size + len(bad_size_bytes)):]
|
||||
)
|
||||
assert len(raw_msg) == len(raw_msg_with_wrong_size)
|
||||
|
||||
return raw_msg_with_wrong_size
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
InvalidMessagesTest().main()
|
||||
|
|
@ -26,9 +26,6 @@ class InvalidTxRequestTest(BitcoinTestFramework):
|
|||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def bootstrap_p2p(self, *, num_connections=1):
|
||||
"""Add a P2P connection to the node.
|
||||
|
||||
|
|
@ -64,7 +61,7 @@ class InvalidTxRequestTest(BitcoinTestFramework):
|
|||
node.p2p.send_blocks_and_test([block], node, success=True)
|
||||
|
||||
self.log.info("Mature the block.")
|
||||
self.nodes[0].generate(100)
|
||||
self.nodes[0].generatetoaddress(100, self.nodes[0].get_deterministic_priv_key().address)
|
||||
|
||||
# b'\x64' is OP_NOTIF
|
||||
# Transaction will be rejected with code 16 (REJECT_INVALID)
|
||||
|
|
|
|||
|
|
@ -93,9 +93,6 @@ class P2PLeakTest(BitcoinTestFramework):
|
|||
self.num_nodes = 1
|
||||
self.extra_args = [['-banscore=' + str(banscore)]]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
no_version_bannode = self.nodes[0].add_p2p_connection(CNodeNoVersionBan(), send_version=False, wait_for_verack=False)
|
||||
no_version_idlenode = self.nodes[0].add_p2p_connection(CNodeNoVersionIdle(), send_version=False, wait_for_verack=False)
|
||||
|
|
@ -106,7 +103,7 @@ class P2PLeakTest(BitcoinTestFramework):
|
|||
wait_until(lambda: no_verack_idlenode.version_received, timeout=10, lock=mininode_lock)
|
||||
|
||||
# Mine a block and make sure that it's not sent to the connected nodes
|
||||
self.nodes[0].generate(1)
|
||||
self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)
|
||||
|
||||
#Give the node enough time to possibly leak out a message
|
||||
time.sleep(5)
|
||||
|
|
|
|||
57
test/bitcoin_functional/functional/p2p_leak_tx.py
Executable file
57
test/bitcoin_functional/functional/p2p_leak_tx.py
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2017-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.
|
||||
"""Test that we don't leak txs to inbound peers that we haven't yet announced to"""
|
||||
|
||||
from test_framework.messages import msg_getdata, CInv
|
||||
from test_framework.mininode import P2PDataStore
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
)
|
||||
|
||||
|
||||
class P2PNode(P2PDataStore):
|
||||
def on_inv(self, msg):
|
||||
pass
|
||||
|
||||
|
||||
class P2PLeakTxTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
gen_node = self.nodes[0] # The block and tx generating node
|
||||
gen_node.generate(1)
|
||||
|
||||
inbound_peer = self.nodes[0].add_p2p_connection(P2PNode()) # An "attacking" inbound peer
|
||||
|
||||
MAX_REPEATS = 100
|
||||
self.log.info("Running test up to {} times.".format(MAX_REPEATS))
|
||||
for i in range(MAX_REPEATS):
|
||||
self.log.info('Run repeat {}'.format(i + 1))
|
||||
txid = gen_node.sendtoaddress(gen_node.getnewaddress(), 0.01)
|
||||
|
||||
want_tx = msg_getdata()
|
||||
want_tx.inv.append(CInv(t=1, h=int(txid, 16)))
|
||||
inbound_peer.last_message.pop('notfound', None)
|
||||
inbound_peer.send_message(want_tx)
|
||||
inbound_peer.sync_with_ping()
|
||||
|
||||
if inbound_peer.last_message.get('notfound'):
|
||||
self.log.debug('tx {} was not yet announced to us.'.format(txid))
|
||||
self.log.debug("node has responded with a notfound message. End test.")
|
||||
assert_equal(inbound_peer.last_message['notfound'].vec[0].hash, int(txid, 16))
|
||||
inbound_peer.last_message.pop('notfound')
|
||||
break
|
||||
else:
|
||||
self.log.debug('tx {} was already announced to us. Try test again.'.format(txid))
|
||||
assert int(txid, 16) in [inv.hash for inv in inbound_peer.last_message['inv'].inv]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
P2PLeakTxTest().main()
|
||||
|
|
@ -34,9 +34,6 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||
self.num_nodes = 3
|
||||
self.extra_args = [['-prune=550', '-addrmantest'], [], []]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def disconnect_all(self):
|
||||
disconnect_nodes(self.nodes[0], 1)
|
||||
disconnect_nodes(self.nodes[1], 0)
|
||||
|
|
@ -46,8 +43,8 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||
disconnect_nodes(self.nodes[1], 2)
|
||||
|
||||
def setup_network(self):
|
||||
super(NodeNetworkLimitedTest, self).setup_network()
|
||||
self.disconnect_all()
|
||||
self.add_nodes(self.num_nodes, self.extra_args)
|
||||
self.start_nodes()
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
|
||||
|
|
@ -62,7 +59,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
blocks = self.nodes[1].generate(292)
|
||||
blocks = self.nodes[1].generatetoaddress(292, self.nodes[1].get_deterministic_priv_key().address)
|
||||
sync_blocks([self.nodes[0], self.nodes[1]])
|
||||
|
||||
self.log.info("Make sure we can max retrieve block at tip-288.")
|
||||
|
|
@ -105,7 +102,7 @@ class NodeNetworkLimitedTest(BitcoinTestFramework):
|
|||
self.disconnect_all()
|
||||
|
||||
# mine 10 blocks on node 0 (pruned node)
|
||||
self.nodes[0].generate(10)
|
||||
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
||||
|
||||
# connect node1 (non pruned) with node0 (pruned) and check if the can sync
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ class SegWitTest(BitcoinTestFramework):
|
|||
height = self.nodes[0].getblockcount() + 1
|
||||
block_time = self.nodes[0].getblockheader(tip)["mediantime"] + 1
|
||||
block = create_block(int(tip, 16), create_coinbase(height), block_time)
|
||||
block.version = version
|
||||
block.nVersion = version
|
||||
block.rehash()
|
||||
return block
|
||||
|
||||
|
|
@ -769,12 +769,16 @@ class SegWitTest(BitcoinTestFramework):
|
|||
# will require a witness to spend a witness program regardless of
|
||||
# segwit activation. Note that older bitcoind's that are not
|
||||
# segwit-aware would also reject this for failing CLEANSTACK.
|
||||
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
||||
with self.nodes[0].assert_debug_log(
|
||||
expected_msgs=(spend_tx.hash, 'was not accepted: non-mandatory-script-verify-flag (Witness program was passed an empty witness)')):
|
||||
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
||||
|
||||
# Try to put the witness script in the script_sig, should also fail.
|
||||
spend_tx.vin[0].script_sig = CScript([p2wsh_pubkey, b'a'])
|
||||
# Try to put the witness script in the scriptSig, should also fail.
|
||||
spend_tx.vin[0].scriptSig = CScript([p2wsh_pubkey, b'a'])
|
||||
spend_tx.rehash()
|
||||
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
||||
with self.nodes[0].assert_debug_log(
|
||||
expected_msgs=('Not relaying invalid transaction {}'.format(spend_tx.hash), 'was not accepted: mandatory-script-verify-flag-failed (Script evaluated without error but finished with a false/empty top stack element)')):
|
||||
test_transaction_acceptance(self.nodes[0], self.test_node, spend_tx, with_witness=False, accepted=False)
|
||||
|
||||
# Now put the witness script in the witness, should succeed after
|
||||
# segwit activates.
|
||||
|
|
|
|||
|
|
@ -208,15 +208,12 @@ class SendHeadersTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 2
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def mine_blocks(self, count):
|
||||
"""Mine count blocks and return the new tip."""
|
||||
|
||||
# Clear out block announcements from each p2p listener
|
||||
[x.clear_block_announcements() for x in self.nodes[0].p2ps]
|
||||
self.nodes[0].generate(count)
|
||||
self.nodes[0].generatetoaddress(count, self.nodes[0].get_deterministic_priv_key().address)
|
||||
return int(self.nodes[0].getbestblockhash(), 16)
|
||||
|
||||
def mine_reorg(self, length):
|
||||
|
|
@ -226,7 +223,8 @@ class SendHeadersTest(BitcoinTestFramework):
|
|||
to-be-reorged-out blocks are mined, so that we don't break later tests.
|
||||
return the list of block hashes newly mined."""
|
||||
|
||||
self.nodes[0].generate(length) # make sure all invalidated blocks are node0's
|
||||
# make sure all invalidated blocks are node0's
|
||||
self.nodes[0].generatetoaddress(length, self.nodes[0].get_deterministic_priv_key().address)
|
||||
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))
|
||||
|
|
@ -235,7 +233,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
|||
tip_height = self.nodes[1].getblockcount()
|
||||
hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1))
|
||||
self.nodes[1].invalidateblock(hash_to_invalidate)
|
||||
all_hashes = self.nodes[1].generate(length + 1) # Must be longer than the orig chain
|
||||
all_hashes = self.nodes[1].generatetoaddress(length + 1, self.nodes[1].get_deterministic_priv_key().address) # Must be longer than the orig chain
|
||||
sync_blocks(self.nodes, wait=0.1)
|
||||
return [int(x, 16) for x in all_hashes]
|
||||
|
||||
|
|
@ -254,7 +252,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
|||
self.test_nonnull_locators(test_node, inv_node)
|
||||
|
||||
def test_null_locators(self, test_node, inv_node):
|
||||
tip = self.nodes[0].getblockheader(self.nodes[0].generate(1)[0])
|
||||
tip = self.nodes[0].getblockheader(self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)[0])
|
||||
tip_hash = int(tip["hash"], 16)
|
||||
|
||||
inv_node.check_last_inv_announcement(inv=[tip_hash])
|
||||
|
|
@ -404,7 +402,7 @@ class SendHeadersTest(BitcoinTestFramework):
|
|||
|
||||
block_time += 9
|
||||
|
||||
fork_point = self.nodes[0].getblock("%02x" % new_block_hashes[0])["previousblockhash"]
|
||||
fork_point = self.nodes[0].getblock("%064x" % new_block_hashes[0])["previousblockhash"]
|
||||
fork_point = int(fork_point, 16)
|
||||
|
||||
# Use getblocks/getdata
|
||||
|
|
|
|||
|
|
@ -66,9 +66,6 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
self.num_nodes = 2
|
||||
self.extra_args = [[], ["-minimumchainwork=0x10"]]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
# Node0 will be used to test behavior of processing unrequested blocks
|
||||
# from peers which are not whitelisted, while Node1 will be used for
|
||||
|
|
@ -85,8 +82,8 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
|
||||
|
||||
# 1. Have nodes mine a block (leave IBD)
|
||||
[ n.generate(1) for n in self.nodes ]
|
||||
tips = [ int("0x" + n.getbestblockhash(), 0) for n in self.nodes ]
|
||||
[n.generatetoaddress(1, n.get_deterministic_priv_key().address) for n in self.nodes]
|
||||
tips = [int("0x" + n.getbestblockhash(), 0) for n in self.nodes]
|
||||
|
||||
# 2. Send one block that builds on each tip.
|
||||
# This should be accepted by node0
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class RPCBindTest(BitcoinTestFramework):
|
|||
self.nodes[0].rpchost = None
|
||||
self.start_nodes([base_args])
|
||||
# connect to node through non-loopback interface
|
||||
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, "regtest2","%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
|
||||
node = get_rpc_proxy(rpc_url(self.nodes[0].datadir, 0, "%s:%d" % (rpchost, rpcport)), 0, coveragedir=self.options.coveragedir)
|
||||
node.getnetworkinfo()
|
||||
self.stop_nodes()
|
||||
|
||||
|
|
|
|||
|
|
@ -48,9 +48,6 @@ class BlockchainTest(BitcoinTestFramework):
|
|||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete
|
||||
|
||||
|
|
@ -128,7 +125,9 @@ class BlockchainTest(BitcoinTestFramework):
|
|||
|
||||
# Test `getchaintxstats` invalid `blockhash`
|
||||
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getchaintxstats, blockhash=0)
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0')
|
||||
assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 1, for '0')", self.nodes[0].getchaintxstats, blockhash='0')
|
||||
assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getchaintxstats, blockhash='ZZZ0000000000000000000000000000000000000000000000000000000000000')
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].getchaintxstats, blockhash='0000000000000000000000000000000000000000000000000000000000000000')
|
||||
blockhash = self.nodes[0].getblockhash(200)
|
||||
self.nodes[0].invalidateblock(blockhash)
|
||||
assert_raises_rpc_error(-8, "Block is not in main chain", self.nodes[0].getchaintxstats, blockhash=blockhash)
|
||||
|
|
@ -206,7 +205,9 @@ class BlockchainTest(BitcoinTestFramework):
|
|||
def _test_getblockheader(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense")
|
||||
assert_raises_rpc_error(-8, "hash must be of length 64 (not 8, for 'nonsense')", node.getblockheader, "nonsense")
|
||||
assert_raises_rpc_error(-8, "hash must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", node.getblockheader, "ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844")
|
||||
assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "0cf7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844")
|
||||
|
||||
besthash = node.getbestblockhash()
|
||||
secondbesthash = node.getblockhash(199)
|
||||
|
|
@ -242,12 +243,12 @@ class BlockchainTest(BitcoinTestFramework):
|
|||
|
||||
def _test_stopatheight(self):
|
||||
assert_equal(self.nodes[0].getblockcount(), 200)
|
||||
self.nodes[0].generate(6)
|
||||
self.nodes[0].generatetoaddress(6, self.nodes[0].get_deterministic_priv_key().address)
|
||||
assert_equal(self.nodes[0].getblockcount(), 206)
|
||||
self.log.debug('Node should not stop at this height')
|
||||
assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3))
|
||||
try:
|
||||
self.nodes[0].generate(1)
|
||||
self.nodes[0].generatetoaddress(1, self.nodes[0].get_deterministic_priv_key().address)
|
||||
except (ConnectionError, http.client.BadStatusLine):
|
||||
pass # The node already shut down before response
|
||||
self.log.debug('Node should stop at this height...')
|
||||
|
|
|
|||
|
|
@ -4,12 +4,17 @@
|
|||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test deprecation of RPC calls."""
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_raises_rpc_error
|
||||
|
||||
class DeprecatedRpcTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
self.extra_args = [[], ["-deprecatedrpc=validateaddress"]]
|
||||
self.extra_args = [[], ["-deprecatedrpc=generate"]]
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
# The generate RPC method requires the wallet to be compiled
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
# This test should be used to verify correct behaviour of deprecated
|
||||
|
|
@ -18,7 +23,10 @@ class DeprecatedRpcTest(BitcoinTestFramework):
|
|||
# self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses")
|
||||
# assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()])
|
||||
# self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
|
||||
pass
|
||||
|
||||
self.log.info("Test generate RPC")
|
||||
assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1)
|
||||
self.nodes[1].generate(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
DeprecatedRpcTest().main()
|
||||
|
|
|
|||
|
|
@ -169,6 +169,8 @@ class GetblockstatsTest(BitcoinTestFramework):
|
|||
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=1)
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,6 @@ class GetChainTipsTest (BitcoinTestFramework):
|
|||
def set_test_params(self):
|
||||
self.num_nodes = 4
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
tips = self.nodes[0].getchaintips()
|
||||
assert_equal(len(tips), 1)
|
||||
|
|
@ -29,8 +26,8 @@ class GetChainTipsTest (BitcoinTestFramework):
|
|||
|
||||
# Split the network and build two chains of different lengths.
|
||||
self.split_network()
|
||||
self.nodes[0].generate(10)
|
||||
self.nodes[2].generate(20)
|
||||
self.nodes[0].generatetoaddress(10, self.nodes[0].get_deterministic_priv_key().address)
|
||||
self.nodes[2].generatetoaddress(20, self.nodes[2].get_deterministic_priv_key().address)
|
||||
self.sync_all([self.nodes[:2], self.nodes[2:]])
|
||||
|
||||
tips = self.nodes[1].getchaintips ()
|
||||
|
|
|
|||
|
|
@ -7,12 +7,18 @@
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error
|
||||
|
||||
import os
|
||||
|
||||
|
||||
class HelpRpcTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
self.test_categories()
|
||||
self.dump_help()
|
||||
|
||||
def test_categories(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
# wrong argument count
|
||||
|
|
@ -37,6 +43,15 @@ class HelpRpcTest(BitcoinTestFramework):
|
|||
|
||||
assert_equal(titles, components)
|
||||
|
||||
def dump_help(self):
|
||||
dump_dir = os.path.join(self.options.tmpdir, 'rpc_help_dump')
|
||||
os.mkdir(dump_dir)
|
||||
calls = [line.split(' ', 1)[0] for line in self.nodes[0].help().splitlines() if line and not line.startswith('==')]
|
||||
for call in calls:
|
||||
with open(os.path.join(dump_dir, call), 'w', encoding='utf-8') as f:
|
||||
# Make sure the node can generate the help at runtime without crashing
|
||||
f.write(self.nodes[0].help(call))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
HelpRpcTest().main()
|
||||
|
|
|
|||
|
|
@ -14,21 +14,18 @@ class InvalidateTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:")
|
||||
self.log.info("Mine 4 blocks on Node 0")
|
||||
self.nodes[0].generate(4)
|
||||
self.nodes[0].generatetoaddress(4, self.nodes[0].get_deterministic_priv_key().address)
|
||||
assert(self.nodes[0].getblockcount() == 4)
|
||||
besthash = self.nodes[0].getbestblockhash()
|
||||
|
||||
self.log.info("Mine competing 6 blocks on Node 1")
|
||||
self.nodes[1].generate(6)
|
||||
self.nodes[1].generatetoaddress(6, self.nodes[1].get_deterministic_priv_key().address)
|
||||
assert(self.nodes[1].getblockcount() == 6)
|
||||
|
||||
self.log.info("Connect nodes to force a reorg")
|
||||
|
|
@ -56,7 +53,7 @@ class InvalidateTest(BitcoinTestFramework):
|
|||
self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
|
||||
assert(self.nodes[2].getblockcount() == 2)
|
||||
self.log.info("..and then mine a block")
|
||||
self.nodes[2].generate(1)
|
||||
self.nodes[2].generatetoaddress(1, self.nodes[2].get_deterministic_priv_key().address)
|
||||
self.log.info("Verify all nodes are at the right height")
|
||||
time.sleep(5)
|
||||
assert_equal(self.nodes[2].getblockcount(), 3)
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import (
|
||||
assert_equal,
|
||||
assert_greater_than_or_equal,
|
||||
assert_greater_than,
|
||||
assert_raises_rpc_error,
|
||||
connect_nodes_bi,
|
||||
p2p_port,
|
||||
wait_until,
|
||||
)
|
||||
from test_framework.mininode import P2PInterface
|
||||
from test_framework.messages import CAddress, msg_addr, NODE_NETWORK, NODE_WITNESS
|
||||
|
||||
class NetTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
|
|
@ -31,6 +34,7 @@ class NetTest(BitcoinTestFramework):
|
|||
self._test_getnetworkinginfo()
|
||||
self._test_getaddednodeinfo()
|
||||
self._test_getpeerinfo()
|
||||
self._test_getnodeaddresses()
|
||||
|
||||
def _test_connection_count(self):
|
||||
# connect_nodes_bi connects each node to the other
|
||||
|
|
@ -101,5 +105,40 @@ class NetTest(BitcoinTestFramework):
|
|||
assert_equal(peer_info[0][0]['minfeefilter'], Decimal("0.00000500"))
|
||||
assert_equal(peer_info[1][0]['minfeefilter'], Decimal("0.00001000"))
|
||||
|
||||
def _test_getnodeaddresses(self):
|
||||
self.nodes[0].add_p2p_connection(P2PInterface())
|
||||
|
||||
# send some addresses to the node via the p2p message addr
|
||||
msg = msg_addr()
|
||||
imported_addrs = []
|
||||
for i in range(256):
|
||||
a = "123.123.123.{}".format(i)
|
||||
imported_addrs.append(a)
|
||||
addr = CAddress()
|
||||
addr.time = 100000000
|
||||
addr.nServices = NODE_NETWORK | NODE_WITNESS
|
||||
addr.ip = a
|
||||
addr.port = 8333
|
||||
msg.addrs.append(addr)
|
||||
self.nodes[0].p2p.send_and_ping(msg)
|
||||
|
||||
# obtain addresses via rpc call and check they were ones sent in before
|
||||
REQUEST_COUNT = 10
|
||||
node_addresses = self.nodes[0].getnodeaddresses(REQUEST_COUNT)
|
||||
assert_equal(len(node_addresses), REQUEST_COUNT)
|
||||
for a in node_addresses:
|
||||
assert_greater_than(a["time"], 1527811200) # 1st June 2018
|
||||
assert_equal(a["services"], NODE_NETWORK | NODE_WITNESS)
|
||||
assert a["address"] in imported_addrs
|
||||
assert_equal(a["port"], 8333)
|
||||
|
||||
assert_raises_rpc_error(-8, "Address count out of range", self.nodes[0].getnodeaddresses, -1)
|
||||
|
||||
# addrman's size cannot be known reliably after insertion, as hash collisions may occur
|
||||
# so only test that requesting a large number of addresses returns less than that
|
||||
LARGE_REQUEST_COUNT = 10000
|
||||
node_addresses = self.nodes[0].getnodeaddresses(LARGE_REQUEST_COUNT)
|
||||
assert_greater_than(LARGE_REQUEST_COUNT, len(node_addresses))
|
||||
|
||||
if __name__ == '__main__':
|
||||
NetTest().main()
|
||||
|
|
|
|||
|
|
@ -38,26 +38,24 @@ class PreciousTest(BitcoinTestFramework):
|
|||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
self.setup_nodes()
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Ensure submitblock can in principle reorg to a competing chain")
|
||||
self.nodes[0].generate(1)
|
||||
gen_address = lambda i: self.nodes[i].get_deterministic_priv_key().address # A non-wallet address to mine to
|
||||
self.nodes[0].generatetoaddress(1, gen_address(0))
|
||||
assert_equal(self.nodes[0].getblockcount(), 1)
|
||||
hashZ = self.nodes[1].generate(2)[-1]
|
||||
hashZ = self.nodes[1].generatetoaddress(2, gen_address(1))[-1]
|
||||
assert_equal(self.nodes[1].getblockcount(), 2)
|
||||
node_sync_via_rpc(self.nodes[0:3])
|
||||
assert_equal(self.nodes[0].getbestblockhash(), hashZ)
|
||||
|
||||
self.log.info("Mine blocks A-B-C on Node 0")
|
||||
hashC = self.nodes[0].generate(3)[-1]
|
||||
hashC = self.nodes[0].generatetoaddress(3, gen_address(0))[-1]
|
||||
assert_equal(self.nodes[0].getblockcount(), 5)
|
||||
self.log.info("Mine competing blocks E-F-G on Node 1")
|
||||
hashG = self.nodes[1].generate(3)[-1]
|
||||
hashG = self.nodes[1].generatetoaddress(3, gen_address(1))[-1]
|
||||
assert_equal(self.nodes[1].getblockcount(), 5)
|
||||
assert(hashC != hashG)
|
||||
self.log.info("Connect nodes and check no reorg occurs")
|
||||
|
|
@ -86,7 +84,7 @@ class PreciousTest(BitcoinTestFramework):
|
|||
self.nodes[1].preciousblock(hashC)
|
||||
assert_equal(self.nodes[1].getbestblockhash(), hashC)
|
||||
self.log.info("Mine another block (E-F-G-)H on Node 0 and reorg Node 1")
|
||||
self.nodes[0].generate(1)
|
||||
self.nodes[0].generatetoaddress(1, gen_address(0))
|
||||
assert_equal(self.nodes[0].getblockcount(), 6)
|
||||
sync_blocks(self.nodes[0:2])
|
||||
hashH = self.nodes[0].getbestblockhash()
|
||||
|
|
@ -95,7 +93,7 @@ class PreciousTest(BitcoinTestFramework):
|
|||
self.nodes[1].preciousblock(hashC)
|
||||
assert_equal(self.nodes[1].getbestblockhash(), hashH)
|
||||
self.log.info("Mine competing blocks I-J-K-L on Node 2")
|
||||
self.nodes[2].generate(4)
|
||||
self.nodes[2].generatetoaddress(4, gen_address(2))
|
||||
assert_equal(self.nodes[2].getblockcount(), 6)
|
||||
hashL = self.nodes[2].getbestblockhash()
|
||||
self.log.info("Connect nodes and check no reorg occurs")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"""
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output
|
||||
from test_framework.util import assert_equal, assert_raises_rpc_error, find_output, disconnect_nodes, connect_nodes_bi, sync_blocks
|
||||
|
||||
import json
|
||||
import os
|
||||
|
|
@ -23,6 +23,45 @@ class PSBTTest(BitcoinTestFramework):
|
|||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def test_utxo_conversion(self):
|
||||
mining_node = self.nodes[2]
|
||||
offline_node = self.nodes[0]
|
||||
online_node = self.nodes[1]
|
||||
|
||||
# Disconnect offline node from others
|
||||
disconnect_nodes(offline_node, 1)
|
||||
disconnect_nodes(online_node, 0)
|
||||
disconnect_nodes(offline_node, 2)
|
||||
disconnect_nodes(mining_node, 0)
|
||||
|
||||
# Mine a transaction that credits the offline address
|
||||
offline_addr = offline_node.getnewaddress(address_type="p2sh-segwit")
|
||||
online_addr = online_node.getnewaddress(address_type="p2sh-segwit")
|
||||
online_node.importaddress(offline_addr, "", False)
|
||||
mining_node.sendtoaddress(address=offline_addr, amount=1.0)
|
||||
mining_node.generate(nblocks=1)
|
||||
sync_blocks([mining_node, online_node])
|
||||
|
||||
# Construct an unsigned PSBT on the online node (who doesn't know the output is Segwit, so will include a non-witness UTXO)
|
||||
utxos = online_node.listunspent(addresses=[offline_addr])
|
||||
raw = online_node.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
|
||||
psbt = online_node.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
|
||||
assert("non_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0])
|
||||
|
||||
# Have the offline node sign the PSBT (which will update the UTXO to segwit)
|
||||
signed_psbt = offline_node.walletprocesspsbt(psbt)["psbt"]
|
||||
assert("witness_utxo" in mining_node.decodepsbt(signed_psbt)["inputs"][0])
|
||||
|
||||
# Make sure we can mine the resulting transaction
|
||||
txid = mining_node.sendrawtransaction(mining_node.finalizepsbt(signed_psbt)["hex"])
|
||||
mining_node.generate(1)
|
||||
sync_blocks([mining_node, online_node])
|
||||
assert_equal(online_node.gettxout(txid,0)["confirmations"], 1)
|
||||
|
||||
# Reconnect
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
connect_nodes_bi(self.nodes, 0, 2)
|
||||
|
||||
def run_test(self):
|
||||
# Create and fund a raw tx for sending 10 BTC
|
||||
psbtx1 = self.nodes[0].walletcreatefundedpsbt([], {self.nodes[2].getnewaddress():10})['psbt']
|
||||
|
|
@ -107,6 +146,9 @@ class PSBTTest(BitcoinTestFramework):
|
|||
# Make sure that a psbt with signatures cannot be converted
|
||||
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx['hex'])
|
||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'])
|
||||
assert_raises_rpc_error(-22, "TX decode failed", self.nodes[0].converttopsbt, signedtx['hex'], False)
|
||||
# Unless we allow it to convert and strip signatures
|
||||
self.nodes[0].converttopsbt(signedtx['hex'], True)
|
||||
|
||||
# Explicitly allow converting non-empty txs
|
||||
new_psbt = self.nodes[0].converttopsbt(rawtx['hex'])
|
||||
|
|
@ -168,6 +210,13 @@ class PSBTTest(BitcoinTestFramework):
|
|||
assert tx_in["sequence"] > MAX_BIP125_RBF_SEQUENCE
|
||||
assert_equal(decoded_psbt["tx"]["locktime"], 0)
|
||||
|
||||
# Regression test for 14473 (mishandling of already-signed witness transaction):
|
||||
psbtx_info = self.nodes[0].walletcreatefundedpsbt([{"txid":unspent["txid"], "vout":unspent["vout"]}], [{self.nodes[2].getnewaddress():unspent["amount"]+1}])
|
||||
complete_psbt = self.nodes[0].walletprocesspsbt(psbtx_info["psbt"])
|
||||
double_processed_psbt = self.nodes[0].walletprocesspsbt(complete_psbt["psbt"])
|
||||
assert_equal(complete_psbt, double_processed_psbt)
|
||||
# We don't care about the decode result, but decoding must succeed.
|
||||
self.nodes[0].decodepsbt(double_processed_psbt["psbt"])
|
||||
|
||||
# BIP 174 Test Vectors
|
||||
|
||||
|
|
@ -224,6 +273,16 @@ class PSBTTest(BitcoinTestFramework):
|
|||
extracted = self.nodes[2].finalizepsbt(extractor['extract'], True)['hex']
|
||||
assert_equal(extracted, extractor['result'])
|
||||
|
||||
# Unload extra wallets
|
||||
for i, signer in enumerate(signers):
|
||||
self.nodes[2].unloadwallet("wallet{}".format(i))
|
||||
|
||||
self.test_utxo_conversion()
|
||||
|
||||
# Test that psbts with p2pkh outputs are created properly
|
||||
p2pkh = self.nodes[0].getnewaddress(address_type='legacy')
|
||||
psbt = self.nodes[1].walletcreatefundedpsbt([], [{p2pkh : 1}], 0, {"includeWatching" : True}, True)
|
||||
self.nodes[0].decodepsbt(psbt['psbt'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
PSBTTest().main()
|
||||
|
|
|
|||
|
|
@ -74,14 +74,15 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [])
|
||||
|
||||
# Test `createrawtransaction` invalid extra parameters
|
||||
#assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo')
|
||||
assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo')
|
||||
|
||||
# Test `createrawtransaction` invalid `inputs`
|
||||
txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
|
||||
assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {})
|
||||
assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {})
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{}], {})
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
|
||||
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].createrawtransaction, [{}], {})
|
||||
assert_raises_rpc_error(-8, "txid must be of length 64 (not 3, for 'foo')", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844')", self.nodes[0].createrawtransaction, [{'txid': 'ZZZ7bb8b1697ea987f3b223ba7819250cae33efacb068d23dc24859824a77844'}], {})
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {})
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
|
||||
|
|
@ -224,9 +225,10 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
# We should not get the tx if we provide an unrelated block
|
||||
assert_raises_rpc_error(-5, "No such transaction found", self.nodes[0].getrawtransaction, tx, True, block2)
|
||||
# An invalid block hash should raise the correct errors
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, True)
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal", self.nodes[0].getrawtransaction, tx, True, "foobar")
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be of length 64", self.nodes[0].getrawtransaction, tx, True, "abcd1234")
|
||||
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[0].getrawtransaction, tx, True, True)
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 6, for 'foobar')", self.nodes[0].getrawtransaction, tx, True, "foobar")
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be of length 64 (not 8, for 'abcd1234')", self.nodes[0].getrawtransaction, tx, True, "abcd1234")
|
||||
assert_raises_rpc_error(-8, "parameter 3 must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].getrawtransaction, tx, True, "ZZZ0000000000000000000000000000000000000000000000000000000000000")
|
||||
assert_raises_rpc_error(-5, "Block hash not found", self.nodes[0].getrawtransaction, tx, True, "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
# Undo the blocks and check in_active_chain
|
||||
self.nodes[0].invalidateblock(block1)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info("Stop node, remove wallet, mine again some blocks...")
|
||||
self.stop_node(0)
|
||||
shutil.rmtree(os.path.join(self.nodes[0].datadir, "regtest2", 'wallets'))
|
||||
shutil.rmtree(os.path.join(self.nodes[0].datadir, "regtest", 'wallets'))
|
||||
self.start_node(0)
|
||||
self.nodes[0].generate(110)
|
||||
|
||||
|
|
@ -65,6 +65,8 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
|||
assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007"))
|
||||
|
||||
self.log.info("Test extended key derivation.")
|
||||
# Run various scans, and verify that the sum of the amounts of the matches corresponds to the expected subset.
|
||||
# Note that all amounts in the UTXO set are powers of 2 multiplied by 0.001 BTC, so each amounts uniquely identifies a subset.
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.008"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.016"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.032"))
|
||||
|
|
@ -82,7 +84,7 @@ class ScantxoutsetTest(BitcoinTestFramework):
|
|||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("8.192"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("16.384"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("4.096"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo([abcdef88/1/2'/3/4h]tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("16.384"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("1.536"))
|
||||
assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("3.584"))
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ class SignRawTransactionsTest(BitcoinTestFramework):
|
|||
# 2) No script verification error occurred
|
||||
assert 'errors' not in rawTxSigned
|
||||
|
||||
def test_with_lock_outputs(self):
|
||||
"""Test correct error reporting when trying to sign a locked output"""
|
||||
self.nodes[0].encryptwallet("password")
|
||||
|
||||
rawTx = '020000000156b958f78e3f24e0b2f4e4db1255426b0902027cb37e3ddadb52e37c3557dddb0000000000ffffffff01c0a6b929010000001600149a2ee8c77140a053f36018ac8124a6ececc1668a00000000'
|
||||
|
||||
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first", self.nodes[0].signrawtransactionwithwallet, rawTx)
|
||||
|
||||
def script_verification_error_test(self):
|
||||
"""Create and sign a raw transaction with valid (vin 0), invalid (vin 1) and one missing (vin 2) input script.
|
||||
|
||||
|
|
@ -138,6 +146,7 @@ class SignRawTransactionsTest(BitcoinTestFramework):
|
|||
def run_test(self):
|
||||
self.successful_signing_test()
|
||||
self.script_verification_error_test()
|
||||
self.test_with_lock_outputs()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
|
|
@ -66,12 +66,18 @@ class MerkleBlockTest(BitcoinTestFramework):
|
|||
txid_spent = txin_spent["txid"]
|
||||
txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2
|
||||
|
||||
# Invalid txids
|
||||
assert_raises_rpc_error(-8, "txid must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["00000000000000000000000000000000"], blockhash)
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, ["ZZZ0000000000000000000000000000000000000000000000000000000000000"], blockhash)
|
||||
# Invalid blockhashes
|
||||
assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 32, for '00000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000")
|
||||
assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')", self.nodes[2].gettxoutproof, [txid_spent], "ZZZ0000000000000000000000000000000000000000000000000000000000000")
|
||||
# We can't find the block from a fully-spent tx
|
||||
assert_raises_rpc_error(-5, "Transaction not yet in block", self.nodes[2].gettxoutproof, [txid_spent])
|
||||
# We can get the proof if we specify the block
|
||||
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent])
|
||||
# We can't get the proof if we specify a non-existent block
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "00000000000000000000000000000000")
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[2].gettxoutproof, [txid_spent], "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
# We can get the proof if the transaction is unspent
|
||||
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_unspent])), [txid_unspent])
|
||||
# We can get the proof if we provide a list of transactions and one of them is unspent. The ordering of the list should not matter.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,11 @@ from .util import bytes_to_hex_str, hex_str_to_bytes
|
|||
|
||||
from . import segwit_addr
|
||||
|
||||
ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
|
||||
|
||||
chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
|
||||
|
||||
|
||||
def byte_to_base58(b, version):
|
||||
result = ''
|
||||
str = bytes_to_hex_str(b)
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import decimal
|
|||
import http.client
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import socket
|
||||
import time
|
||||
import urllib.parse
|
||||
|
|
@ -71,19 +72,12 @@ class AuthServiceProxy():
|
|||
self._service_name = service_name
|
||||
self.ensure_ascii = ensure_ascii # can be toggled on the fly by tests
|
||||
self.__url = urllib.parse.urlparse(service_url)
|
||||
port = 80 if self.__url.port is None else self.__url.port
|
||||
user = None if self.__url.username is None else self.__url.username.encode('utf8')
|
||||
passwd = None if self.__url.password is None else self.__url.password.encode('utf8')
|
||||
authpair = user + b':' + passwd
|
||||
self.__auth_header = b'Basic ' + base64.b64encode(authpair)
|
||||
|
||||
if connection:
|
||||
# Callables re-use the connection of the original proxy
|
||||
self.__conn = connection
|
||||
elif self.__url.scheme == 'https':
|
||||
self.__conn = http.client.HTTPSConnection(self.__url.hostname, port, timeout=timeout)
|
||||
else:
|
||||
self.__conn = http.client.HTTPConnection(self.__url.hostname, port, timeout=timeout)
|
||||
self.timeout = timeout
|
||||
self._set_conn(connection)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith('__') and name.endswith('__'):
|
||||
|
|
@ -102,6 +96,10 @@ class AuthServiceProxy():
|
|||
'User-Agent': USER_AGENT,
|
||||
'Authorization': self.__auth_header,
|
||||
'Content-type': 'application/json'}
|
||||
if os.name == 'nt':
|
||||
# Windows somehow does not like to re-use connections
|
||||
# TODO: Find out why the connection would disconnect occasionally and make it reusable on Windows
|
||||
self._set_conn()
|
||||
try:
|
||||
self.__conn.request(method, path, postdata, headers)
|
||||
return self._get_response()
|
||||
|
|
@ -178,3 +176,13 @@ class AuthServiceProxy():
|
|||
|
||||
def __truediv__(self, relative_uri):
|
||||
return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn)
|
||||
|
||||
def _set_conn(self, connection=None):
|
||||
port = 80 if self.__url.port is None else self.__url.port
|
||||
if connection:
|
||||
self.__conn = connection
|
||||
self.timeout = connection.timeout
|
||||
elif self.__url.scheme == 'https':
|
||||
self.__conn = http.client.HTTPSConnection(self.__url.hostname, port, timeout=self.timeout)
|
||||
else:
|
||||
self.__conn = http.client.HTTPConnection(self.__url.hostname, port, timeout=self.timeout)
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ def get_legacy_sigopcount_tx(tx, accurate=True):
|
|||
return count
|
||||
|
||||
def witness_script(use_p2wsh, pubkey):
|
||||
"""Create a scriptPubKey for a pay-to-wtiness TxOut.
|
||||
"""Create a scriptPubKey for a pay-to-witness TxOut.
|
||||
|
||||
This is either a P2WPKH output for the given pubkey, or a P2WSH output of a
|
||||
1-of-1 multisig for the given pubkey. Returns the hex encoding of the
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ CBlock, CTransaction, CBlockHeader, CTxIn, CTxOut, etc....:
|
|||
msg_block, msg_tx, msg_headers, etc.:
|
||||
data structures that represent network messages
|
||||
|
||||
ser_*, deser_*: functions that handle serialization/deserialization."""
|
||||
ser_*, deser_*: functions that handle serialization/deserialization.
|
||||
|
||||
Classes use __slots__ to ensure extraneous attributes aren't accidentally added
|
||||
by tests, compromising their intended effect.
|
||||
"""
|
||||
from codecs import encode
|
||||
import copy
|
||||
import hashlib
|
||||
|
|
@ -31,7 +35,6 @@ MY_VERSION = 70014 # past bip-31 for ping/pong
|
|||
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
|
||||
MY_RELAY = 1 # from version 70001 onwards, fRelay should be appended to version messages (BIP37)
|
||||
|
||||
MAX_INV_SZ = 50000
|
||||
MAX_LOCATOR_SZ = 101
|
||||
MAX_BLOCK_BASE_SIZE = 1000000
|
||||
|
||||
|
|
@ -54,9 +57,6 @@ MSG_TYPE_MASK = 0xffffffff >> 2
|
|||
def sha256(s):
|
||||
return hashlib.new('sha256', s).digest()
|
||||
|
||||
def ripemd160(s):
|
||||
return hashlib.new('ripemd160', s).digest()
|
||||
|
||||
def hash256(s):
|
||||
return sha256(sha256(s))
|
||||
|
||||
|
|
@ -185,7 +185,10 @@ def ToHex(obj):
|
|||
|
||||
# Objects that map to bitcoind objects, which can be serialized/deserialized
|
||||
|
||||
class CAddress():
|
||||
|
||||
class CAddress:
|
||||
__slots__ = ("ip", "nServices", "pchReserved", "port", "time")
|
||||
|
||||
def __init__(self):
|
||||
self.time = 0
|
||||
self.nServices = 1
|
||||
|
|
@ -215,7 +218,10 @@ class CAddress():
|
|||
return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
|
||||
self.ip, self.port)
|
||||
|
||||
class CInv():
|
||||
|
||||
class CInv:
|
||||
__slots__ = ("hash", "type")
|
||||
|
||||
typemap = {
|
||||
0: "Error",
|
||||
1: "TX",
|
||||
|
|
@ -244,7 +250,9 @@ class CInv():
|
|||
% (self.typemap[self.type], self.hash)
|
||||
|
||||
|
||||
class CBlockLocator():
|
||||
class CBlockLocator:
|
||||
__slots__ = ("nVersion", "vHave")
|
||||
|
||||
def __init__(self):
|
||||
self.nVersion = MY_VERSION
|
||||
self.vHave = []
|
||||
|
|
@ -264,7 +272,9 @@ class CBlockLocator():
|
|||
% (self.nVersion, repr(self.vHave))
|
||||
|
||||
|
||||
class COutPoint():
|
||||
class COutPoint:
|
||||
__slots__ = ("hash", "n")
|
||||
|
||||
def __init__(self, hash=0, n=0):
|
||||
self.hash = hash
|
||||
self.n = n
|
||||
|
|
@ -283,7 +293,9 @@ class COutPoint():
|
|||
return "COutPoint(hash=%064x n=%i)" % (self.hash, self.n)
|
||||
|
||||
|
||||
class CTxIn():
|
||||
class CTxIn:
|
||||
__slots__ = ("nSequence", "prevout", "scriptSig")
|
||||
|
||||
def __init__(self, outpoint=None, scriptSig=b"", nSequence=0):
|
||||
if outpoint is None:
|
||||
self.prevout = COutPoint()
|
||||
|
|
@ -311,7 +323,9 @@ class CTxIn():
|
|||
self.nSequence)
|
||||
|
||||
|
||||
class CTxOut():
|
||||
class CTxOut:
|
||||
__slots__ = ("nValue", "scriptPubKey")
|
||||
|
||||
def __init__(self, nValue=0, scriptPubKey=b""):
|
||||
self.nValue = nValue
|
||||
self.scriptPubKey = scriptPubKey
|
||||
|
|
@ -332,7 +346,9 @@ class CTxOut():
|
|||
bytes_to_hex_str(self.scriptPubKey))
|
||||
|
||||
|
||||
class CScriptWitness():
|
||||
class CScriptWitness:
|
||||
__slots__ = ("stack",)
|
||||
|
||||
def __init__(self):
|
||||
# stack is a vector of strings
|
||||
self.stack = []
|
||||
|
|
@ -347,7 +363,9 @@ class CScriptWitness():
|
|||
return True
|
||||
|
||||
|
||||
class CTxInWitness():
|
||||
class CTxInWitness:
|
||||
__slots__ = ("scriptWitness",)
|
||||
|
||||
def __init__(self):
|
||||
self.scriptWitness = CScriptWitness()
|
||||
|
||||
|
|
@ -364,7 +382,9 @@ class CTxInWitness():
|
|||
return self.scriptWitness.is_null()
|
||||
|
||||
|
||||
class CTxWitness():
|
||||
class CTxWitness:
|
||||
__slots__ = ("vtxinwit",)
|
||||
|
||||
def __init__(self):
|
||||
self.vtxinwit = []
|
||||
|
||||
|
|
@ -392,7 +412,10 @@ class CTxWitness():
|
|||
return True
|
||||
|
||||
|
||||
class CTransaction():
|
||||
class CTransaction:
|
||||
__slots__ = ("hash", "nLockTime", "nVersion", "sha256", "vin", "vout",
|
||||
"wit")
|
||||
|
||||
def __init__(self, tx=None):
|
||||
if tx is None:
|
||||
self.nVersion = 1
|
||||
|
|
@ -496,7 +519,10 @@ class CTransaction():
|
|||
% (self.nVersion, repr(self.vin), repr(self.vout), repr(self.wit), self.nLockTime)
|
||||
|
||||
|
||||
class CBlockHeader():
|
||||
class CBlockHeader:
|
||||
__slots__ = ("hash", "hashMerkleRoot", "hashPrevBlock", "nBits", "nNonce",
|
||||
"nTime", "nVersion", "sha256")
|
||||
|
||||
def __init__(self, header=None):
|
||||
if header is None:
|
||||
self.set_null()
|
||||
|
|
@ -565,6 +591,8 @@ class CBlockHeader():
|
|||
|
||||
|
||||
class CBlock(CBlockHeader):
|
||||
__slots__ = ("vtx",)
|
||||
|
||||
def __init__(self, header=None):
|
||||
super(CBlock, self).__init__(header)
|
||||
self.vtx = []
|
||||
|
|
@ -636,7 +664,9 @@ class CBlock(CBlockHeader):
|
|||
time.ctime(self.nTime), self.nBits, self.nNonce, repr(self.vtx))
|
||||
|
||||
|
||||
class PrefilledTransaction():
|
||||
class PrefilledTransaction:
|
||||
__slots__ = ("index", "tx")
|
||||
|
||||
def __init__(self, index=0, tx = None):
|
||||
self.index = index
|
||||
self.tx = tx
|
||||
|
|
@ -664,8 +694,12 @@ class PrefilledTransaction():
|
|||
def __repr__(self):
|
||||
return "PrefilledTransaction(index=%d, tx=%s)" % (self.index, repr(self.tx))
|
||||
|
||||
|
||||
# This is what we send on the wire, in a cmpctblock message.
|
||||
class P2PHeaderAndShortIDs():
|
||||
class P2PHeaderAndShortIDs:
|
||||
__slots__ = ("header", "nonce", "prefilled_txn", "prefilled_txn_length",
|
||||
"shortids", "shortids_length")
|
||||
|
||||
def __init__(self):
|
||||
self.header = CBlockHeader()
|
||||
self.nonce = 0
|
||||
|
|
@ -703,9 +737,11 @@ class P2PHeaderAndShortIDs():
|
|||
def __repr__(self):
|
||||
return "P2PHeaderAndShortIDs(header=%s, nonce=%d, shortids_length=%d, shortids=%s, prefilled_txn_length=%d, prefilledtxn=%s" % (repr(self.header), self.nonce, self.shortids_length, repr(self.shortids), self.prefilled_txn_length, repr(self.prefilled_txn))
|
||||
|
||||
|
||||
# P2P version of the above that will use witness serialization (for compact
|
||||
# block version 2)
|
||||
class P2PHeaderAndShortWitnessIDs(P2PHeaderAndShortIDs):
|
||||
__slots__ = ()
|
||||
def serialize(self):
|
||||
return super(P2PHeaderAndShortWitnessIDs, self).serialize(with_witness=True)
|
||||
|
||||
|
|
@ -715,9 +751,12 @@ def calculate_shortid(k0, k1, tx_hash):
|
|||
expected_shortid &= 0x0000ffffffffffff
|
||||
return expected_shortid
|
||||
|
||||
|
||||
# This version gets rid of the array lengths, and reinterprets the differential
|
||||
# encoding into indices that can be used for lookup.
|
||||
class HeaderAndShortIDs():
|
||||
class HeaderAndShortIDs:
|
||||
__slots__ = ("header", "nonce", "prefilled_txn", "shortids", "use_witness")
|
||||
|
||||
def __init__(self, p2pheaders_and_shortids = None):
|
||||
self.header = CBlockHeader()
|
||||
self.nonce = 0
|
||||
|
|
@ -778,7 +817,8 @@ class HeaderAndShortIDs():
|
|||
return "HeaderAndShortIDs(header=%s, nonce=%d, shortids=%s, prefilledtxn=%s" % (repr(self.header), self.nonce, repr(self.shortids), repr(self.prefilled_txn))
|
||||
|
||||
|
||||
class BlockTransactionsRequest():
|
||||
class BlockTransactionsRequest:
|
||||
__slots__ = ("blockhash", "indexes")
|
||||
|
||||
def __init__(self, blockhash=0, indexes = None):
|
||||
self.blockhash = blockhash
|
||||
|
|
@ -818,7 +858,8 @@ class BlockTransactionsRequest():
|
|||
return "BlockTransactionsRequest(hash=%064x indexes=%s)" % (self.blockhash, repr(self.indexes))
|
||||
|
||||
|
||||
class BlockTransactions():
|
||||
class BlockTransactions:
|
||||
__slots__ = ("blockhash", "transactions")
|
||||
|
||||
def __init__(self, blockhash=0, transactions = None):
|
||||
self.blockhash = blockhash
|
||||
|
|
@ -840,12 +881,14 @@ class BlockTransactions():
|
|||
def __repr__(self):
|
||||
return "BlockTransactions(hash=%064x transactions=%s)" % (self.blockhash, repr(self.transactions))
|
||||
|
||||
class CPartialMerkleTree():
|
||||
|
||||
class CPartialMerkleTree:
|
||||
__slots__ = ("nTransactions", "vBits", "vHash")
|
||||
|
||||
def __init__(self):
|
||||
self.nTransactions = 0
|
||||
self.vHash = []
|
||||
self.vBits = []
|
||||
self.fBad = False
|
||||
|
||||
def deserialize(self, f):
|
||||
self.nTransactions = struct.unpack("<i", f.read(4))[0]
|
||||
|
|
@ -868,7 +911,10 @@ class CPartialMerkleTree():
|
|||
def __repr__(self):
|
||||
return "CPartialMerkleTree(nTransactions=%d, vHash=%s, vBits=%s)" % (self.nTransactions, repr(self.vHash), repr(self.vBits))
|
||||
|
||||
class CMerkleBlock():
|
||||
|
||||
class CMerkleBlock:
|
||||
__slots__ = ("header", "txn")
|
||||
|
||||
def __init__(self):
|
||||
self.header = CBlockHeader()
|
||||
self.txn = CPartialMerkleTree()
|
||||
|
|
@ -888,7 +934,9 @@ class CMerkleBlock():
|
|||
|
||||
|
||||
# Objects that correspond to messages on the wire
|
||||
class msg_version():
|
||||
class msg_version:
|
||||
__slots__ = ("addrFrom", "addrTo", "nNonce", "nRelay", "nServices",
|
||||
"nStartingHeight", "nTime", "nVersion", "strSubVer")
|
||||
command = b"version"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -945,7 +993,8 @@ class msg_version():
|
|||
self.strSubVer, self.nStartingHeight, self.nRelay)
|
||||
|
||||
|
||||
class msg_verack():
|
||||
class msg_verack:
|
||||
__slots__ = ()
|
||||
command = b"verack"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -961,7 +1010,8 @@ class msg_verack():
|
|||
return "msg_verack()"
|
||||
|
||||
|
||||
class msg_addr():
|
||||
class msg_addr:
|
||||
__slots__ = ("addrs",)
|
||||
command = b"addr"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -977,7 +1027,8 @@ class msg_addr():
|
|||
return "msg_addr(addrs=%s)" % (repr(self.addrs))
|
||||
|
||||
|
||||
class msg_inv():
|
||||
class msg_inv:
|
||||
__slots__ = ("inv",)
|
||||
command = b"inv"
|
||||
|
||||
def __init__(self, inv=None):
|
||||
|
|
@ -996,7 +1047,8 @@ class msg_inv():
|
|||
return "msg_inv(inv=%s)" % (repr(self.inv))
|
||||
|
||||
|
||||
class msg_getdata():
|
||||
class msg_getdata:
|
||||
__slots__ = ("inv",)
|
||||
command = b"getdata"
|
||||
|
||||
def __init__(self, inv=None):
|
||||
|
|
@ -1012,7 +1064,8 @@ class msg_getdata():
|
|||
return "msg_getdata(inv=%s)" % (repr(self.inv))
|
||||
|
||||
|
||||
class msg_getblocks():
|
||||
class msg_getblocks:
|
||||
__slots__ = ("locator", "hashstop")
|
||||
command = b"getblocks"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1035,7 +1088,8 @@ class msg_getblocks():
|
|||
% (repr(self.locator), self.hashstop)
|
||||
|
||||
|
||||
class msg_tx():
|
||||
class msg_tx:
|
||||
__slots__ = ("tx",)
|
||||
command = b"tx"
|
||||
|
||||
def __init__(self, tx=CTransaction()):
|
||||
|
|
@ -1050,13 +1104,16 @@ class msg_tx():
|
|||
def __repr__(self):
|
||||
return "msg_tx(tx=%s)" % (repr(self.tx))
|
||||
|
||||
|
||||
class msg_witness_tx(msg_tx):
|
||||
__slots__ = ()
|
||||
|
||||
def serialize(self):
|
||||
return self.tx.serialize_with_witness()
|
||||
|
||||
|
||||
class msg_block():
|
||||
class msg_block:
|
||||
__slots__ = ("block",)
|
||||
command = b"block"
|
||||
|
||||
def __init__(self, block=None):
|
||||
|
|
@ -1074,9 +1131,12 @@ class msg_block():
|
|||
def __repr__(self):
|
||||
return "msg_block(block=%s)" % (repr(self.block))
|
||||
|
||||
|
||||
# for cases where a user needs tighter control over what is sent over the wire
|
||||
# note that the user must supply the name of the command, and the data
|
||||
class msg_generic():
|
||||
class msg_generic:
|
||||
__slots__ = ("command", "data")
|
||||
|
||||
def __init__(self, command, data=None):
|
||||
self.command = command
|
||||
self.data = data
|
||||
|
|
@ -1087,13 +1147,16 @@ class msg_generic():
|
|||
def __repr__(self):
|
||||
return "msg_generic()"
|
||||
|
||||
class msg_witness_block(msg_block):
|
||||
|
||||
class msg_witness_block(msg_block):
|
||||
__slots__ = ()
|
||||
def serialize(self):
|
||||
r = self.block.serialize(with_witness=True)
|
||||
return r
|
||||
|
||||
class msg_getaddr():
|
||||
|
||||
class msg_getaddr:
|
||||
__slots__ = ()
|
||||
command = b"getaddr"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1109,7 +1172,8 @@ class msg_getaddr():
|
|||
return "msg_getaddr()"
|
||||
|
||||
|
||||
class msg_ping():
|
||||
class msg_ping:
|
||||
__slots__ = ("nonce",)
|
||||
command = b"ping"
|
||||
|
||||
def __init__(self, nonce=0):
|
||||
|
|
@ -1127,7 +1191,8 @@ class msg_ping():
|
|||
return "msg_ping(nonce=%08x)" % self.nonce
|
||||
|
||||
|
||||
class msg_pong():
|
||||
class msg_pong:
|
||||
__slots__ = ("nonce",)
|
||||
command = b"pong"
|
||||
|
||||
def __init__(self, nonce=0):
|
||||
|
|
@ -1145,7 +1210,8 @@ class msg_pong():
|
|||
return "msg_pong(nonce=%08x)" % self.nonce
|
||||
|
||||
|
||||
class msg_mempool():
|
||||
class msg_mempool:
|
||||
__slots__ = ()
|
||||
command = b"mempool"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1160,7 +1226,26 @@ class msg_mempool():
|
|||
def __repr__(self):
|
||||
return "msg_mempool()"
|
||||
|
||||
class msg_sendheaders():
|
||||
|
||||
class msg_notfound:
|
||||
__slots__ = ("vec", )
|
||||
command = b"notfound"
|
||||
|
||||
def __init__(self, vec=None):
|
||||
self.vec = vec or []
|
||||
|
||||
def deserialize(self, f):
|
||||
self.vec = deser_vector(f, CInv)
|
||||
|
||||
def serialize(self):
|
||||
return ser_vector(self.vec)
|
||||
|
||||
def __repr__(self):
|
||||
return "msg_notfound(vec=%s)" % (repr(self.vec))
|
||||
|
||||
|
||||
class msg_sendheaders:
|
||||
__slots__ = ()
|
||||
command = b"sendheaders"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1180,7 +1265,8 @@ class msg_sendheaders():
|
|||
# number of entries
|
||||
# vector of hashes
|
||||
# hash_stop (hash of last desired block header, 0 to get as many as possible)
|
||||
class msg_getheaders():
|
||||
class msg_getheaders:
|
||||
__slots__ = ("hashstop", "locator",)
|
||||
command = b"getheaders"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1205,7 +1291,8 @@ class msg_getheaders():
|
|||
|
||||
# headers message has
|
||||
# <count> <vector of block headers>
|
||||
class msg_headers():
|
||||
class msg_headers:
|
||||
__slots__ = ("headers",)
|
||||
command = b"headers"
|
||||
|
||||
def __init__(self, headers=None):
|
||||
|
|
@ -1225,7 +1312,8 @@ class msg_headers():
|
|||
return "msg_headers(headers=%s)" % repr(self.headers)
|
||||
|
||||
|
||||
class msg_reject():
|
||||
class msg_reject:
|
||||
__slots__ = ("code", "data", "message", "reason")
|
||||
command = b"reject"
|
||||
REJECT_MALFORMED = 1
|
||||
|
||||
|
|
@ -1256,7 +1344,9 @@ class msg_reject():
|
|||
return "msg_reject: %s %d %s [%064x]" \
|
||||
% (self.message, self.code, self.reason, self.data)
|
||||
|
||||
class msg_feefilter():
|
||||
|
||||
class msg_feefilter:
|
||||
__slots__ = ("feerate",)
|
||||
command = b"feefilter"
|
||||
|
||||
def __init__(self, feerate=0):
|
||||
|
|
@ -1273,7 +1363,9 @@ class msg_feefilter():
|
|||
def __repr__(self):
|
||||
return "msg_feefilter(feerate=%08x)" % self.feerate
|
||||
|
||||
class msg_sendcmpct():
|
||||
|
||||
class msg_sendcmpct:
|
||||
__slots__ = ("announce", "version")
|
||||
command = b"sendcmpct"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1293,7 +1385,9 @@ class msg_sendcmpct():
|
|||
def __repr__(self):
|
||||
return "msg_sendcmpct(announce=%s, version=%lu)" % (self.announce, self.version)
|
||||
|
||||
class msg_cmpctblock():
|
||||
|
||||
class msg_cmpctblock:
|
||||
__slots__ = ("header_and_shortids",)
|
||||
command = b"cmpctblock"
|
||||
|
||||
def __init__(self, header_and_shortids = None):
|
||||
|
|
@ -1311,7 +1405,9 @@ class msg_cmpctblock():
|
|||
def __repr__(self):
|
||||
return "msg_cmpctblock(HeaderAndShortIDs=%s)" % repr(self.header_and_shortids)
|
||||
|
||||
class msg_getblocktxn():
|
||||
|
||||
class msg_getblocktxn:
|
||||
__slots__ = ("block_txn_request",)
|
||||
command = b"getblocktxn"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1329,7 +1425,9 @@ class msg_getblocktxn():
|
|||
def __repr__(self):
|
||||
return "msg_getblocktxn(block_txn_request=%s)" % (repr(self.block_txn_request))
|
||||
|
||||
class msg_blocktxn():
|
||||
|
||||
class msg_blocktxn:
|
||||
__slots__ = ("block_transactions",)
|
||||
command = b"blocktxn"
|
||||
|
||||
def __init__(self):
|
||||
|
|
@ -1346,7 +1444,10 @@ class msg_blocktxn():
|
|||
def __repr__(self):
|
||||
return "msg_blocktxn(block_transactions=%s)" % (repr(self.block_transactions))
|
||||
|
||||
|
||||
class msg_witness_blocktxn(msg_blocktxn):
|
||||
__slots__ = ()
|
||||
|
||||
def serialize(self):
|
||||
r = b""
|
||||
r += self.block_transactions.serialize(with_witness=True)
|
||||
|
|
|
|||
|
|
@ -21,7 +21,38 @@ import struct
|
|||
import sys
|
||||
import threading
|
||||
|
||||
from test_framework.messages import CBlockHeader, MIN_VERSION_SUPPORTED, msg_addr, msg_block, MSG_BLOCK, msg_blocktxn, msg_cmpctblock, msg_feefilter, msg_getaddr, msg_getblocks, msg_getblocktxn, msg_getdata, msg_getheaders, msg_headers, msg_inv, msg_mempool, msg_ping, msg_pong, msg_reject, msg_sendcmpct, msg_sendheaders, msg_tx, MSG_TX, MSG_TYPE_MASK, msg_verack, msg_version, NODE_NETWORK, NODE_WITNESS, sha256
|
||||
from test_framework.messages import (
|
||||
CBlockHeader,
|
||||
MIN_VERSION_SUPPORTED,
|
||||
msg_addr,
|
||||
msg_block,
|
||||
MSG_BLOCK,
|
||||
msg_blocktxn,
|
||||
msg_cmpctblock,
|
||||
msg_feefilter,
|
||||
msg_getaddr,
|
||||
msg_getblocks,
|
||||
msg_getblocktxn,
|
||||
msg_getdata,
|
||||
msg_getheaders,
|
||||
msg_headers,
|
||||
msg_inv,
|
||||
msg_mempool,
|
||||
msg_notfound,
|
||||
msg_ping,
|
||||
msg_pong,
|
||||
msg_reject,
|
||||
msg_sendcmpct,
|
||||
msg_sendheaders,
|
||||
msg_tx,
|
||||
MSG_TX,
|
||||
MSG_TYPE_MASK,
|
||||
msg_verack,
|
||||
msg_version,
|
||||
NODE_NETWORK,
|
||||
NODE_WITNESS,
|
||||
sha256,
|
||||
)
|
||||
from test_framework.util import wait_until
|
||||
|
||||
logger = logging.getLogger("TestFramework.mininode")
|
||||
|
|
@ -40,6 +71,7 @@ MESSAGEMAP = {
|
|||
b"headers": msg_headers,
|
||||
b"inv": msg_inv,
|
||||
b"mempool": msg_mempool,
|
||||
b"notfound": msg_notfound,
|
||||
b"ping": msg_ping,
|
||||
b"pong": msg_pong,
|
||||
b"reject": msg_reject,
|
||||
|
|
@ -175,10 +207,13 @@ class P2PConnection(asyncio.Protocol):
|
|||
|
||||
This method takes a P2P payload, builds the P2P header and adds
|
||||
the message to the send buffer to be sent over the socket."""
|
||||
tmsg = self.build_message(message)
|
||||
self._log_message("send", message)
|
||||
return self.send_raw_message(tmsg)
|
||||
|
||||
def send_raw_message(self, raw_message_bytes):
|
||||
if not self.is_connected:
|
||||
raise IOError('Not connected')
|
||||
self._log_message("send", message)
|
||||
tmsg = self._build_message(message)
|
||||
|
||||
def maybe_write():
|
||||
if not self._transport:
|
||||
|
|
@ -188,12 +223,12 @@ class P2PConnection(asyncio.Protocol):
|
|||
# Python 3.4 versions.
|
||||
if hasattr(self._transport, 'is_closing') and self._transport.is_closing():
|
||||
return
|
||||
self._transport.write(tmsg)
|
||||
self._transport.write(raw_message_bytes)
|
||||
NetworkThread.network_event_loop.call_soon_threadsafe(maybe_write)
|
||||
|
||||
# Class utility methods
|
||||
|
||||
def _build_message(self, message):
|
||||
def build_message(self, message):
|
||||
"""Build a serialized P2P message"""
|
||||
command = message.command
|
||||
data = message.serialize()
|
||||
|
|
@ -295,6 +330,7 @@ class P2PInterface(P2PConnection):
|
|||
def on_getheaders(self, message): pass
|
||||
def on_headers(self, message): pass
|
||||
def on_mempool(self, message): pass
|
||||
def on_notfound(self, message): pass
|
||||
def on_pong(self, message): pass
|
||||
def on_reject(self, message): pass
|
||||
def on_sendcmpct(self, message): pass
|
||||
|
|
@ -313,7 +349,7 @@ class P2PInterface(P2PConnection):
|
|||
self.send_message(msg_pong(message.nonce))
|
||||
|
||||
def on_verack(self, message):
|
||||
self.verack_received = True
|
||||
pass
|
||||
|
||||
def on_version(self, message):
|
||||
assert message.nVersion >= MIN_VERSION_SUPPORTED, "Version {} received. Test framework only supports versions greater than {}".format(message.nVersion, MIN_VERSION_SUPPORTED)
|
||||
|
|
@ -376,9 +412,9 @@ class P2PInterface(P2PConnection):
|
|||
|
||||
# Message sending helper functions
|
||||
|
||||
def send_and_ping(self, message):
|
||||
def send_and_ping(self, message, timeout=60):
|
||||
self.send_message(message)
|
||||
self.sync_with_ping()
|
||||
self.sync_with_ping(timeout=timeout)
|
||||
|
||||
# Sync up with the node
|
||||
def sync_with_ping(self, timeout=60):
|
||||
|
|
@ -500,9 +536,9 @@ class P2PDataStore(P2PInterface):
|
|||
wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock)
|
||||
|
||||
if expect_disconnect:
|
||||
self.wait_for_disconnect()
|
||||
self.wait_for_disconnect(timeout=timeout)
|
||||
else:
|
||||
self.sync_with_ping()
|
||||
self.sync_with_ping(timeout=timeout)
|
||||
|
||||
if success:
|
||||
wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout)
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ def hash160(s):
|
|||
_opcode_instances = []
|
||||
class CScriptOp(int):
|
||||
"""A single script opcode"""
|
||||
__slots__ = []
|
||||
__slots__ = ()
|
||||
|
||||
@staticmethod
|
||||
def encode_op_pushdata(d):
|
||||
|
|
@ -361,8 +361,11 @@ class CScriptTruncatedPushDataError(CScriptInvalidError):
|
|||
self.data = data
|
||||
super(CScriptTruncatedPushDataError, self).__init__(msg)
|
||||
|
||||
|
||||
# This is used, eg, for blockchain heights in coinbase scripts (bip34)
|
||||
class CScriptNum():
|
||||
class CScriptNum:
|
||||
__slots__ = ("value",)
|
||||
|
||||
def __init__(self, d=0):
|
||||
self.value = d
|
||||
|
||||
|
|
@ -393,6 +396,8 @@ class CScript(bytes):
|
|||
|
||||
iter(script) however does iterate by opcode.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
@classmethod
|
||||
def __coerce_instance(cls, other):
|
||||
# Coerce other into bytes
|
||||
|
|
|
|||
|
|
@ -54,10 +54,9 @@ class Socks5Command():
|
|||
return 'Socks5Command(%s,%s,%s,%s,%s,%s)' % (self.cmd, self.atyp, self.addr, self.port, self.username, self.password)
|
||||
|
||||
class Socks5Connection():
|
||||
def __init__(self, serv, conn, peer):
|
||||
def __init__(self, serv, conn):
|
||||
self.serv = serv
|
||||
self.conn = conn
|
||||
self.peer = peer
|
||||
|
||||
def handle(self):
|
||||
"""Handle socks5 request according to RFC192."""
|
||||
|
|
@ -137,9 +136,9 @@ class Socks5Server():
|
|||
|
||||
def run(self):
|
||||
while self.running:
|
||||
(sockconn, peer) = self.s.accept()
|
||||
(sockconn, _) = self.s.accept()
|
||||
if self.running:
|
||||
conn = Socks5Connection(self, sockconn, peer)
|
||||
conn = Socks5Connection(self, sockconn)
|
||||
thread = threading.Thread(None, conn.handle)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
|
||||
def __init__(self):
|
||||
"""Sets test framework defaults. Do not override this method. Instead, override the set_test_params() method"""
|
||||
self.chain = 'regtest2'
|
||||
self.setup_clean_chain = False
|
||||
self.nodes = []
|
||||
self.network_thread = None
|
||||
|
|
@ -121,7 +120,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
parser.add_argument("--coveragedir", dest="coveragedir",
|
||||
help="Write tested RPC commands into this directory")
|
||||
parser.add_argument("--configfile", dest="configfile",
|
||||
default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../../config.ini"),
|
||||
default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../config.ini"),
|
||||
help="Location of the test framework config file (default: %(default)s)")
|
||||
parser.add_argument("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true",
|
||||
help="Attach a python debugger if test fails")
|
||||
|
|
@ -138,8 +137,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(open(self.options.configfile))
|
||||
self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/elementsd' + config["environment"]["EXEEXT"])
|
||||
self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/elements-cli' + config["environment"]["EXEEXT"])
|
||||
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'),
|
||||
|
|
@ -162,12 +161,13 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
success = TestStatus.FAILED
|
||||
|
||||
try:
|
||||
if self.options.usecli and not self.supports_cli:
|
||||
raise SkipTest("--usecli specified but test does not support using CLI")
|
||||
if self.options.usecli:
|
||||
if not self.supports_cli:
|
||||
raise SkipTest("--usecli specified but test does not support using CLI")
|
||||
self.skip_if_no_cli()
|
||||
self.skip_test_if_missing_module()
|
||||
self.setup_chain()
|
||||
self.setup_network()
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
self.run_test()
|
||||
success = TestStatus.PASSED
|
||||
except JSONRPCException as e:
|
||||
|
|
@ -260,11 +260,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
extra_args = self.extra_args
|
||||
self.add_nodes(self.num_nodes, extra_args)
|
||||
self.start_nodes()
|
||||
self.import_deterministic_coinbase_privkeys()
|
||||
|
||||
def import_deterministic_coinbase_privkeys(self):
|
||||
if self.setup_clean_chain:
|
||||
return
|
||||
|
||||
for n in self.nodes:
|
||||
try:
|
||||
n.getwalletinfo()
|
||||
|
|
@ -272,7 +270,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
assert str(e).startswith('Method not found')
|
||||
continue
|
||||
|
||||
n.importprivkey(n.get_deterministic_priv_key()[1])
|
||||
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
|
||||
|
||||
def run_test(self):
|
||||
"""Tests must override this method to define test logic"""
|
||||
|
|
@ -294,7 +292,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), self.chain, rpchost=rpchost, timewait=self.rpc_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))
|
||||
self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=self.rpc_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"""
|
||||
|
|
@ -441,11 +439,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
|
||||
# Create cache directories, run bitcoinds:
|
||||
for i in range(MAX_NODES):
|
||||
datadir = initialize_datadir(self.options.cachedir, i, self.chain)
|
||||
datadir = initialize_datadir(self.options.cachedir, i)
|
||||
args = [self.options.bitcoind, "-datadir=" + datadir, '-disablewallet']
|
||||
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), self.chain, extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, 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=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
|
||||
self.nodes[i].args = args
|
||||
self.start_node(i)
|
||||
|
||||
|
|
@ -466,7 +464,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
for peer in range(4):
|
||||
for j in range(25):
|
||||
set_node_times(self.nodes, block_time)
|
||||
self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key()[0])
|
||||
self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key().address)
|
||||
block_time += 10 * 60
|
||||
# Must sync before next peer starts generating blocks
|
||||
sync_blocks(self.nodes)
|
||||
|
|
@ -477,7 +475,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
self.disable_mocktime()
|
||||
|
||||
def cache_path(n, *paths):
|
||||
return os.path.join(get_datadir_path(self.options.cachedir, n), self.chain, *paths)
|
||||
return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths)
|
||||
|
||||
for i in range(MAX_NODES):
|
||||
os.rmdir(cache_path(i, 'wallets')) # Remove empty wallets dir
|
||||
|
|
@ -489,7 +487,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
from_dir = get_datadir_path(self.options.cachedir, i)
|
||||
to_dir = get_datadir_path(self.options.tmpdir, i)
|
||||
shutil.copytree(from_dir, to_dir)
|
||||
initialize_datadir(self.options.tmpdir, i, self.chain) # Overwrite port/rpcport in bitcoin.conf
|
||||
initialize_datadir(self.options.tmpdir, i) # Overwrite port/rpcport in bitcoin.conf
|
||||
|
||||
def _initialize_chain_clean(self):
|
||||
"""Initialize empty blockchain for use by the test.
|
||||
|
|
@ -497,7 +495,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
Create an empty blockchain and num_nodes wallets.
|
||||
Useful if a test case wants complete control over initialization."""
|
||||
for i in range(self.num_nodes):
|
||||
initialize_datadir(self.options.tmpdir, i, self.chain)
|
||||
initialize_datadir(self.options.tmpdir, i)
|
||||
|
||||
def skip_if_no_py3_zmq(self):
|
||||
"""Attempt to import the zmq package and skip the test if the import fails."""
|
||||
|
|
@ -526,7 +524,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
|
|||
config = configparser.ConfigParser()
|
||||
config.read_file(open(self.options.configfile))
|
||||
|
||||
return config["components"].getboolean("ENABLE_UTILS")
|
||||
return config["components"].getboolean("ENABLE_CLI")
|
||||
|
||||
def is_wallet_compiled(self):
|
||||
"""Checks whether the wallet module was compiled."""
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import subprocess
|
|||
import tempfile
|
||||
import time
|
||||
import urllib.parse
|
||||
import collections
|
||||
|
||||
from .authproxy import JSONRPCException
|
||||
from .util import (
|
||||
|
|
@ -58,12 +59,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, chain, *, rpchost, timewait, bitcoind, bitcoin_cli, 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.chain = chain
|
||||
self.rpchost = rpchost
|
||||
self.rpc_timeout = timewait
|
||||
self.binary = bitcoind
|
||||
|
|
@ -85,7 +85,7 @@ class TestNode():
|
|||
"-uacomment=testnode%d" % i
|
||||
]
|
||||
|
||||
self.cli = TestNodeCLI(bitcoin_cli, self.datadir, self.chain)
|
||||
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
|
||||
self.use_cli = use_cli
|
||||
|
||||
self.running = False
|
||||
|
|
@ -100,20 +100,40 @@ class TestNode():
|
|||
|
||||
def get_deterministic_priv_key(self):
|
||||
"""Return a deterministic priv key in base58, that only depends on the node's index"""
|
||||
AddressKeyPair = collections.namedtuple('AddressKeyPair', ['address', 'key'])
|
||||
PRIV_KEYS = [
|
||||
# address , privkey
|
||||
('mjTkW3DjgyZck4KbiRusZsqTgaYTxdSz6z', 'cVpF924EspNh8KjYsfhgY96mmxvT6DgdWiTYMtMjuM74hJaU5psW'),
|
||||
('msX6jQXvxiNhx3Q62PKeLPrhrqZQdSimTg', 'cUxsWyKyZ9MAQTaAhUQWJmBbSvHMwSmuv59KgxQV7oZQU3PXN3KE'),
|
||||
('mnonCMyH9TmAsSj3M59DsbH8H63U3RKoFP', 'cTrh7dkEAeJd6b3MRX9bZK8eRmNqVCMH3LSUkE3dSFDyzjU38QxK'),
|
||||
('mqJupas8Dt2uestQDvV2NH3RU8uZh2dqQR', 'cVuKKa7gbehEQvVq717hYcbE9Dqmq7KEBKqWgWrYBa2CKKrhtRim'),
|
||||
('msYac7Rvd5ywm6pEmkjyxhbCDKqWsVeYws', 'cQDCBuKcjanpXDpCqacNSjYfxeQj8G6CAtH1Dsk3cXyqLNC4RPuh'),
|
||||
('n2rnuUnwLgXqf9kk2kjvVm8R5BZK1yxQBi', 'cQakmfPSLSqKHyMFGwAqKHgWUiofJCagVGhiB4KCainaeCSxeyYq'),
|
||||
('myzuPxRwsf3vvGzEuzPfK9Nf2RfwauwYe6', 'cQMpDLJwA8DBe9NcQbdoSb1BhmFxVjWD5gRyrLZCtpuF9Zi3a9RK'),
|
||||
('mumwTaMtbxEPUswmLBBN3vM9oGRtGBrys8', 'cSXmRKXVcoouhNNVpcNKFfxsTsToY5pvB9DVsFksF1ENunTzRKsy'),
|
||||
('mpV7aGShMkJCZgbW7F6iZgrvuPHjZjH9qg', 'cSoXt6tm3pqy43UMabY6eUTmR3eSUYFtB2iNQDGgb3VUnRsQys2k'),
|
||||
AddressKeyPair('mjTkW3DjgyZck4KbiRusZsqTgaYTxdSz6z', 'cVpF924EspNh8KjYsfhgY96mmxvT6DgdWiTYMtMjuM74hJaU5psW'),
|
||||
AddressKeyPair('msX6jQXvxiNhx3Q62PKeLPrhrqZQdSimTg', 'cUxsWyKyZ9MAQTaAhUQWJmBbSvHMwSmuv59KgxQV7oZQU3PXN3KE'),
|
||||
AddressKeyPair('mnonCMyH9TmAsSj3M59DsbH8H63U3RKoFP', 'cTrh7dkEAeJd6b3MRX9bZK8eRmNqVCMH3LSUkE3dSFDyzjU38QxK'),
|
||||
AddressKeyPair('mqJupas8Dt2uestQDvV2NH3RU8uZh2dqQR', 'cVuKKa7gbehEQvVq717hYcbE9Dqmq7KEBKqWgWrYBa2CKKrhtRim'),
|
||||
AddressKeyPair('msYac7Rvd5ywm6pEmkjyxhbCDKqWsVeYws', 'cQDCBuKcjanpXDpCqacNSjYfxeQj8G6CAtH1Dsk3cXyqLNC4RPuh'),
|
||||
AddressKeyPair('n2rnuUnwLgXqf9kk2kjvVm8R5BZK1yxQBi', 'cQakmfPSLSqKHyMFGwAqKHgWUiofJCagVGhiB4KCainaeCSxeyYq'),
|
||||
AddressKeyPair('myzuPxRwsf3vvGzEuzPfK9Nf2RfwauwYe6', 'cQMpDLJwA8DBe9NcQbdoSb1BhmFxVjWD5gRyrLZCtpuF9Zi3a9RK'),
|
||||
AddressKeyPair('mumwTaMtbxEPUswmLBBN3vM9oGRtGBrys8', 'cSXmRKXVcoouhNNVpcNKFfxsTsToY5pvB9DVsFksF1ENunTzRKsy'),
|
||||
AddressKeyPair('mpV7aGShMkJCZgbW7F6iZgrvuPHjZjH9qg', 'cSoXt6tm3pqy43UMabY6eUTmR3eSUYFtB2iNQDGgb3VUnRsQys2k'),
|
||||
]
|
||||
return PRIV_KEYS[self.index]
|
||||
|
||||
def get_mem_rss(self):
|
||||
"""Get the memory usage (RSS) per `ps`.
|
||||
|
||||
Returns None if `ps` is unavailable.
|
||||
"""
|
||||
assert self.running
|
||||
|
||||
try:
|
||||
return int(subprocess.check_output(
|
||||
["ps", "h", "-o", "rss", "{}".format(self.process.pid)],
|
||||
stderr=subprocess.DEVNULL).split()[-1])
|
||||
|
||||
# Avoid failing on platforms where ps isn't installed.
|
||||
#
|
||||
# We could later use something like `psutils` to work across platforms.
|
||||
except (FileNotFoundError, subprocess.SubprocessError):
|
||||
self.log.exception("Unable to get memory usage")
|
||||
return None
|
||||
|
||||
def _node_msg(self, msg: str) -> str:
|
||||
"""Return a modified msg that identifies this node by its index as a debugging aid."""
|
||||
return "[node %d] %s" % (self.index, msg)
|
||||
|
|
@ -156,7 +176,7 @@ class TestNode():
|
|||
# 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.chain)
|
||||
delete_cookie_file(self.datadir)
|
||||
|
||||
# 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")
|
||||
|
|
@ -175,7 +195,7 @@ class TestNode():
|
|||
raise FailedToStartError(self._node_msg(
|
||||
'bitcoind exited with status {} during initialization'.format(self.process.returncode)))
|
||||
try:
|
||||
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.chain, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
|
||||
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
|
||||
self.rpc.getblockcount()
|
||||
# If the call to getblockcount() succeeds then the RPC connection is up
|
||||
self.rpc_connected = True
|
||||
|
|
@ -186,7 +206,9 @@ class TestNode():
|
|||
if e.errno != errno.ECONNREFUSED: # Port not yet open?
|
||||
raise # unknown IO error
|
||||
except JSONRPCException as e: # Initialization phase
|
||||
if e.error['code'] != -28: # RPC in warmup?
|
||||
# -28 RPC in warmup
|
||||
# -342 Service unavailable, RPC server started but is shutting down due to error
|
||||
if e.error['code'] != -28 and e.error['code'] != -342:
|
||||
raise # unknown JSON RPC exception
|
||||
except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting
|
||||
if "No RPC credentials" not in str(e):
|
||||
|
|
@ -194,6 +216,10 @@ class TestNode():
|
|||
time.sleep(1.0 / poll_per_s)
|
||||
self._raise_assertion_error("Unable to connect to bitcoind")
|
||||
|
||||
def generate(self, nblocks, maxtries=1000000):
|
||||
self.log.debug("TestNode.generate() dispatches `generate` call to `generatetoaddress`")
|
||||
return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries)
|
||||
|
||||
def get_wallet_rpc(self, wallet_name):
|
||||
if self.use_cli:
|
||||
return self.cli("-rpcwallet={}".format(wallet_name))
|
||||
|
|
@ -249,7 +275,7 @@ class TestNode():
|
|||
|
||||
@contextlib.contextmanager
|
||||
def assert_debug_log(self, expected_msgs):
|
||||
debug_log = os.path.join(self.datadir, self.chain, 'debug.log')
|
||||
debug_log = os.path.join(self.datadir, 'regtest', 'debug.log')
|
||||
with open(debug_log, encoding='utf-8') as dl:
|
||||
dl.seek(0, 2)
|
||||
prev_size = dl.tell()
|
||||
|
|
@ -264,6 +290,29 @@ class TestNode():
|
|||
if re.search(re.escape(expected_msg), log, flags=re.MULTILINE) is None:
|
||||
self._raise_assertion_error('Expected message "{}" does not partially match log:\n\n{}\n\n'.format(expected_msg, print_log))
|
||||
|
||||
@contextlib.contextmanager
|
||||
def assert_memory_usage_stable(self, perc_increase_allowed=0.03):
|
||||
"""Context manager that allows the user to assert that a node's memory usage (RSS)
|
||||
hasn't increased beyond some threshold percentage.
|
||||
"""
|
||||
before_memory_usage = self.get_mem_rss()
|
||||
|
||||
yield
|
||||
|
||||
after_memory_usage = self.get_mem_rss()
|
||||
|
||||
if not (before_memory_usage and after_memory_usage):
|
||||
self.log.warning("Unable to detect memory usage (RSS) - skipping memory check.")
|
||||
return
|
||||
|
||||
perc_increase_memory_usage = (after_memory_usage / before_memory_usage) - 1
|
||||
|
||||
if perc_increase_memory_usage > perc_increase_allowed:
|
||||
self._raise_assertion_error(
|
||||
"Memory usage increased over threshold of {:.3f}% from {} to {} ({:.3f}%)".format(
|
||||
perc_increase_allowed * 100, before_memory_usage, after_memory_usage,
|
||||
perc_increase_memory_usage * 100))
|
||||
|
||||
def assert_start_raises_init_error(self, extra_args=None, expected_msg=None, match=ErrorMatch.FULL_TEXT, *args, **kwargs):
|
||||
"""Attempt to start the node and expect it to raise an error.
|
||||
|
||||
|
|
@ -352,17 +401,16 @@ class TestNodeCLIAttr:
|
|||
class TestNodeCLI():
|
||||
"""Interface to bitcoin-cli for an individual node"""
|
||||
|
||||
def __init__(self, binary, datadir, chain):
|
||||
def __init__(self, binary, datadir):
|
||||
self.options = []
|
||||
self.binary = binary
|
||||
self.datadir = datadir
|
||||
self.chain = chain
|
||||
self.input = None
|
||||
self.log = logging.getLogger('TestFramework.bitcoincli')
|
||||
|
||||
def __call__(self, *options, input=None):
|
||||
# TestNodeCLI is callable with bitcoin-cli command-line options
|
||||
cli = TestNodeCLI(self.binary, self.datadir, self.chain)
|
||||
cli = TestNodeCLI(self.binary, self.datadir)
|
||||
cli.options = [str(o) for o in options]
|
||||
cli.input = input
|
||||
return cli
|
||||
|
|
@ -384,7 +432,7 @@ class TestNodeCLI():
|
|||
pos_args = [str(arg).lower() if type(arg) is bool else str(arg) for arg in args]
|
||||
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()]
|
||||
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call"
|
||||
p_args = [self.binary, "-datadir=" + self.datadir, "-chain=" + self.chain] + self.options
|
||||
p_args = [self.binary, "-datadir=" + self.datadir] + self.options
|
||||
if named_args:
|
||||
p_args += ["-named"]
|
||||
if command is not None:
|
||||
|
|
|
|||
|
|
@ -273,8 +273,8 @@ def p2p_port(n):
|
|||
def rpc_port(n):
|
||||
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
|
||||
|
||||
def rpc_url(datadir, i, chain, rpchost=None):
|
||||
rpc_u, rpc_p = get_auth_cookie(datadir, chain)
|
||||
def rpc_url(datadir, i, rpchost=None):
|
||||
rpc_u, rpc_p = get_auth_cookie(datadir)
|
||||
host = '127.0.0.1'
|
||||
port = rpc_port(i)
|
||||
if rpchost:
|
||||
|
|
@ -288,13 +288,13 @@ def rpc_url(datadir, i, chain, rpchost=None):
|
|||
# Node functions
|
||||
################
|
||||
|
||||
def initialize_datadir(dirname, n, chain):
|
||||
def initialize_datadir(dirname, n):
|
||||
datadir = get_datadir_path(dirname, n)
|
||||
if not os.path.isdir(datadir):
|
||||
os.makedirs(datadir)
|
||||
with open(os.path.join(datadir, "elements.conf"), 'w', encoding='utf8') as f:
|
||||
f.write("chain=%s\n" % chain)
|
||||
f.write("[%s]\n" % chain)
|
||||
with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f:
|
||||
f.write("regtest=1\n")
|
||||
f.write("[regtest]\n")
|
||||
f.write("port=" + str(p2p_port(n)) + "\n")
|
||||
f.write("rpcport=" + str(rpc_port(n)) + "\n")
|
||||
f.write("server=1\n")
|
||||
|
|
@ -302,26 +302,6 @@ def initialize_datadir(dirname, n, chain):
|
|||
f.write("discover=0\n")
|
||||
f.write("listenonion=0\n")
|
||||
f.write("printtoconsole=0\n")
|
||||
# Elements:
|
||||
f.write("con_blocksubsidy=5000000000\n")
|
||||
f.write("con_connect_coinbase=0\n")
|
||||
f.write("con_has_parent_chain=0\n")
|
||||
f.write("parentgenesisblockhash=0\n")
|
||||
f.write("anyonecanspendaremine=0\n")
|
||||
f.write("con_blockheightinheader=0\n")
|
||||
f.write("con_elementsmode=0\n")
|
||||
f.write("con_signed_blocks=0\n")
|
||||
f.write("multi_data_permitted=0\n")
|
||||
f.write("walletrbf=0\n") # Default is 1 in Elements
|
||||
f.write("con_bip34height=100000000\n")
|
||||
f.write("con_bip65height=1351\n")
|
||||
f.write("con_bip66height=1251\n")
|
||||
f.write("con_genesis_style=bitcoin\n")
|
||||
f.write("con_csv_deploy_start=0\n") # Default is -1 (always active)
|
||||
f.write("blindedaddresses=0\n")
|
||||
f.write("pubkeyprefix=111\n")
|
||||
f.write("scriptprefix=196\n")
|
||||
f.write("bech32_hrp=bcrt\n")
|
||||
os.makedirs(os.path.join(datadir, 'stderr'), exist_ok=True)
|
||||
os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
|
||||
return datadir
|
||||
|
|
@ -330,15 +310,15 @@ def get_datadir_path(dirname, n):
|
|||
return os.path.join(dirname, "node" + str(n))
|
||||
|
||||
def append_config(datadir, options):
|
||||
with open(os.path.join(datadir, "elements.conf"), 'a', encoding='utf8') as f:
|
||||
with open(os.path.join(datadir, "bitcoin.conf"), 'a', encoding='utf8') as f:
|
||||
for option in options:
|
||||
f.write(option + "\n")
|
||||
|
||||
def get_auth_cookie(datadir, chain):
|
||||
def get_auth_cookie(datadir):
|
||||
user = None
|
||||
password = None
|
||||
if os.path.isfile(os.path.join(datadir, "elements.conf")):
|
||||
with open(os.path.join(datadir, "elements.conf"), 'r', encoding='utf8') as f:
|
||||
if os.path.isfile(os.path.join(datadir, "bitcoin.conf")):
|
||||
with open(os.path.join(datadir, "bitcoin.conf"), 'r', encoding='utf8') as f:
|
||||
for line in f:
|
||||
if line.startswith("rpcuser="):
|
||||
assert user is None # Ensure that there is only one rpcuser line
|
||||
|
|
@ -346,8 +326,8 @@ def get_auth_cookie(datadir, chain):
|
|||
if line.startswith("rpcpassword="):
|
||||
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, chain, ".cookie")):
|
||||
with open(os.path.join(datadir, chain, ".cookie"), 'r', encoding="ascii") as f:
|
||||
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
|
||||
with open(os.path.join(datadir, "regtest", ".cookie"), 'r', encoding="ascii") as f:
|
||||
userpass = f.read()
|
||||
split_userpass = userpass.split(':')
|
||||
user = split_userpass[0]
|
||||
|
|
@ -357,10 +337,10 @@ def get_auth_cookie(datadir, chain):
|
|||
return user, password
|
||||
|
||||
# If a cookie file exists in the given datadir, delete it.
|
||||
def delete_cookie_file(datadir, chain):
|
||||
if os.path.isfile(os.path.join(datadir, chain, ".cookie")):
|
||||
def delete_cookie_file(datadir):
|
||||
if os.path.isfile(os.path.join(datadir, "regtest", ".cookie")):
|
||||
logger.debug("Deleting leftover cookie file")
|
||||
os.remove(os.path.join(datadir, chain, ".cookie"))
|
||||
os.remove(os.path.join(datadir, "regtest", ".cookie"))
|
||||
|
||||
def get_bip9_status(node, key):
|
||||
info = node.getblockchaininfo()
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ import re
|
|||
import logging
|
||||
|
||||
# Formatting. Default colors to empty strings.
|
||||
BOLD, BLUE, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
|
||||
BOLD, GREEN, RED, GREY = ("", ""), ("", ""), ("", ""), ("", "")
|
||||
try:
|
||||
# Make sure python thinks it can write unicode to its stdout
|
||||
"\u2713".encode("utf_8").decode(sys.stdout.encoding)
|
||||
|
|
@ -41,20 +41,33 @@ except UnicodeDecodeError:
|
|||
CROSS = "x "
|
||||
CIRCLE = "o "
|
||||
|
||||
if os.name == 'posix':
|
||||
if os.name != 'nt' or sys.getwindowsversion() >= (10, 0, 14393):
|
||||
if os.name == 'nt':
|
||||
import ctypes
|
||||
kernel32 = ctypes.windll.kernel32
|
||||
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
|
||||
STD_OUTPUT_HANDLE = -11
|
||||
STD_ERROR_HANDLE = -12
|
||||
# Enable ascii color control to stdout
|
||||
stdout = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
|
||||
stdout_mode = ctypes.c_int32()
|
||||
kernel32.GetConsoleMode(stdout, ctypes.byref(stdout_mode))
|
||||
kernel32.SetConsoleMode(stdout, stdout_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
# Enable ascii color control to stderr
|
||||
stderr = kernel32.GetStdHandle(STD_ERROR_HANDLE)
|
||||
stderr_mode = ctypes.c_int32()
|
||||
kernel32.GetConsoleMode(stderr, ctypes.byref(stderr_mode))
|
||||
kernel32.SetConsoleMode(stderr, stderr_mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
|
||||
# primitive formatting on supported
|
||||
# terminal via ANSI escape sequences:
|
||||
BOLD = ('\033[0m', '\033[1m')
|
||||
BLUE = ('\033[0m', '\033[0;34m')
|
||||
GREEN = ('\033[0m', '\033[0;32m')
|
||||
RED = ('\033[0m', '\033[0;31m')
|
||||
GREY = ('\033[0m', '\033[1;30m')
|
||||
|
||||
TEST_EXIT_PASSED = 0
|
||||
TEST_EXIT_SKIPPED = 77
|
||||
|
||||
# 20 minutes represented in seconds
|
||||
TRAVIS_TIMEOUT_DURATION = 20 * 60
|
||||
|
||||
BASE_SCRIPTS = [
|
||||
# Scripts that are run by the travis build process.
|
||||
# Longest test should go first, to favor running tests in parallel
|
||||
|
|
@ -92,8 +105,7 @@ BASE_SCRIPTS = [
|
|||
# vv Tests less than 30s vv
|
||||
'wallet_keypool_topup.py',
|
||||
'interface_zmq.py',
|
||||
# ELEMENTS:
|
||||
#'interface_bitcoin_cli.py',
|
||||
'interface_bitcoin_cli.py',
|
||||
'mempool_resurrect.py',
|
||||
'wallet_txn_doublespend.py --mineblock',
|
||||
'wallet_txn_clone.py',
|
||||
|
|
@ -109,8 +121,7 @@ BASE_SCRIPTS = [
|
|||
'wallet_disableprivatekeys.py --usecli',
|
||||
'interface_http.py',
|
||||
'rpc_psbt.py',
|
||||
# ELEMENTS:
|
||||
#'rpc_users.py',
|
||||
'rpc_users.py',
|
||||
'feature_proxy.py',
|
||||
'rpc_signrawtransaction.py',
|
||||
'wallet_groups.py',
|
||||
|
|
@ -125,6 +136,7 @@ BASE_SCRIPTS = [
|
|||
'mining_prioritisetransaction.py',
|
||||
'p2p_invalid_locator.py',
|
||||
'p2p_invalid_block.py',
|
||||
'p2p_invalid_messages.py',
|
||||
'p2p_invalid_tx.py',
|
||||
'feature_assumevalid.py',
|
||||
'example_test.py',
|
||||
|
|
@ -138,11 +150,12 @@ BASE_SCRIPTS = [
|
|||
'feature_versionbits_warning.py',
|
||||
'rpc_preciousblock.py',
|
||||
'wallet_importprunedfunds.py',
|
||||
'rpc_zmq.py',
|
||||
'p2p_leak_tx.py',
|
||||
'rpc_signmessage.py',
|
||||
'feature_nulldummy.py',
|
||||
'mempool_accept.py',
|
||||
'wallet_import_rescan.py',
|
||||
'wallet_import_with_label.py',
|
||||
'rpc_bind.py --ipv4',
|
||||
'rpc_bind.py --ipv6',
|
||||
'rpc_bind.py --nonloopback',
|
||||
|
|
@ -161,15 +174,14 @@ BASE_SCRIPTS = [
|
|||
'rpc_getblockstats.py',
|
||||
'p2p_fingerprint.py',
|
||||
'feature_uacomment.py',
|
||||
'feature_filelock.py',
|
||||
'p2p_unrequested_blocks.py',
|
||||
# ELEMENTS:
|
||||
#'feature_includeconf.py',
|
||||
'feature_includeconf.py',
|
||||
'rpc_scantxoutset.py',
|
||||
'feature_logging.py',
|
||||
'p2p_node_network_limited.py',
|
||||
'feature_blocksdir.py',
|
||||
# ELEMENTS:
|
||||
#'feature_config_args.py',
|
||||
'feature_config_args.py',
|
||||
'rpc_help.py',
|
||||
'feature_help.py',
|
||||
# Don't append tests at the end to avoid merge conflicts
|
||||
|
|
@ -201,15 +213,16 @@ def main():
|
|||
epilog='''
|
||||
Help text and arguments for individual test script:''',
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('--combinedlogslen', '-c', type=int, default=0, help='print a combined log (of length n lines) from all test nodes and test framework to the console on failure.')
|
||||
parser.add_argument('--combinedlogslen', '-c', type=int, default=0, metavar='n', help='On failure, print a log (of length n lines) to the console, combined from the test framework and all test nodes.')
|
||||
parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface')
|
||||
parser.add_argument('--ci', action='store_true', help='Run checks and code that are usually only enabled in a continuous integration environment')
|
||||
parser.add_argument('--exclude', '-x', help='specify a comma-separated-list of scripts to exclude.')
|
||||
parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests')
|
||||
parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).')
|
||||
parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit')
|
||||
parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.')
|
||||
parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.')
|
||||
parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs')
|
||||
parser.add_argument('--quiet', '-q', action='store_true', help='only print dots, results summary and failure logs')
|
||||
parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs")
|
||||
parser.add_argument('--failfast', action='store_true', help='stop execution after the first test failure')
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
|
|
@ -220,7 +233,7 @@ def main():
|
|||
|
||||
# Read config generated by configure.
|
||||
config = configparser.ConfigParser()
|
||||
configfile = os.path.abspath(os.path.dirname(__file__)) + "/../../config.ini"
|
||||
configfile = os.path.abspath(os.path.dirname(__file__)) + "/../config.ini"
|
||||
config.read_file(open(configfile, encoding="utf8"))
|
||||
|
||||
passon_args.append("--configfile=%s" % configfile)
|
||||
|
|
@ -231,6 +244,11 @@ def main():
|
|||
|
||||
# Create base test directory
|
||||
tmpdir = "%s/test_runner_₿_🏃_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
||||
|
||||
# If we fixed the command-line and filename encoding issue on Windows, these two lines could be removed
|
||||
if config["environment"]["EXEEXT"] == ".exe":
|
||||
tmpdir = "%s/test_runner_%s" % (args.tmpdirprefix, datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))
|
||||
|
||||
os.makedirs(tmpdir)
|
||||
|
||||
logging.debug("Temporary test directory at %s" % tmpdir)
|
||||
|
|
@ -268,11 +286,13 @@ def main():
|
|||
|
||||
# Remove the test cases that the user has explicitly asked to exclude.
|
||||
if args.exclude:
|
||||
exclude_tests = [re.sub("\.py$", "", test) + ".py" for test in args.exclude.split(',')]
|
||||
exclude_tests = [test.split('.py')[0] for test in args.exclude.split(',')]
|
||||
for exclude_test in exclude_tests:
|
||||
if exclude_test in test_list:
|
||||
test_list.remove(exclude_test)
|
||||
else:
|
||||
# Remove <test_name>.py and <test_name>.py --arg from the test list
|
||||
exclude_list = [test for test in test_list if test.split('.py')[0] == exclude_test]
|
||||
for exclude_item in exclude_list:
|
||||
test_list.remove(exclude_item)
|
||||
if not exclude_list:
|
||||
print("{}WARNING!{} Test '{}' not found in current test list.".format(BOLD[1], BOLD[0], exclude_test))
|
||||
|
||||
if not test_list:
|
||||
|
|
@ -283,28 +303,29 @@ def main():
|
|||
if args.help:
|
||||
# Print help for test_runner.py, then print help of the first script (with args removed) and exit.
|
||||
parser.print_help()
|
||||
subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'bitcoin_functional', 'functional', test_list[0].split()[0]), '-h'])
|
||||
subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', test_list[0].split()[0]), '-h'])
|
||||
sys.exit(0)
|
||||
|
||||
check_script_list(config["environment"]["SRCDIR"])
|
||||
check_script_list(src_dir=config["environment"]["SRCDIR"], fail_on_warn=args.ci)
|
||||
check_script_prefixes()
|
||||
|
||||
if not args.keepcache:
|
||||
shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True)
|
||||
|
||||
run_tests(
|
||||
test_list,
|
||||
config["environment"]["SRCDIR"],
|
||||
config["environment"]["BUILDDIR"],
|
||||
tmpdir,
|
||||
test_list=test_list,
|
||||
src_dir=config["environment"]["SRCDIR"],
|
||||
build_dir=config["environment"]["BUILDDIR"],
|
||||
tmpdir=tmpdir,
|
||||
jobs=args.jobs,
|
||||
enable_coverage=args.coverage,
|
||||
args=passon_args,
|
||||
combined_logs_len=args.combinedlogslen,
|
||||
failfast=args.failfast,
|
||||
runs_ci=args.ci,
|
||||
)
|
||||
|
||||
def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False):
|
||||
def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False, runs_ci):
|
||||
args = args or []
|
||||
|
||||
# Warn if bitcoind is already running (unix only)
|
||||
|
|
@ -319,7 +340,7 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
|
|||
if os.path.isdir(cache_dir):
|
||||
print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir))
|
||||
|
||||
tests_dir = src_dir + '/test/bitcoin_functional/functional/'
|
||||
tests_dir = src_dir + '/test/functional/'
|
||||
|
||||
flags = ['--cachedir={}'.format(cache_dir)] + args
|
||||
|
||||
|
|
@ -339,22 +360,29 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
|
|||
raise
|
||||
|
||||
#Run Tests
|
||||
job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags)
|
||||
job_queue = TestHandler(
|
||||
num_tests_parallel=jobs,
|
||||
tests_dir=tests_dir,
|
||||
tmpdir=tmpdir,
|
||||
test_list=test_list,
|
||||
flags=flags,
|
||||
timeout_duration=40 * 60 if runs_ci else float('inf'), # in seconds
|
||||
)
|
||||
start_time = time.time()
|
||||
test_results = []
|
||||
|
||||
max_len_name = len(max(test_list, key=len))
|
||||
|
||||
for _ in range(len(test_list)):
|
||||
test_count = len(test_list)
|
||||
for i in range(test_count):
|
||||
test_result, testdir, stdout, stderr = job_queue.get_next()
|
||||
test_results.append(test_result)
|
||||
|
||||
done_str = "{}/{} - {}{}{}".format(i + 1, test_count, BOLD[1], test_result.name, BOLD[0])
|
||||
if test_result.status == "Passed":
|
||||
logging.debug("\n%s%s%s passed, Duration: %s s" % (BOLD[1], test_result.name, BOLD[0], test_result.time))
|
||||
logging.debug("%s passed, Duration: %s s" % (done_str, test_result.time))
|
||||
elif test_result.status == "Skipped":
|
||||
logging.debug("\n%s%s%s skipped" % (BOLD[1], test_result.name, BOLD[0]))
|
||||
logging.debug("%s skipped" % (done_str))
|
||||
else:
|
||||
print("\n%s%s%s failed, Duration: %s s\n" % (BOLD[1], test_result.name, BOLD[0], test_result.time))
|
||||
print("%s failed, Duration: %s s\n" % (done_str, test_result.time))
|
||||
print(BOLD[1] + 'stdout:\n' + BOLD[0] + stdout + '\n')
|
||||
print(BOLD[1] + 'stderr:\n' + BOLD[0] + stderr + '\n')
|
||||
if combined_logs_len and os.path.isdir(testdir):
|
||||
|
|
@ -363,7 +391,10 @@ def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=Fal
|
|||
print('\n============')
|
||||
print('{}Combined log for {}:{}'.format(BOLD[1], testdir, BOLD[0]))
|
||||
print('============\n')
|
||||
combined_logs, _ = subprocess.Popen([sys.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
|
||||
combined_logs_args = [sys.executable, os.path.join(tests_dir, 'combine_logs.py'), testdir]
|
||||
if BOLD[0]:
|
||||
combined_logs_args += ['--color']
|
||||
combined_logs, _ = subprocess.Popen(combined_logs_args, universal_newlines=True, stdout=subprocess.PIPE).communicate()
|
||||
print("\n".join(deque(combined_logs.splitlines(), combined_logs_len)))
|
||||
|
||||
if failfast:
|
||||
|
|
@ -417,11 +448,12 @@ class TestHandler:
|
|||
Trigger the test scripts passed in via the list.
|
||||
"""
|
||||
|
||||
def __init__(self, num_tests_parallel, tests_dir, tmpdir, test_list=None, flags=None):
|
||||
assert(num_tests_parallel >= 1)
|
||||
def __init__(self, *, num_tests_parallel, tests_dir, tmpdir, test_list, flags, timeout_duration):
|
||||
assert num_tests_parallel >= 1
|
||||
self.num_jobs = num_tests_parallel
|
||||
self.tests_dir = tests_dir
|
||||
self.tmpdir = tmpdir
|
||||
self.timeout_duration = timeout_duration
|
||||
self.test_list = test_list
|
||||
self.flags = flags
|
||||
self.num_running = 0
|
||||
|
|
@ -450,12 +482,13 @@ class TestHandler:
|
|||
log_stderr))
|
||||
if not self.jobs:
|
||||
raise IndexError('pop from empty list')
|
||||
dot_count = 0
|
||||
while True:
|
||||
# Return first proc that finishes
|
||||
time.sleep(.5)
|
||||
for job in self.jobs:
|
||||
(name, start_time, proc, testdir, log_out, log_err) = job
|
||||
if os.getenv('TRAVIS') == 'true' and int(time.time() - start_time) > TRAVIS_TIMEOUT_DURATION:
|
||||
if int(time.time() - start_time) > self.timeout_duration:
|
||||
# In travis, timeout individual tests (to stop tests hanging and not providing useful output).
|
||||
proc.send_signal(signal.SIGINT)
|
||||
if proc.poll() is not None:
|
||||
|
|
@ -470,9 +503,12 @@ class TestHandler:
|
|||
status = "Failed"
|
||||
self.num_running -= 1
|
||||
self.jobs.remove(job)
|
||||
|
||||
clearline = '\r' + (' ' * dot_count) + '\r'
|
||||
print(clearline, end='', flush=True)
|
||||
dot_count = 0
|
||||
return TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr
|
||||
print('.', end='', flush=True)
|
||||
dot_count += 1
|
||||
|
||||
def kill_and_join(self):
|
||||
"""Send SIGKILL to all jobs and block until all have ended."""
|
||||
|
|
@ -502,7 +538,7 @@ class TestResult():
|
|||
|
||||
def __repr__(self):
|
||||
if self.status == "Passed":
|
||||
color = BLUE
|
||||
color = GREEN
|
||||
glyph = TICK
|
||||
elif self.status == "Failed":
|
||||
color = RED
|
||||
|
|
@ -530,20 +566,21 @@ def check_script_prefixes():
|
|||
raise AssertionError("Some tests are not following naming convention!")
|
||||
|
||||
|
||||
def check_script_list(src_dir):
|
||||
def check_script_list(*, src_dir, fail_on_warn):
|
||||
"""Check scripts directory.
|
||||
|
||||
Check that there are no scripts in the functional tests directory which are
|
||||
not being run by pull-tester.py."""
|
||||
script_dir = src_dir + '/test/bitcoin_functional/functional/'
|
||||
script_dir = src_dir + '/test/functional/'
|
||||
python_files = set([test_file for test_file in os.listdir(script_dir) if test_file.endswith(".py")])
|
||||
missed_tests = list(python_files - set(map(lambda x: x.split()[0], ALL_SCRIPTS + NON_SCRIPTS)))
|
||||
if len(missed_tests) != 0:
|
||||
print("%sWARNING!%s The following scripts are not being run: %s. Check the test lists in test_runner.py." % (BOLD[1], BOLD[0], str(missed_tests)))
|
||||
if os.getenv('TRAVIS') == 'true':
|
||||
if fail_on_warn:
|
||||
# On travis this warning is an error to prevent merging incomplete commits into master
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class RPCCoverage():
|
||||
"""
|
||||
Coverage reporting utilities for test_runner.
|
||||
|
|
@ -599,7 +636,7 @@ class RPCCoverage():
|
|||
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):
|
||||
for root, _, files in os.walk(self.dir):
|
||||
for filename in files:
|
||||
if filename.startswith(coverage_file_prefix):
|
||||
coverage_filenames.add(os.path.join(root, filename))
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||
self.stop_node(2)
|
||||
|
||||
def erase_three(self):
|
||||
os.remove(os.path.join(self.nodes[0].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
os.remove(os.path.join(self.nodes[1].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
os.remove(os.path.join(self.nodes[2].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
os.remove(os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
os.remove(os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
os.remove(os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("Generating initial blockchain")
|
||||
|
|
@ -155,13 +155,13 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||
self.erase_three()
|
||||
|
||||
# Start node2 with no chain
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest2', 'blocks'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest2', 'chainstate'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'blocks'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'chainstate'))
|
||||
|
||||
# Restore wallets from backup
|
||||
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, 'regtest2', 'wallets', 'wallet.dat'))
|
||||
shutil.copyfile(os.path.join(self.nodes[0].datadir, 'wallet.bak'), os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, 'wallet.bak'), os.path.join(self.nodes[1].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
shutil.copyfile(os.path.join(self.nodes[2].datadir, 'wallet.bak'), os.path.join(self.nodes[2].datadir, 'regtest', 'wallets', 'wallet.dat'))
|
||||
|
||||
self.log.info("Re-starting nodes")
|
||||
self.start_three()
|
||||
|
|
@ -176,8 +176,8 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||
self.erase_three()
|
||||
|
||||
#start node2 with no chain
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest2', 'blocks'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest2', 'chainstate'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'blocks'))
|
||||
shutil.rmtree(os.path.join(self.nodes[2].datadir, 'regtest', 'chainstate'))
|
||||
|
||||
self.start_three()
|
||||
|
||||
|
|
@ -197,10 +197,10 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||
|
||||
# Backup to source wallet file must fail
|
||||
sourcePaths = [
|
||||
os.path.join(self.nodes[0].datadir, 'regtest2', 'wallets', 'wallet.dat'),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest2', '.', 'wallets', 'wallet.dat'),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest2', 'wallets', ''),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest2', 'wallets')]
|
||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', 'wallet.dat'),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest', '.', 'wallets', 'wallet.dat'),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets', ''),
|
||||
os.path.join(self.nodes[0].datadir, 'regtest', 'wallets')]
|
||||
|
||||
for sourcePath in sourcePaths:
|
||||
assert_raises_rpc_error(-4, "backup failed", self.nodes[0].backupwallet, sourcePath)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from test_framework.util import (
|
|||
assert_array_result,
|
||||
assert_equal,
|
||||
assert_fee_amount,
|
||||
assert_greater_than,
|
||||
assert_raises_rpc_error,
|
||||
connect_nodes_bi,
|
||||
sync_blocks,
|
||||
|
|
@ -27,10 +28,9 @@ class WalletTest(BitcoinTestFramework):
|
|||
self.skip_if_no_wallet()
|
||||
|
||||
def setup_network(self):
|
||||
self.add_nodes(4)
|
||||
self.start_node(0)
|
||||
self.start_node(1)
|
||||
self.start_node(2)
|
||||
self.setup_nodes()
|
||||
# Only need nodes 0-2 running at start of test
|
||||
self.stop_node(3)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
connect_nodes_bi(self.nodes, 1, 2)
|
||||
connect_nodes_bi(self.nodes, 0, 2)
|
||||
|
|
@ -92,13 +92,13 @@ class WalletTest(BitcoinTestFramework):
|
|||
assert_equal(txout['value'], 50)
|
||||
|
||||
# Send 21 BTC from 0 to 2 using sendtoaddress call.
|
||||
# Locked memory should use at least 32 bytes to sign each transaction
|
||||
# Locked memory should increase to sign transactions
|
||||
self.log.info("test getmemoryinfo")
|
||||
memory_before = self.nodes[0].getmemoryinfo()
|
||||
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11)
|
||||
mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10)
|
||||
memory_after = self.nodes[0].getmemoryinfo()
|
||||
assert(memory_before['locked']['used'] + 64 <= memory_after['locked']['used'])
|
||||
assert_greater_than(memory_after['locked']['used'], memory_before['locked']['used'])
|
||||
|
||||
self.log.info("test gettxout (second part)")
|
||||
# utxo spent in mempool should be visible if you exclude mempool
|
||||
|
|
@ -134,9 +134,15 @@ class WalletTest(BitcoinTestFramework):
|
|||
assert_equal([unspent_0], self.nodes[2].listlockunspent())
|
||||
self.nodes[2].lockunspent(True, [unspent_0])
|
||||
assert_equal(len(self.nodes[2].listlockunspent()), 0)
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
|
||||
assert_raises_rpc_error(-8, "txid must be of length 64 (not 34, for '0000000000000000000000000000000000')",
|
||||
self.nodes[2].lockunspent, False,
|
||||
[{"txid": "0000000000000000000000000000000000", "vout": 0}])
|
||||
assert_raises_rpc_error(-8, "txid must be hexadecimal string (not 'ZZZ0000000000000000000000000000000000000000000000000000000000000')",
|
||||
self.nodes[2].lockunspent, False,
|
||||
[{"txid": "ZZZ0000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
|
||||
self.nodes[2].lockunspent, False,
|
||||
[{"txid": "0000000000000000000000000000000000000000000000000000000000000000", "vout": 0}])
|
||||
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
|
||||
self.nodes[2].lockunspent, False,
|
||||
[{"txid": unspent_0["txid"], "vout": 999}])
|
||||
|
|
@ -473,7 +479,7 @@ class WalletTest(BitcoinTestFramework):
|
|||
# Verify nothing new in wallet
|
||||
assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
|
||||
|
||||
# Test getaddressinfo. Note that these addresses are taken from disablewallet.py
|
||||
# Test getaddressinfo on external address. Note that these addresses are taken from disablewallet.py
|
||||
assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
|
||||
address_info = self.nodes[0].getaddressinfo("mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
|
||||
assert_equal(address_info['address'], "mneYUmWYsuk7kySiURxCi3AGxrAqZxLgPZ")
|
||||
|
|
@ -481,6 +487,22 @@ class WalletTest(BitcoinTestFramework):
|
|||
assert not address_info["ismine"]
|
||||
assert not address_info["iswatchonly"]
|
||||
assert not address_info["isscript"]
|
||||
assert not address_info["ischange"]
|
||||
|
||||
# Test getaddressinfo 'ischange' field on change address.
|
||||
self.nodes[0].generate(1)
|
||||
destination = self.nodes[1].getnewaddress()
|
||||
txid = self.nodes[0].sendtoaddress(destination, 0.123)
|
||||
tx = self.nodes[0].decoderawtransaction(self.nodes[0].getrawtransaction(txid))
|
||||
output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
|
||||
assert len(output_addresses) > 1
|
||||
for address in output_addresses:
|
||||
ischange = self.nodes[0].getaddressinfo(address)['ischange']
|
||||
assert_equal(ischange, address != destination)
|
||||
if ischange:
|
||||
change = address
|
||||
self.nodes[0].setlabel(change, 'foobar')
|
||||
assert_equal(self.nodes[0].getaddressinfo(change)['ischange'], False)
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletTest().main()
|
||||
|
|
|
|||
|
|
@ -13,26 +13,22 @@ can be disabled or reordered if needed for debugging. If new test cases are
|
|||
added in the future, they should try to follow the same convention and not
|
||||
make assumptions about execution order.
|
||||
"""
|
||||
|
||||
from decimal import Decimal
|
||||
import io
|
||||
|
||||
from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase, send_to_witness
|
||||
from test_framework.messages import BIP125_SEQUENCE_NUMBER, CTransaction
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_greater_than, assert_raises_rpc_error, bytes_to_hex_str, connect_nodes_bi, hex_str_to_bytes, sync_mempools
|
||||
|
||||
import io
|
||||
|
||||
WALLET_PASSPHRASE = "test"
|
||||
WALLET_PASSPHRASE_TIMEOUT = 3600
|
||||
|
||||
|
||||
class BumpFeeTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
self.extra_args = [[
|
||||
"-deprecatedrpc=addwitnessaddress",
|
||||
"-walletrbf={}".format(i),
|
||||
"-mintxfee=0.00002",
|
||||
] for i in range(self.num_nodes)]
|
||||
|
|
@ -107,8 +103,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address):
|
|||
# which spends it, and make sure bumpfee can be called on it.
|
||||
|
||||
segwit_in = next(u for u in rbf_node.listunspent() if u["amount"] == Decimal("0.001"))
|
||||
segwit_out = rbf_node.getaddressinfo(rbf_node.getnewaddress())
|
||||
rbf_node.addwitnessaddress(segwit_out["address"])
|
||||
segwit_out = rbf_node.getaddressinfo(rbf_node.getnewaddress(address_type='p2sh-segwit'))
|
||||
segwitid = send_to_witness(
|
||||
use_p2wsh=False,
|
||||
node=rbf_node,
|
||||
|
|
@ -157,7 +152,7 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address):
|
|||
signedtx = peer_node.signrawtransactionwithwallet(signedtx["hex"])
|
||||
rbfid = rbf_node.sendrawtransaction(signedtx["hex"])
|
||||
assert_raises_rpc_error(-4, "Transaction contains inputs that don't belong to this wallet",
|
||||
rbf_node.bumpfee, rbfid)
|
||||
rbf_node.bumpfee, rbfid)
|
||||
|
||||
|
||||
def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address):
|
||||
|
|
@ -187,11 +182,11 @@ def test_dust_to_fee(rbf_node, dest_address):
|
|||
# (32-byte p2sh-pwpkh output size + 148 p2pkh spend estimate) * 10k(discard_rate) / 1000 = 1800
|
||||
# P2SH outputs are slightly "over-discarding" due to the IsDust calculation assuming it will
|
||||
# be spent as a P2PKH.
|
||||
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000-1800})
|
||||
bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 50000 - 1800})
|
||||
full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1)
|
||||
assert_equal(bumped_tx["fee"], Decimal("0.00050000"))
|
||||
assert_equal(len(fulltx["vout"]), 2)
|
||||
assert_equal(len(full_bumped_tx["vout"]), 1) #change output is eliminated
|
||||
assert_equal(len(full_bumped_tx["vout"]), 1) # change output is eliminated
|
||||
|
||||
|
||||
def test_settxfee(rbf_node, dest_address):
|
||||
|
|
@ -222,7 +217,7 @@ def test_rebumping_not_replaceable(rbf_node, dest_address):
|
|||
rbfid = spend_one_input(rbf_node, dest_address)
|
||||
bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False})
|
||||
assert_raises_rpc_error(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"],
|
||||
{"totalFee": 20000})
|
||||
{"totalFee": 20000})
|
||||
|
||||
|
||||
def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
|
||||
|
|
@ -276,7 +271,7 @@ def test_locked_wallet_fails(rbf_node, dest_address):
|
|||
rbfid = spend_one_input(rbf_node, dest_address)
|
||||
rbf_node.walletlock()
|
||||
assert_raises_rpc_error(-13, "Please enter the wallet passphrase with walletpassphrase first.",
|
||||
rbf_node.bumpfee, rbfid)
|
||||
rbf_node.bumpfee, rbfid)
|
||||
|
||||
|
||||
def spend_one_input(node, dest_address):
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""Test the dumpwallet RPC."""
|
||||
|
||||
import os
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
|
@ -19,11 +18,12 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
|
|||
Also check that the old hd_master is inactive
|
||||
"""
|
||||
with open(file_name, encoding='utf8') as inputfile:
|
||||
found_addr = 0
|
||||
found_legacy_addr = 0
|
||||
found_p2sh_segwit_addr = 0
|
||||
found_bech32_addr = 0
|
||||
found_script_addr = 0
|
||||
found_addr_chg = 0
|
||||
found_addr_rsv = 0
|
||||
witness_addr_ret = None
|
||||
hd_master_addr_ret = None
|
||||
for line in inputfile:
|
||||
# only read non comment lines
|
||||
|
|
@ -60,14 +60,14 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
|
|||
# count key types
|
||||
for addrObj in addrs:
|
||||
if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=":
|
||||
# a labeled entry in the wallet should contain both a native address
|
||||
# and the p2sh-p2wpkh address that was added at wallet setup
|
||||
if len(addr.split(",")) == 2:
|
||||
addr_list = addr.split(",")
|
||||
# the entry should be of the first key in the wallet
|
||||
assert_equal(addrs[0]['address'], addr_list[0])
|
||||
witness_addr_ret = addr_list[1]
|
||||
found_addr += 1
|
||||
if addr.startswith('m') or addr.startswith('n'):
|
||||
# P2PKH address
|
||||
found_legacy_addr += 1
|
||||
elif addr.startswith('2'):
|
||||
# P2SH-segwit address
|
||||
found_p2sh_segwit_addr += 1
|
||||
elif addr.startswith('bcrt1'):
|
||||
found_bech32_addr += 1
|
||||
break
|
||||
elif keytype == "change=1":
|
||||
found_addr_chg += 1
|
||||
|
|
@ -82,13 +82,13 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
|
|||
found_script_addr += 1
|
||||
break
|
||||
|
||||
return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret
|
||||
return found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
|
||||
|
||||
|
||||
class WalletDumpTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
self.extra_args = [["-keypool=90", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]]
|
||||
self.extra_args = [["-keypool=90", "-addresstype=legacy"]]
|
||||
self.rpc_timeout = 120
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
|
|
@ -102,49 +102,54 @@ class WalletDumpTest(BitcoinTestFramework):
|
|||
wallet_unenc_dump = os.path.join(self.nodes[0].datadir, "wallet.unencrypted.dump")
|
||||
wallet_enc_dump = os.path.join(self.nodes[0].datadir, "wallet.encrypted.dump")
|
||||
|
||||
# generate 20 addresses to compare against the dump
|
||||
# but since we add a p2sh-p2wpkh address for the first pubkey in the
|
||||
# wallet, we will expect 21 addresses in the dump
|
||||
test_addr_count = 20
|
||||
# generate 30 addresses to compare against the dump
|
||||
# - 10 legacy P2PKH
|
||||
# - 10 P2SH-segwit
|
||||
# - 10 bech32
|
||||
test_addr_count = 10
|
||||
addrs = []
|
||||
for i in range(0,test_addr_count):
|
||||
addr = self.nodes[0].getnewaddress()
|
||||
vaddr= self.nodes[0].getaddressinfo(addr) #required to get hd keypath
|
||||
addrs.append(vaddr)
|
||||
# Should be a no-op:
|
||||
self.nodes[0].keypoolrefill()
|
||||
for address_type in ['legacy', 'p2sh-segwit', 'bech32']:
|
||||
for i in range(0, test_addr_count):
|
||||
addr = self.nodes[0].getnewaddress(address_type=address_type)
|
||||
vaddr = self.nodes[0].getaddressinfo(addr) # required to get hd keypath
|
||||
addrs.append(vaddr)
|
||||
|
||||
# Test scripts dump by adding a P2SH witness and a 1-of-1 multisig address
|
||||
witness_addr = self.nodes[0].addwitnessaddress(addrs[0]["address"], True)
|
||||
# Test scripts dump by adding a 1-of-1 multisig address
|
||||
multisig_addr = self.nodes[0].addmultisigaddress(1, [addrs[1]["address"]])["address"]
|
||||
script_addrs = [witness_addr, multisig_addr]
|
||||
|
||||
# Refill the keypool. getnewaddress() refills the keypool *before* taking a key from
|
||||
# the keypool, so the final call to getnewaddress leaves the keypool with one key below
|
||||
# its capacity
|
||||
self.nodes[0].keypoolrefill()
|
||||
|
||||
# dump unencrypted wallet
|
||||
result = self.nodes[0].dumpwallet(wallet_unenc_dump)
|
||||
assert_equal(result['filename'], wallet_unenc_dump)
|
||||
|
||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc, witness_addr_ret = \
|
||||
read_dump(wallet_unenc_dump, addrs, script_addrs, None)
|
||||
assert_equal(found_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_script_addr, 2) # all scripts must be in the dump
|
||||
found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
|
||||
read_dump(wallet_unenc_dump, addrs, [multisig_addr], None)
|
||||
assert_equal(found_legacy_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_script_addr, 1) # all scripts must be in the dump
|
||||
assert_equal(found_addr_chg, 0) # 0 blocks where mined
|
||||
assert_equal(found_addr_rsv, 90 * 2) # 90 keys plus 100% internal keys
|
||||
assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key
|
||||
|
||||
#encrypt wallet, restart, unlock and dump
|
||||
# encrypt wallet, restart, unlock and dump
|
||||
self.nodes[0].encryptwallet('test')
|
||||
self.nodes[0].walletpassphrase('test', 10)
|
||||
# Should be a no-op:
|
||||
self.nodes[0].keypoolrefill()
|
||||
self.nodes[0].dumpwallet(wallet_enc_dump)
|
||||
|
||||
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _, witness_addr_ret = \
|
||||
read_dump(wallet_enc_dump, addrs, script_addrs, hd_master_addr_unenc)
|
||||
assert_equal(found_addr, test_addr_count)
|
||||
assert_equal(found_script_addr, 2)
|
||||
found_legacy_addr, found_p2sh_segwit_addr, found_bech32_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
|
||||
read_dump(wallet_enc_dump, addrs, [multisig_addr], hd_master_addr_unenc)
|
||||
assert_equal(found_legacy_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_p2sh_segwit_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_bech32_addr, test_addr_count) # all keys must be in the dump
|
||||
assert_equal(found_script_addr, 1)
|
||||
assert_equal(found_addr_chg, 90 * 2) # old reserve keys are marked as change now
|
||||
assert_equal(found_addr_rsv, 90 * 2)
|
||||
assert_equal(witness_addr_ret, witness_addr)
|
||||
|
||||
# Overwriting should fail
|
||||
assert_raises_rpc_error(-8, "already exists", lambda: self.nodes[0].dumpwallet(wallet_enc_dump))
|
||||
|
|
@ -155,13 +160,13 @@ class WalletDumpTest(BitcoinTestFramework):
|
|||
|
||||
# Make sure the address is not IsMine before import
|
||||
result = self.nodes[0].getaddressinfo(multisig_addr)
|
||||
assert(result['ismine'] == False)
|
||||
assert not result['ismine']
|
||||
|
||||
self.nodes[0].importwallet(wallet_unenc_dump)
|
||||
|
||||
# Now check IsMine is true
|
||||
result = self.nodes[0].getaddressinfo(multisig_addr)
|
||||
assert(result['ismine'] == True)
|
||||
assert result['ismine']
|
||||
|
||||
if __name__ == '__main__':
|
||||
WalletDumpTest().main()
|
||||
|
|
|
|||
|
|
@ -25,12 +25,6 @@ class WalletHDTest(BitcoinTestFramework):
|
|||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
# Make sure can't switch off usehd after wallet creation
|
||||
self.stop_node(1)
|
||||
self.nodes[1].assert_start_raises_init_error(['-usehd=0'], "Error: Error loading : You can't disable HD on an already existing HD wallet")
|
||||
self.start_node(1)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
|
||||
# Make sure we use hd, keep masterkeyid
|
||||
masterkeyid = self.nodes[1].getwalletinfo()['hdseedid']
|
||||
assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid'])
|
||||
|
|
@ -75,11 +69,11 @@ class WalletHDTest(BitcoinTestFramework):
|
|||
|
||||
self.log.info("Restore backup ...")
|
||||
self.stop_node(1)
|
||||
# we need to delete the complete regtest2 directory
|
||||
# we need to delete the complete regtest directory
|
||||
# otherwise node1 would auto-recover all funds in flag the keypool keys as used
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest2", "blocks"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest2", "chainstate"))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest2", "wallets", "wallet.dat"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat"))
|
||||
self.start_node(1)
|
||||
|
||||
# Assert that derivation is deterministic
|
||||
|
|
@ -101,9 +95,9 @@ class WalletHDTest(BitcoinTestFramework):
|
|||
|
||||
# Try a RPC based rescan
|
||||
self.stop_node(1)
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest2", "blocks"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest2", "chainstate"))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest2", "wallets", "wallet.dat"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "blocks"))
|
||||
shutil.rmtree(os.path.join(self.nodes[1].datadir, "regtest", "chainstate"))
|
||||
shutil.copyfile(os.path.join(self.nodes[1].datadir, "hd.bak"), os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat"))
|
||||
self.start_node(1, extra_args=self.extra_args[1])
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
self.sync_all()
|
||||
|
|
|
|||
|
|
@ -122,16 +122,14 @@ class ImportRescanTest(BitcoinTestFramework):
|
|||
|
||||
# Import keys with pruning disabled
|
||||
self.start_nodes(extra_args=[[]] * self.num_nodes)
|
||||
super().import_deterministic_coinbase_privkeys()
|
||||
for n in self.nodes:
|
||||
n.importprivkey(privkey=n.get_deterministic_priv_key().key, label='coinbase')
|
||||
self.stop_nodes()
|
||||
|
||||
self.start_nodes()
|
||||
for i in range(1, self.num_nodes):
|
||||
connect_nodes(self.nodes[i], 0)
|
||||
|
||||
def import_deterministic_coinbase_privkeys(self):
|
||||
pass
|
||||
|
||||
def run_test(self):
|
||||
# Create one transaction on node 0 with a unique amount for
|
||||
# each possible type of wallet import RPC.
|
||||
|
|
|
|||
134
test/bitcoin_functional/functional/wallet_import_with_label.py
Executable file
134
test/bitcoin_functional/functional/wallet_import_with_label.py
Executable file
|
|
@ -0,0 +1,134 @@
|
|||
#!/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.
|
||||
"""Test the behavior of RPC importprivkey on set and unset labels of
|
||||
addresses.
|
||||
|
||||
It tests different cases in which an address is imported with importaddress
|
||||
with or without a label and then its private key is imported with importprivkey
|
||||
with and without a label.
|
||||
"""
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal
|
||||
|
||||
|
||||
class ImportWithLabel(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
"""Main test logic"""
|
||||
|
||||
self.log.info(
|
||||
"Test importaddress with label and importprivkey without label."
|
||||
)
|
||||
self.log.info("Import a watch-only address with a label.")
|
||||
address = self.nodes[0].getnewaddress()
|
||||
label = "Test Label"
|
||||
self.nodes[1].importaddress(address, label)
|
||||
address_assert = self.nodes[1].getaddressinfo(address)
|
||||
|
||||
assert_equal(address_assert["iswatchonly"], True)
|
||||
assert_equal(address_assert["ismine"], False)
|
||||
assert_equal(address_assert["label"], label)
|
||||
|
||||
self.log.info(
|
||||
"Import the watch-only address's private key without a "
|
||||
"label and the address should keep its label."
|
||||
)
|
||||
priv_key = self.nodes[0].dumpprivkey(address)
|
||||
self.nodes[1].importprivkey(priv_key)
|
||||
|
||||
assert_equal(label, self.nodes[1].getaddressinfo(address)["label"])
|
||||
|
||||
self.log.info(
|
||||
"Test importaddress without label and importprivkey with label."
|
||||
)
|
||||
self.log.info("Import a watch-only address without a label.")
|
||||
address2 = self.nodes[0].getnewaddress()
|
||||
self.nodes[1].importaddress(address2)
|
||||
address_assert2 = self.nodes[1].getaddressinfo(address2)
|
||||
|
||||
assert_equal(address_assert2["iswatchonly"], True)
|
||||
assert_equal(address_assert2["ismine"], False)
|
||||
assert_equal(address_assert2["label"], "")
|
||||
|
||||
self.log.info(
|
||||
"Import the watch-only address's private key with a "
|
||||
"label and the address should have its label updated."
|
||||
)
|
||||
priv_key2 = self.nodes[0].dumpprivkey(address2)
|
||||
label2 = "Test Label 2"
|
||||
self.nodes[1].importprivkey(priv_key2, label2)
|
||||
|
||||
assert_equal(label2, self.nodes[1].getaddressinfo(address2)["label"])
|
||||
|
||||
self.log.info("Test importaddress with label and importprivkey with label.")
|
||||
self.log.info("Import a watch-only address with a label.")
|
||||
address3 = self.nodes[0].getnewaddress()
|
||||
label3_addr = "Test Label 3 for importaddress"
|
||||
self.nodes[1].importaddress(address3, label3_addr)
|
||||
address_assert3 = self.nodes[1].getaddressinfo(address3)
|
||||
|
||||
assert_equal(address_assert3["iswatchonly"], True)
|
||||
assert_equal(address_assert3["ismine"], False)
|
||||
assert_equal(address_assert3["label"], label3_addr)
|
||||
|
||||
self.log.info(
|
||||
"Import the watch-only address's private key with a "
|
||||
"label and the address should have its label updated."
|
||||
)
|
||||
priv_key3 = self.nodes[0].dumpprivkey(address3)
|
||||
label3_priv = "Test Label 3 for importprivkey"
|
||||
self.nodes[1].importprivkey(priv_key3, label3_priv)
|
||||
|
||||
assert_equal(label3_priv, self.nodes[1].getaddressinfo(address3)["label"])
|
||||
|
||||
self.log.info(
|
||||
"Test importprivkey won't label new dests with the same "
|
||||
"label as others labeled dests for the same key."
|
||||
)
|
||||
self.log.info("Import a watch-only legacy address with a label.")
|
||||
address4 = self.nodes[0].getnewaddress()
|
||||
label4_addr = "Test Label 4 for importaddress"
|
||||
self.nodes[1].importaddress(address4, label4_addr)
|
||||
address_assert4 = self.nodes[1].getaddressinfo(address4)
|
||||
|
||||
assert_equal(address_assert4["iswatchonly"], True)
|
||||
assert_equal(address_assert4["ismine"], False)
|
||||
assert_equal(address_assert4["label"], label4_addr)
|
||||
|
||||
self.log.info("Asserts address has no embedded field with dests.")
|
||||
|
||||
assert_equal(address_assert4.get("embedded"), None)
|
||||
|
||||
self.log.info(
|
||||
"Import the watch-only address's private key without a "
|
||||
"label and new destinations for the key should have an "
|
||||
"empty label while the 'old' destination should keep "
|
||||
"its label."
|
||||
)
|
||||
priv_key4 = self.nodes[0].dumpprivkey(address4)
|
||||
self.nodes[1].importprivkey(priv_key4)
|
||||
address_assert4 = self.nodes[1].getaddressinfo(address4)
|
||||
|
||||
assert address_assert4.get("embedded")
|
||||
|
||||
bcaddress_assert = self.nodes[1].getaddressinfo(
|
||||
address_assert4["embedded"]["address"]
|
||||
)
|
||||
|
||||
assert_equal(address_assert4["label"], label4_addr)
|
||||
assert_equal(bcaddress_assert["label"], "")
|
||||
|
||||
self.stop_nodes()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ImportWithLabel().main()
|
||||
|
|
@ -11,8 +11,14 @@ from test_framework.util import (
|
|||
assert_greater_than,
|
||||
assert_raises_rpc_error,
|
||||
bytes_to_hex_str,
|
||||
hex_str_to_bytes
|
||||
)
|
||||
|
||||
from test_framework.script import (
|
||||
CScript,
|
||||
OP_0,
|
||||
hash160
|
||||
)
|
||||
from test_framework.messages import sha256
|
||||
|
||||
class ImportMultiTest(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
|
|
@ -48,7 +54,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
|
||||
# RPC importmulti -----------------------------------------------
|
||||
|
||||
# Bitcoin Address
|
||||
# Bitcoin Address (implicit non-internal)
|
||||
self.log.info("Should import an address")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
result = self.nodes[1].importmulti([{
|
||||
|
|
@ -62,6 +68,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
assert_equal(address_assert['ischange'], False)
|
||||
watchonly_address = address['address']
|
||||
watchonly_timestamp = timestamp
|
||||
|
||||
|
|
@ -89,6 +96,20 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['timestamp'], timestamp)
|
||||
assert_equal(address_assert['ischange'], True)
|
||||
|
||||
# ScriptPubKey + internal + label
|
||||
self.log.info("Should not allow a label to be specified when internal is true")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": address['scriptPubKey'],
|
||||
"timestamp": "now",
|
||||
"internal": True,
|
||||
"label": "Example label"
|
||||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -8)
|
||||
assert_equal(result[0]['error']['message'], 'Internal addresses should not have a label')
|
||||
|
||||
# Nonstandard scriptPubKey + !internal
|
||||
self.log.info("Should not import a nonstandard scriptPubKey without internal flag")
|
||||
|
|
@ -107,7 +128,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
assert_equal('timestamp' in address_assert, False)
|
||||
|
||||
|
||||
# Address + Public key + !Internal
|
||||
# Address + Public key + !Internal(explicit)
|
||||
self.log.info("Should import an address with public key")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
result = self.nodes[1].importmulti([{
|
||||
|
|
@ -115,7 +136,8 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
"address": address['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"pubkeys": [ address['pubkey'] ]
|
||||
"pubkeys": [ address['pubkey'] ],
|
||||
"internal": False
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
|
|
@ -198,7 +220,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -8)
|
||||
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
|
||||
assert_equal(result[0]['error']['message'], 'Watch-only addresses should not include private keys')
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
|
@ -339,7 +361,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -8)
|
||||
assert_equal(result[0]['error']['message'], 'Incompatibility found between watchonly and keys')
|
||||
assert_equal(result[0]['error']['message'], 'Watch-only addresses should not include private keys')
|
||||
|
||||
|
||||
# Address + Public key + !Internal + Wrong pubkey
|
||||
|
|
@ -355,7 +377,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -5)
|
||||
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
||||
assert_equal(result[0]['error']['message'], 'Key does not match address destination')
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
|
@ -375,7 +397,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
result = self.nodes[1].importmulti(request)
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -5)
|
||||
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
||||
assert_equal(result[0]['error']['message'], 'Key does not match address destination')
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
|
@ -395,7 +417,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -5)
|
||||
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
||||
assert_equal(result[0]['error']['message'], 'Key does not match address destination')
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
|
@ -414,7 +436,7 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
}])
|
||||
assert_equal(result[0]['success'], False)
|
||||
assert_equal(result[0]['error']['code'], -5)
|
||||
assert_equal(result[0]['error']['message'], 'Consistency check failed')
|
||||
assert_equal(result[0]['error']['message'], 'Key does not match address destination')
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
|
@ -458,6 +480,147 @@ class ImportMultiTest(BitcoinTestFramework):
|
|||
"timestamp": "",
|
||||
}])
|
||||
|
||||
# Import P2WPKH address as watch only
|
||||
self.log.info("Should import a P2WPKH address as watch only")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32"))
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": address['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], True)
|
||||
assert_equal(address_assert['solvable'], False)
|
||||
|
||||
# Import P2WPKH address with public key but no private key
|
||||
self.log.info("Should import a P2WPKH address and public key as solvable but not spendable")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32"))
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": address['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"pubkeys": [ address['pubkey'] ]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
assert_equal(address_assert['solvable'], True)
|
||||
|
||||
# Import P2WPKH address with key and check it is spendable
|
||||
self.log.info("Should import a P2WPKH address with key")
|
||||
address = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="bech32"))
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": address['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"keys": [self.nodes[0].dumpprivkey(address['address'])]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(address['address'])
|
||||
assert_equal(address_assert['iswatchonly'], False)
|
||||
assert_equal(address_assert['ismine'], True)
|
||||
|
||||
# P2WSH multisig address without scripts or keys
|
||||
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
sig_address_2 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].addmultisigaddress(2, [sig_address_1['pubkey'], sig_address_2['pubkey']], "", "bech32")
|
||||
self.log.info("Should import a p2wsh multisig as watch only without respective redeem script and private keys")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": multi_sig_script['address']
|
||||
},
|
||||
"timestamp": "now"
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
||||
assert_equal(address_assert['solvable'], False)
|
||||
|
||||
# Same P2WSH multisig address as above, but now with witnessscript + private keys
|
||||
self.log.info("Should import a p2wsh with respective redeem script and private keys")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": multi_sig_script['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"witnessscript": multi_sig_script['redeemScript'],
|
||||
"keys": [ self.nodes[0].dumpprivkey(sig_address_1['address']), self.nodes[0].dumpprivkey(sig_address_2['address']) ]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
||||
assert_equal(address_assert['solvable'], True)
|
||||
assert_equal(address_assert['ismine'], True)
|
||||
assert_equal(address_assert['sigsrequired'], 2)
|
||||
|
||||
# P2SH-P2WPKH address with no redeemscript or public or private key
|
||||
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="p2sh-segwit"))
|
||||
pubkeyhash = hash160(hex_str_to_bytes(sig_address_1['pubkey']))
|
||||
pkscript = CScript([OP_0, pubkeyhash])
|
||||
self.log.info("Should import a p2sh-p2wpkh without redeem script or keys")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": sig_address_1['address']
|
||||
},
|
||||
"timestamp": "now"
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(sig_address_1['address'])
|
||||
assert_equal(address_assert['solvable'], False)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
||||
# P2SH-P2WPKH address + redeemscript + public key with no private key
|
||||
self.log.info("Should import a p2sh-p2wpkh with respective redeem script and pubkey as solvable")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": sig_address_1['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"redeemscript": bytes_to_hex_str(pkscript),
|
||||
"pubkeys": [ sig_address_1['pubkey'] ]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(sig_address_1['address'])
|
||||
assert_equal(address_assert['solvable'], True)
|
||||
assert_equal(address_assert['ismine'], False)
|
||||
|
||||
# P2SH-P2WPKH address + redeemscript + private key
|
||||
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress(address_type="p2sh-segwit"))
|
||||
pubkeyhash = hash160(hex_str_to_bytes(sig_address_1['pubkey']))
|
||||
pkscript = CScript([OP_0, pubkeyhash])
|
||||
self.log.info("Should import a p2sh-p2wpkh with respective redeem script and private keys")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": sig_address_1['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"redeemscript": bytes_to_hex_str(pkscript),
|
||||
"keys": [ self.nodes[0].dumpprivkey(sig_address_1['address'])]
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(sig_address_1['address'])
|
||||
assert_equal(address_assert['solvable'], True)
|
||||
assert_equal(address_assert['ismine'], True)
|
||||
|
||||
# P2SH-P2WSH 1-of-1 multisig + redeemscript with no private key
|
||||
sig_address_1 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
|
||||
multi_sig_script = self.nodes[0].addmultisigaddress(1, [sig_address_1['pubkey']], "", "p2sh-segwit")
|
||||
scripthash = sha256(hex_str_to_bytes(multi_sig_script['redeemScript']))
|
||||
redeem_script = CScript([OP_0, scripthash])
|
||||
self.log.info("Should import a p2sh-p2wsh with respective redeem script but no private key")
|
||||
result = self.nodes[1].importmulti([{
|
||||
"scriptPubKey": {
|
||||
"address": multi_sig_script['address']
|
||||
},
|
||||
"timestamp": "now",
|
||||
"redeemscript": bytes_to_hex_str(redeem_script),
|
||||
"witnessscript": multi_sig_script['redeemScript']
|
||||
}])
|
||||
assert_equal(result[0]['success'], True)
|
||||
address_assert = self.nodes[1].getaddressinfo(multi_sig_script['address'])
|
||||
assert_equal(address_assert['solvable'], True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
ImportMultiTest ().main ()
|
||||
|
|
|
|||
|
|
@ -73,11 +73,10 @@ class KeyPoolTest(BitcoinTestFramework):
|
|||
time.sleep(1.1)
|
||||
assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0)
|
||||
|
||||
# drain them by mining
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].generate, 1)
|
||||
# drain the keypool
|
||||
for _ in range(3):
|
||||
nodes[0].getnewaddress()
|
||||
assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress)
|
||||
|
||||
nodes[0].walletpassphrase('test', 100)
|
||||
nodes[0].keypoolrefill(100)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
|
|||
self.skip_if_no_wallet()
|
||||
|
||||
def run_test(self):
|
||||
wallet_path = os.path.join(self.nodes[1].datadir, "regtest2", "wallets", "wallet.dat")
|
||||
wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")
|
||||
wallet_backup_path = os.path.join(self.nodes[1].datadir, "wallet.bak")
|
||||
self.nodes[0].generate(101)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ class WalletLabelsTest(BitcoinTestFramework):
|
|||
|
||||
# Note each time we call generate, all generated coins go into
|
||||
# the same address, so we call twice to get two addresses w/50 each
|
||||
node.generate(1)
|
||||
node.generate(101)
|
||||
node.generatetoaddress(nblocks=1, address=node.getnewaddress(label='coinbase'))
|
||||
node.generatetoaddress(nblocks=101, address=node.getnewaddress(label='coinbase'))
|
||||
assert_equal(node.getbalance(), 100)
|
||||
|
||||
# there should be 2 address groups
|
||||
|
|
@ -42,8 +42,9 @@ class WalletLabelsTest(BitcoinTestFramework):
|
|||
linked_addresses = set()
|
||||
for address_group in address_groups:
|
||||
assert_equal(len(address_group), 1)
|
||||
assert_equal(len(address_group[0]), 2)
|
||||
assert_equal(len(address_group[0]), 3)
|
||||
assert_equal(address_group[0][1], 50)
|
||||
assert_equal(address_group[0][2], 'coinbase')
|
||||
linked_addresses.add(address_group[0][0])
|
||||
|
||||
# send 50 from each address to a third address not in this wallet
|
||||
|
|
@ -77,7 +78,7 @@ class WalletLabelsTest(BitcoinTestFramework):
|
|||
label.verify(node)
|
||||
|
||||
# Check all labels are returned by listlabels.
|
||||
assert_equal(node.listlabels(), [label.name for label in labels])
|
||||
assert_equal(node.listlabels(), sorted(['coinbase'] + [label.name for label in labels]))
|
||||
|
||||
# Send a transaction to each label.
|
||||
for label in labels:
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
def set_test_params(self):
|
||||
self.num_nodes = 2
|
||||
|
||||
def import_deterministic_coinbase_privkeys(self):
|
||||
assert_equal(0, len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True)))
|
||||
super().import_deterministic_coinbase_privkeys()
|
||||
self.num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))
|
||||
|
||||
def skip_test_if_missing_module(self):
|
||||
self.skip_if_no_wallet()
|
||||
|
||||
|
|
@ -31,6 +26,9 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
self.nodes[0].generate(1)
|
||||
sync_blocks(self.nodes)
|
||||
|
||||
# save the number of coinbase reward addresses so far
|
||||
num_cb_reward_addresses = len(self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True))
|
||||
|
||||
self.log.info("listreceivedbyaddress Test")
|
||||
|
||||
# Send from node 0 to 1
|
||||
|
|
@ -68,11 +66,15 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
|
||||
assert_array_result(res, {"address": addr}, expected)
|
||||
assert_equal(len(res), 1)
|
||||
# Test for regression on CLI calls with address string (#14173)
|
||||
cli_res = self.nodes[1].cli.listreceivedbyaddress(0, True, True, addr)
|
||||
assert_array_result(cli_res, {"address": addr}, expected)
|
||||
assert_equal(len(cli_res), 1)
|
||||
# Error on invalid address
|
||||
assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling")
|
||||
# Another address receive money
|
||||
res = self.nodes[1].listreceivedbyaddress(0, True, True)
|
||||
assert_equal(len(res), 2 + self.num_cb_reward_addresses) # Right now 2 entries
|
||||
assert_equal(len(res), 2 + num_cb_reward_addresses) # Right now 2 entries
|
||||
other_addr = self.nodes[1].getnewaddress()
|
||||
txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
|
||||
self.nodes[0].generate(1)
|
||||
|
|
@ -89,7 +91,7 @@ class ReceivedByTest(BitcoinTestFramework):
|
|||
assert_equal(len(res), 1)
|
||||
# Should be two entries though without filter
|
||||
res = self.nodes[1].listreceivedbyaddress(0, True, True)
|
||||
assert_equal(len(res), 3 + self.num_cb_reward_addresses) # Became 3 entries
|
||||
assert_equal(len(res), 3 + num_cb_reward_addresses) # Became 3 entries
|
||||
|
||||
# Not on random addr
|
||||
other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
|
||||
|
|
|
|||
|
|
@ -53,8 +53,10 @@ class ListSinceBlockTest (BitcoinTestFramework):
|
|||
"42759cde25462784395a337460bde75f58e73d3f08bd31fdc3507cbac856a2c4")
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
|
||||
"0000000000000000000000000000000000000000000000000000000000000000")
|
||||
assert_raises_rpc_error(-5, "Block not found", self.nodes[0].listsinceblock,
|
||||
assert_raises_rpc_error(-8, "blockhash must be of length 64 (not 11, for 'invalid-hex')", self.nodes[0].listsinceblock,
|
||||
"invalid-hex")
|
||||
assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'Z000000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].listsinceblock,
|
||||
"Z000000000000000000000000000000000000000000000000000000000000000")
|
||||
|
||||
def test_reorg(self):
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Verify that a bitcoind node can load multiple wallet files
|
|||
"""
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.test_node import ErrorMatch
|
||||
|
|
@ -29,7 +30,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
data_dir = lambda *p: os.path.join(node.datadir, 'regtest2', *p)
|
||||
data_dir = lambda *p: os.path.join(node.datadir, 'regtest', *p)
|
||||
wallet_dir = lambda *p: data_dir('wallets', *p)
|
||||
wallet = lambda name: node.get_wallet_rpc(name)
|
||||
|
||||
|
|
@ -38,6 +39,8 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
return wallet_dir(name, "wallet.dat")
|
||||
return wallet_dir(name)
|
||||
|
||||
assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': '' }] })
|
||||
|
||||
# check wallet.dat is created
|
||||
self.stop_nodes()
|
||||
assert_equal(os.path.isfile(wallet_dir('wallet.dat')), True)
|
||||
|
|
@ -68,6 +71,8 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
wallet_names = ['w1', 'w2', 'w3', 'w', 'sub/w5', os.path.join(self.options.tmpdir, 'extern/w6'), 'w7_symlink', 'w8', '']
|
||||
extra_args = ['-wallet={}'.format(n) for n in wallet_names]
|
||||
self.start_node(0, extra_args)
|
||||
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8'])
|
||||
|
||||
assert_equal(set(node.listwallets()), set(wallet_names))
|
||||
|
||||
# check that all requested wallets were created
|
||||
|
|
@ -76,7 +81,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
assert_equal(os.path.isfile(wallet_file(wallet_name)), True)
|
||||
|
||||
# should not initialize if wallet path can't be created
|
||||
exp_stderr = "boost::filesystem::create_directory: (The system cannot find the path specified|Not a directory):"
|
||||
exp_stderr = "boost::filesystem::create_directory:"
|
||||
self.nodes[0].assert_start_raises_init_error(['-wallet=wallet.dat/bad'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX)
|
||||
|
||||
self.nodes[0].assert_start_raises_init_error(['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist')
|
||||
|
|
@ -121,7 +126,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
self.start_node(0, ['-wallet=w4', '-wallet=w5'])
|
||||
assert_equal(set(node.listwallets()), {"w4", "w5"})
|
||||
w5 = wallet("w5")
|
||||
w5.generate(1)
|
||||
node.generatetoaddress(nblocks=1, address=w5.getnewaddress())
|
||||
|
||||
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded
|
||||
os.rename(wallet_dir2, wallet_dir())
|
||||
|
|
@ -139,11 +144,13 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
|
||||
self.restart_node(0, extra_args)
|
||||
|
||||
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy'])
|
||||
|
||||
wallets = [wallet(w) for w in wallet_names]
|
||||
wallet_bad = wallet("bad")
|
||||
|
||||
# check wallet names and balances
|
||||
wallets[0].generate(1)
|
||||
node.generatetoaddress(nblocks=1, address=wallets[0].getnewaddress())
|
||||
for wallet_name, wallet in zip(wallet_names, wallets):
|
||||
info = wallet.getwalletinfo()
|
||||
assert_equal(info['immature_balance'], 50 if wallet is wallets[0] else 0)
|
||||
|
|
@ -156,7 +163,7 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo)
|
||||
|
||||
w1, w2, w3, w4, *_ = wallets
|
||||
w1.generate(101)
|
||||
node.generatetoaddress(nblocks=101, address=w1.getnewaddress())
|
||||
assert_equal(w1.getbalance(), 100)
|
||||
assert_equal(w2.getbalance(), 0)
|
||||
assert_equal(w3.getbalance(), 0)
|
||||
|
|
@ -165,13 +172,13 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
w1.sendtoaddress(w2.getnewaddress(), 1)
|
||||
w1.sendtoaddress(w3.getnewaddress(), 2)
|
||||
w1.sendtoaddress(w4.getnewaddress(), 3)
|
||||
w1.generate(1)
|
||||
node.generatetoaddress(nblocks=1, address=w1.getnewaddress())
|
||||
assert_equal(w2.getbalance(), 1)
|
||||
assert_equal(w3.getbalance(), 2)
|
||||
assert_equal(w4.getbalance(), 3)
|
||||
|
||||
batch = w1.batch([w1.getblockchaininfo.get_request(), w1.getwalletinfo.get_request()])
|
||||
assert_equal(batch[0]["result"]["chain"], "regtest2")
|
||||
assert_equal(batch[0]["result"]["chain"], "regtest")
|
||||
assert_equal(batch[1]["result"]["walletname"], "w1")
|
||||
|
||||
self.log.info('Check for per-wallet settxfee call')
|
||||
|
|
@ -219,6 +226,10 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
# 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 one wallet is a copy of another, test this twice to make sure that we don't re-introduce #14304
|
||||
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')
|
||||
|
||||
|
|
@ -262,7 +273,11 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
assert 'w1' not in self.nodes[0].listwallets()
|
||||
|
||||
# Successfully unload the wallet referenced by the request endpoint
|
||||
# Also ensure unload works during walletpassphrase timeout
|
||||
w2.encryptwallet('test')
|
||||
w2.walletpassphrase('test', 1)
|
||||
w2.unloadwallet()
|
||||
time.sleep(1.1)
|
||||
assert 'w2' not in self.nodes[0].listwallets()
|
||||
|
||||
# Successfully unload all wallets
|
||||
|
|
@ -276,6 +291,8 @@ class MultiWalletTest(BitcoinTestFramework):
|
|||
assert_equal(self.nodes[0].listwallets(), ['w1'])
|
||||
assert_equal(w1.getwalletinfo()['walletname'], 'w1')
|
||||
|
||||
assert_equal(sorted(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), ['', os.path.join('sub', 'w5'), 'w', 'w1', 'w2', 'w3', 'w7', 'w7_symlink', 'w8', 'w8_copy', 'w9'])
|
||||
|
||||
# Test backing up and restoring wallets
|
||||
self.log.info("Test wallet backup")
|
||||
self.restart_node(0, ['-nowallet'])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue