Bitcoin Forum
June 08, 2026, 09:05:26 PM *
News: Latest Bitcoin Core release: 31.0 [Torrent]
 
  Home Help Search Login Register More  
  Show Posts
Pages: [1] 2 »
1  Bitcoin / Development & Technical Discussion / Nested ECC - A new hash algorithm with tremendous benefits? on: April 14, 2024, 11:15:32 PM
A new hash algorithm?

All right, this may be more cryptography than Bitcoin, but bear with me. Doin' some thinkin'.

After one new huge public release after the other, we see salts and many rounds of hashing using good old hashing algorithms such as PBKDF2-SHA512; NIST even promotes some of the methods.

Got half an hour to kill? Read this straight from the mouth of the horse, the scientific primary literature.

Nested Elliptic Curve Cryptography (NECC) - My suggested solution

Pick a random number. That's you private key. Rather: have a computer pick one for you, as we human suck as large numbers.

According to Secp256k1, the large integer can be anything between 1 and 115792089237316195423570985008687907852837564279074904382605163141518161494337. It is a very large number indeed.

I prefer Python to do it for me, and I don't mind hexadecimal annotation:

Code:
>>> import random
>>> privkey = random.randint(1,115792089237316195423570985008687907852837564279074904382605163141518161494337)
>>> print (hex(privkey).zfill(64)[2:])
2d05ad49ddd07abb19571bfd238a5a241a80a14c3a9b31db3e144d4fc239ceda

You could produce the same end-result with a one-liner in bash:

Code:
openssl rand -hex 32
.
No need to go online at any state of keypair or wallet generation!

The use case I had in mind was not cryptocurrencies, but I'd love your comments on it.

"The Regular Website" need a database with both usernames and passwords hashed. The problem with SHA1, SHA-256 or even fancier stuff like bscryp, script or PBKDF2-SHA512 so secure store use and store user credentials - and hope and pray these are never leaked. Not good for "The big website" nor for the user, as we have seen in numerous hacsks over the past years. (More that 97% in "haveibeenpwnd" has been reversed. Not good.

So, what is a cood hashing method in 2024? SHA256 for storing passwords is Stone Age.
  • It should be "expensive" for both CPU and memory
  • It should be intrinsically slow; the fastest rigs in the universe should be able to check one (1) in a second); not millions per second               
  • No immediate gains when using GPU (clusters)

So, allow me to introduce Nested ECC! Pseudocode below:

Code:
<any password/phrase/file>        ---SHA256--->
32 bytes      ---ECC according to Secp256k1--->
33 bytes (X)  ---ditch 1st byte, whether Y is even or odd--->
32 bytes

Repeat the last steps as needed; a trade-off between computational demands and user experience. n(lopp)=1,024 is where I would begin.

See what I'm doing there?
1. Using one cryptographically secure RNG to roll the dice
2. Treating the random number as a private key; all as defined by Secp256k1
3. Looking up its corresponding public key coordinate (X,Y), discarding everything that's not X (yes, Y is wholly omitted, even its sign)
4. Backfeeding the new "X only" to step 3 in a loop (1,000 rounds?)

Since ECC is so much more CPU and memory-intensive than the good old SHA family, I think we have something for future webmasters and TLS-issues (to begin with). Instead of nesting SHA256 or the like, we are jumping back a fort between private and public keys on Secp256k1—until we, and only we, know where we started.
,
You could (should?) be perfectly open about what cryptographic methods you use. Let's say the worst happens, and your user/pass database is in the wild. How bad is it? It's not like a bot army could fire up Hashcat and have a stab and your ned mystery hashes.

Let me hear from you, crypto-wizards! Something in me that got you thinking of one or two ideas in crypto design. Am I right?




2  Bitcoin / Bitcoin Technical Support / Would P2WPKH v1/bech32m addressee be legal (and usable and spendable)? on: March 01, 2024, 12:48:29 AM
We have a public key. We have its RIPEMD(SHA256(pubkey)) hash, a.k.a. HASH160

We can easily construct a valid native segwit address by

Code:
> bitcoinutils.bech32.encode('bc',0,memoryview(bytes.fromhex(our_hash160)).tolist())
> bc1qmgt5t6d4fx7sh7s626vhr3m7hgcv6kjt450t6x

So far, nothing strange. Works as intended.

But if we change the version from 0 to 1 and disregard all taproot standards, we get a bech32m public address like so:

Code:
> bitcoinutils.bech32.encode('bc',1,memoryview(bytes.fromhex(our_hash160)).tolist())
> bc1pmgt5t6d4fx7sh7s626vhr3m7hgcv6kjttkgvj0

Good for anything? Will wallets accept it? Will nodes propagate a transaction to it over the BTC network? Can we use normal privkeys to spend from it with, as we do with regular native segwit?

Due to lack of better terminology, we can call them P2WPKH(Bech32m). A thing or not? That's the question.
.
3  Local / Skandinavisk / Skaffa crypto on: February 24, 2024, 12:18:16 AM
I don't speak a word Swedish (?), but as I am totally bribable, and I took 1000 tBTC in exchange, from some random dude messaging me, for posting ons link right here in this subforum.

Said and done. Testnet coins are all mine!

Here it is the link:

https://skaffacrypto.se/

 Smiley

4  Bitcoin / Bitcoin Discussion / 120 USD to transfer 25 cents - Taproot genius transaction on: January 20, 2024, 09:36:43 PM
This recent transaction stands out a bit...

0.00288744 BTC (120.19 USD) to transfer 600 sats (25 cents)

