1import wallycore as wally
2import os
3
4address_prefix = wally.WALLY_CA_PREFIX_LIQUID_REGTEST
5network = wally.WALLY_NETWORK_LIQUID_REGTEST
6wif_prefix = wally.WALLY_ADDRESS_VERSION_WIF_TESTNET
7
8mnemonic = "supreme layer police brand month october rather rack proud strike receive joy limit random hill inside brand depend giant success quarter brain butter mechanic"
9
10# start-create_p2pkh_address
11_, seed = wally.bip39_mnemonic_to_seed512(mnemonic, '')
12wallet_master_key = wally.bip32_key_from_seed(
13    seed,
14    wally.BIP32_VER_TEST_PRIVATE, 0)
15wallet_derived_key = wally.bip32_key_from_parent(
16    wallet_master_key,
17    1,
18    wally.BIP32_FLAG_KEY_PRIVATE)
19address = wally.bip32_key_to_address(
20    wallet_derived_key,
21    wally.WALLY_ADDRESS_TYPE_P2PKH,
22    wally.WALLY_ADDRESS_VERSION_P2PKH_LIQUID_REGTEST)
23# end-create_p2pkh_address
24
25# start-derive_blinding_key
26master_blinding_key = wally.asset_blinding_key_from_seed(seed)
27script_pubkey = wally.address_to_scriptpubkey(
28    address,
29    wally.WALLY_NETWORK_LIQUID_REGTEST)
30private_blinding_key = wally.asset_blinding_key_to_ec_private_key(
31    master_blinding_key,
32    script_pubkey)
33public_blinding_key = wally.ec_public_key_from_private_key(
34    private_blinding_key)
35# end-derive_blinding_key
36
37# start-create_conf_address
38confidential_address = wally.confidential_addr_from_addr(
39    address,
40    wally.WALLY_CA_PREFIX_LIQUID_REGTEST,
41    public_blinding_key)
42# end-create_conf_address
43
44tx_hex = """\
45020000000101b4c2af876d9d24bf4e3f3da5b4d2cae4b23228074b1e9a0c95daa3374f23a78701000000171600140c0031f1b57a9363146e7f8412daedb348712062fdffffff030b86ae25b435f740074a9cabd6a9dd56ed23f4da5a7733a0236986c92c7750912108d998d28d0780cb8f12732f20298b53af93f697e3038e39ea1036628d68074854033feb02f8fa4c9a1afe3cdfead7a097e9958ee1dd25f06448df7ac067ed918efe17a914cf5de8a32131ae2a9e439a3b27900379ad23e079870a813de038afb522753b25f1bbb6e6ea783280a955e482d024dd588698125b5e2208b171fb20da2d42aa94c565425826592b3c5ab9a46c8c32235fa94d9eb8cd184803364c9e99314681c70c3c8bf5ac0ff5c7bfa5cc25b1a86d9ececca1fb9451d8451976a9147726e526b5a8675a4485bcd4d5e5d88a7dc7be2688ac0125b251070e29ca19043cf33ccd7324e2ddab03ecc4ae0b5e77c4fc0e5cf6c95a01000000000000553c000000000000000002473044022016663118197f2a2708cc68bea746648e9edea9dce1978454a6f60c8f2a43fbcd02206ab2778e25ffcb90a0da57c689a5b43906979e95ca07ac091893175df257ccc6012103041b5150cca7d970a073c15869b1df699e23831cc25d239da16e8dd0fde230e700430100010f1dce6a97ea615da0e244c030a7c717bc7b97b9f2212a84c56cb7929720f4486a8758ec3f056d5c6b87fff1f25c470abc5a31a5ff1fdf3defd6fc8d774fe37afd0e106032000000000000000126dba401d525c642770fb55e503ec7ed68491fc6a70f4a69cfc1206f296b7412db18eb9977396fb665e36bf335487ba2c9cbb3e140e5d9f1d57860156fbf347f75f00608c37a4ea19f8041b8c41d1d6ae39e6a8fbd8274fa986e9bc2a00bcd2438b5d4204a84e1b9819ddcc323cb2061bd217bc6f83a630f4ec4ba08e0eb1d567b7119f76ce14e03316198bb27836f897f0bd2ba836a78fafaba1017b97fb94157a9ea64e7b051bfbafefb427b991d6e85f8b958478045987d9434faffb8b25b5cdc0d9abfc3a9d2f25630327e62e5e178abfa16e54fe482ee9ebf29e862253f0f2319c59510f062283235452e5c1ad26ba31f2483e21ed82c44112414e88f585d000caaac1f5bdebe590d40cf94a5d6e6c5736e193333f35fd30e9eba4e3b93f6129e6eb53506dcc9dfd3ab7b88f1c471537a6ac20c4b6c3aa2d010bd1545c129a5d73f853bcfde0ddcfde080ba84dd16aa336258bd7e3e6e9b94da7fb4e5f90a8b4f508023046fe3b967e9f171a5146e7f9bb1f01d10bdf394704103a5ef26db8712c2fc2c356cfa731cf1ab0d7a7c21f70c73d225624b96305ee6af27b2ef8b22914ef37d38e6ca5bfb60e1802a193c1cefbc3f825515555fd8003ace845cd2d3d6008e6972cbb1a9ad73f4326791e4f0610a00e9b540650911277f50fd1e406f47539a96610f45197d57b93bd7e9617767daeddd8b42a6431d452efb5cbcb593e8d12a06f3970ad5b80cfd053a59ec09c50e5aadf6cd47fff311f332297b043f94aeeba5675572c1c4671ed53d14a04dca2c6bb99986e5d63b89d5c083c492f65f0b617b38a48031b07c5ce18d43a472c703f3760e4270086102af22daf5aeac5039018582c8cc45ccdd17d3a4a4aa833d4449087d2cfb1c211b6a2ee973542443a70f13fca340e198b24af6be8f8a91d21c0a130da9d238528cbe9f376c641f4e73b1ae5a11a7d0369166b97cdebe4d84b5735064bd1f97b1ad5c234f8a4eee7c897884f937f704d4c30d7c65950e670b925c591093491896bfe030aaeaa3822c81852d5de56e8eb48ceaf8c0de6104f8ed105da7c77c7ff860505d452bed6778648a595fb7cd2b8fa4549ea91576c623b5d9f4868eb2044365aa5019db98eff5d01e1a3f314d00fe9ecca5c35bb4d635acf7e6faa94a5cc1ae1cf465d8520cae53f07c3cd31dd1489fffd869dcdfc5cfe43616b148c98d1f38b579aaf56c4f84144383a213680d5df111bc2ad72d5e6572a699716d02039e652bff4c24f0b3ebe72f660a6c753ae03cb246e5db242e8dd96068439d3a1c74e42ceef1fae94c0c320e910d985ac53300cb5cf07853561ea80dda60154075dba28b904dad9a4cc0b27df6c488b72009b1520c0e6a5b70a9fdb27d51bf040e3d99093035f596baccf206741440b954df75390719c6f6885d1dab1ca6ede6a31dca0fa2824a2ec6e8cfd4cc81a9c657aac0c3c1c23590d52b8a85f0d0ba16e8bf202fed0709bc85216867edc376da0f1194fa59e984087318e54c703eb63685feecb9410d1615c83fcf1c1241f8fc8ffe41cf06c7e28986c1118aff66a0f82712a601829f15b201dc9b2f3de98e416f26e19ebd09b0fbe035fa65bb831636a4e6b8a95f9ad0957baeaea9d96841701a0e0b6af64811a52bd28edc86dc3816d822ec14b85b01419429476f6119d449a68cba580063d29069d933f9ae9e704a6199354b283377b5b2dfcc9e7ce6d1c78b4092152b2cc1e24d9701189e03d9b8bc0df212eefdd4678f16789f853ed7311e327d1b07769d8978494c6593b3034a0d187cf0a432ab98d90d0b62590f0ab687114d9cdbefc043d1d0831dfda11bf476508fef691662315eda7bf6caea740c40b6680c5dd0631a88d92877e0f2bd51eed4236e5fc45fa432aed43625236aede94b199d66ae3e14d417ed6a34579bb48421b312c9f609312827fe23e4a6140e1190738f67ea4d1105dc86a5a626d9531c76067f6d418a89dd054e32f852cbf6ce78583f0b193b9fc7d3ebeba46e5a4241078ed956cc3caa02b6d178f6e0351ed88af30b3a7c4c240c083d4e65ab64193adc34e68e0da6e7a55bbd9cab6e2a73c9d0ff8146669899ee9fa5d7a659ca0c5ad79b716a74fc3d0bb059022baaef366b82e2754dea03ce82d2931548a10f9095a8f34cda88fb396a18ad2ea67dd753a96181c20dd37f9ddb03edb8ac4325a95529fcb523d2d9a74ee997657b670f64462b44a382e303ff9f783e426cec64e7133d82adffb565eed49401a4a6dece7cde12d17d2e79edff8a2cbd8c09aaf036b74dd07e6b6b556ac5437bb0766701e3918dfe2d3a5c6b196c7704d504184d16eee3c35b3d5abd4dae1ce41cc5d3951e67f7e27a774ffc597a52ea729ceeb66eabfea556daa02393d2495475bbd37e505ead6fd7bbe64887c39bc22410afbad0c3381d3318bb8693d2f2862ce653f0bc483a343674c0b3af12a8aa9c020d7f2e94392556d998c8b8fbadc10e0948571ce6058c98a8e385970e9a63b23dd518b1e814a851a8f5ea4c0f723eae891fef5bc9f71b0558ce128498043a7049f11b184d9073da594e9159efa5e43692e10cf56f75a3b2a28709d4d07210d84345f386c7cd6c72c14181d1b65bc607240325c0138c0d1d47e86953b8f2a1d7b6f0edab3187a485bec12d346ba9011e1001ff81161f4f34930fba1be0a1909f5d10e182aa8e78d96245a2302ca35554d0867dfb401413b609b941c1754b568dff54be9986134155ffed7ba714c18f8bbe11fc1e7977a4f15ec8e5ddb1b739b9bfccb6976a45e5bcf8be08667cd7c90023a12cb02b36bdb25cbfa43648b07e51bee64729786825daa1fb2034a8e07ef89e43598d3cbec43bfb69b4c9b22e5b33b18df0747eb34ef046db9dbba6a0ca1d993c6234695aa8db198de3553bb64be2816896532810e173ef2bc7ffa891d2b81ca33a6d20d8df30e84069143601d60cbfb0e60e9333bda0b4677fecc09d2498a57b8d481a54a77a008c22d1a19ece9a1298f2d7784c1f444c3ebeefa6b6b8530e902bca7bf168d8e257527cdb0affe6a6f5d9aa5e27d38d324c6745ad40d1c73fd33ab9c61ed38f873a2a91bb3f5f38e293813fbbd5bfb90cb835b30ff9fd19e29ee7551cf7400540be80effe9c6c4f56447e25ce7291c3eba7d96722a04606b5a95c23b5594f96769eebf7271e5a2f28ce36989f778cfa8e6f5027840f4bcebaa96e7917268668d3dca622e830009e2ba79dfccedf639dbba5512399b5452ce1385eb149fa42b31052dee0c63a2ec0403b38dcfa519dc154ed0a0d3f2814d40a37991e42895ffef7d6f02caa3ba54dd3b5eda3e6ac19210ad94a922b6ce112c13f2d2757332fb9eba18d6ae3759c7a2019f55c32139cd093d105a4ce03986493c808811f1c219104d2f89a6f6197692ea335960754b2b8281776937920a759474cbc31cb0fc821e94dd337669f1df3422392f0aabe36be5d4c22b2d948505b754e4216aed5195d1ed21b5d03350dd9b3c34f05c7ecea0f5b2b85122d145153768f92166f708726b5b27da6a072462b8eb2fa5ef520ffc7119be6f39ea32ea6fdac56d3db7afe05c19db7dcd9858b5c0eebeb850ad64987eafab01c5b9bf0a731b450a76521c27670c4f25881705ba717dc17dcff723bcd59013a4c504b50395f35b8ec498c8ebffc340ad95fcdbda21724e4edd3695af113300d01c571a7494e3af7d389e3d6bfc3efca037b12697812f41a3107f79629a8dfc784d740e364aeec91b2a24f6d6455c5b5a39a980a9b8cbce6171fa7a8b67cf81af5ac3c37006c05013590d888706fb1feae2da7331aff78cfb2df435f771765b94909ae6552cd6d6b938d58f5e7efd54ea3e9ca14cce9a18a891b52e6185f8e2735942678a8520b0a2c65044fe0a6f2fd293b81e3a11b371c53501adce45762cd63453a856a16c93ea3a1cf2025d4d81f621930e1bb6f4f8362adda0fcf6aa7c2442f4329361495c2cb51635ba690dd6d84a960d4fe2c92020ae2dcc3edad40b36885b7efdfbebe91a5059d01e6abe18c7a82d2c86ed65086f312be79db0bfd8e8fe27e0c9f3b18769701f66a7ab944a0df1e22ee840b560bb26679c1fc55295c3a4816ecfe0c31ad7ae76373a0517bbe37f00226ca511f1c51361fcbb7922c799e4055c18fda01086ea0f8bda040b09cdc13fb57adc7fa8a55de30856cc564df25344ddfd99392007bb5b6ecb84d11b580d88bd4000e0a49fd712f2d8cef4a67c9c79654a773d9d7c4083a30da38485aa1614252b03439521cb9084abcab20445c866ff3cdbb0f5a5d055da959917c5b36801383710e678d3d3ab661f74a531bfb74810e5d53f09ac696024a99a30126d5c86f008f1cdb7f55f182c8d99e68b5e3f09559bec98d68b8d48c1b380ccbbdf1a5a3239062e1fc1b9c6fbdb2e6afaa4db0d9c5a3ca2452e40898819ff660991590fe2d7d9d6be154954f08860af6241af565cc52b00f5af9950eaa270e793a3e52fa8408c2cb36e8c4035180dd1e212f665e1cb4f98c1c923d5fdd2d0410b74a159551d5540a3c85466be9a808c3b7ee32a31943d05f249e64d86ea96f4be787a79cd540c68eb9e00ee393234ffda412548f6ec6e84a661cd14cfc51a60cb887036468e218266b878e579791bc1a98364ab5de78f47eb0839174c9a0c76cdfc7d5f77c1afcef4e9c5fd095746cd62ea645be5452cb9667871729308cf2caaaa8c30c0dd5ec2d577f2c8e999435ab1a04892e97ca2de131a98cc52d8c7e1e00dd7a2f9a975915ba4c2a636efb4b11908bd5884d57ada05efbd17183e2b851d4e7949ac58f69cd6faca2d19ef5a3d7c090976c8e56cdda7faf81c03e4adf44dde11f22bc54a130354db5728bdf4356944f07d090abf0f3b71f03f86512c57b8a325425b7d9a441949ccf72b74656ed1a9e1b2b0d329008e169febf26752085753973343379ec1955fbc58ec3d70b9722d3a00ce609cca84a4f534e776f463b917bc368e5c4f63eccbc36197991141089811681781c45f3cc194fc5d7370342e96fee6ffc45d037930691c8e6ab395c3f5a543a9f1a3ddb42cd1f9285b0ae2427f767147fbee9f7f61e80dd6b4a156f1cc81290f607bfe8ad5ba75cf4be245ef41757b7d1e1b543702368a1519f6c17127acbe8e26c1bf80ac93ba0e822eae900ecd090d8d3d15aad8798353fdb5f9127723da52cad1fdcabe766a9fb50e86b313c733c33aa2a84b539052bf0e17fb0263999edecd58cd2f1a9ed3d20514204a6537208866bdce33bf5423003e7de9bff110aba42d40714f7bd0a245866ce8e6d5f04fabef9062e1788af4c1600b8ce50ce4c89cd5a10486db33d75c47dd8195f57dceb2523c909068eaddaea85ac8f00b8cd30c57532a0e35100163c232661ce0824b812ecfad9118878e86248f49f5412dcf9e852f0946afca6fa7868fd0e63ab6f3c2556a4c8a93e8824702a7d784b4a905aa5ff864218b1809c43c7fd7a9bb9c0bf4315fa2e427653168cda2c4bbd30c774f6bdc29190df56658b4cf495c750378fa029073ac647720583683545f1acd595b8923f4c28a24bbd17d0691e4cb7c36f3598153357485ff8929472cebce720388459a8c254c41219ebf29a3c33f5fafae5a696d89b90226def4e6761c045efa3339cc4d4df11d24fbdd16c03d9d7bd48c142e767bfbc87452972a1f48221967016b4728dea61b7d16b02804207dc4c44b37417ce899a5e9bd54a54a802e8881ecba231f246dc2ff257dfb4630b92801b68bc8b3350867d4e0a04051f7cf3fdf11043010001d163502b5bf6d10ca6799c371261ecc633475cd11a26bcd97b473a09dabd61caae7f2121b3db169500100fe536bf4f1e721633d5bb1df29e27dbf3fa515424c6fd4d0b6023000000000000000131f9015e1cf8bb5847a55e0eb809de16a28f96a0416869a57f91088370db6feb1cedb165a7f00fdb834560d909fa80ca26cac9ced13433eb006f699e2d6a17c59c4c40b0d405d5fdd2ea0ea3dd4ae8000615c6c0ac068429e94b124e763e81844275b4c49c26d3d9fb22b94f9662bd57424b8a3c06ff04b41c4235d6f7e389c852fc2651de9c1ea8ca8b7943539296fc0c36562451c22a1d85b603437e17a0391347b041b7cb2f9063e7ca384ec6a15987916664bd8f3faee0423201bab556207fee96322e4a04dff82896ac334a6042600ddbdb81ac5884ac302294bd80b7187d59a50eda4405b396b840787a2a0891c100fd2cb27d4531baa6a3c41f3e72a9bc7ef302399811df17e72972a3f718f4b0d029e83ea14dc5af5f91e2697fb85881a90eb4dfebecb518609af552c497e8a2b7d6523d3bfc3a0dcb0524dba478f2f1e0be391b3889e958a9c12a07239d3f0d71bab5e5ff84fb8436a0b6a7c22a0f3e62908a049f39ebe154a97655152ff308417a9687925481e2049e6ae932d169034901a3382bb031953bd7b93aed838b56da6625c27092d7c51c6c91532bc54f82719d6e029e0dfa309c7c6e981176fe86b6fb5a2b744309b4da313cc5b445dc88c4c305f6aa1a421ab6308412500c4d6489a320bb52124b69afe247dd263a67a474532f2825b600a1b2ef779d708448e5d5dd356c2a55d83bacc7b759a8808577035f9087fe57982809757820b977d01b41b520775d85dab189cf29b950ee7eaaff113615ef1834e5dd3738210a1f10a702369e41959ec05d28ecfcb9b712f74aba5f01efeb02e23cf1d93e202281c46061296f1f8cfeddf8d6f8dd2916d9544a6e4456e5b2ba4717137df3866c0d458ee6fd51035152baaa8108bcbd6ebf19aa0c712213210c52f1c81d3a3606c108c580b4d9c212ba9ec5e34491e0576a1f33f46084f69c12e698b9799b31d3c66458da917859e437e2ca95f7305485af41632d7014c94eb9c815e5a16582e2978c484836f237414259980014a6b8b051713ab237faa3ab61ef2c07f0cf522ab6c3ee17697946109981b94e4ef556d2d85ed3fe241d992a34d6fb07082f0ad01f599d2a220294fbac0bc831c1690fdaf91505da30d902a521627a42813802acb910699ec93533b6352ee2894b9b88e06ade914a2708440ecfb01b1ab9052ff24da7a41822df15be0257439f79d9ffcec1783034aa2573859126e0316a26c4f950ee161e33fdb06951a0c1df3ecebdb8a1fd5818e06e43d70e242ff53ca51fc8c0db4dc73e854513157cd6a908824da3b4638fe419b9f328ad9869ddcadb1959710b9897dbc9155e1d05ec8bbec6cb2dab8004ff58c9943d73344a21d8c974ae689ac54c89356de6a42b5ec3c5bae882b4e3824584f1f879bcec99e7d14a0901ad6dd24fdff986cd6660df50c9b2dc90560de8f023f2a469906e60b532c12b4dd2348eacb04d92f3425af499fd48ffef5fcb48c33cc68b9a7461bfa2a23c0d0b480cf932ec79862f8913f3d64f7f734ba630d454f9b3369ea1329cceea9ffd17e9c027c124377e8790a34543f7c4608c776914251a487952edc91fa3feb52a169e7a51aec9bfbac08f7ef1f4ad94ebc2c9e0f90979d934f5661add09036118e782870491246cb65bbe4026e6daa6bee79fa69234d42155508ebee9459d89ab269f88005e397a44d60989782cc1e751072df82430b0d022708173ea40354aab6bbe09acd9804d68c682b47407ea7f0f216a3d6cb23139932f4bf9fdb00d23b050c58b4a3805a250ab539aa30214df2cc0d1ec2d33035288cead053c6497370b393ee1526958276ef337c6ffaefd1f162fe3fb45458733be38cc695e9c9ec48002c64b2d7c106c12b55172a44c3cdc798a7e7b7b2db6e74980b1aa62f3c7bd22a9392d94515579fa4879b23bc06bf40feb8a879f520c30437dd3db6349122cf0b00568afd5598cc01c985de75ff13e0293783361391eb87273fae1abfe81a495d81a67481c4fe9feeaed68fc1915fc3c045eabc8eed6f62a61b637cca78b846e2b076cd83b0dd72239d5e43068ad920b1706100d66ac9c3c200d6b4e4a2fc29d338fb44e7fbc8e203221de98d7a1bd00b832ef9c7c7fd3811cb8f825e363561d2acabafbb619f2cdbfbe71458babc944c20b289f1b85e169b6da2134dd89acafd7a6a51d0550f5c5cd7b13ea4555d7cedb2cb43b7bb57c37201c5eb8d25e5820eaadf683f423eac23a2ee4c31eedfdc2df76f55b7fe1c7c2809137d4d83b9398e3c61b427173a3880f78ed2d3c62d9c7bef94949ebe745b8d0ff2d8612c389cf28b2c87e45b30b3f5ffdb948039dd07fd27f8b31defde240732c593f82ce667b8df484d1cb733df59c719a37c78e7625fb904b05a71525cc027634136a06277dd5558164c651c4132304c6acfc07c35fd6d44428cf2c84399a63820c8eb57d34a0721b35002e8a325d80d38a52cdff4103da36ecb665530da35a6ebd365cf8345750e315d652c0d0f606ed1eec78ebd7bc9aae5e43ee617cb961a98fb2ce4c0f4dc2daa9324094dba3242e6ff4cfc4c825e1d76d65574bda4c8d81014609a9d5228c81e251112c60373abd829e712b39806485e6e1d4bbe26468a2bde6f45dbb01174b58c1e94cecf460e2770cd13de6a152a9eba47a2334c07beec8d04bf343b342ca76a06bed2391286b1537a41654334ea27a3781e090aae01580a92bf0958b3573e061b73b03a4bd96fa2504804bdfbe3756618699f258b021e51ff7fac2a2f5eeacaaf2ff74e63c866962632673dd8ef92d880592843f24e8dd977ed14fff323a5ff3ac870a15aba994b6d84d6650b3134dc49ff21cbf7d90d08cc3ee8dcddf88add06c9fe487cb658c799a4f3f7c802d8ea6bc976c6796a3c6730c1891ac818418b5c819f3e1bc924a0428defada9fd221139551ba35414059027d17b659f1583060fe035d96319d20e3cd3a29ce795c258a03aea052729c64b86118037d8d5b701c98aa29d447b128601af35aa6d743c62eb8b2e25b8243e7f9a1c3f248de57b49531f45653d4f0bf23815f4169c5b7e887ad5100e5e0311182967912a1147feebb9d6d73064493b8bde54a9c9d58e472650b99c5fa4f37392c9e01bf83dd057b69d0c1f7d0fb0be49b8eeff00b1ac7f5e041b0691974bee5cfea998cdb05f8642ad51e542f2fe1e5805b782cbbe8e120eb62cb1e49018902ae731a3f3bc3d00a4d61e84439bfc8dafc2b7309cdd4da00f5a38579ba4de17e60bfb532bdc76896c827444f8af7f75b4ef99a81aba27081a3f48f230428a942ad080251c2c7b6bf66a019e3618ef00d191b655b27f356d30f9e6b446546679f9633ad8217c15c63b22ca577e6270f845f3bcdabc16b79b38036320116dda6ad52a9c879a95a4b77884a88b9cfaec712b942e430e396a2e29a35aaafda94416e98089ce07ff9eb678aafc2a89d546fe8f16d36e5f9f5e2cf4c933f73274b531d395a8dfade99fd8b23ae1a02be6a818c149b6e5cc38b4285a9916cece697831c9acda14734f1d5ea03ed8e914b84342e2cedcfdc403e2531e27e3220d09573f274ab48bb5590c6a9ef76920f13ffdef19c05fe6c8422512444420c7313dd2d329c01e8361c5c897fb03f355150e4bfd8932b85332d4ace9cc00f70ebe19c19900024bc6c0cd4e21bf5f1864e424d78142177a2c20688deb948b586110af50c5bec1f0ac69a2f03e11371253180351ac29b1aba45d330d9117c620393055cea3370a2396af28ba5e031199bb446433b5c8423bdb614343ee05b50afd3849e7b1f6b3a61e5c93e50149d7042fac214f64fa89d10be4ad16ad0455bf6f4945d4f953b376c2873759aa689da45090340b804de2b9d06d6586615877f2d3d9790cd78ae592043c1b640b15f5b6a9e3451ecabdb13c8f8076d6563630edfc4ccf46b2a72dbd16d8b62e221a7a0f7a5958fed6405bb6691b1443807a663bc4eba2d4cb44a97abfc446b28c62efc7f0b1dc191545b8ebdfa1bfee2ba596c1cee7150a96cd18882a23758fecafad405e033eb3a2093bfe6d62fec4ca2560a0000\
46"""
47# start-create_tx
48tx = wally.tx_from_hex(
49    tx_hex,
50    wally.WALLY_TX_FLAG_USE_ELEMENTS | wally.WALLY_TX_FLAG_USE_WITNESS)
51# end-create_tx
52
53# start-unblind
54asset_generators_in = b''
55asset_ids_in = b''
56values_in = []
57abfs_in = b''
58vbfs_in = b''
59script_pubkeys_in = []
60vouts_in = []
61num_outputs = wally.tx_get_num_outputs(tx)
62for vout in range(num_outputs):
63    script_pubkey_out = wally.tx_get_output_script(tx, vout)
64    if script_pubkey_out != script_pubkey:
65        continue
66
67    vouts_in.append(vout)
68
69    sender_ephemeral_pubkey = wally.tx_get_output_nonce(tx, vout)
70    rangeproof = wally.tx_get_output_rangeproof(tx, vout)
71    script_pubkey = wally.tx_get_output_script(tx, vout)
72    asset_id = wally.tx_get_output_asset(tx, vout)
73    value_commitment = wally.tx_get_output_value(tx, vout)
74
75    script_pubkeys_in.append(script_pubkey)
76
77    value, asset_id, abf, vbf = wally.asset_unblind(
78        sender_ephemeral_pubkey,
79        private_blinding_key,
80        rangeproof,
81        value_commitment,
82        script_pubkey,
83        asset_id)
84
85    asset_generator = wally.asset_generator_from_bytes(asset_id, abf)
86
87    asset_generators_in += asset_generator
88    asset_ids_in += asset_id
89    values_in.append(value)
90    abfs_in += abf
91    vbfs_in += vbf
92# end-unblind
93
94destination_address = "AzpwMmJacz8ngdJszGjNeNBeQ2iu5qNYWpZfkqBoZU6acK6tSbEdpt9PsWdRtcb2pxAQcdTySE4KmhJk"
95fee = 1000 # arbitrary
96
97# start-define_outputs
98total_in = sum(values_in)
99output_values = [total_in - fee,]
100confidential_output_addresses = [destination_address,]
101output_asset_ids = asset_ids_in[:wally.ASSET_TAG_LEN]
102# end-define_outputs
103
104# start-blinding_factors
105num_inputs = len(values_in)
106num_outputs = 1
107abfs_out = os.urandom(32 * num_outputs)
108vbfs_out = os.urandom(32 * (num_outputs - 1))
109vbfs_out += wally.asset_final_vbf(
110    values_in + output_values,
111    num_inputs,
112    abfs_in + abfs_out,
113    vbfs_in + vbfs_out)
114# end-blinding_factors
115
116# start-decompose_address
117blinding_pubkeys = [
118    wally.confidential_addr_to_ec_public_key(
119        confidential_address, address_prefix)
120    for confidential_address in confidential_output_addresses]
121
122non_confidential_addresses = [
123    wally.confidential_addr_to_addr(
124        confidential_address, address_prefix)
125    for confidential_address in confidential_output_addresses]
126
127script_pubkeys = [
128    wally.address_to_scriptpubkey(
129        non_confidential_address, network)
130    for non_confidential_address in non_confidential_addresses]
131# end-decompose_address
132
133# start-create_output_tx
134version = 2
135locktime = 0
136output_tx = wally.tx_init(version, locktime, 0, 0)
137# end-create_output_tx
138
139# start-create_outputs
140for value, blinding_pubkey, script_pubkey in zip(
141        output_values, blinding_pubkeys, script_pubkeys):
142
143    abf, abfs_out = abfs_out[:32], abfs_out[32:]
144    vbf, vbfs_out = vbfs_out[:32], vbfs_out[32:]
145    asset_id, output_asset_ids = output_asset_ids[:32], output_asset_ids[32:]
146
147    generator = wally.asset_generator_from_bytes(asset_id, abf)
148
149    value_commitment = wally.asset_value_commitment(
150        value, vbf, generator)
151
152    ephemeral_privkey = os.urandom(32)
153    ephemeral_pubkey = wally.ec_public_key_from_private_key(
154        ephemeral_privkey)
155
156    rangeproof = wally.asset_rangeproof(
157        value,
158        blinding_pubkey,
159        ephemeral_privkey,
160        asset_id,
161        abf,
162        vbf,
163        value_commitment,
164        script_pubkey,
165        generator,
166        1, # min_value
167        0, # exponent
168        36 # bits
169    )
170
171    surjectionproof = wally.asset_surjectionproof(
172        asset_id,
173        abf,
174        generator,
175        os.urandom(32),
176        asset_ids_in,
177        abfs_in,
178        asset_generators_in
179    )
180
181    wally.tx_add_elements_raw_output(
182        output_tx,
183        script_pubkey,
184        generator,
185        value_commitment,
186        ephemeral_pubkey,
187        surjectionproof,
188        rangeproof,
189        0
190    )
191# end-create_outputs
192
193# start-add_fee
194BITCOIN = "5ac9f65c0efcc4775e0baec4ec03abdde22473cd3cf33c0419ca290e0751b225"
195BITCOIN = wally.hex_to_bytes(BITCOIN)[::-1]
196
197wally.tx_add_elements_raw_output(
198    output_tx,
199    None,
200    bytearray([0x01]) + BITCOIN,
201    wally.tx_confidential_value_from_satoshi(fee),
202    None, # nonce
203    None, # surjection proof
204    None, # range proof
205    0)
206# end-add_fee
207
208# start-sign
209flags = 0
210prev_txid = wally.tx_get_txid(tx)
211for vout in vouts_in:
212
213    wally.tx_add_elements_raw_input(
214        output_tx,
215        prev_txid,
216        vout,
217        0xffffffff,
218        None, # scriptSig
219        None, # witness
220        None, # nonce
221        None, # entropy
222        None, # issuance amount
223        None, # inflation keys
224        None, # issuance amount rangeproof
225        None, # inflation keys rangeproof
226        None, # pegin witness
227        flags)
228
229for vin, script_pubkey in enumerate(script_pubkeys_in):
230
231    privkey = wally.bip32_key_get_priv_key(wallet_derived_key)
232    pubkey = wally.ec_public_key_from_private_key(privkey)
233
234    sighash = wally.tx_get_elements_signature_hash(
235        output_tx, vin, script_pubkey, None, wally.WALLY_SIGHASH_ALL, 0)
236
237    signature = wally.ec_sig_from_bytes(
238        privkey, sighash, wally.EC_FLAG_ECDSA)
239
240    scriptsig = wally.scriptsig_p2pkh_from_sig(
241        pubkey, signature, wally.WALLY_SIGHASH_ALL)
242
243    wally.tx_set_input_script(output_tx, vin, scriptsig)
244# end-sign
245
246# start-to_hex
247tx_hex = wally.tx_to_hex(output_tx, wally.WALLY_TX_FLAG_USE_WITNESS)
248# end-to_hex
249