No change address (you're welcome, miners)

https://blockchair.com/bitcoin/transaction/7d57e84ab62612c501d4f2a6c3df1b806b7057165b82a444e97f041ad9f7516c

Here is the raw transaction (~25k bytes - for scrolling purposes):

Code:
010000000001011c8baccf477db1a1b941699b98ad9ac53faf6dafea14f693b87c5b99ccfb83e60000000000fdffffff015802000000000000225120fe08248c30dee7d16c6bab58a03634eb1ca48a43726f4185e6b458fdc18d22640340a189ae2b7fd67482da9d123ae721ec0d90c1badbcba60a58a5ee269ec8339e903a1ebc9892fdb43af707bdadd9419c54afc6b27418b3333b6d8b7174df3a5a11fdff5f2051e7111c98bf4699122e43b7ec74f26ba98bd42ccd8c01fa60c8a17367f37547ac0063036f726401010a696d6167652f6a706567004d0802ffd8ffdb00430006040506050406060506070706080a100a0a09090a140e0f0c1017141818171416161a1d251f1a1b231c1616202c20232627292a29191f2d302d283025282928ffdb0043010707070a080a130a0a13281a161a2828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828282828ffc0001108014000de03012200021101031101ffc4001d000001050101010100000000000000000006030405070802010009ffc40049100001030204030505040803060603010001020304051100061221073141132251617114328191a1084252b11516236272c1d1f0243382344353a2e1f117257392b2c226354463ffc4001b01000105010100000000000000000000000200010304050607ffc40032110001040201020405020603010000000001000203110421311241051351712232618191a1b10614c1d1e1f015234252ffda000c03010002110311003f00b9dd274af491ab7b5f03afbb518e9d5254a5a01b0292304ba0151e97271c96d1bed7dba9c7259b03a61a716fb2d28650ced686d895ed20075dd07a052b0b20ab5dbb6bf86d7bfd70f65c2d692adc27ee84201f9f5c4795b6d93dabfa540d8828b586394c864d0c9d25c7deff00cabcd2c936d0955b6ef2d04f8dcdbf3c74953ad0f71957faf7c36724a05f4a92b37e4500617f69614c052a385f4dc8fe5878f24d0802dccf95ff0094e632765ba4eda7132117753a40d8d8dedf2c0c66ead4aa12d97e1c30b88b3671fb15e93e631349909d000612124db4eab62463c8438d594d84246d7bf3c6de078b471bc195c0aa3958af73486e957233a332100395b723dcdcf6704dc7cce39fd2b97df27daeb15790a2790469c58b2a1d3e620a24476dc6f9fbbcf03d3b2bd35c5130c498ae0df53476fae378f8ce38d596fb57f6596fc09fb51fcff743455936c753b37578aaff00d31da15939d294a263e83fbce287f2c4d8a13339869994fc93a4d940afdef5be1e44a1d269c16ca2032b046a5958d6af99e58c897c5a07b4b83ddf63fe1586e04cc781d23f0a11a919622b5644ced8037b15951fadb0afb7531fbaa3412b0073034fe5878ed232fa1dd688435937d22f61f5c347a914a75d21100f78ee02942df5c52ff92c6ffe9df956c61649ff00c80108d5e9b4aa84f71d69894e4955ae1b775004799f8617a3d1b3036e110c2e135a74eb90f951f509c1ac169988de88d192c7fe9f5f89c7aa77b4429424250126c75916f9e19fe3f357971ec0f5da963f09693d4f3b3e9a4850e13915a089b294fb8a55d6b51e4a3b75c12bc52d3694a893e02d7be07341411ed0438ca8ee08ba4f5e63d3139db372882e2d4d5baa791c67c196f697bf5d4e2aecd086f4b47012a99290004b2bb789b0c3395254f92840d09077b1e7845dd1af4b4e2c83d54ae785d0c26c3b421092744d0802dcf5c432e6644d6cb147d11b21633e22936425275a949006d603738edc9246e7b5d3e236185fd8d1b80543e18e64c64b6ca8a8baa006e41bdf031c192c69ae3e899f244e76d22d38a44b4155cb6e0d2028f23fdfe787cfaf4347c4ed6c3642597a3a0b4a4e9e971b8b61ca1a2b482b714bb795b16e096789859bbe42af27438f5260a7141abad413a76212309f64b2ad924f5df0ea7389688421b04f3dcff2c378ca5a96bfda9585f216b5b10799d4ea91c49fa7aa2ad5b428c9398a9f01f5c598f2997529493742940df90040373fd313b93ea512a6fb8a872da92128370856e9dc731cc7c710ad3663d656a5107b7680df6ba9076fa13894a3d2a1cdab194ec6064f62a495a094ab4ea4ec483b8db1b7e1f379af0093a0abc8de9b442dbe1401b7bde5cef865260a16a2b43614544a8af5d958808598195988c6a0a5dd22e904db6eb89e8f2ff6ef474a09ecc91a89e58d1c9c7748de9902a914c01b6a6e94bcc0ee38a0907dd7771ffbb1f225590a42e2055cdcd8dc1c3354292a9052e29c7c137b25561855da7c869bd41842537f7756a563939229ec98c1a1ebb5a83a356522fa5b52ae9425bdec1215aaf87b4fa734a4a4be8dd5bd89c7915bf6617ecd01d3b92e1b63e9350750d952742556b020eac0e3f4c4e2f9859f4a46e2f7fc0c5e56130a2b3a925b494924e83b81f0df104e664692c82d84b8502f7d36b8c35acca6cb254f28978e4d0802c12df5fef7c46502ce5599400a4a0826cadc72c1ca2395c65e9aa5a98f86d115c9ba528fe609eb5292da43693eed922ff5c206a95056a205cabc40fcb12f369a894495592e78a799c0fc881221b4a25d538941b15a46e3aee302d95b2775344d89dae90a52993de520b726e9701d94073c2acaa42db297dd5a77b9d7dd1861017a10e2eca4b961a0ad277f961c4894b7e239dbc6414904a53aec4586f888b689aeea19583a8d04b38f2587121480a58049d1bdbcbf2fae3cf696c3dbd8122e4dfc7c710ec4f5eed259482a22eb4af513e47ae1e3da1b5a166ea706d62709d1749a2a3e94fe3b9fb425c702d6adb61b01e1842408b2c760b51d947bc136b1f5c354bae04ea2a0516dadb6f86ce4a756416dd712a3726dd7c2d7c264766f8286ab8524c1769ebd2b054856cab0dbe587b0657b315026ecbbb116e581fede549428252b4903485dbfbdf71cb0f5aed5a691dba86b02e4155ce1dcc2dddfe12203851442c2e09035ad2b70abf668fbca3e9f3c0d46ae562b5a971e652696da544043ca05c1636dc2bfa624db4b69d0ea8685a482176e57c79558301e7532274186b4a85cad4dd8abe237df1a5e1b9b8f8ed2d95967daff00759b9d8724c4796efe8993d0a6291ae4e764377e619084fe44620e643a09708995facd51fe88689fe87045129d457077291114e0e4ab9524fc0e1eb4cb4c3a030d351d36dd0ca0241f96345fe391443febb34d0802f4a03fa2a0df0b95c7e3a1f725054b835896b4ae98c4e8915360872448d3a7d53cfe38398129d661351e53c57312801c7103ba4f8fe584e3cb536b73512e3215a4ebe60f879f3c4b4669875b4ba84a4a4ee0018cac8f1174ed0c6b43473f5fcab8313c925ce36992a2a96145c1dc29052e85f78a8f3fe5f3c75063943cde924a529b1d479e1d3cc0490900a6fb91d00c370ebadb64a9ad409b8208b8c67c6da9017581deb68cbadb41215dff000d221c8426fa5f424dbf7bbbf99189ea1364cc5104ff00967f3180ecc4f862893961e25aba1eef9b965616951dfc0d8fa1c1f50c832d4a06c0b7cfc7718ed3c2608db7230836a84ce77054452e0453458652ca10a53285dc0b1be918ee3beda64a92103b5513debf3c294d5139769e52013ecadef6e5dd18087f3154e6ce94de5e80c2d319d5071d79c03bc363b123f9e34326296724466ab92555748c87e647cd2425d4d810a57526fbe3b797d8a35682a755b580bdf00461e7190da24c8acc78e147ba961bd4a171e406249acbb9b8341c19a798be95c71718ad1e10db7cc17f7fec98e51f9ba0fe9fdd163a82b8a52b362bdd57e9812afb919afd9a95d9041b14369dd5e649c7ca819d9955c56a96ea52365b8d5bff00ae036bb51ac4798a54ea8515e7c7de477ede561b6027f077640a89cd2ace2f89c70bae5691fefba9275c88569d085e81651dbbc7f2c3192fc804a93da2509dd211ccdb4d0802f9e253f48c2aa51d894db0969f166dd412410b16b917e693bdb106f4849d40147bdb1b124e399971dd0c86378d8fc2eeb09ed9e3123468aeccd905cf6870b81cbd829c56e30fe3ce7e7a8a56e9eefbcbe571f9620dc94deaeeb65646db8b5b0434b2574c6d4a6509529474a53b5fd7eb88a5686b6e94d90d6b19749e5dd712a723f67fb31de528db1d3290a417491a9c17245ca47a61bfb239d8f68b63bb62a2350dfc3fbf5c725e8ea6d0a43a50c27bba06e126d8afd3aa0b29c4176939404b0162f6dae6c6e6f86c95aae80905cd6adc5bf3be3b4f6c875b72c0b6a05245bbc478dc0c287405155edbf323ae078fada89dcaf11a4af506ca5b50b10a16c22eb6104ba349484f7475070a2d47b54a749d405ac0639d085152528bacf7b49e5f3c26e8da405af194a10ead2c2825d22f61d2d8e996cb274a0294e13752bf10385a3a034a4a8a13aee495116b9385342cbaee9792dc829ba09dd22c708bacd5a73413b8e94ad871b26e922f63d309d2d2d90ea1cd0a55f6d4798feef87a129009041eeee6dcf00f54656a9ee8df495ec474c45034496d254d8d179b6d2518bd25a600434d85ab90091b0c45d764181508cf3cf1430a6eca005c6af03e7cbe58848b01d5ad29dd3bee4a88bfa624931da8b4e94f54d1aa3b26c56a1aec790b7cfeb8b90e3b41a1bb523e06466eed4d20a0c7438a0a2858d87bc3f961cc35943641b147ee2b10d469484d08029295ad9b08ea374b62e7b31b6db1feef89c6e3eb1ab4e9db62396294edf2ddd2167cc00f84a946e45f4a6d752bae155205f702fe7d4621521d8ee6b51524720a1b83855eadc7842d366308f0054357cb9e2de1cb67a5c093ecb326686ec1a5f54a98cc98cf009494ad252b491b2d3d41c4fe5e2a04036d9bb6df0c0d315da7549b7d302407dd424296842140dafd361825cb0165575dae504f3f318dcc28dec9a9a2afb281ef0f65da6941bab2dd3ac6ff00e15bff00e2302758ca74390e3f224c671a90a429d5299734ea55afcb95f9e0b32c1272dd32e36311bb1ff48c37a933da37b7bc11649b72dbfed8d8ca9e484db0d2abe5325d3c215a7e4882f25a0cd42a8db2a4850097ed6f861fb79069612a53d36a4a50fc722de9d3042cb85b808717604148528ec3cf0e19703ad59a297f51ba7ba2c9eb8a03c4261aea29ce1c47748793912901496d6a9ee2ad720bfb7e588b9b4da4c4716d53a236d693a0ab4eb5a8faaaff004c1cb89f628ca70a94fba373756dcbf2c575549325131d90d06d2db86faca8aafe361f2c4597953f45759df65a7e178313a4eae909a4da5ae42c8d0fa8acf3bd8abd30f289428ec3c5c9292a09d9294a8dc1f3c2306aafb3da487bb5503dd49d3b0bf9623e4e6a5c27921a4178826e55d49f4fcb186e6cd25b5a57505b311e5b7853153cb66448764b2e96b59d9096ff003c2b1232e347431a90b75b036274dee74d0802038bccf516d0e3b2c86d0bb84a00dc7f4c3ec9d5d8f5243897367db1de16b958e87cf0d2433b63b76c0a413473b63f8ce8295699985a9adc85682b51084ea2ab0b78f861ab14df6676eb7da5b2a56b5d8101200f31e9877212b5ce6dc121410e120274f3f2df0a38cea0943ad950b1b923603ae21f308fa2ce076b8d4cbd74c5714a20f86d6c271d68529492e13a37b5b61ebfdf5c2ea8cc345bd294dd63bba6f841dd77d20d80fba0eff1be23041be51380ecbe71c56a4a92906fd52797c708a176090a590ddc93736c7920bda9b119285b5cc9fc3e3f1c72124a54b4f748d5a4017dadff005389034042dd2ea629f4b804546bec48528a873eb87adc84c869a324ab505058b123593d2c37ff00b622a2cd78c8ec909d9c4eea48b9e5e9e9890a1a2c125e09b68b8b277b9e7fcb05233a1bbe513ab9532ddd285ea04a80b9030ca951db98db925454505d524241e601b611abd453160489093a090129d7b5c9db0334fcca696ef632438d950b94a93b1f31e388a2c69248c960da96089cf612d47469ec76a1453d6e05f963ba9b48934a7e13a90965d468511cc79e059bcd5ed3cc59bbdb500458ff0076f9e1cccab331d0cf6ae4b521c49b2834549b8e62e37c1c516447a69a286489ed23a94a65aa246a6c7722a35ac2bbc14a3750e9fd312ab65d83b217a9b572494e222895b61f4b9a1b79e421ab9750dab4a940f2b9f861d31517a77681504d0802654616fd9a9e02c7e009b6249a13e597bcfc5ef4a9c8d90bc9770996636e7d5e9ea89065086e9372a00f7923a6db8bedf2c4451325390d497e74c44c4a772c25bb249f337df04becefeadee9245c9e98790d2b6c8083aafb1bf5c0c3e272c51f92dd0279a16b3e6c58defeb3ca6b4e8916015688ed365ddca909b5fc060ae80947b49008090ded6f518839ad282429b0148fbc93d4624b2ba829d73b3577745eca1b8df96343c2f3648662c7eefbf751cb135cdb6e933cb4afff001ba6002dfe15bb9ff48c3172738894a69f6d5a472b0bec3afe787b966c2854f079760d8e7fba30de7e972a2b6ae06846a5288bedff004c6c78a35ef883e33b514040710e0ba5381d085a53a92a581a2dcb0f62bccc55b8e48576655be9209b7a7fd311aa609483a0ab56e149e7fd71f202d493a13a5636373755bcaf8e6bf9d96175bdbbfd15c1131e3451138eb521a4a91a5c6542ca237b0f31811cc2ba3bcfa076c9496beea517f5b7f5c4b4358742639286d4069d572924785bc710f9a18a7422a6d96f54a50d4e7664ea4a0785b95fc71a6eca3951d80294d87188e5ada189f250e3c5b8cda747ba1c50bdbe1e3cf11b24b3198588ac280528f6afac6a23fa7a0c3c964ae67b3aa38430da2e54a583bf80b7d6fbf3c309cb5bfa5844677d99a1a93d99dbd76f8e2bb2da68fdd751111aa429547c195d8cb97dc165274a49bfc061dd1a5c6a655624880a5b4d0802a526ca4b6de92a0798f13d71354ea4b6f29c7bd95652b3b122c4fc0fae08f2ed322c73ed652d29ce44946e8f4bfc713cb971b1bd26d4b9194c6b0b794b38343a8ec945c4070ba82a3cafd3f3f9e1c36efb469b77483ba56711ee4898c5416e32d76d017601b2ab287ef0bfe470fda611206b6755c1dee3191330801c561c8c737652edb9d9a8a5494920822df74f8e19d73d9da2d3fda065615deb1beaf31878a8dac5d4850572d49173887a8c204a6438eeabd93d9b834903c46f88e10d2e401c3ba59e8d27da75c57d2a6d1651b2412b1e1e18f9e53b21f25d64b11000a0abf7544f4b78e388ab4cb5a23bb7d413701173bfe589890c86d90b90b504a39006d6b625749d068848bbd140d223351e59bf6eb75448d205f481cff90f8608cb284242da41d86950b73ebbe388115284adc710845fbe156ba85fcf1cc79f1264954487202f48d4a520f9f8e2295ce94db6e873e884349d84259fea8cb4fb701ed4a0a1add581cbc00f99bfae2029d2d315b4b0fa8498aab292851ef23cd2705bc4788e2e030e25ad4d34a254e0172302f4aa6c77d0975120a9b1c814dcb6af31e18d9c5730c0085bb8be598027ac4e8506b288d11112585d94991314529493bee3cb6c1a22655dc42d265e5d53407b85c0363e041c08b14175a75499d1d89113501a93cc6aebe23ae167f26a10b52d1188687bae2577047f7d317ce4e206005bc7d2ff00aae73370e64d0802965eaf335db749cc99d58625b688cba64890b05219614576f32705d4c4badc74974dd411723cfae11cbd0e2c38b6698650fa869d4001a81f1b75c3b6753285347576645b4820dafd3181e219114c008db5eca08daf6021eeb5db2ebaa528badf66d1dc1271cb6f82a0e2567b326d7b7d70e02504840490b000d2a3704613931f5b7a11717dc0b6c3cbd31961a3aae923452ee20873f66bee1dd409f0c4c6556f438a56c54a41b903cc6071414cb69515dc7255872f2c10e57793dbad045c041208f518dbf05923fe6ee4d0dd2af90d3e5d3534a1b6114485e1d823ff0088c3475a0b439db824bcb215d3bbe1f961d46514d06136923529a693bf9daff4be3870a654b5a1b5254d2156241e47a8c74733f5d2a90f55e25013d9b85b71b08b58817ba463a75c664ab4a595a6dbad645bf3c39929d4da52362a3649c75d9b4d365b6da4950dca9439e31e680cae2c154acc6ea03d5454d7994c471c942c94f25a8f8605bdbe1bef38a4b8a52547495a473be19e77ae25e925b0b086d2a08173b5baa8dbe387bc3ea226a044b503ecedfba142d7dff9ef8a6cc227e527f65d0c5136083cd90a7086a3b0c253235261df5681b6bc0fbf9852fccf65a44271c6d1be948ee9f026dcfe3822cc31d954c5344add94a591d9a4f7424f2b5be3f2c0c1cae9a4a83912aaea5e3b84a53629f2b83be2f6033159d6325df10e39afd150ca7643fa3c81a3cffa53d84d0802ce6637e4a4b70996d48bad5ad5b587a9c70b9d5f4bda22c186a24723c81f1e631cc7a2bcf8538fcf92e159b6a5294557f2df126f658a4d0a94f55732561d62020594a5280d47c073b9f202f8d3c6c68726405a06be8554c832c4db7ddfb84213ebb5c6dc52243511d2851b691717f01638b332c531e7a851e4d6d68a79746b2d95d8792b7f2b6289cc5c578712438de47a5371d23b89a8cf1db3c7cd0855d29e9e3e98ac2b15aa8d664b926ad3e4cc794775bce157d31bf2f87e23d81a182fd785970e465024bdfaf4e56adafe6dcab42458e668121e49b16504b8b3bf822f817ffc50ca121ebbce3aa36b6a31c903d473c6665b9acdd477b72031e254355f7c663bf87f11c6c023d95c199201b2b522789d949d4a522ae50840d82a33813e5bdb0b2730d2eb92c88b54a4ca4941b362458dcfeeaac49f4c657b809e46d8f890523bc74f300e059fc3d8ad36093ee54accf7b7900ad3f58a455a645ec915652dad212965cd9361e9cf036ed32a94301f04b67fe232be5fdf9e2abcb59e2bb97163d82585c7db547909ed5b57c0f2f51638bc723f17f2b568a61e66889a4c95f77b404ae3ac9f3b5d3f1dbcf133fc2d81b4c0b4e3f1a6b4539aa432be6e4cb68c1aeecb3b21e70582c781feb84ab1942ef2a6515f47676b8655d4f91feb89ecd392a22a3a2651d0dbd0c8d602157b5faa48e60e2068f3570096838b494fdd59b83f3c72f910bf1a434d0802d1a3e878fb2d382464adf331ddee143d27333d05e11e702e35aff6a87059493cae3fbf0c58b4d0d4d89a1890e258500b4949f76fcb156d4e8af2e72dd2f92b7544951e46fd30fa93227d13d9036a0a6d2e1b2c9d8a0fdc57c8efe7891cc89f4e69f708f271db336dba28e9b4bb019790f3a97d0cab49b5c2bd4e1cb7293274a50bbb846a41079f961b4aab45729af4c6e52825690157fb9bdadf90f9607613cefb4b4aa6eb5292af781ba083b75ea3199262db89e3d165790e22d1e23f62e275d8baae7bf2187cceea24df7b00474c0f351fb549b1576a7df513cfcb0f227b5b6f069e787649dc1d37d4314090d3affced52963214829b4970a57bea36208c4a65c496262d0374f666df31862ea75a2e91b8f0c4ad12cb7cab6f708fa8c743e090b2579791eca84cf20528f8ed698b0b558b486d24dfc74e036666da4d2fda23466dc71c0ea94becb70adf7b9e573e589ecd14c72ad4010a2bc5890b693a5cb9d200b1b1b78f2c569061d6a82eae0ab2e479cedee1f214b0a1f0205be18eaa0c68250eeb76fd2ebf52b232e6963700c1a3df953d2b8881e5129a63e848b0490e8b8fa610aaf12a3b90171e3b125972c4384949d44f4bf4c70b8b9a64b449a653a9ccea2147b34a48fcce04ea517ff380d4d9497ca1475ad09005c73000f95f155b16035ee2f02fe849ff000b47021cec970f2bf50005f301556752b90b794faf7691f77483cbe67e4d080298b8597ff56b2fc6a7b3632b47ed0fe12772715f64c6239a8aaaa228086c94b401d811d4dfc3062e38cbeda65482a5bab510db7f8d5e36f018c8cb99a1c463e87ecba991b2b9ad8f20dd735ea99b4c48ed4be0b4e38e9365137bdf0a762853aa4ba7b4524d96a3d55e00741855d43d19c6131d67da57b2ac361e5f9e241dfd1b40caf50add4d6a530c36a5d946da95d123cc9b01eb8ab8b82667f48e7bda19f25b0b7a8a16cd99c29792e297e681267287ec2224dbfd44f41fd8c673ceb9ceb19be71915894b5328512cc649d2d33fc29f1f13cf0cb31d66557ab0f54272ca9c715aadd1291c80f202d6c47c38b26a339a8d0a3b92253cad2d32da752964f8018ecb0f15b8ece91cae7f226333ba8f09ad945371bfc396385124ee71633b906350d4d2f3bd7a24216bae9f055dbcc1fba45b424fa9db0cabb53c844476e8f972a690c2bf68e3f3aca7c7ef000e9f81c5c556d02eae9b7adb1d0bf427e5830a9d6f28d412de8ca6f538a45898750577bd42d2adff00ae1310727546e21d4aa9487feea6734990d7a15b7650f5d070495942ecc87e3af5c7796dab95d048be0a6859868cb023e6ca1b72e3a95fed909423c86fcf61a17f14dfcf11953a04aa7a5b536f43a8c6755a1b760ba1db9e76b7bc93e440c42b89095949050a1cc11c8e1b9495dadf0620e64a41aa70ff00323150655b88f29becdc41fc2a23911b7318ab73265cabe5aa81854d08025c82f447c0b8d63baa1e2950d88f4388ea4d527d1a6a25d2e5bd16427938d28a4e2eac97c568b9a128cb9c4e8f1e74090425a98b4e9534be435116b7f10dc75db00eb6ed204841dc36e2956b24bc98f733e8eb37721bcad85f9941fba7e98d1305ca166aa1a2b344b3919e3fb4481df695d5b50f118a378bdc28919354aa9d2cb92e82b57bc4dd71c9e415e29e5657cf01f9173955325d50cba6ac2e3bb64c98ab3743c9f03e07c08dc6337c4705b9b11034eec558c7c8742eea69d2d2e69284c7d685a8a12ad4855bc3fbfa61a4984dad25ab26ce0d69b0f1fefe9890a355a157690c562924b91240fda32a3ba1439a4f8287f4c31a9e969bd685280beb69606c2fcd27c31c116c8c798dda23b2e960c8269d7a4ad2281d8a24345c059929b9b8f7543fadbe9884a89a65124a0355142813df4b0755bd40daf846bb527aa2944344a9317426fa032549749fde1be23a07e8d8f666b5164a54937b84f30474e5e58e931b05afc712ca493e839fd562e4f8bccd9cc4ca03d4f08b29b9b69b1d03b28b3e42c77406d9f7beb822a756a9f5768a61bda5e4fbcc3a34b88f50701d4ecd2d26326140a4bd20a0ecb5dc0f5db7c7cd501eadcb12e746547569b365034007a1b9dcfd719b3e062efcd059f5bbfd153764cce7fc243bed5faab32110a652a3b288dc5f129462532941205b41fcc605b2ad2c51a088cb98ec82361af9277e982ca381ed4afe034d0802f98c745e158d1451011b83bea14123dcedb8515031e3193ecef05aca94d0483ab6d3e98988ec3282de9412a479fbde2afefc70da9ac06a9ed0500b05a4dc5b602dcb1ebf3d98ad38a74861b6b6bab972e9868a06b2dc792a601cf21a3685b36d45c614435705a0b78a41f794390f9dbe58a7d501e529b717acbf24ef6e7bf327ebf3c1ce677fdbaa6c4a5a9d3095add4a6f6040db7b78ff3c455210e55aa4853f6645b4d80f753cb6c6131a606927924aedfc399e4437f94454868354d8f19a1adc70042004db5247326de7d7cb124ec594b5b66227b55a4d8a9276bfe1187196e9485469d224b861c66068d6e2ac1081b9dcf216c557c45e3394a5548c869f658cd92833ca7bebf1ecc11ddbefde3bfa62e61f86bb20798ed5ac6ccf106c7210cd956ecc9941cb14f4ab3555a2c37dc174216aba879848ba8f5ded8a138cdc418b982241a2d0e417a9b1aee3ae842901d70dc0d8ef603ea4e2b47dc975398a7663ef4a94e6e54b515ad47d4dcf8e18a884e92851b1f118e8a0c58e1ae91b58b24cf93e72b800b8b0940249d8003727066d4e4e4d2b6689243959798eca5cc458fb3957bcd347c7902bebb81b731461c430cb8f924c8be96adf77c55f95bd7075c09c9433966fbcc4934c8403f27f7ff000a3e26f7f2071746b6abbca93e1d708eb59c02274e2aa7d2d67576cf26ea747ee8e6af5e5831ceb4acabc2b729b029f95d35eac54412db4d0802935c25208206c9dc5c922c00f8e2e2cfb9be959032fb73e7b2e29a2a0c30c47481a95624247448001f9628ecff00c47a5670811d9cc795ab14a434b0ec4a8b2a05c68f880523503b1b03d39e001738ed4564f29084bcbd98ab51f2d67cc9c8caf5097fecb3630533651f76e923913b7322fe18a973965f9195b33d468d2cea7623ca6f581ef8fbaaf88b62ff00c87c3367375520668a86725e6380cad3a52b42fb4253b86d654494d8dae3fef8aebed2ceb6f716ea49608d486590e11f8c207fd3e5836d0d04e0ed55ed3cfb0f21d6564389374ad074a81f51be252af9825d6c309ac94ca7190109925203c13f84abef01bdb55f9f3c430438a0a5241ba7755872c3a8d1572d9714d594e362e503deb0eb6ea3c7c3d3048976ba5adc61c9105424b28dd413efa078a91cede62e3cf11dcba6178efb8c3c975970b6f2374ad06c463c90b53cf2dc5848528dc84a74827d06c309257970478b02168cb39c5e4bf49793d93121fef763716ecd7e283b0df97a62378e1c2dfd5370d6e820bb4290bef360dfd98ab90bf541e87a72c533cb179f07f89b1d707f53f3bafda68b291eced3ef1bf620eda144fddf03d3d30045246c6d08f08b3a1ca75df679cb51a34c210f8e7d9ab90700f2defe44e349b903b39adba9d0e47793b8e6971246c47aed8ca79ff2b3d94b35cda3bea2b420f691dde8eb6add2a1f0d8f98c682fb3be66199b27b945a92b5cda54d08021084289ef164fbbf2b11f018c2f16f081943cd8cd3ebf2ade3e5ba2d1e1174782dc35f62c5d292aed10927dd5786272530d49652a5a06a3bdedc8e1a4d60b12c216bd5648d2a037e7d70e10a0a6bb35281d5ba48fefd71c6b0cadeb864f980fd959907553da92ec0b08b856948dc91b5b08006c41beb49e67a8fece1ceb523502a2a03a1c26f10a68ac22ca27c71926dc0da763b7b4e6280e36494dafb83899a182996b1bfb9fcc6216095d88b7740c4dd147f8955bf01fcc63d1bc0e8e1b7a34167647ce547a64371e9b1d4e7fc34d80e676c5679c264bac4f3010f2427701906debea7c7d7166aa237229d1ef7d4594d8f86d8690a831613c8948405be2fadc56e77c597e339fa055dc2c98b1ade45b90098ef314f87157fb4521b293b69d8ab9fc37fa61e50a92513c200056a290916fafcff002c4cd7197a42b4c4602d4a52d208e7fdff00d7031c46aeaf2964e9735bbb155927d8e1dcee091df73e093b79918c38217644a19d815acecfa809f5409c78cf86a12579628ce94d2a1ab44b7107fda5e1b14ff08fa9c08e4ee1e4acd3946bb5b832d953b4f46a44341bbabb6e6e3a0b5ede2461be4fcbb5a34f39be1d319a9d3693242df65c72e4e9ef12520df48ea7f3df0b66ecf31ff59ddac64344ba1ae746d135b4ac04eb57bfa2dd0d87c795b1d6b581a0342e6c924a739e6a343aa70ff284c82dc689558bda4299158b254a09d24396f34d0802f13d4e2b490a1da2d4d254945ee90a3736e97c7cb24a8a89249def8e08bf51e983013d505f1559b09b6fd71aefeccb45149e1b89cf2036e545e53e54adaed8eea7e1b1f9e322a8070b694f33618b5f8cf9cdf021e4aa2cc29a3d223b715f5366ddbbc84d95723a03d3c6f82e503c58a577f152b39073050e4d0abf98a032eead485b6eeb5b0e8040558785cdc79e02a8dc47cd828eacbf4ea652b382d96bb2625c374af5206c0b8d73d85ba0e5d7153d238419d2b14a6aa30a943d95e4071aed1e4214e248b82013d702b53a6d6b2a559b6ea31e5d32a0dd9c46aba143c1408fe5870028e96a5fb3be4aace51a655ea39842a1ae614a9308abfcb4a6e4ad43a137b5bc06331675acaf30e6eab54df51bca90b5a40e80abba3e56c5fb46e274eadf00b31cca82c7e97829108bc058b9da694a57eb626fe97c672a34272a5548f09b763b2e48586d0e3ee766807a5d47dddedb9f1c3b4240f75db2e3b125852416642069525636578820f8f50713ff00a2d52a9cacc395cb8d3904854c8c855dc8aae8e27a968f8f43b1dac7052eb1fae0fbb40cd6c7e8ecf71006e34a72c813ec3665de9ac8b6973ef6c0f8e03287549b94b3337362a571aa30dc536f30f0d9639290b07a117041c49569ed483f4b8b9aa88fd5e88d866ab0d1da5469e81b147590d0fc1f891f76f71b602d16512951dfc716ae7aa57e837e8fc41c8f762953541d4a502e21c8fbcc4d0802a87e1e76bec45c61a662cb1133565a7737e4f63b35347ff36a5362e622ff00e2363996cee7caf8048140d4ba739567571e3906684dda66dbbd6e6907f15b90eb6b73e7196293859971c65d43adaca1e6c8521493b82391189cad45353a57eb1b5203cfbd214dcf68234965d3ba57b7dd5ef6f0208f0c245749c55b301ae654a7c6a8294ba95255d9c77d46e5c8eadf41f34aad6f227133c12cca32df11a03af2f4439bfe19fbf2017c8fc15638aec1df1da5450b4a813a9241bdf96048bd254b70d667b30de9f2ea321a6598d70b71c5694a00c53f9838e88612eb397e0f6ae5fbb2a41b240f240dfe67152661cd159cd935835075c94e9d2d32c206d7e42c073276dcee7177e44e014630da959cdf79d7d60130985684b7e4a50dc9f4b63020f02858f334df1389ff007dd4f2e512d0c6aab9ee2fe7379d2e0abe903eea184691f4c1cf0e78ca9993d8a6e7165a01c584a27b6346951e5da2795b9ee3962ca3c11c8896d4914976e77bfb5bb71ff36289e3470c86467989d4e7d7229325cd0039fe632bdce927ef0201b1f2c691c1c57e8c63f0ab891c3bad54ca5a284ad82952143baa49b83894a27fb5aff80fe6319cbeccd9c1d7952b2d4e7cad2da3b786147702fde48f983f3c68ca291ed6bfe03f98c48d89b100c68a0809276535a52d6b80c25c6ca7f649b5faed8596d5ee09363bd874c7d0d36a6c6df6ec90adfd3153e7ae35d2288fbb4d08020e8ad1aacf6d5a14b0ad2c208fde1babe1f3c34719634026d11f88e95853e0ada25c68924381d02f6e963fdf9633dfda4ea8ed4337d3a03575b71a1a5494277bb8e28df6f1d86236adc67ced396bece54686c93b34c474edf155ce03a7d72a798731459b5094db53d4b6db124a7425163dd51b0e9e9d315e2c430cc5edf948fd558ea25a01e53aadc9a74382cb3446ab549a996c313e3bef7ecdc16ef1d8022e7ee904605e34753ee8420124f80e83051c4535c56729ad665aa3754a846b32b94d2c292a03958d86df0c2d92a2a1540ce338b7a97169e94215f80add4a4fd2e3e38bc39a437a49641c9dfad7539a5f93ec747a6b064ce9405f4362e6c91d546c40c09cc534a9af184d2da8e56a536dad5a94947404ed736b5f172e470dd37ecf19ce7a6c244d98d430473d20a4dbeaac52e94ddc79441b0c184c0d95ca829b90828202d2411e479e39756a5beb538a2b756a2a513d49e7832e17b0d3fc52a03129943ccb9292dadb5a6e9524a48208c11719f85d2b29555e9d4b65c7a84f28ad0b48bf617fbaaf0b743870989a2b4b70af31d3b3164ca4ae24a8cb92d456db90c366c5a5a52014e93b8c575f6b48d4c732753a438eb09aab32c2594dc17168524ea1e361649c65a43b263b816cadc6d5c82d06df2231d34c4ca94b4a007a4485ec9162b52bf9e1fa36a2228a710ead2a351e65290e110a5b8dbaea07de522fa7ff0091fa61ba43264d080223da9a74bb74942c2bba91bdc116defb6f7e98baf87bf67baa558225e6875ca5c456e96001db91e60ec9f8e09ea5f666635134accb21a4ef64c88e17f5491f961fa8709750e155d12ab4fcdf929302ad2998599e8c9d74e9afaf4fb5b23ffe752cfdf4eda493d2d8fab6139db262f316a4feb0d20218a9a00ef49609d2dc8f3503dd51ebb1c16d43ecdd991b20c6aad324abaea2b47ff53819a8f0673fd1fb431a98ebc8582da950dd0ad483cc100dec76d88e98707d0a560a21fb3a5462d59dac647ad9ed29956614b690a3eeba2d7d3e06db8f34e21f2cc89fc1de2f9835024c15ac469248b21e8eb3dd72de5b1f81180c61bcc9936aedcd4c19b4ea8c65ea6dc5b046823aee2d85738e7cade72f65398dd8f29d8e0a50ea584b6e693cd24a6d71c8ef8770b292b0bed0dc31465c98331d01b1fa1662ff0068da3dd8ee2b716fdc574f03b7862accaf352c5417164ba96a05411ec9254a4ea4a12a3b2edfba6ca1e983d81c67a9af2afead660a744aad1cc6f65b28969ed20774ea1717164ef6e98aa1c2359d8efcf0005271c6d3dcc14a9544ac4ca64f4689515c28581c8f811e44588f23860855f05d9ba6ab3050a8d5a580a98c3029d357a85d4a47f94a239eedd85fc5380f4e1d204dab67ecf1424d6b88b1a4c84a3d9694d194ad4362a06c9e7e6a07e18d475ace596e8c8d553ae4062df74bc14aff00da9b9fa630736b296d5675680bd84d0802a41201f5c5ab95381b5fad448f39f994d894f780525d43a1e5107c9171f350c0385a62168acb7c43cb19aaa2ec1a254d2fca420aca14da91a923991a80bdb11bc66a3b35ae1d56997477a3b2a94daadc968dc7f31f1c33e1af0be9391e5ae6b12a4cca8a9b2d29d72c94849b5ec91e839e1ef1a2b91e87902acb907bd3185446500fbcb58b7d05cfc3118e7485663e0a3ce47e27d014c83fb45a90ab75494aaffdf9636a51143da55fc07f318c91f676a4aa7711512ca4f614f616e2956d8295dd48f8dcfcb1ade8e926528a522da0f5f31852ba9c9c854371f338cf8fec195e98f9663b90db725a906ca55f922fd058027c6f8a4e974c7aa7558d029cd15ca7dc0d369f127960d78cc8718e244f2e02a4a9a6549fe12d2797d7035956a1fa173751ea4e1b222cb6dd5dcfdd0adfe97c101414a34acb7b801980450e2275354f69bf6254a041f0bdad8adf35651ace5a9023d7a0bcc6b49ecd7b290bf450d8e2fce337146ad9666c3879762b6a69e643fedaf36a536b0770947206c2d737eb6c54d5de29e6bcd1497a9b3e253a64558dc221a8a9047250215b11e3870ebe530b55b3c84b6121b64a3424256abdf51f1f8e08b2866166910ebf4f9a93ec35882a8eb504dca1d49d6dabd350b1fe2c0ebda9e202edaadcc61000a4e955883b607ba93908a32f66211b2957f2fbee111e729990cedb21d42b7f9a6ff2181569760e8b12b57bb6c7853a4d08025764efb5f972c26a49bdc83eb6c103a4aa94b502b9328799215662259f6a8ae768da5e4dd17b5b71b62d24fda0b33f60a4c8814477c52b6d7df1e9aad8a5420ad56482707194385b98b37c254ba3b7156ca55a0a9c9094904795efe1d30605ed46ea3ca9739eb294e965fad640a738e93752a14c71804ff0f2f1c58593f8c7c3da0694c0ca6fd296aee97194a1c51ff55f562a68dc2bae4fa8c881489747a8cf6012e31167214b16363cec363816ccb96eaf96e5a62d721bd11f3ba52e751e20f23f0c1f2a33b5b163f1bf21bad25c5d61c609fb8e4672e3e40e3d778db905bb95570abaf763387f96339f09b859ff0088147a8cd45723d3fd89cd2e36eb4556494dc2af7161cfe5898a1f07f2fd72a8aa753b8874b7e7a49019447512ab7e125402be17e581e96a657548e3c6426d0149a9c970dbdd4c473f98c44c9fb45e4e6ae5962a920df925909fcc8c665cfb418f963344da2c79e8a87b22fb371f437a06a03bc9b1bf2371cfa61de5fe1ee6acc54e13e8d44932a1951476a9d2012398dc8e5b61fa02402bfe57da472d84a928a2d4a424fdd77b303f3380fa9f1ab27d45f509fc3c88fb479a94a6f51ff97f9e00d3c1dcf2a5a42a82ea0ab6016f349b9f8ab08e5ea353e453b30d26ad096c57a332e3b11eed140871add6ca93c8dd2156f0230830764f41279eab9936ab1db5659cb2fd1e5a9ed6ead5254b468b7ba94dec37f2e980b51f4d0802da5c136bed718f95a549373a54000001cf1eb6a55c03de1d0619185c04ea55bae3e29db6bf9e3b4049594d8dfa6fc8e3e585037b77af638492e50b2058f2e5be0832b66dae656794e50ea2f45d7ef363bc85faa4dc7d30ce244554a338184032a3b65c291cdd6d3b93ea91bf981e588b40ba8026c0f5c24bdd5a5238e19cdd8a1944a88caad62f37193a8fcee3e9812a9d7f31e6f971635467cca9be57a58656abd94adb61cb13bc2be1f319ea5cb8ee55c417a300e16fb1d6a71076ba4dc0d8dafeb8d0d92386397f27c94ca8a87a5cdd36f689041d3fc200db00e70621d0292e16651fd4ccb622ad4daa7c83daca700e6ab6c91e405edf1c591969e529e373feecee3aee30c1f4b22cbd22c3a5b0fe85a0ca568040ecef61ea314cbba8da5d9517f687cb4eda9598a3b654caa3a23c923eea87ba4fadc8f8628f712142c3dee871b9a4c38953a30813994bd19e6421c4286ca16ffb633e672e07d5a2cc79dcbae37362a957434b7021c4791becac5a089aeec508e52e24e62caf4ff61614c4ea62410224c6c38845f9dba81cf6bdb0eab3c58cd35284ec288e45a3c0713a54c53d84b57079efcfeb846370a73b4890195515c6c03badc710123eb819ce797e4e56ae2e9335f6dd9486d2b7bb337082adf4dfd2df3c49a013e8943c5b2e3dd9b7a97ded29d2375780c376db2a717703ba0ed8b038574b1327562a0a48526934a9335371fef34e944d08027c8aaff0c03328ddc039945f1101b461de8bd850df972fd9e1b0e48796ab21b6d254a57a0182a87c3dcdd2d650de5ea9dff7982903d49db135c13425bcfd4f438f3918cc43ec36fb66ca415b6b01493e37e58d3315aaf51a451298d37fa5a9c96bb3995290fa50f02391d1f7ba5f7bef8323a5039f45638cd793eb1952a898b5960c579d407529d415749f31b78e0da89c1fccb56a2b556cbb53a5498ee22e95b121695dc0dd27ba2ca1d462e2ce5c316eb99764418f569332a71df54861739d4b85bd42e5ab800849d88bf2c52b4d6f3e70f2aaea29d1ea115c51efa12d76ad3be6458a55eb891a6c690f55a11c9b946bb5bcd6cd1a9a170aab671454fea6b40483aae40bf88f8e13cc997ea28ab49a5b72c5625436d6f3eb8ae29c6db4a05d7b90397538b64cfe2bf1007b1f62b810d63b375f31d318683ceeab6a23c860de9d9220e44ca53e9d120caa9caaac290d4da92027f65fb3569045ee9413e17e5738575a2849b59fb8662ab53a6e67cbd440b5caa8c24ba1941ef3bd93814a40f54951b75d36c5c54ba2d53302f25ad394dccbad65d4a1e973e4361b5bc5b1729401ba81b13bf8fce9de06cf34ce2ce5e709d9c7cc73bffc44a91f9918d739bf36516244aa535755868a9a61baa118ba90e5f41b0b78f2db9e11241d21fa2c315a96e546b53e63cabade796e2b7fc4a27047597b32c4caf979c72a6f1a43a8717111196a4a595055964d080215603bf7b1e679e0413771e5274a94e2cd8002e6e7161f0ab8952f21c97a2cb8c27515f56a7a2ac0ba1636d48bf23cae3adb06e3d930e1279ba3e79969a2d72b299f247b134a872db46ad284dca6e53c9439efbf538b6f2370f1dcbf4ca966fcd9359796aa73cf84824a8a9c6cdd4b2a037dc8b789c4e43e3d64931038a766b0bd3fe47b3124795c6d8a9f8a5c54a8f1094dd168911e8d4a5b89b3406a764afa5c0e9e007c711824e9172502650cae7312a73afd462d2e0434254f4b9415d9a4a95a529ee83b937f91c5a0df00d2c086e55738d2a3b129696d8521b27b652b90415100923962cee1c651a8e4dc80d42851a9f26b72dd4c99916639a4141b02816bee05b722d72706f59551de954ea3d5a965f4481a99bc52e32d293c81501649f0e5cb005c9ecac4d9be80e65acc955a3beb0f2e13bd9f680690bea156f3047cf10ce256a68381b50403a54a03bbabfaff004c18f1924b72789b9994d9053ed7d9dc7eea424fe4712b128ed35f67eaad565274b922b4ca22923ded09503f452be5892f48ae820aa2497299261d5994057b2c84eb491749ea01f220287c3129c47a52699991e762d3cc0a64d025406caf582cab9107c39edd2f84e932194e43aec77903b554a8ab656472235dc7c89f962573f4f765655c8f19f6ac18a6b850e9e6e02f2c01f0091f3c32495e0c54d54de20d1969274bcefb2afcd2b1a47d6df2c6bd6d0e24a92e104d080253f77cb18ab87a871cce5466d9bf68a98c84d875d631b6dc1ad4a36b006f7c472042534536bb90ab69230fe80344a5a6e2da09fa8c2170a3b1c3fa327fc5aff80fe6310060074912bd8a2d0983ab70848fa617beb1b0f9e1bc655a2300dedd9a798f2c288eedcfdd3bdf1202109b052a9041b6314710e69aa677aeccd57ed263801fdd49d23e80636c0f5f3c61dcd705da6664a9c27c1ed5a90b49bf928fe7fcf06368e3e558ff0067c8ed546979e69e143db24d2b43493cd49ef5fea51f3c534d1ec9fd2e0ef27ba411cb059c27ccdfaa39fe9b51717a226bec6413ff00095b1f96c7e187fc6acb68cbb9f2598813fa32a004a8ab49ba5495ee6c7c8dc7c461c23e0afa86c38ac969af52d7a6ad97a7053a81ccb2b50285fc15a927d71a1327e669959a64ecd5166aea74e75a045158613dbc57936d4da5448d439f3e7707198b87f989bcbf5eed27345fa64a6d5166b039b8ca858dbcc6c4798c15536b750e136730ec177dbf2fce09753a7dd9718fbab4f82c6e3d458e0cb6c2170b5a45d9145a455589e63b91a7d6d486d4b0d2fbe427bbda5b649036b9f4c34872aa70e9a95c191fad5ae7a92e38da9a64c76efba76365141dadb1c345e70a6c8a444ce30ab928d0109ec9f86cc70e6a528dbbe00d49527d790c3ea64155226414e52a6d391419aa54898438a42c2962e1681b8df6b8db11f081213e5542b226879da865a4d1e5f6a641095b4d080252d948bea3fb877b8bdc5b08bcfe59865dae4779c71acc611195219ed1d6d64a4a52a205c236b8bed87aed5e465a65a6b354c350f6f9bd84776343290d255eea5cb122c396ac235247ea9d4a7e629b5698687d925bfd18c470b4b4a2400a4048bee6f7fe2c24cb11adc7e8d5e4b8d2b4498722e95782d0ae7f318b8dce1ae67ab658a94dabc089186a76aee5494e25d7a4ddbba5b401b849dc9bf538ad38a50bd873ed71a00f66b94b7dbb8b771cefa763bf250c68cab715e9342c9b41a5aa148a8ae4d21af6b2c280f666d4d845d57e6796db731be2724f64dc959528f33d82b5066dafecefa1ed3fc2a07f9634ed4321e52cf99c6a8ec8aaad732446665c6661c711c36d285f515588749dae7a632bbe121d568274dce9f4c5a3c3ee33d6727d00d2131234e8e80a31d4f1505324f416e69bef6f338675f64cd348be8dc14cbb58add4e0d3f33cb5b94d73b390daa0e9524f9126c473dfcb07f9332753f2fb9598196297261d72284866af568fdab6e83d5b22c00e62c37f1c0ad338a1033ac2a3b150cccf655ab46752ec9521a019936e81649b7a1db7eb8b332fd3171abb35ca34a4cfcbd55429d7d6b9ea75c6dd3ff0c0040491e63cb11127ba3b5215083023c66f31e62ece3d562452d3b3e315fec92459561bdc5c922e0db1e4e952e8f478758fd3acbf4685114ecb53ed02b94026e9585a4800f2e9637c34a14aa750e8d53a665a79cac44d08028a5bba5c88fcd1da35a8ee92b5f2005ed7f0b5f14471f33eb1549cba4502a128c25a5027321692c6b4f24a2d7e5d4836270c059480b552c975fac55df7acb724cc7ca801cd4a5abf3248c5c5c745b395f2364fc871ca7da63b5edd348e8e285bf3d7f0b606783102042972f38661ba6914401c6d24ff009f279b6da7c4ec4fc301f9bf304ccd398e7d66a0abbf29c2a09bec84fdd48f202c31223e545adf598c966ffb24ab5916f78dbfeff3c19f12935681fa0689578edb29a7404060246eb4b9df2a27af7afe96c79c26ca8f666ccc871c4a452a9a3dae6bceecda509df493e645bd2f880ccb5a9f982b0f4faa4a5c990a3a42d479247203c874c3f291a45fc07a77e91e24d34a924a23154855ba684923eba71af0916dff002c519f662cbfd953ea15e792753caf6666fe03751f9948f862f250f2c4521da0499012bbf8f41890a41ff14ab0fb87f3188f3b0f1c3ca328894a1fb87a798c4692558b188ca77d909e9e58eae54920917036046136140b0900dca523e38eb51b8501b5b7181624ed709468dd36bee39f9e33f7da3727bad4f466586d12c3c94b724a47bab1b051f516f962ff00364a86fddc2753811aa94f91066b49763484143883d41fec7cb12b4d2606b6b05be8bf7873bf2c4d2f344897955ba0d4d1ed3162afb586e93fb48c4fbc907aa0f81e446d821e286419b936b0a49497a98f1263be06c47e13e04600169215749b6d4d0802e1892bba96ed24e1093dd3e63c713712be1da31a5d46ef450bed5904d94c38762a41f03b5d2763e477c4158157785b6e9841cecf4f3255d41c134d24768ab28e6dab64cac7b6d1248495775d6563532f8f050fe7cc62fcca3c56ca35cac3152ad1728b987b0f6525c71463ad37bec47779f2b8071948950b80481cec0e3a2a584f7966dd124df04e01c80adb541ad1a30659a85795995552987b1723368223a0fe2d2a3dc1e3d312adb350a05027b91ea06bb2cb8a718135f6d94827fddebe400df9e30725c5a07754503c8e3c54976d6ed5453e1736c0f9482c2b23ed0ae2a467e448744644a7e130e3e88cf8790972c414858e76db167655e10c7cdd96f2f5613597e2c7954e65a9b1d0deaed422db055c5afa53d3622f8cc8a5952bf2be35fe45ce2c656e19e4da7478126ab5ba846bc6811ac14b1a8f7893b24799f0c13ada3490dace9c69a0b39778935aa7c46c351438971940e410b48501f0b91f0c035b717e7cf17271f65c5cd2aa466c8119c8ca7d2e4198cac82a69e68fba48e7dd3cfc060532bc4a7cca11830202eaf9b6a8efb34769493a21b42c7b41e2b3bee764817c2f74246d03816e470f224d971d47d9a4beca8f3ecdc29fcb16467ac9d47a2b948ca5416dcaae715a93edcfb6e12da167fdca53cb6ea4f2b7c94e21f0d69b936994c86babbd37364c28bd3d86c142751f1e7cec0789c35828802156aa9925c539da497c973f4d0802cc2564ebf5f1c24122dcf6f4c58d9f784f3b24e598b56aa5561176414a443485769acee520f23a7a9f2c56e906e2fd7c70ad48d4f173a5bf01884b7dc30d851536c93dd4957336f13fcb04192328bf98e4a9e7de6e9f458c7fc6545f212db23c05fde59e891bee31c18d49a04c8a9aa45915393d921e7a3073b06db2a1a820aac54ad8a6f6b73230d330e62995b296d69662c06bfc883153a18647927a9f151b93e381e53fb222cdd9a623119ecbb925c7e365a06eb52ae9726aed62b73a907a0e400e581fca74099992bd129701b2b79e5004db6427aa8f90c239728551cc75466052632e44970d8048d923c49e8078e35af0b38790f23d38ad6b126acfa6cfbf6d923f0a3cb95fc6d844d0427489f2f51a365fa243a6421666336100dbde3d547d4dcfc70fbe38ed4ae86fe18abeb326bf9b2bd51a6d06488b1201d2a585946b572dc8df73cbd31012ab4f30885d59f45659df6c38a42cfb6ac023641fcc62b5e1fe61a89ab4acbf9815aa7300a9b7147736e6927aed637c5994940f6c51df741fcc610450ce2567537eff0044ab49d2d2146c3ba06dd70aaac6dd41c26d6eda072213cb1da492a283d395b0e029526849dd1f781d89eb851926dbdee30c2bf5883428266d45d0d360e804024a89e800f8e0159e2d531551d0b852111af60edc157ae9ff00ae15aaf36545110d7b80255815aa642ad535d81538e99115d165215d3cc781f3c6694d0802e20f06ead4679e934369ca853b752740bb8d8f0501e1e231a7204d8f5088dc986ea5d61c4ea4a93d70e072befe5836ba94cd76ac6c2fcff931d6c294979b28524d94950b11866f7662fe36dac317afda8ebd15eac42a1c36d9eda3a7b794e2503515abdd493e42e7e38a256803b88f788ba89c4a3e2da96f4923de20db9240e5cad852044933e635129d1dd9329e569436da4a94a3e40626b27655a8e6daca29d4b424048d6f3ee1d2db0d8e6b5a8f20317465e9d0b2aa5ccbbc24807306667469975a5b7fb26bc4249d801bdb7b7ae1c9a4c7486a93c134d32022a5c46af43a04555888e5414f2873b6fb03cf617c48c2570ad978c7cb3936bd9aa437b76b65e859f9ff00f5c58995f83b1dd969acf10263b982b6e596a438b3d8b4ae7602fdeb7c07962d24b712934f5f60d331a23282b296d21094802e761e57c465c4a03be160aceb218939a67b91e8c288df6ba44117fd8690014ef6dee0dfd71a9689c3f7aa997b2555e0d6e6d1aa70e9488c571d2956a6d42e47786c7bc77f318cb92d6731e73ed145579f30ac802e4768e136fa8c6adace61af3d9fd3923273b0a9ed52a1a1d95326361cee0d200420daf6053f33b8b60dfc2434a2f8afc39a7c3e0ecb83446965701dfd2256e2b538ea80b38a27c48bfcb19e78799c5ec989abbf4e8c955665b023459245cc6b9ef280f122c06355644add42bd51ccd43acca85578d08219f6e88d766d4d0802bbda27bcd9009171bf238caf323c9e1c7142d2580e9a6ccd610b170eb57b8e7e29c269ec520adecbb1a0f08320ab35d6d025672aba498cdbdba90542fbdfc39a8f98187dc08c953aad56733f66e2a7e648257103c3727976b6e800d923c37f0c0d64e813b8dbc4d935dae2168a053d42cc13dd0906e864799dca8faf962c2fb43e7a4e5acbcdd068ca09ab5411d9e86c6ecb27bbb01c89e43e3803774112a478f99bc66fceeefb0a8ae974c1ecad287baa55cea58f53cbc92301d93e0333f30c54cbbfb0b6aed6491d1940d4bfa023e385f3740fd00b628a5695cb6521d9853f75f50ddbbfee0b0f5270ea330691921d9abba5fab3862b23af628b29d57a15684fc158900a4e144e61a93d5cadcda83e2ce4a74a827f08e413e80587c317764ee00b4f330e6e61aaad4d3cda1d5458cde9235241d2567c2fbd862a4e1e51cd7739d269e91a92ebe9d7b7dc06eafa038dbe2dc811b0d862291dd291b1a51396f2dd232d421168905a8ad7ded22ea5ff00128ee712c4dffa63a1b73e58e40569efdafe588aed09e170ac56156899972a662a85472f44f6d8538f68e37a35693cec40df637b11e38b354a16b8dfcc61bad452ab127d4f4c250cb08940b34557d90f2d55155a7b31e6225335d074347de04ed723a6c2c062d5a36f2d76fc07f318864ba01b13bf4c4bd0cde52cfee1e9e630e0228a11137a5bf72ba477129df7037c2c149b8015b9e4064d080228ee2a56aace66c7692c3aea63b61096d96ee0ac917b9b7337fcb10902b799b28cc1a9525a413de624215a543d0ff2c302b35fe28d6c85a5a681a2516f1fa4afb6a3c504e9d2e3b60799b81fd7e7822a470da8ec659227b3dacf759d6b7ca88ecd4537ee8e5b60038919922668a7d166c5fd948694b6df649b96d47491ea0db6f4c59f9db318a6640449d6049991d0db43f7949173f0049c255c18a592491f44002bf087b81539d760d521aaea658712b41bec0aae08fa03f138b2aab399a652e54e9474b11995bcb3e491738aff008174e723e5f992d6086e53ff00b3bf509005fe77f9639fb44555ca670c66a195695cc75b8c4fee9b93f9609a2d68e082216daca799aaef57731546ad2f77253ca7adcf4dcec3e02c3e18ef2ae5f99986acdc0881295b9753af2cd911da1ef38b3e0073c43955877bdd27a7962d085064c4a551b28d1d5a2af990b6f541e02e50d2b7435e4027be7c49c59ad2bb68832c50559b96acaf9314ec0ca51143f49d54a6ced41cfe9cf4a7901b9c680cb597a9796694d53e8715b8d1d1cc24779c57e251e649f1c2b95683032cd12352a96d06e3b29d8f32b51e6a27a92702bc42e2865fc8f20459eb764d4149d7ecb1802a483c8a892026ff003f2c424971d2624da3fdadcfe1e18af38f598d197787150b2b4c99ff00e09900efdf0751f826ff003c09d1fed1196e54f4333e9f5082cac84f6ea297128bf55006f64d0802f4be2abfb406746f3966d662525f1269908764c29bdc3ab55b52878dcd80f4f3c3b186f696979f671cb6acc1c446673a8061d2c7b4aee9b82be4d8f9effe9c69cccd9132c57aa3fa4eb74d6de9486f429e2eadbd481d15a48047ae2b9e11063874fe5dcab3a2ad55dcc485cd94b26dece84a09423ccf74dc74270313e75727d638b796a64d90f21319e98c36b55f4842d3b27c0141b5b96d8775b8a6f75773157ca99619a4d3623f4f84dd454110588c91a5e27a8d22de1de3e3cf1537daab289974c8599e1b64bb147b3ca291feec9eea8fa1247c462b6ad57a32b87fc3990ca87e91a63f2127c4250f25607d538b469798a75738e35ecab5a92a91409b19c651154068427b24b8950f3b13bf9e040e9368aac28dfb33e7c81032c55e8f524b6c2a9cdb95042d2002eb63df07c5436b791f2c05e5ca8b999336661e22e61405c1a40f6869a59eeae4728ec8f21607fd38af335525dcb79866c06df4bada16b436fb4bd4979bbd810473b8e7834cf79868adf0d32b65ccace1531654da8150b2cc8f76cbff009ade40624af44c0faaaf66c97aa550764c85a9d9721d53ae288f794a3727e77c4b668abfe925c0619496e2d3e2b711a413f87752bfd4a2a3f1c49f0b2237fa5a7d6a5b61c8b4688e4b5a563baa72da5b4fc56a1f2c08ead6e5c91e26c3061103a5797d97e84a935da9565c412d44603083e2b5ee7e401f9e3470680513a6de7808e04d08027504d078774f4ba8289132f2dd07982af747c13a7e6707d7b8eb8a52b5b21da7ba4895002e2e7c463d55c8ef103adce29dcf7c74a7529d97072f43336734a536a7deeeb2950d891637558fa72c528fcdce59e26bb24fe92a8ad292b2194ab43691b9b01b0c491c247cc84ba96ca3dd51f03cc613751a81b100f3dc73c67fe09713df44c672d66278ad95abb38b25c36536ae8dabcba0ea09c68302c4df98d8e19cde92903698ad9d20588d5d6d895a12ff00c42b573d07f31864e800ded7bf9e1dd1bfdad5ccf70fe630ddd3aadb8c7449716744ccb4e07f63a50e94f34107baafe5f0c4e5233a50735d2110eb823b6f389d2f32f1b26fe2927c7e988ee36d6e5c18b120c65e866505976dccdbf973c05d3b87731eca6f56e54b6a3252c97db6940a8a936bdee395fa61b85cfcd298b21ed8db762c85179ef2e8cbf551ec6f264d39fef30f2541408ea924751fd30d6bd5d935b6a9ccb80a5b871d11da6c6fc858abd4d87cb1109716f252dad674837093e3899ca55a8b44a87b5c8a6353d69dd0975564a3ced6e786b59064ea7903e16bbef48a28552cf74ba5a5f88cc8fd191d1ab43aca4a4207aef6f4c0d71c33c3799b24532396bb096dced6f22e5492342ac41f5e98b12a1c6261fa638cb147507dc4147ed1c0509bedcadbfa62a1cf39625b7c3b5660923b36bdb5b69b414eea0a0ababd390f9e0d9f305ad89216c8d644e2e1defb2af72a4d0802d28d7b35d1e94dd819925b64927a13b9f95f174f0dd4ccbfb4454d45612965b9498c850fc27401f04dfe58a2e85545d1abf4fa933bae1be87c007f0aaf8b53f4b46a1f1de0d6db3a29b2e5878384d8065f1ccfa6a3f2c59ad15bc168dcf99899ca994ea1587b495c76c86904fbee1d923e76f80c655ca594559e0d5b33e67ad374da625e519339e4ea2a74efa522e3c47f2c5f7f68fa6bf50e19495c4b94c779b7dc03aa05c5fea319bb2638e56e8937283950661892fa26445485e8695210082851fbba92763e291e3818c7c291e538cf9c3cfd03488b5da4541aab65f9474b731a4146956fb2d26f6e47041c1ccbf0680e319df3aad98947615fe090f83da4877f121037569f4b5ce2c566552783bc326293998b759a84c5ade14eb85b649e82e0808046e6db93b633f666af56f3cd7152a421c92f9d998ec2094328e8942472030e2ca5c23be21f149798788947aee5080fb5329cda99654ea038a7afa803a05fa28d879e20aa3973889992a332b732975432250b3ef96c30149f023ba2d6b7cb12396d9ce54788da698ed172da148b3921f7e3b2fafcd4a51539f0007a6139d457aa8bd799b89d4c709f1912255be49b6100024802ab45a952c844e6741bec03a95f3fe12712197735d5681980561a587e6f64b64aa482bba4a341f3d86c305b1322e4f75690e712e9c951ea603e3ea462073f658a365e6221a4669875d5bea505263b4a47644d080291d4eaf1bfd304404db08ab87d41a767ce1c4ca0c579a6b3653e4392e1217b17da5245db07aee0fa1b1c55329a763b8a8cfb6a69d6494ad0a162950e77c3acb51aa532bb022d10ba9a93ef25b8e5a514a82c9b0b11cb1a3f8d9c23556171ead459308d7fb24a674553a94192b09035a6ff007bc6fcf03749c6c5acf94dcc2fd3f2c5528ad32d86aa0e34e3af58eb21b2484f85ae6ff0c3de1e52915cce948a749536db322423b42b5048d17b9e7e3cbe3886ac52675167bb02ad19d892daf79a7536230be5c7e9d0eb3164565891261215a9c6e3bbd9acdb9595636e987ab09c696f6424240094684a4580bf2b72c740d8efbe04b86f9de1676a5bd221c49311519496d6d3fbf31b10ae4791f960bbc31548a28f45641cdd4cfd41e2c972a509b9b4e32bdb1b6dd4dd2f32a513e971b8f518d65419b4faa50e24da329b301f405b5d9a74803d07223707d0e0178e1927f5bf2b17a1a3ff0035a7853b1ec377536ef37f1d88f318acbece99f174daa0cb35373fc1cb59f67528ff0094f7e1f457e7eb898fc6db41c14e3ed0b908c596acd14760263ac01310d8ff002d77d9cf43717f023cf06bc16cfade67a2a69f3dd48ad424042d2a3bbcd800070789e87d2f8b3e7b0dca8ee3321a4bac3a929536a170a079838caf9f32ccce19e738958a1157b0f685d8c49f76dcd957c3e6309a43c7494b8dad3cb502373cfa61d500ff008a5a57b1083f98c04d0802f654ae45ccb97e155610b34fa2fa49b94286c527d0df049471aa62efb770fe6310f0511da1de23656199a9e9ec34a66b24a99528ec41e6938a49d9156a0bb3a9aea9d616eb5d83adba76d17bed7f1b731d0e34cb89d2a5824edb9be33166c9c6a9986a1315b871d568df9241b0fa5b02e34b07c5e36b2a469a71fd943026e49dcf962ccc9b3f2745c90f8abb0cb95605cb25682a52b6eedadd3d7cf10dc31cba9af662b4a68aa0b292e3a0f23e09f8ff00238b09ee13519c78a99973596caafd9dd2a1cf90247f5c20150c3c599cd3230037ea81f8470933b39b6a2cb4b61b6d6e2d2ea358b721cfadc8c5adc56a21cc5c3facd39b482f763dab22df7d1de1f911f1c3fcb79729b97595b74d64a56b165b8b56a52ade27fa62681db7c1b74b770314e3c74ee4f2bf3b9e46959bf306df2c1b65f7066ea347a1b801ac4342840513fed2d7331ff881b94f8dede1891e3964c772b67196e34c9fd1939464465a47746a37523e07f318add975c8cf36f475adb710a0b42926ca4a86e083f2c5b69ee15be395a3385fc518dfa3ce53cfe7fc39418a896f0b774edd9bde1e015e5bf8e05f893c0fabd25e7676576d555a539df436d8d4eb693b8d87bc3cc601331e70566869a7aab1194d65a4e85cd6469f691fff00a239157ef0b798c1470df8b558c9e13152a13e980dcc47d5eeff00e9af729f4dc796174776a7bb55d54691598a8067d3e7b491fb304d08025e65400b6f61718605cecee9eccb771b8bf3c1cbb9933b66fcc951a9d25fac4878a96ef63154a5762d6ad8048e82e072c4cf0e2b359aee74834bcc8fb7269ed2cb931154650b4b6d2775df58ba7e639e16d2e368428d3f29b2847e95a254252c7bc5b9c1a07fe4383ca356f83c74267655acb64f357b676d6ff993f962d27f26706330d4d2cc2914f44b7ec94330e6a9b0a2795937b5f1f4efb37e537428c4a8d5a328f20548700f9807eb80eb6f74f4a3e8396b82398dc4a603a861e50d99765b8cabe4a3f9633e71362d369f9eab30686929a6c67cb2c82b2bd93b1dcf3def8bd66fd99e31d661e65747825d8636f92f19db3152a451ab7329931252fc47d6cac91cc836bfc79fc709a41e0a675a7997a7d468af5a9ae1872e6a0369936d2a4b6a36eeab9a6fd48dec316e71238133e854135ca5d4dcaa2d96bb59a87400e0b0ba9683d40df63be0427e507b31e4da557b2b25551721454c5aa4440bbcc2d17b2c239a90536dc751895a1f10f3fd6b2dab26d36199badaf65ed4b0a2fa1b3b692bbd86d717239611bec8855209a855dead6510dd52438fcca6c84a63b8e9d4b2cb80dd1a8ef6494022ff0088e20e9cdbeecd8cd47415beb71286d16e6a2761f136c16678a2b393a0374171d69fadbe52fcf2d2b5263817d0d03f8b724fc30ff84f94b34cfa847cc940a5b331aa6c84a92990e0425c50df48b917b6de982ba4cb59e535d51dcbf04d08029798223312a7d9e979965574a48d85be16dba5f126b525a6d4b71612948ba94a360079e0038bdc435e44a3435310bb6a9ce0aec42f76db29b5f55ad7e7c86283127885c5d94a6905e93110774a0062337ebc813f338ae197b2889a5a269dc4fcad3f353740853cbf31c5766db8da6eca97f842efcf149fda1f273596330c7af52569663545c2a2d215a54dbc372a4f91e7e4709669e1854f86946a6667667a264a8b2db5be86dbd28677b820dee45fba761cf02fc5bcf4acf5989996db2b8f063b5d9c76546e77dd4a3e64fd06256b68db5092b45706b3cb79cf2d2532de41ac4301b908bd94b4fdd72de7d7cc608337d0a0e60a24ba7d4c0f667504ebeada87258f4c63ecab3ab39566c0ccb018750d25e2da1d524f66f103bed93e847cf165f1378c4acc1436e9d4169c88d496409cb5fbc09e6da4f878abadf0c633d56d4fd5aa525c08aa2a9199ead951521b9313bcfc775a56a49526c0e93e0458fc31a128a6f316477bb87f318ccfc01ca751915f67313a85314e612b4b6a50ff003c91a6c3c86fbf9634b50d25335cb7e03f98c472d75693b784f6602a4b846d706fbe326bc34ca743809b13b7873c6b751d4920edcc1271956bb19506b7518aea6ce36f2d3f5ffb620256178e3496b4ab9382114232c48925235bcfe906dd123fa938b0fa73c00f071e4af27342e6ecbae24803a937fcadf3c1ea4f5e5830b4b00018ec03d17a078e3e514d0802b0bd89e9618f89dba63c27c4e1d5b5119b72d5333651d74dac31da32a3a90a1ef36afc493d0fe78c9dc4ee1555f273eb92949994b52bb925b4fba0f20b1f74fd31b202b6dbc31e38943ccada79095b4b4e952142e083d08c48c796a62db5f9dca459442ae93cef8e013cb6d43adf1afb3bf042815d0ec8a29fd17355736482a6947cc731f0f96333670cacf65ecd4ba0175997506d686d45824a75ab9277037dc7cf165af0e1a51914af3fb2bc34d0b2a663cd93fbac805b4a88ff0076d8d6bf99b0ff004e28faa6655d51ccc75094fbbfa4aaae8b009ee96cab52813d3922c3cb1a178b09ff00c3de00c2cbcc14a65484b705c5245b51502a755f1b1f9e33ccbc9b3e054f2f42714dae4d6596de650806ed8717a53abf3f8e05a6eca73e8b89396ab5963f572ad29a11d55029930825c1da1095021440e57dad89ba9f12f3e4fadd4108add49a71d757aa3b2ea9294589ba40bec06ff2c14fda51b70e78a1d16981e90e52e90cb290d825434dcdec3c80270f3ecdb498954a467a93398664c8441b36b75214b429497495027704db9e15d0b495a7f673ce92b356487d1567cbd3296ef64e3ee2ae5c6c82a4a944f516209f003033c66cad9573e4d72465caf52066865365b024234c948d8026f6d63a6fe4719ce9d992af4aa2d46934f9ce47a7d42ded4c200fdadb95cdaf6e7c8f5c2ce50cc6ca34ecc05d0b6e54c7a216827dc2da50abdfcf5f4d0802d30c194eb4fd569fc74e6cc81572fb48a8d226b474958051abc8f450f98382697c60cfd578bec2c4a4b2b786952e1c64a1d73fd437f95b0d6abc68cef3a1370d35444788d8094b6cb08d92058024824e1bbf51cff46a3335a7deaac2a7542c1125090da1c07716200e7bf2c173ca56a02a54795439b11dcd9125b66527da0b055a5e7117e649be9b9bee45f0749e38d660418d032d52e9b49a745484b6c84974903c492373d4db0139c73139999fa5ae717dd95162fb2b921e73529eb29452a3f0501f0c5d75dc8d979efb3fb754a453d866a2984d4b76426ea5a949f7c5c936befcb02e15ca4173c6e7ce7ae10d073640688447795dbb60df4055d24fa05247cf167f052ab02afc36a3b94e65a6032dfb3bcd369b04ba8d947e3b2be38c97133bd7e264e732cc49c5aa4b8b5971a4b69ba82b9a4a88bdbcb164fd96b3418198a5e5d90e5a3d4125e641e8ea06ff003483ff00b4601cdf869383b5a3735d1daafe5ba9d25db144b8eb6924f4511b1f81b6319e4bc8d56ccb9a954461b536f30bb4b52fbbd8202aca51077b8f0c6e0b8b0c5239e52723f1a28f9ad002697590214d206c959b2751f8049ff49c046ee42723bab226e4ca339924658119029e967b340d2352556ff33f8afbdf149d1b8052915261559ab30e424af53adb28505aec7902761716f4be2f0ccd9ba8797dd43157a9c788f2d1ad2dad5de526f6b81cf9e19d0f34526bcb7d4d080234d925cec6da94a6d481bf815017c087380d27a0a463c5620c3623c4692cc66101b6db40b0481d0624a84b0a94bfe03cfd4619b97b72bfa61b53ead0a1560c590e94bea60b9a12093a7501736c477b4488d6428124edd77e58a478db484c6ac31536402dca4695dba383fa8b7cb13dc60ac55e03adc380a221cb6d416509ef5c1dc5efe9f338ada2d3b315622ad98eccc96cb36514137d3cfc7e3b62161bdac1f13c90fb803493ea8d382f564b721f80e2804a876a804daea1b11f23f4c5c3da24a6da93b7bdbf2c50b43c97999975a79884ec77afa92b2ea53a4efe77eb89f4f0f73048256fd49965d528a94a2ea965571c8db130254783913c71f97d04d7db4adb42c2db052a4a872d8e1253a8436a756a09404ea52942d603a9fae01b286419343abb750915953ba428161b052955c72373b8f862733d526756e82b854c94db0eb8a1acacdb527a8b8f87cb0f6b61b248632e2da2915e7acbc800a6a4855cd88093b7d31f399f72d363ff00da215e212da8ff002c572df0baa82425b5c968b7b152ba7c30430b8550d2e132a7ad681c827ae107159832739e7e160fba3ba0660a6d71b52e9927b5083650d25247c0e33471078639c2a19f6b954814979e8ab96b79a752e27bc39820137f0f91c68ecb997a9d97da7134e4a8297efad6ab93fd31321692077c1f8e0d8f2d5ab087960f339eeb1e3197b3a663ac52689556eaaf4544848d3202ca4d08021804d89b9e5b5f139c46cc2bcb1c7054d5c24c94d2c3288ccb84a1252190126e01ea49f5c6a80ea40d943ccdf11356cbf42acba5caad2a9f31c29d1adf612b55bc2e45fa9c4be7ef85274aa0b83cfc8cf5c4dcd398e7a021e305c096d049092e2740483e49047c702b92bf5e728d2aadfa1294fb31a6243121d7e38b809d43bbabf88f4c6a1cb596287961996dd061b7093295adc283737b5b6277007418126f86a85a9c32eaaa78ad64ea5024efea79e04cd5c055f21f2c60794dea3ef4aa68591dda7f06aba853909daf545c61e4c54b892e34d209245ff11b83a478605b2e70c739d6d71a9819ec20f69db10eca4686ef6baf4055ef603a5f6c68697c36656e25d89532d3a9b003b3db6f8e2432fe428547aa355013e43af364ab4ec949245be5b9c0099ddd56864cb73ea46003dd0af1c72dd3a93c18723d3e0b297222e300e34d778e9212544f3e57bdfc719fd79ab31d7f2cd3327583d4e8eea4b0ca19bb9aae6ddee7f78e36dbc1a75b2d3c96d6dac58a56010af5070ca2d3a9b016a5c2830e32d5ef299692827e4304d9282d2ab59a3885c236f2a70de2d6c2de5d5d0ea0cd46b0a6d095dc7776e874827cf121c3be2050e9dc27ac50b324a7125e2eb31996db2b59438ddefe40289e67ae2fdcdf4e6ebb94eaf4c500b32232db009fbd6ba7e46df2c643a370fea4ff007aa91e532a245994b64ac8f1f2182120e9f894534ad80753b8534dcb019f67bca3033466897fa660b92a9f159ed01d452df69a8582bc6e2fb7960b78fd4b5e51ce996f35d1586e332d8435669364a56d9b8161e2836f8627b2bc8afe5da7262e5fcb6dc48c482a023a8a9c23ef2893727cfcf0719de88bce7c3e91025b0db3517980eb6852b669f02e37f98f42701e682eb4106436614d09e54f3ee5aa652e34da955e2c76e43297d0d85eb590a4dc7753738a2b8b9c59a466ea13f46814b7d4d8752e3531d5e829527ef045b95891b9eb88dcbbc0dcc952702ab0ec6a4b236bb8a0f2cfa049b7d7167d1b81f94e9d1d4658935494126c5e77b341574d93623a75c387318ac1b2140d3733a731e55a14acc90d6fd1fd8dca74b790c05ad1211eeaf5734eda08ded7be18371e4885024e69f6955213194c535e534aecdb7357bee213bee2f6241e589481faf1488e6994ba77b2446cd834c476b40f89beaf5249c3c09e223c8d2eb8f94754add6adf2e588dd20eca97f3bdba49fb28fa554e7cb10d798eab2a3d09d7d6d9900ab4bda7ddb585d20eff2c1070fe54a567cab3f4d79da8c76e39610a7104e940520a6c4db6b7e586d020e7776633ed8f8117582b6dd5a0a00bfe01b7d316be5d0c373dd71b6d94ad4dd94ab004d88b6003f6ace3ca6606da5beebffd96821c151e7111c98bf4699122e43b7ec74f26ba98bd42ccd8c01fa60c8a17367f3754700000000

WHY?

What was the plan? Can we think of any sort of justisifaction other than making it to the hall of shame?
5  Bitcoin / Development & Technical Discussion / Need help reversing bitcoinutils "tagged_hash" to generate Taproot addresses on: January 15, 2024, 09:33:16 PM
[Addition, the problem was solved down here]


Let's begin with this private key

Code:
0000000000000000000000000000000000000000000000000000000000000001

Using any good old tool, bitcoinutils included, it gives us

Code:
Private key compressed (WIF):                 KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn
Public key compressed (HEX):                  0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

HASH160 uncompressed:                         91b24bf9f5288532960ac687abb035127b1d28a5
HASH160 compressed:                           751e76e8199196d454941c45d1b3a323f1433bd6

Legacy uncompressed public address (P2PKH):   1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
Legacy compressed public address (P2PKH):     1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
Nested segwit public address (P2SH-P2WPKH):   3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN
Native segwit public address (P2WPKH):        bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

I won't go into legacy or nested segwit here, but I would like to mention how we easily derive the native segwit public address using the HASH160 compressed

Code:
bitcoinutils.bech32.encode('bc',0,bytes.fromhex('751e76e8199196d454941c45d1b3a323f1433bd6'))
#bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4

(Likewise, we can produce the segwit bech32 (P2WSH) address by using the single SHA256 of the compressed public key to get bc1qpac4ht6afshdx2tctnhjnetz7u6g3j9zhwwmc4cqkdsa2jumq42qd3drf7; another thread.)

However, here is where I need your help.

I know that the P2TR address corresponding to this private key and its witness program are

Code:
Tweaked Taproot public address (P2TR):        bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9
Witness program (HEX):                        da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21

since I can quickly arrive at them using bitcoinutils

I can furthermore reproduce and verify it with:

Code:
bitcoinutils.bech32.encode('bc',1,bytes.fromhex('da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21'))
#bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9

However, I fail to reverse how bitcoilutils does it. Specifically, this function from here that generates the tweaked public key...

Code:
def tagged_hash(data: bytes, tag: str) -> bytes:
    """
    Tagged hashes ensure that hashes used in one context can not be used in another.
    It is used extensively in Taproot

    A tagged hash is: SHA256( SHA256("TapTweak") ||
                              SHA256("TapTweak") ||
                              data
                            )
    """

    tag_digest = hashlib.sha256(tag.encode()).digest()
    return hashlib.sha256(tag_digest + tag_digest + data).digest()

... gives me a headache.

I don't see it. How do you go from the 32-byte x-only public address to that witness program?

In other words, how do I reproduce this transformation in Python (without relying on bitcoinutils as a mystery box library)?

Code:
Input:                                        79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
to
Output:                                       da4710964f7852695de2da025290e24af6d8c281de5a0b902b7135fd9fd74d21

Need your help! I'm not sure what the library uses as its standard "TapTweak", and I get confused by bitcoinutil's nested (pun intended) code.

How do we use hashlib only and arrive at the same tweaked witness program, and thus the identical P2TR public address? I am very well aware you are allowed to use whatever as "TapTweak". Can we, however, simply reproduce the "library recipe"? What is its standard "TapTweak," and how to arrive at this public address, given the data above, using simple Python?

Many thanks.
6  Bitcoin / Development & Technical Discussion / How to redeem a "dumb script" native P2WPKH? (Nested P2SH-P2WPKH went well) on: January 07, 2024, 04:54:18 PM
I fooled around a bit with "dumb scripts" like so:

Script("OP_DROP", "OP_1") is dumb but valid, will accept any one value in, drop it, and leave just a True on top of the stack. It is simply 0x7151 in hex.

Proven on testnet with (Python 3, import hashlib, base58 and bitcoinutils):

Code:
dumb_script="7551"
dumb_hash = hashlib.new('ripemd', hashlib.sha256(bytes.fromhex(dumb_script)).digest()).hexdigest()
dumb_address = base58.b58encode_check(bytes.fromhex('c4' + dumb_hash)).decode()
print(dumb_address)
#2NAfhvQFw2GR1A1iN8Eke47HqVuDcsW4Uzw

I sent 1 tBTC to 2NAfhvQFw2GR1A1iN8Eke47HqVuDcsW4Uzw, tx id 85fd05407575d31155824f6cdbaae1b544af78158cc643dd4d8f7c7351ef5bfb

To take it back, I created a raw transaction the lazy way using Cointoolkit:

Code:
0100000001fb5bef51737c8f4ddd43c68c1578af44b5e1aadb6c4f825511d375754005fd85000000000451027551ffffffff0118ddf5050000000017a914628cde58e1bcd42efb72b1821ec9fdf49e0f1d498700000000

...and broadcast it successfully in Electrum, got the tBTC back within the same block, tx id 4d7eee43f95a1402128aee4577daf0fd287f8c6aab9893f6aad559ab688cc91f

Comments: Used "OP_1, OP_DROP, OP_1" as the sigScript, which, including length prefixes, is 0x0451027551 - all it took.

I suppose I could have pushed any single number, but I went with OP_1 - and it worked as intended.

So far, so good. But now I wanted to repeat the experiment with native Segwit P2WPKH, so I changed formats while still using the same (dumb) script:

Code:
dumb_script="7551"
dumb_hash = hashlib.new('ripemd', hashlib.sha256(bytes.fromhex(dumb_script)).digest()).hexdigest()
dumb_address = bitcoinutils.bech32.encode('tb',0,memoryview(bytes.fromhex(dumb_hash)).tolist())
print(dumb_address)
#tb1qhudhq5jad3wa26unkzmt0llg4r0wt4euhpwxg7

Sent another 1 tBTC to tb1qhudhq5jad3wa26unkzmt0llg4r0wt4euhpwxg7, tx id 2df1208d368035e6ff923f5a40053792f220b3d87628db62e51a7bcdf0a50a3a

Uh oh. Need help!

No sigScript allowed when spending... hm. How do I create a witness program for a dumb script for which there is no known public and private key? Is it even possible?

Staring into a random raw P2PWKH transaction but fail to see "it."

If possible, there is 1 tBTC in it for you. Take it, and please share how the witness part was created. In case it is impossible, please explain why.

Many thanks!
7  Bitcoin / Development & Technical Discussion / At least 14(!) unique public addresses from one single seed (0 derivation paths) on: December 26, 2023, 11:20:08 PM
Do you agree that a not-uncommon Bitcoin discussion goes along the lines:

"Remember that one private key controls two public addresses, the uncompressed and the compressed." Next, someone smart-ass says, "You're forgetting nested and native segwit - it's four addresses, guys."

What about newer stuff like Taproot? What about crazy things like 1-of-1-multisig? What about older formats like P2K and P2MS that no one has used in years but would still be accepted by the network?

I decided to give it a shot.

The overall goal here is to show how many unique public addresses are actually derived from one single seed, using no "HD Wallet wizardry" with optional additional keyphrases and derivation paths. I decided no input other than the "bad_seed" string is allowed; absolutely no mnemonic phrases or derivations paths from BIPs.

By the way, I call the only input "seed" rather than password/passphrase, and I define a seed to be a 64-character hexadecimal number, such as

Code:
0000000000000000000000000000000000000000000000000000000000000001

because it can then be interpreted as 32 bytes or as a script. (This example wouldn't run as a script, but that's a separate story).

For this project, I've experimented with Python and cross-verified outputs with online services as needed, but I thought my actual code was of limited interest. If you, against all odds, wanna take a look at my scripts, say when.

Back to the title subject. From the seed, I can begin with deriving:

Code:
[[[OUTPUTS]]]

Master root XPRV:
xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21TeqtDeZVxb

Uncompressed public key:                                    0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
Compressed public key:                                      0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Uncompressed RIPEMD160 a.k.a. HASH160:                      91b24bf9f5288532960ac687abb035127b1d28a5
Compressed RIPEMD160 a.k.a. HASH160:                        751e76e8199196d454941c45d1b3a323f1433bd6


Private keys
~~~~~~~~~~~~

Uncompressed (WIF):                                         5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf
Compressed (WIF):                                           KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn

Nothing special so far, except maybe my XPRV experiment.

But how about this? I've never found anything online that is this extensive (and way too many examples on Github that do bits and pieces of it).

Code:
Public addresses
~~~~~~~~~~~

Public script - rare but valid (P2S)**                      0000000000000000000000000000000000000000000000000000000000000001
Old 1-of-1 multisig uncompressed - rare but valid (P2MS):   51410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b851ae
Old 1-of-1 multisig compressed - rare but valid (P2MS):     51210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179851ae
Uncompressed public key - rare but valid (P2PK):            0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
Compressed public key - rare but valid (P2PK):              0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Uncompressed legacy public key (P2PKH):                     1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
Compressed legacy public key (P2PKH):                       1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH
Nested SegWit public address (P2WPKH-P2SH):                 3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN
Nested SegWit script public address (P2SH)**:               3D24NWLpGxY9x8WZYpvowwyNPyZyN7aRNB
New 1-of-1 multisig uncompressed - weird (P2SH):            33RjLdp9usumz3BNqa5PB9umJZjiw7kmjK
New 1-of-1 multisig compressed - weird (P2SH):              3DicS6C8JZm59RsrgXr56iVHzYdQngiehV
Native SegWit public address (P2WPKH):                      bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
Native Segwit public address (P2WSH)**:                     bc1qa3y3dhfgl3xpp4uw9p72tkwv28hp4eeuhl0q334nwvjvh74v30zs5faqjp
Taproot public address (P2TR):                              bc1pmfr3p9j00pfxjh0zmgp99y8zftmd3s5pmedqhyptwy6lm87hf5sspknck9

[Those marked with ** require the underlying script to be executbale, or the address is unspendable.]

My comments:

I thought I'd take it from the beginning and in chronological order of appearance from 2009 until today.

Pay-to-script (P2S) has, to the best of my knowledge, always been allowed, but there are few examples from the past decade. Paying to the script used in this example but be advised against; it is probably not spendable.

The same goes for early-day multi-signature addresses, for which you had to write the public key(s) in clear text (P2MS). As far as I understand, they are still legal but very scarce. The special case of 1-of-1 was probably never an intended feature - it makes little sense - but they weren't disallowed back then, and they are still accepted today. We can write one each for the uncompressed and the compressed public keys, respectively.

Then, we have the two legacy addresses that reigned for many years (especially the compressed ones).

First among the "3-addresses" is one with many names. I like "nested Segwit" best, but if you prefer P2WPKH-P2SH, I'm cool.

Next in line is "Nested SegWit script public address (P2SH)**" - and I would like you to suggest a better name. The code I use to construct them is:

Code:
base58.b58encode_check(bytes.fromhex('05'+ hashlib.new('ripemd160', hashlib.sha256(bytes.fromhex(bad_seed)).digest()).hexdigest())).decode()

They are, I think, only good if the corresponding script is good (and I strongly suspect "bad_seed" will not pass as a valid Bitcoin Script).

Then we have these weird 1-of-1 multi-sig transactions again. Take a look at this link collection about "Crazy1to1" and good luck getting any wiser! In any case, we can easily create two 1-of-1 multi-sig addresses, one for the uncompressed public key and one for the compressed ditto, and wrap them up in P2SH containers.

Native Segwit, or shall we call them "bc1"-addresses shouldn't surprise anyone. At least not the first. The second one, which I call "(P2WSH)**", is just me using the seed as a script again; hence, 32 instead of 20 bytes and a longer address. In honor of full transparency, I think the address format is correct, but since "bad_seed" isn't a real script, I doubt the address is spendable.

The last one is "just" a regular Taproot. It is also the format that I know the least about. I am struggling with theory in combination with super-enthusiastic Youtubers, but it is still to little avail - I am not sure I get "it" when it comes to Taproot/bc1p and how it changes the world for the better. Is it possible to make Taproot variations without introducing arbitrary extra code? I take pride in that all the above are derived from one single seed and that anyone who reproduces parts or all of them should get the same public addresses.

I am super excited about your feedback! Did I leave anything obvious out? Did I make any mistakes, big or small? In other words, what should I correct? Have others derived more than 14 public addresses from one hardcoded seed in a deterministic and reproducible manner? Should I make public my Python script?

For good measure, iteration 2 yields:

Code:
[[[INPUT]]]]                                                [[[We treat this single input a private key OR a script (HEX)]]]

Bad seed:                                                   0000000000000000000000000000000000000000000000000000000000000002

[[[OUTPUTS]]]

Master root XPRV:
xprv9s21ZrQH143K24Mfq5zL5MhWK9hUhhGbd45hLXo2Pq2oqzMMo63oStZzF93Y5wvzdUayhgkkFoicQZcP3y52uPPxFnfoLZB21TeqtEE6Pxo

Uncompressed public key:                                    04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a
Compressed public key:                                      02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5
Uncompressed RIPEMD160 a.k.a. HASH160:                      d6c8e828c1eca1bba065e1b83e1dc2a36e387a42
Compressed RIPEMD160 a.k.a. HASH160:                        06afd46bcdfd22ef94ac122aa11f241244a37ecc


Private keys
~~~~~~~~~~~~

Uncompressed (WIF):                                         5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAvUcVfH
Compressed (WIF):                                           KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU74NMTptX4

Public addresses
~~~~~~~~~~~

Public script - rare but valid (P2S)**                      0000000000000000000000000000000000000000000000000000000000000002
Old 1-of-1 multisig uncompressed - rare but valid (P2MS):   514104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a51ae
Old 1-of-1 multisig compressed - rare but valid (P2MS):     512102c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee551ae
Uncompressed public key - rare but valid (P2PK):            0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
Compressed public key - rare but valid (P2PK):              0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
Uncompressed legacy public key (P2PKH):                     1LagHJk2FyCV2VzrNHVqg3gYG4TSYwDV4m
Compressed legacy public key (P2PKH):                       1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP
Nested SegWit public address (P2WPKH-P2SH):                 3FWHHE3RVgyv5vYmMrcoRdA25uugWvQbso
Nested SegWit script public address (P2SH)**:               3CNVyupnE7C8FMCv9vPWSpriuVQZVt6Fzh
New 1-of-1 multisig uncompressed - weird (P2SH):            3G1kW5oNxKs2whEgi6cwVy5KEoAqkwuGHr
New 1-of-1 multisig compressed - weird (P2SH):              32KTvowh8quz8eFfxgX98QJUdUGgryn28R
Native SegWit public address (P2WPKH):                      bc1qq6hag67dl53wl99vzg42z8eyzfz2xlkvxechjp
Native Segwit public address (P2WSH)**:                     bc1qjfna8kldsq55zjplrtaz567x3hjlv5cj3t9fhu2xr3ws5wkndmfqhhl956
Taproot public address (P2TR):                              bc1pet7ep3czdu9k4wvdlz2fp5p8x2yp7t6ttyqg2c6cmh0lgeuu9lasmp9hsg

[Those marked with ** require the underlying script to be executable, or the address is unspendable.]
8  Bitcoin / Development & Technical Discussion / In theory,THE most unsafe HD Wallet - [BIP32, BIP39, BIP44, BIP84] - am I close? on: December 21, 2023, 11:15:08 PM
DISCLAIMER: Consider this a theoretical exercise in producing the worst imaginable HD Wallet and its private keys and public addresses from a safety and good practice perspective. It contains overriding as many safety measures as possible - on purpose. Don't try this at home.

Brief introduction
Firstly, I will skip a proper intro and instead recommend those interested to read up on BIP32, BIP39, BIP44, and BIP84 as needed. These are intended to add safety and utility to Bitcoin, and I chose to try my best to misuse them.

I will use Python and some common crypto-related libraries, leaving out most whys and hows.

My idea is to create the worst imaginable BTC mainnet extended private key (XPRV) from a cryptographic viewpoint and derive the first of its corresponding key pairs. In other words: "Catastrophic private keys" in WIF format and the different flavors of public addresses they control - details you can import in Electrum and sweep clean in a matter of seconds.

This is hopefully somewhat entertaining and, in the best of worlds, even rewarding in one way or the other.

I hypothesize that if you learn to do every step wrong, you become better at making it right when needed. I look forward to your comments, corrections, and feedback!

Let's get going
We need a disastrous XPRV to begin with. Let's aim for the worst of them all. There are excellent online tools, such as this, this and this you can use to create high-entropy and human-readable mnemonic phrases based on standardized word lists, but they have safety measures, as they should have, against week phrases. Also, remember that creating cryptographically sound XPRVs involves many rounds of one-way hashing and the incremental use of random salts and checksums (PBKDF2-HMAC-SHA512).

Can we break it? I think we can:

Code:
from bip32 import BIP32

bip32 = BIP32.from_seed(bytes.fromhex(""))
master_xpriv = bip32.get_xpriv()
xpriv_from_path = bip32.get_xpriv_from_path("m")

print(master_xpriv)
print(xpriv_from_path)

See what I did there? I overrode all traces of good practice: I used an empty string ("") as the passphrase, didn't hash anything, didn't salt, used no derivation path at all ("m"), and confirmed both outputs, the master and the first derivation, equate to the same value:

Code:
xprv9s21ZrQH143K37GktPqduLh1DoBuxUQvLPY9yR3eJ4zQB4KzSYeoHNutnWNasXJJmEHCneeFhpSuC8Ppc33RXvzsuhSTLLqurx7kLvw9d6p

Please tell me if you imagine a more unsafe and stupid method to create a master XPRV for Bitcoin! (Further, consider all this a homage to the marvelous 50 BTC transaction to the address that belongs to SHA256(*empty string*) in 2015.)

Now, let's use this master XPRV, once again without derivation paths, to find the possible private keys and all(?) corresponding public addresses, given BTC standards of 2023:

Code:
import sympy
from bitcoinutils.setup import setup
from bitcoinutils.keys import P2pkhAddress, P2shAddress, PrivateKey
from bitcoinutils.hdwallet import HDWallet as hdw

setup('mainnet')

xprivkey = "xprv9s21ZrQH143K4YUcKrp6cVxQaX59ZFkN6MFdeZjt8CHVYNs55xxQSvZpHWfojWMv6zgjmzopCyWPSFAnV4RU33J4pwCcnhsB4R4mPEnTsMC"
path = ""
hdw = HDWallet(xprivkey, path)
priv1 = hdw.get_private_key()
wif1 = priv1.to_wif(compressed=False)
wif2 = priv1.to_wif()
pub1 = priv1.get_public_key()
script_witness = priv1.get_public_key().get_segwit_address().to_script_pub_key()
add1 = pub1.get_address(compressed=False).to_string()
add2 = pub1.get_address().to_string()
add3 = P2shAddress.from_script(script_witness).to_string()
add4 = pub1.get_segwit_address().to_string()
add5 = pub1.get_taproot_address().to_string()

After some prettification (actual print commands omitted), the output is

Code:
Private key uncompressed:       5JBSnNFYrX7VZcomqnzmmVZqTuubdCDJbkmR8Z7g9qJ48FmxDkV
Private key compressed:         Kxq6oEoDbZuf4y3SvN1zbP5vunX9pkVJgQB3WLkTozAGns2p7PWe

Legacy address uncompressed:    15np5mEdrT7CAaFePSDY9PwiqZqZaT4noQ
Legacy address compressed:      1ATHjwQRMgxmCm6c8Pj9snyrd39UMZyKBZ
Nested segwit address:          32ZjiUAL8FNXj9gQ7Jqcsi2zGHL4VxAop7
Native segwit address:          bc1qv7c7h5d8thdd8gxsmqaquhe8xkzk5cdmjmjyxg
Taproot address:                bc1p6tx5tl7cp49alj4n48kfca0yslgvzhvakja7fysx3y384thl2wmqj8nszu

Concluding remarks and questions
At least one of these public addresses has appeared on the blockchain before. I claim no fame in finding these. I just added what has been out for years together, but I sincerely wonder - can you think of an even more stupid and/or insecure way of using XPRV to set up an HD Wallet?

I haven't even bothered with playing around with derivation paths yet. It should be a simple loop in Python to spit out millions, if not billions, of "hardened" (not so hardened) children and change addresses that are derived from this single disastrous XPRV.

What say you? Can you possibly do worse? Smiley
9  Bitcoin / Development & Technical Discussion / World's fastest and simplest block parser for those who (only) need all HASH160 on: September 05, 2023, 01:45:59 PM
The question never really dies; since Brainflayer in 2016, the dream seems to live forever, so to speak: "How can I get all HASH160 ever seen on the blockchain in one file?"

There are confusingly many different solutions here and on Github (and shadier places). One more advanced than the other. I went in the other direction, thinking, "It can't be that difficult."

It isn't. It's much easier than you think. Assuming you have a fully synced Bitcoin Core local installation (the .blk files on your hard drive, downloaded with txindex=1). Also, that you are on *nix (or have Ubuntu on a VM or something - more than good enough), this needs no extra downloads, no dependencies, not much extra HDD space, very little CPU and RAM, and no GPU.

Assuming you're in the terminal and the ~/blocks folder, just:

Code:
cat blk00000.dat| xxd -p | grep -oE '1976a914[0-9a-f]{40}88ac' | sed 's/1976a914//;s/88ac//' | sort -u > P2PKH-unique00000.txt

It shouldn't take longer than 1-2 seconds per .dat file, even on an old budget computer.

That's it. Done.

Some comments:

  • For all .dat files in one go, start with "cat blk* |" instead (and remove the numbers in the output file name). I opted for the first file only as the first proof of concept because there is zero waiting until you know it works.
  • What does it do? Briefly and on the fly - and in this order: Reads the blk file[ s ], changes format from binary data to human readable hexadecimal (the blockchain files have no deeper code to crack than that), searches for the P2PKH pattern, selects the "middle part," which is the HASH160, sorts all hits alphabetically and removes duplicates, forgets all else and writes the result to one text file.
  • Want P2SH-P2WPK and native Segwit too ("3" and "bc1q" addresses), maybe even Taproot? No problem, change the prefix and suffix bytes accordingly (very easy to find). I recommend saving these to separate text files since you can't tell "naked" HASH160:es from each other, but... whatever floats your boat.


Yeah, about the title. I think this is the world's fastest and simplest solution; I will, of course, change it when/if proven wrong.

Happy HASH160!
10  Bitcoin / Development & Technical Discussion / P2PK - send to AND spend from a public address - will it work in 2023? on: September 04, 2023, 12:16:34 PM
I don't think an introduction to P2PK is necessary in this forum. Briefly, it was popular in the early days of the blockchain and more or less abandoned for P2PHK ("Legacy", "1-addresses", or what you prefer to call them; several years later, Segwit and Taproot and yadda yadda.)

Here, consider this random 32-byte string as the starting point/private key. (I like "openssl rand -hex 32" but won't argue against other random number generation methods.)

Code:
91e1ff59d1c1452034ddcb38930176e5e3d4ab31b905eab73bf6843c149c4a67

(Never use it; the usual disclaimers.)

From it, we can derive the uncompressed public key, which will always be a 130-digit hexadecimal number (intentionally disregarding the compressed version for simplicity).

Code:
04038a7f3eb49c316d94e228ffb155113a0897e40f1f04f0878559fd8b7b37d8270ff752c2cd7e479c4c4844286fc6d924e578217d0354b97c42afe1f74c472e15

We can type out the private key in standard base58check WIF format and the corresponding public addresses on mainnet and testnet - but let's not use these for now.

Code:
Private key (uncompressed WIF): 5JvXxk75aku9ed11dMfDebgknrAYj2fk8gWHuLsqfMRkVtpWWTH
Public address (uncompressed testnet): mghXH5mxtsWPjqZtjEqJdg1qs7qJJTvTeL
Public address (uncompressed mainnet): 12BZz2gz5r58xj6H1frvokoX18EbPVkrsS

What I'm not after is a lecture on whether using P2PK today is a good idea; the only question is - can we?

More specifically, the question is two-fold:

1. How would I send to the public key (NOT the public address) - in practice?
2. How would I claim the unspent transition to "only" a public key - in practice?


I think, please chime in, that the answer to the first question is straightforward. A quick-and-dirty dry-run in Electrum, and sure, I can specify the public key as to where I want to send to. I can sign the transaction, but I haven't tried it online yet, i.e. broadcast it. Would it propagate and be picked up, or would the current p2p network consider it unusual or even invalid and drop it?

The proof is in the pudding, I guess - I could try with some tBTC and see what happens. In my experience, however, just because something works on testnet, it is not guaranteed to work on mainnet.

Would the transaction go through (i.e. be picked up and included in coming blocks) on the mainnet today?

Question number 2 is more interesting, in my opinion. Let's assume I indeed can spend to a public key on mainnet using old-school (2009) kung fu. What would be the most straightforward approach to claim it? I have assumed, without actual testing, that importing the private key in Bitcoin Core or Electrum (or other wallet software) will not allow me to spend from the associated public key, since P2PK barely been used in the past decade. And that I, in that case, would need to author (there are decent online tools) the transaction manually. Yes, no?

Looking forward to your thoughts and insights!
11  Bitcoin / Development & Technical Discussion / Prime number Bitcoin keypairs - How and why on: March 20, 2021, 01:30:51 AM
HOW

First, consider this Bitcoin key pair:

Code:
Private key compressed (wif):
L3ACAgUJquKbnuYUywUqJNo6QACyMZvMvtx7Gt7QrbsrMkBhCDwA

P2PKH Public Address (Legacy):
1HBK1zXfLLJw9GUidvnb5bBVt8GReDnXhj

At a first glance, they look random and nothing special at all. Let's however convert these base58 numbers to hexadecimal, and we get (note that I use only the compressed form):

Code:
Private key (hex):
b136fef8391b4956312a6df2f6dc99b7cf238982dbcfbcb629f4ed6d35671a77

Public Address hash160 (hex):
b175364aaea8ecb515c1779cd00b0c3ba157bb25

Still not impressed? Alright, let's convert them to decimal (ordinary) numbers, so that:

Code:
Private key (dec):
80156543676389067380819750297890580630517839339787739613967701593439506733687

Public Address hash160 (dec):
1013105283100545924034097521935085705519926065957

Decimal numbers are easier for us humans. Do you see it now? These numbers are prime! You can easily verify this by trying to factor the two numbers here, or with programs like Matlab or other programs that can handle large numbers.

These two are only divisible with themselves and 1. In other words, they are prime. How cool is that?


The code

It took me some time to figure out how to produce key pairs like this. Large number factorization is computationally heavy. The pseudo-code works like:

Code:
1. Generate a random 32-byte number

2. If it is prime, go to step 3 - if it is not prime, go back to step 1

3. We have a prime private key; from it, compute the compressed public address, and more specifically its hash160

4. If both the private key and hash160 are prime, we are done - if the hash160 is not a prime, go back to step 1

If anybody is interested, I have the complete code in Python3 with several speed optimizations. Do tell!

On a regular laptop and using CPU only, it takes about 2-10 seconds to produce what I call "a true prime Bitcoin key pair".


Example output

When executed, the script outputs the following

Code:
==== RESULTS ===================================================

Private Key (32-byte PRIME NUMBER in HEX):
b136fef8391b4956312a6df2f6dc99b7cf238982dbcfbcb629f4ed6d35671a77

Public Address (HASH160 - 20-byte PRIME NUMBER in HEX)
b175364aaea8ecb515c1779cd00b0c3ba157bb25

==== PRIVATE KEY AND PUBLIC ADDRESSES (COMPRESSED ONLY) ========

Private key (WIF):
L3ACAgUJquKbnuYUywUqJNo6QACyMZvMvtx7Gt7QrbsrMkBhCDwA

P2PKH Public Address (Legacy):
1HBK1zXfLLJw9GUidvnb5bBVt8GReDnXhj

P2WPKH-P2SH Public Address (Wrapped):
39PGSGyV2dokiPxBUnsLR1a8N2bE1Hv9h2

Segwit P2SH Public Address (Bech32):
bc1qk96nvj4w4rkt29wpw7wdqzcv8ws40we9pynp28

==== IMPORT IN ELECTRUM WITH ===================================

p2pkh:L3ACAgUJquKbnuYUywUqJNo6QACyMZvMvtx7Gt7QrbsrMkBhCDwA
p2wpkh-p2sh:L3ACAgUJquKbnuYUywUqJNo6QACyMZvMvtx7Gt7QrbsrMkBhCDwA
p2wpkh:L3ACAgUJquKbnuYUywUqJNo6QACyMZvMvtx7Gt7QrbsrMkBhCDwA

(For other wallets: Read the manual)

==== VERIFICATION ==============================================

Paranoid people should use independent and offline software to
confirm that 80156543676389067380819750297890580630517839339787739613967701593439506733687 and
1013105283100545924034097521935085705519926065957 are prime
numbers, and that they are equal to the hexadecimal numbers in
the first paragraph.


WHY

They say that "prime numbers are the atoms of math, and math is the language of the universe."

It is beautiful. It is satisfactory. It is nerdy.

After coming up with this, I use only perfect Bitcoin primes myself.

But does it have any actual use? I'd love your take on it.

Does it add value? (Primes cannot - by definition - be factorized, so no one could ever arrive at your private key by factorization and multiplication [if that's even a thing].)

Are primes handled "better" (whatever that means) when for example signing transactions, resulting in better byte economy for the blockchain?

Is this unsafe? (I think not, according to the prime number theorem (PNT) there should be about 6.54*10^74 primes - a huge number - in the range as defined by the secp256k1 with the ECDSA algorithm. In other words, of all possible private keys, approximately 0.056% are prime, but only a few of these correspond to public addresses whose hash160 happen to be prime too.)

What do you think?
12  Bitcoin / Bitcoin Technical Support / Pulp Fiction and multiple OP_RETURN, valid tx on testnet on: September 13, 2020, 11:36:17 PM
How Jules ended up on the blockchain

Like many others, I've experimented with including arbitrary code in valid transactions.

The contemporary standard-method is OP_RETURN, with a huge disclaimer: only one per transaction - or the tx will be invalid (interestingly, coinbase transactions may and often do contain several OP_RETURN, but that's a different story).

The manual says you can push up to 80 bytes of data using this method, as it appears that many in the community are skeptical to the existence of OP_RETURN (the blockchain should contain tx data, not arbitrary junk, fine, I agree)

Anyway, I thought of one of my favorite movie quotes, from Pulp Fiction (1994) in which characters Jules reads quotes "Ezekiel 25:17" (Quentin Tarantino pushed his liberal arts beautifully here, no real bible contains these words) before killing his victims:
 


The path of the righteous man is beset on all sides by the inequities of the selfish and the tyranny of evil men. Blessed is he, who in the name of charity and good will, shepherds the weak through the valley of darkness, for he is truly his brother's keeper and the finder of lost children. And I will strike down upon thee with great vengeance and furious anger those who would attempt to poison and destroy my brothers. And you will know my name is the Lord when I lay my vengeance upon thee.



If we take this, then perform an ASCII to hex conversion, we get:

Code:
5468652070617468206f6620746865207269676874656f7573206d616e206973206265736574206f6e20616c6c2073696465732062792074686520696e6571756974696573206f66207468652073656c6669736820616e642074686520747972616e6e79206f66206576696c206d656e2e20426c65737365642069732068652c2077686f20696e20746865206e616d65206f66206368617269747920616e6420676f6f642077696c6c2c2073686570686572647320746865207765616b207468726f756768207468652076616c6c6579206f66206461726b6e6573732c20666f72206865206973207472756c79206869732062726f746865722773206b656570657220616e64207468652066696e646572206f66206c6f7374206368696c6472656e2e20416e6420492077696c6c20737472696b6520646f776e2075706f6e207468656520776974682067726561742076656e6765616e636520616e6420667572696f757320616e6765722074686f73652077686f20776f756c6420617474656d707420746f20706f69736f6e20616e642064657374726f79206d792062726f74686572732e20416e6420796f752077696c6c206b6e6f77206d79206e616d6520697320746865204c6f7264207768656e2049206c6179206d792076656e6765616e63652075706f6e20746865652e

Clearly more than 80 bytes. If fact, it is 495 bytes.

Hm. What next. I really wanted this one to stick on the blockchain. So I fired up Ecectrum (in testmode), and from the menu, I chose "pay to many". Using Notepad++, I ended up with the following recipients (in other words, I just sliced the sling into 40-byte strings, and added a "0" so nothing would actually be transferred to a provably unspendable address.)

Like this:



Since some of it is cropped in the image, here is the full list of "recipients":

Code:
OP_RETURN 5468652070617468206f6620746865207269676874656f7573206d616e206973206265736574206f,0
OP_RETURN 6e20616c6c2073696465732062792074686520696e6571756974696573206f66207468652073656c,0
OP_RETURN 6669736820616e642074686520747972616e6e79206f66206576696c206d656e2e20426c65737365,0
OP_RETURN 642069732068652c2077686f20696e20746865206e616d65206f66206368617269747920616e6420,0
OP_RETURN 676f6f642077696c6c2c2073686570686572647320746865207765616b207468726f756768207468,0
OP_RETURN 652076616c6c6579206f66206461726b6e6573732c20666f72206865206973207472756c79206869,0
OP_RETURN 732062726f746865722773206b656570657220616e64207468652066696e646572206f66206c6f73,0
OP_RETURN 74206368696c6472656e2e20416e6420492077696c6c20737472696b6520646f776e2075706f6e20,0
OP_RETURN 7468656520776974682067726561742076656e6765616e636520616e6420667572696f757320616e,0
OP_RETURN 6765722074686f73652077686f20776f756c6420617474656d707420746f20706f69736f6e20616e,0
OP_RETURN 642064657374726f79206d792062726f74686572732e20416e6420796f752077696c6c206b6e6f77,0
OP_RETURN 206d79206e616d6520697320746865204c6f7264207768656e2049206c6179206d792076656e6765,0
OP_RETURN 616e63652075706f6e20746865652e,0

Lo and behold, I could sign and broadcast the tx without a problem. It was included in a block within minutes. The net result is here:

https://blockstream.info/testnet/tx/68838b9f4fb8f23db46cf9e71511211a4d66b45fd02320481cfc5c352433dcb9?expand

Looks I have to work on the ordering, though, it seems the entires get lexicographically sorted so that the text turns up scrablmed. But still, yeah baby! Jules famous words are now forever imprinted on the blockchain.

Well.... that of the testnet. When trying to reproduce this on the mainnet, I got an error saying I was using too many OP_RETURN. Really?  Smiley

I was surprised the "one only" rule is disabled on the testnet.

Kinda cool, I thought. Maybe everybody already knew? Ye like?





If you have another trick for mainnet, I'm all ears! One that doesn't rely on OP_RETURN would be nice. Thanks!
13  Bitcoin / Development & Technical Discussion / Shortest possible raw transaction (below 85 bytes possible)? on: August 30, 2020, 05:01:35 PM
I have experimented with creating the shortest possible raw transaction, which has been successfully broadcast and mined.

A very quick Google search (my due diligence is admittedly so-so) reveals that someone boasts about sending a 129-byte transaction.

I have sent an 85-byte transaction! Txid: fbff3bdec5b34bff4e3bd9066fd53262b014abe0227898ce9bcc8552f31f7394

Is it possible to beat this, i.e. do even shorter than 85 bytes?

My strategy:

-- Spend from an any-one-can-spend address with a 4-byte sigscript (I have failed to go shorter than this, can you?)
-- Send to a native segwit address, the shortest of the predefined standard formats

Here is my transaction...

Code:
01000000012f107ec7a860784725acc93d2362a0dc9b2560eafe5ff3f0b1faef5e0831517b0100000003510161ffffffff0186959800000000001600141ee44a2f2c8d366945ff02676bd608f70a559ea700000000

... and let's break it down (and look for any potential room for improvement):

01000000 - version number (always 4 bytes)
01 - number of inputs (always 1 byte)
2f107ec7a860784725acc93d2362a0dc9b2560eafe5ff3f0b1faef5e0831517b - txid in little endian format (always 32 bytes)
01000000 - vout little endian (always 4 bytes)
03510161 - sigscript including length byte padding (1+3=4 bytes)
ffffffff (sequence number - always 4 bytes)
01 - number of outputs (1 byte)
8695980000000000 - amount (little endian, always 8 bytes)
1600141ee44a2f2c8d366945ff02676bd608f70a559ea7 -- (a native segwit address, 1+22=23 bytes [shortest possible standard address])
00000000 - locktime (block 0, always 4 bytes)

4 + 1 + 32 + 4 + 4 + 4 + 1 + 8 + 23 + 4 = 85 bytes

Seems to check out.

OK, can we go shorter? My reasoning - I'd love your comments:

-- Most of the values have hardcoded lengths, you can for example never reference a txid that isn't exactly 32 bytes

-- I want the transaction to be accepted on the mainnet, which excludes sending to pure scripts (P2S), as these are no longer accepted by Bitcoin Core nodes, due to IsStandard() and IsStandardtx() checks, so we are limited to the predefined address formats of which native segwit is the shortest, byte-wise (and there is no witness data here since we use a stupid any-one-can-spend address)

-- All my attempts to assemble shorter sigscritps have failed. A sigscript must contain an unlocking script that is "push only", so OP_1 (51) it is for the unlocking script, and it must be followed by the locking script, which cannot be empty (I think?!), and the whole shebang must be prefixed with a length byte; I haven't been able to get anything below 4 bytes in total to work

-- You could cheat and spend to OP_RETURN 01 only, which is considered a standard address (whether you like it or not); such transactions, however, always lead to provably unspendable outputs, so add that to my list of requirements: the transaction should not trap coins in unspendable outputs

Is my 85-bytes transaction some sort of record? If so, cool, I guess.

Can we go shorter than 85 bytes? Shoot! Thanks.

14  Bitcoin / Development & Technical Discussion / Is this P2SH _obviously_ vulnerable? [0.1 tBTC stake] on: August 22, 2020, 12:44:53 AM
A vulnerable P2SH address - but how vulnerable?

I have been fooling around some more with custom P2SH addresses. Got a new one for you: 2N3jiV8cRVN8y8Vgn2wvTW24zPsDX5dKjGT

(Yeah, testnet only this time around, but the principals are identical.) Edit: real BTC added, see below.

You can look it up here or here, for example.

The address had been funded once with 0.1 tBTC. It has then been spent from once (hint!).

I sent 0.1 tBTC to it again, waiting for it to be plucked.

Can and will you snatch it?



If it is successfully emptied by someone, who won't write here about how they didn't, I'll do it.

If no one is able to rob it, which I doubt given the expertise on this forum, I will take it back in a day or two - then tell you all about it.

Win-win?



Give it a shot!

15  Bitcoin / Development & Technical Discussion / A breakable P2SH address - Bitcoin testnet inside on: August 03, 2020, 11:12:18 AM
Long story short, I created this not-very-standard P2SH public address: 2NA4ZpHbzfp7VkAXHjpZc8Ze6SpNfS7jSbF

And gave it some history on the blockchain (hint!) and just funded it again with 0.11111111 tBTC

Show me you can break it and sweep the coins!

It's NOT of those "try and bruteforce my 32-byte private key" or the like. The solution is simple.

If no one has touched the coins in a day or so, I'll show you exactly how.

Do it!



Edit: The updated challenge is here
16  Bitcoin / Development & Technical Discussion / Can Bech32 be P2SH? [Bounty inside!] on: July 31, 2020, 12:24:10 AM
Some background

I have fooled around a bit with "stupid" scripts and their corresponding P2SH addresses ("3"-format). Have written about some findings for example here. (And to be clear, I don't mean so-called wrapped P2WPKH-P2SH addresses; those are "3-addresses" too, but on the contrary, do have a private keys, rely on ECC and so forth - very different from "pure" P2SH.)

To mention one, the stupid anyone-can-spend script "OP_1" is 0x51 in hexadecimal and is easily converted to the public address like so (Python 3):

Code:
>>> import binascii, hashlib, base58, bitcoinutils
>>> from bitcoinutils import bech32
>>> script='51'
>>> hash160 = hashlib.new('ripemd160', hashlib.sha256(binascii.unhexlify(script)).digest()).hexdigest()
>>> p2sh_b58 = base58.b58encode_check(binascii.unhexlify('05'+ hashlib.new('ripemd160', hashlib.sha256(binascii.unhexlify(script)).digest()).hexdigest())).decode()
>>> print(p2sh_b58)
3MaB7QVq3k4pQx3BhsvEADgzQonLSBwMdj

This public address, 3MaB7QVq3k4pQx3BhsvEADgzQonLSBwMdj, has at the time of writing 790 transactions.

Now, what is interesting is that you only need fundamental insights in Bitcoin raw transactions to spend from this address; here the most recent transaction out:

Code:
0100000001d34fe68a3c6054aae1e092fb5e395a7e72c99783a05c010d2be298e318a0248100000000020151ffffffff01080700000000000017a914a89aec4cd53e6d74215332459b7fea3ec4aca9758700000000

Now, you can't create such a transaction in Bitcoin Core or Electrum, but it is easy enough to do in Notepad++. The magic is the Sigscript

Code:
020151

right before the ffffffff separator, which it Bitcoin script for simply saying "push OP_1 onto the stack", and voilla - you control the coins.

No ECC or private key involved. Simple. And stupid. Because of its anyone-can-spend nature.


The real question - do Bech32 P2SH addresses exist?

Until just recently, I believed that all Bech32 addresses - the by-now-not-so-new "bc1" format - are either P2WPKH or P2WSH, which means they behave more or less like legacy address, and the only difference is that the raw transactions are constructed differently (the Sigscript must be empty and witness data must be presented as a new entity, after the receiving address - we call this segwit and it's pretty cool), but one sentence in the Bitcoin Wiki made me wonder:

https://en.bitcoin.it/wiki/List_of_address_prefixes

First table: "Bech32 pubkey hash or script hash" (my underlining)

What is this? Do they actually mean script hash (SH) and not witness script hash (WSH)? If so, then there are "real" Bech32 P2SH addresses, right? (Or is the wiki written sloppily?)

So, I did some testing and converted "stupid" scripts (like in the introduction) to their Bech32 addresses, using this code:

Code:
>>> p2sh_b32 = bitcoinutils.bech32.encode('bc',0,memoryview(binascii.unhexlify(hash160)).tolist())
>>> print(p2sh_b32)
bc1qmgt5t6d4fx7sh7s626vhr3m7hgcv6kjt450t6x
OK, so bc1qmgt5t6d4fx7sh7s626vhr3m7hgcv6kjt450t6x has to date never been used, suggesting this is uncharted territory.

But - I then tried a slight variation, i.e.

Code:
script = <short series of opcodes>

which led me to a Bech32 address that in early 2017 received more than 1 BTC.

For natural reasons, I will not write it out here, as they have never been spent.

The key question (pun intended) is then how one would go about spending from such an address. Because if we take a look at one typical spending from a Bech32 P2WPKH address, I picked this transaction - 4bce99b9f78fd0d5d7d52dd41b6c406577c59ee5f6105541683fe527f6c3f43c - randomly, its raw transaction is

Code:
0100000000010128746e138c008ca1c61ebd8d3b7d5d9e8e2d4375d59690661e3f70d0b1de8ca300000000000000000001c9896c000000000017a914269ef48bf373a19deaa94b32cae5cbe3c93062fb8702483045022100b893c9d2f1b2525e84e9bb31c016a65f4891f6a954fc1c0c1d06189bcc8ae65002205e1f3b5de07be06775cd141a4e1e187c41ad03a1c6955b21568079482aef8648012102a5daf09e8da80f53edca8c8e59a5f4a6363a7b94cfbffb9c9240d4b2e239d1dd00000000

Let's skip a few numbers and cut to the chase, the witness program (last in the serialized output, because of segwit). In this example it is (cheating by convering to a JSON object):

Code:
"witness": [
                "3045022100b893c9d2f1b2525e84e9bb31c016a65f4891f6a954fc1c0c1d06189bcc8ae65002205e1f3b5de07be06775cd141a4e1e187c41ad03a1c6955b21568079482aef864801",
"02a5daf09e8da80f53edca8c8e59a5f4a6363a7b94cfbffb9c9240d4b2e239d1dd" ]

Alright, clearly some signing has been performed here, using a private key. In the first instance, we fairly easily find the r- and s-values (after the code separator "02"), and the second instance is simply the public key (not to be confused with the public address).

Then we have a problem with the maybe P2SH Bech32 address I found - because I know its script, which means I cannot know either its public key or create signatures since there is no private key for it.

The big question is - is it spendable? I have been trying to read up on BIP173 and valid structures for segwit witnesses, but find the documentation vague and elusive.

Remember how easy it was to spend from the "normal stupid" P2SH address above by simply pushing 3 bytes of data in the Sigscript? For Bech32 and segwit, the Sigscript must always be empty, which creates an interesting obstacle.

Is possible to construct witnesses for what I know is a Bech32 address, or at least an attempt to make one, an address that has had more than 1 BTC untouched since 2017? The whole address is the product of one simple script, and there is no cryptography involved at all.

Is it possible to construct "stupid" "020151"-like witnesses for this address and assemble a valid raw transaction that can be broadcast without errors (i.e. accepted by the majority of the network), or is it simply so that Bech32 is never P2SH (despite what the wiki says)?

Looking forward to hearing your thoughts on this. (For what it's worth, I have a smaller collection of Bech32 P2SH addresses with positive balances according to the blockchain and it would feel bad if they were forever stuck there because of a programming error or something.)


TL;DR

Do Bech32 P2SH addresses exist, and if they do, how do you construct valid transactions from them? Many thanks!
17  Bitcoin / Development & Technical Discussion / Custom P2SH redeem script - any wallet software that can handle it? on: July 12, 2020, 06:31:58 PM
It is very easy to create valid, custom scriptSig/scriptPubkey-combinations, calculate a P2SH address, send coins to it, and semi-manually spend from it. One example:

scriptSig
Code:
#Push 8 byte secret hexadecimal string "0123456789abcdef"
8 0x0123456789abcdef
Result (written as part of a raw transaction): 080123456789abcdef

scriptPubkey
Code:
#SHA-256 of the input, push SHA-256 hash of string in scriptSig, verify that the are equal, which will return "TRUE", i.e. a valid script
OP_SHA256
32 0x55c53f5d490297900cefa825d0c8e8e9532ee8a118abe7d8570762cd38be9818
OP_EQUAL
Result (written as part of a raw transaction): a82055c53f5d490297900cefa825d0c8e8e9532ee8a118abe7d8570762cd38be981887

The redeem script is simply combining the two, i.e. (here padded with a lenght byte "2c" in front to make it valid):
Code:
2c080123456789abcdefa82055c53f5d490297900cefa825d0c8e8e9532ee8a118abe7d8570762cd38be981887

Calculating the P2SH address can easily be done in Python like so:
Code:
>>> import hashlib, base58, binascii
>>> base58.b58encode_check(binascii.unhexlify('05'+ hashlib.new('ripemd160', hashlib.sha256(binascii.unhexlify(b'a82055c53f5d490297900cefa825d0c8e8e9532ee8a118abe7d8570762cd38be981887')).digest()).hexdigest())).decode()
'33CGouuJW2G66mDaQ13pMBDuztW9eLKiKw'

So, we have a public P2SH address 33CGouuJW2G66mDaQ13pMBDuztW9eLKiKw, and all you need to spend from it is the redeem script.

You can use this online service to spend from it:

https://bitcoin-script-debugger.visvirial.com/

This works almost OK in my experience (specifically this tends to insert an annoying OP_PUSHDATA1 that you may have to delete [and fix length size byte], before you can push the unsigned transaction via a web service directly or in your wallet); broadcast('xxx') in Electrum works like a charm for me in these cases.

In other words, I can get all of the above to work well, but it is semi-manual work.

And yes, this example should not be used IRL, since the first time you spend from it, the scriptSig will be exposed on the blockchain; an since there are no real signatures involved, anyone can spend from the address using the same scriptSig again and again.

My question:
Is there any wallet software (not a web service!) that can take a scriptSig and a scriptPubkey (or just "import redeem script"), calculate and treat your custom P2SH address as a "normal" address and give you "normal" control over it? Without involving private keys, for which there are none in examples like this.


As already mentioned, I can already do all of it manually, but... software wallets, hello?
18  Bitcoin / Development & Technical Discussion / Compile and run a "rude" full node - tips wanted! on: July 07, 2020, 03:34:12 PM
I want to run a "rude" Bitcoin full node. As an experiment. Will build from source and run on a decent machine with a backbone fiber connection.

(For clarity, this has nothing to do with just pimping the config-file.)

Looking at the source code for Bitcoin core, my first changes will be to modify IsStandard() and IsStandardTx() in

https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp

to always return "True", i.e. I want to relay all kinds of ugly transactions to the network, and not have any of them deleted from my mempool.

What else can we think of?

Hm, fees. I don't my node to say no to zero satoshi transaction fees. What do I change here (and/or elsewhere)?

https://github.com/bitcoin/bitcoin/blob/master/src/policy/fees.cpp

What more... the maximum number of different sorts connections needs to be addressed, here:

https://github.com/bitcoin/bitcoin/blob/master/src/net.h

I'm thinking that several numbers must be changed here, especially the two values that end with "=8" (I can't write the names of the functions out, Cloudflare - interestingly - blocks me when I try to write them) should be changed to "=500" or so.

So far and in conclusion, I have: Whack "IsStandard", allow zero satoshi tx fees, and increase the number of allowed simultaneous connections to big numbers.

Your turn! Hit me with suggestions what a "rude" node should do (and please point me to the right places in the source code).
19  Bitcoin / Development & Technical Discussion / Catastrophic P2SH public addresses? on: June 23, 2020, 11:15:36 AM
Been diving into redeemScript and their corresponding P2SH addresses. Have a question I can't find a definite answer for, trying here:

Is it possible to create what I would call a catastrophic redeem script, hash it and output its "3-address", which will - even though you have the full script and hence the private key - always fail, i.e. always return "false", so that any coins sent to it are forever unspendable?

Since P2SH addresses contain only the hash of the script, it is impossible for anyone to call it "bad" until the underlying full script is revealed, i.e. when someone tries to spend from it.

If I understand things right, redeemScript are actually executed during spending, not only "this hash matches this input, we're good", and I would guess that it was fairly easy to create a script that no matter what always returns "false"?

Am I right? Can I create a "P2SH public address blackhole", send coins to it, reveal its full script (private key), and still no one would ever be able to spend the coins?

If this is a well-known thing, what is it normally called? Thanks.



 
20  Bitcoin / Development & Technical Discussion / Privkey burner - what say you? on: June 20, 2020, 11:43:51 PM
Privkey Burner - Yes/No?

I was thinking of new methods, standards, or procedures - call it what you want - with the goal to further discourage address reuse, and to give Bitcoin users an additional layer of plausible deniability and the benefit of the doubt.

For the sake of privacy and anonymity, and the advancement of Bitcoin.

So, it struck me that if there existed a service - it could be a simple webpage, to begin with, even though an optimal solution would be a peer-to-peer implementation [maybe as a tool in Bitcoin core and Electrum] - on which you could publish used private keys that you never intend to use again - there would exist a public database of "burned" public addresses containing the ultimate proof - their private keys - which everyone could easily verify.

And anyone ever confronted with the question whether he or she controls a certain public address could answer "since its private key is in the public domain, not only I but every person on Earth controls that address".

My questions:

-- Is this a new idea; what is the "prior art", or whatever you prefer to call it?
-- Do you like the idea? I could mention a couple more upsides, but are there downsides that I haven't thought of?

I'd love to hear your input! If this is worth pursuing, I'm ready to get technical and start working on a service for this.

Please!

---
Edit (additions)

-- Submission to "the list" must, of course, be anonymous and difficult to trace (like how a Bitcoin transaction is broadcasted)
-- "The list" shouldn't contain timestamps linked to individual privkeys (ideally, "the list" contains no meta-data at all)
-- Only privkeys that correspond to public addresses that have appeared on the blockchain and have had a balance should be accepted (or "the list" could easily be spammed with quadrillions of entries)
Pages: [1] 2 »
Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!