diff --git a/src/main/scala/fr/acinq/bitcoin/scala/Bech32.scala b/src/main/scala/fr/acinq/bitcoin/scala/Bech32.scala index 5371909f..d2f4e627 100644 --- a/src/main/scala/fr/acinq/bitcoin/scala/Bech32.scala +++ b/src/main/scala/fr/acinq/bitcoin/scala/Bech32.scala @@ -8,6 +8,20 @@ import scodec.bits.ByteVector object Bech32 { val alphabet = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" + sealed trait Encoding { + val constant: Int + } + + object Encoding { + object Bech32 extends Encoding { + override val constant: Int = 1 + } + + object Bech32m extends Encoding { + override val constant: Int = 0x2bc830a3 + } + } + // 5 bits integer // Bech32 works with 5bits values, we use this type to make it explicit: whenever you see Int5 it means 5bits values, and // whenever you see Byte it means 8bits values @@ -56,12 +70,12 @@ object Bech32 { } /** - * decodes a bech32 string - * - * @param bech32 bech32 string - * @return a (hrp, data) tuple - */ - def decode(bech32: String): (String, Array[Int5]) = { + * decodes a bech32 string + * + * @param bech32 bech32 string + * @return a (hrp, data) tuple + */ + def decode(bech32: String): (String, Array[Int5], Encoding) = { require(bech32.toLowerCase == bech32 || bech32.toUpperCase == bech32, "mixed case strings are not valid bech32") bech32.foreach(c => require(c >= 33 && c <= 126, "invalid character")) val input = bech32.toLowerCase() @@ -75,30 +89,37 @@ object Bech32 { data(i) = elt } val checksum = polymod(expand(hrp), data) - require(checksum == 1, s"invalid checksum for $bech32") - (hrp, data.dropRight(6)) + val encoding = checksum match { + case Encoding.Bech32.constant => Encoding.Bech32 + case Encoding.Bech32m.constant => Encoding.Bech32m + case _ => throw new IllegalArgumentException(s"invalid checksum for $bech32") + } + (hrp, data.dropRight(6), encoding) } /** - * - * @param hrp Human Readable Part - * @param data data (a sequence of 5 bits integers) - * @return a checksum computed over hrp and data - */ - private def checksum(hrp: String, data: Array[Int5]): Array[Int5] = { + * + * @param hrp Human Readable Part + * @param data data (a sequence of 5 bits integers) + * @return a checksum computed over hrp and data + */ + private def checksum(hrp: String, data: Array[Int5]): Array[Int5] = checksum(hrp, data, Encoding.Bech32) + + private def checksum(hrp: String, data: Array[Int5], encoding: Encoding): Array[Int5] = { val values = expand(hrp) ++ data - val poly = polymod(values, Array(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) ^ 1.toByte + val poly = polymod(values, Array(0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte, 0.toByte)) ^ encoding.constant val result = new Array[Int5](6) for (i <- 0 to 5) result(i) = ((poly >>> 5 * (5 - i)) & 31).toByte result } /** - * - * @param input a sequence of 8 bits integers - * @return a sequence of 5 bits integers - */ + * + * @param input a sequence of 8 bits integers + * @return a sequence of 5 bits integers + */ private def eight2five(input: Array[Byte]): Array[Int5] = { + /**/ var buffer = 0L val output = collection.mutable.ArrayBuffer.empty[Byte] var count = 0 @@ -145,9 +166,13 @@ object Bech32 { * @return a bech32 encoded witness address */ def encodeWitnessAddress(hrp: String, witnessVersion: Byte, data: ByteVector): String = { - // prepend witness version: 0 + require(witnessVersion >= 0 && witnessVersion <= 16, s"invalid witness version $witnessVersion") + val encoding = witnessVersion match { + case 0 => Encoding.Bech32 + case _ => Encoding.Bech32m + } val data1 = witnessVersion +: Bech32.eight2five(data.toArray) - val checksum = Bech32.checksum(hrp, data1) + val checksum = Bech32.checksum(hrp, data1, encoding) hrp + "1" + new String((data1 ++ checksum).map(i => alphabet(i))) } @@ -161,25 +186,29 @@ object Bech32 { */ def decodeWitnessAddress(address: String): (String, Byte, ByteVector) = { if (address.indexWhere(_.isLower) != -1 && address.indexWhere(_.isUpper) != -1) throw new IllegalArgumentException("input mixes lowercase and uppercase characters") - val (hrp, data) = decode(address) + val (hrp, data, encoding) = decode(address) require(hrp == "bc" || hrp == "tb" || hrp == "bcrt", s"invalid HRP $hrp") val version = data(0) require(version >= 0 && version <= 16, "invalid segwit version") val bin = five2eight(data.drop(1)) require(bin.length >= 2 && bin.length <= 40, s"invalid witness program length ${bin.length}") + if (version == 0) require(encoding == Encoding.Bech32, "version 0 must be encoded with Bech32") if (version == 0) require(bin.length == 20 || bin.length == 32, s"invalid witness program length ${bin.length}") + if (version != 0) require(encoding == Encoding.Bech32m, "version 1 to 16 must be encoded with Bech32m") (hrp, version, ByteVector.view(bin)) } /** - * - * @param hrp human readable prefix - * @param int5s 5-bit data - * @return hrp + data encoded as a Bech32 string - */ - def encode(hrp: String, int5s: Array[Int5]): String = { + * + * @param hrp human readable prefix + * @param int5s 5-bit data + * @return hrp + data encoded as a Bech32 string + */ + def encode(hrp: String, int5s: Array[Int5]): String = encode(hrp, int5s, Encoding.Bech32) + + def encode(hrp: String, int5s: Array[Int5], encoding: Encoding): String = { require(hrp.toLowerCase == hrp || hrp.toUpperCase == hrp, "mixed case strings are not valid bech32 prefixes") - val checksum = Bech32.checksum(hrp, int5s) + val checksum = Bech32.checksum(hrp, int5s, encoding) hrp + "1" + new String((int5s ++ checksum).map(i => alphabet(i))) } } diff --git a/src/test/resources/data/key_io_invalid.json b/src/test/resources/data/key_io_invalid.json index 9b52943a..8f55abfe 100644 --- a/src/test/resources/data/key_io_invalid.json +++ b/src/test/resources/data/key_io_invalid.json @@ -6,177 +6,207 @@ "x" ], [ - "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y" + "1GAdfviErV2Ew95FPtZyikz2qGP3gyCB6Hyu94sedAkPpA523m3fQwps9YKUZkKgQckGPKhRsFR" ], [ - "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv" + "37G2kMDLpmWVhimxRdzwNfE8JFvWXnJYnVcXeeGrek2qumdJuK7XArcVVpRtLLjRra3t64BEPF2" ], [ - "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S" + "giymtio7u7oqWtmC9YnvAEKkLF3JQpAdkEFkVJKYrVDfaLbhaDpX1ihfF2vZmya1i61fwLPC3YQ" ], [ - "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf" + "8iVk9nLM3nYwRuwypjy9NK5rsuZH7BbrQRZ1pgcQmvMnjAgRXD" ], [ - "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq" + "cPTVQ1hbo4qdoysf6Jx5GthqucNmdfqt6J2pZRFeXv8Ep7Kmjqud" ], [ - "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb" + "cQbR2Ny85XFBzUMx3Ed6HsTLw2pVruSgPvt5AofnBUnhiv86gYeW" ], [ - "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs" + "2UB3iG3VJbX2TRrMwm6ssWskgvU9VjFBYSqCzwqkrihCwo7mg4mtS4WuGZgxTKuxf5A3EcotYEymz" ], [ - "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3" + "cQe12pqwPR6ExtZKfrKf1q4b3CTh1Qi7MwuvMvzs79nWXDvESfBJ" ], [ - "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th" + "tc1qeul5g2xfkvdkrhcfmdursv73ad64jnkjl9c40f" ], [ - "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va" + "bt1pq65rzej5glw3ra79gav6fqnx4haa0z257qr3mc8cggkefahmgvyseufhc0" ], [ - "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk" + "tb13hty4qmumlwpp6chxjvcyzza4duqgtmxw3xhm3u9ahj4nyhtwz8eq7ynrj4" ], [ - "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs" + "bcrt1r2qxpwuge" ], [ - "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo" + "bc10uexgzna2dpfk0vjt35srz6a27ps6m0l89jweznt83n2sqn2fx4hvn9ym5af8wut34sfrqhk3" ], [ - "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso" + "tb1qum6uh0pt4q253qaf520929737v63w5gf" ], [ - "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq" + "bcrt1q888ryfgxpvl0k7vum8zpyar2u2sexvdhkf38ue37yknmqq0ycrwpl3w48y" ], [ - "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN" + "bc1qdsuzmn04k2z8vryw8l4dj8m5ygqgnne5n" ], [ - "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i" + "tb1qlj8es50nc8j8r8xshrjgzmw5azx89efghmw8ju6zcqla0g6xcnrstsjz7k" ], [ - "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos" + "bcrt1qzwmyj0z924g7fzs5yvnrkc43y76RVyr2lh5t4r" ], [ - "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu" + "bc1qpu6d26mrulzetu4jqhd7rsunv9aqru26f5c4j8" ], [ - "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb" + "tb1qun6d26ufh77ghny6u5u8cwz9da7qwc6k4wkuceae9tth06eqlw0syupl4w" ], [ - "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ" + "bcrt1qj7g2jps453kj9htk9cxyyc2nxe69x4kzzmth7v" ], [ - "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ" + "bc1p702xksx4z3uqf0u2phllxkfe5cgu0adxptqs0uelx0tqt8e885sqryes2l" ], [ - "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu" + "tb1z7gmh0v6pc30z4xum76lmw8w86yswrlmw" ], [ - "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU" + "bcrt1sjsrw6nun4h502cr97xmnyyuhkr22q0s6efrgtu" ], [ - "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs" + "2UVPFpGYnLHJezFzjUo42our6PMEoozzRdM" ], [ - "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn" + "2MygHQjE1U33q3LSC53p69YqFjP8PihumJAF" ], [ - "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj" + "KzNbAQ4mexfAxa6RKBzHQqfoTycaeWpv2p" ], [ - "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny" + "2jDPrDfAKihCGPbPD9ztY8TswAia4V8Bc6vx" ], [ - "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc" + "4VQUNG1hG64QFtaNyQZQWDdwpxB275Pwb3tvyPt2HDxB8Mi2MgH8Tz3AC83YYiz9LydsLNXEZJLHY" ], [ - "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ" + "39TKsUQ5QpEL1wowc6GMUqak94ijirPuP69ooV3xsFmiKQX2dau" ], [ - "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP" + "2UEJjT3dSdwc8dAo7oedPzznXceXCEsBbDfAvSymqpqDrkZMv7JBEUpLyhkghioYAWC9W4sKysry" ], [ - "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw" + "7VmMEkphxCFSV1y659Th4dkk6x6bJS5eQvbt8rzUYKQyd6ACgwQ4vXHtXKFUwP2kW3XULipnHJdZ7" ], [ - "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX" + "tc1qdlapns4zkn03juf2k9xwwpct209suj6mgcd9gh" ], [ - "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB" + "bt1psa5eptk29c4jc9yumeseat3a0l5e2fpmw635za2p4gpwdnthueysxga9je" ], [ - "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ" + "tb13w8c43lykfj3lvm9sgp6dsnfjla3d57cm83seykunf0ltxjc9lt2q4efm4d" ], [ - "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs" + "bcrt1rjqr2tdkm" ], [ - "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ" + "bc10lyxwnxa70l270e6fcmxr4x7dtgu2yvy7gzkurwxy4zhdvgaqrrn6pfg2flyhqzy5t5se8yu3" ], [ - "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4" + "TB1QFDFM763VXVSUNZHQLPWC0Q8FG5LJX6ZN" ], [ - "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK" + "bcrt1q60chha7wfwlau4kdr4mlvyeyc8mnnh9dhxk05e0hmrxcuhghefj36uwyha" ], [ - "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig" + "bc1gmk9yu" ], [ - "EsYbG4tWWWY45G31nox838qNdzksbPySWc" + "tb1ly0q7p" ], [ - "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT" + "bcrt1qdwttaw38uf42wxw40kwk3u8nguyTQH3hx6jmqp" ], [ - "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx" + "bc1qtsvlht6730n04f2mpaj5vv8hrledn5n5ug8c79" ], [ - "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde" + "tb1dclvmr" ], [ - "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU" + "bcrt1q3fqvctqu48wsvggrt09vj0yk2gzzcscdp4h98u" ], [ - "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf" + "bc1prklpq7tjcawg89cmwwqr3u5apwav36xa4zz56ady7crsllm6mpnqts7p86" ], [ - "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd" + "tb1zkm58zyhxz3ffkfgsyprflg543slsl4c4" ], [ - "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED" + "bcrt1snzr5kaypnfhpnjanrhd20fhqcjxm3hfh7dw9fu" ], [ - "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty" + "2GgnYKqBGuA2Mm5GnrPsMTZR81xPhNtgMYoFUZngZGiobhCuUpCaTriUHRcgFreEekNdPAR17q8d" ], [ - "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5" + "AZEah8d1EK362okRBS66e8SvdtYkrE8tsX" ], [ - "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2" + "gep8xr77FyPW6zYP15RiV9W8nL6w2HyHB16cUDakfyDceMA6ZzUdhJjk2LPuLYHnLkBqkRTTi6z" ], [ - "bc1rw5uspcuh" + "2NDNP7GY59tTJPZTpbkprhM9SR99Nn5rUs7" ], [ - "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90" + "2Csgzy2T287YAjeU5tFtt1nPshBZAUFQi4WtgaWyZGKSBNnKXHy2Tmxo8QK4Mfdds977ShcDWC5o" ], [ - "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P" + "Kwjk3Vy6sdXMQDGWJzaWmqFxUNtWZCX1q4F4Kpt8jNNUoWJUUaTY" ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7" + "Svj8kk98bAS9V4L2crmxakbhmnPm3cJ1tJ4Je4yVzDreU8eSTFURS1SPYv5oWEQD8Q9VBDvx5uF" ], [ - "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du" + "KNYsv6v9GtkGeD4WdQnBEJCrPKQm91PTxAbCfXr66LEd4JDmhPWC" ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv" + "2UJ2H2xvAeXmFKfQwMyDoSdQTTPFMNCT3SsoUafBWKzoGP3NsUK1buEgQZG38viyD53jgMdpqfT7" ], [ - "bc1gmk9yu" + "6aLMfayKF4TW4ecn5SEc8FExpyJA2peKxYRGZhes6tQ4NTTzuGy" + ], + [ + "7VP4FmcebU2thJns9MnXde7LWfuqR5vMizrAuUoq2GcJjzTyA4RHFcPVdZL8PLg1SbpSFdJrvLXoY5" + ], + [ + "tc1q5qdvt99uc92jyz663dtdpfpv6nr67ahmgwcpq2" + ], + [ + "bt1peu3ppd7x796sjjenp09r8cs22rhylqm9lhggk72qp8q22vzft0wq2a0x6j" + ], + [ + "tb1323z3lnz7dl3kd0nsuh6xy4he9almzl67anxgg3xdzkaxc9rwntlqdhdzd7" + ], + [ + "bcrt1r2gc42sky" + ], + [ + "bc10fd889x4hd54tqu2ewg9t4hhft2wl7m6x50av4uswzw46xe6as0xmltfg7vrjfkvm459vld7w" + ], + [ + "TB1QZY7V0F2AT3308YGGNGN66ULJTCN3RY6F" + ], + [ + "bcrt1qjg3cwht92znyw0l4r5rtctmls337nrc7g0ry9drjxmlecjd3atl3fake7c" + ], + [ + "bc1qmgf8xt8xkecl79k04mma3lz34gqep7hg4" + ], + [ + "TB1Q3F9WGNXE9ZMTTMDN5VKVKHYZ8Y0LCV72YV7V5LSXTJXEYHNHEHASLYL0TZ" ] ] diff --git a/src/test/resources/data/key_io_valid.json b/src/test/resources/data/key_io_valid.json index 8418a600..c051f8b7 100644 --- a/src/test/resources/data/key_io_valid.json +++ b/src/test/resources/data/key_io_valid.json @@ -1,533 +1,610 @@ [ [ - "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", - "76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac", + "1FsSia9rv4NeEwvJ2GvXrX7LyxYspbN2mo", + "76a914a31c06bd463e3923bc1aadbde48b16976c08071788ac", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", - "a91474f209f6ea907e2ea48f74fae05782ae8a66525787", + "36j4NfKv6Akva9amjWrLG6MuSQym1GuEmm", + "a914373b819a068f32b7a6b38b6b38729647cfde01c287", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", - "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac", + "mzK2FFDEhxqHcmrJw1ysqFkVyhUULo45hZ", + "76a914ce28b26c57472737f5c3561a1761185bd8589a4388ac", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isPrivkey": false } ], [ - "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", - "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac", + "2NC2hEhe28ULKAJkW5MjZ3jtTMJdvXmByvK", + "a914ce0bba75891ff9ec60148d4bd4a09ee2dc5c933187", { - "isPrivkey": false, - "chain": "regtest" + "chain": "test", + "isPrivkey": false } ], [ - "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", - "a9146349a418fc4578d10a372b54b45c280cc8c4382f87", + "mww4LvqtTMKvmeQvizPz2EQv26xTneWrbg", + "76a914b4110ba93ac54afc14da3bdd19614774a2d55d2988ac", { - "isPrivkey": false, - "chain": "test" + "chain": "signet", + "isPrivkey": false + } + ], + [ + "2N1r7aC69VHeE7yQJPDLi9T1PYq4wnwvjuT", + "a9145e5a35ab44b3efaea5129ba22b88ba3e2976614587", + { + "chain": "signet", + "isPrivkey": false } ], [ - "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", - "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", + "n4fajahJrAuKbN7uNsKjLjQkz9Qn5ewJXQ", + "76a914fdeca3b08e38af53d7c4c60e3ad208ce5066441088ac", { + "chain": "regtest", + "isPrivkey": false + } + ], + [ + "2MxFajLApXpYk4VodBSZSt7rw8y4ryABkfA", + "a91436e9f191e0b75036a77f65e2eaa4752443233fbe87", + { + "chain": "regtest", + "isPrivkey": false + } + ], + [ + "5JuW2AMDYu4xVwRG9DZW18VbzQrGcd5RCgb99sS6ehJsNQXu5b9", + "8f8943bf956de595665c38ffff23827e17c10cdc1c27a028caae6c9810626198", + { + "chain": "main", "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", - "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4", + "L5nJeqKmpHp4P7F8ZYyjwc5a7P4d8EabuGAzfGJk7yC1BJyzNaEd", + "ff778740f88ddcf102aeb81daee289c044c4a4571c4b6f287400f4b8e0b843f8", { + "chain": "main", "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", - "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + "92ZdE5HoLafywnTBbzPxbvRmp75pSfzvdU3XaZGh1cToipgdHVh", + "80c32d81e91bdea04cd7a3819b32275fc3298af4c7ec87eb0099527d041ced5c", { + "chain": "test", "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", - "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", + "cV83kKisF3RQSvXbUCm9ox3kaz5JjEUBWcx8tNydfGJcyeUxuH47", + "e0fcd4ce4e3d0e3de091f21415bb7cd011fac288c42020a879f28c2a4387df9b", { + "chain": "test", + "isCompressed": true, + "isPrivkey": true + } + ], + [ + "92QuSnywrhsV7WPZChTgSQA23uSmj9MCEEno1eRBDG9sg8M29cX", + "6cf636ed8ac1bab033b64f66feaba65f70e684731e3f39105605968d3a963801", + { + "chain": "signet", "isCompressed": false, - "isPrivkey": true, - "chain": "regtest" + "isPrivkey": true } ], [ - "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", - "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", + "cND53Dhp8eCZqG2ghe8YhSCGesXZ8fE5PGD1khrqNvEi4RBoXhEK", + "12b5a10f3a11e708dc5412833c47ab7c368a21b9efe19293793ec879ce683018", { + "chain": "signet", "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", - "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", + "91mn1wYKEB1zyof1VFm8tMtocZx1oBrKKRCu9GCpgZvPmBLEJjp", + "18a86e5a6c6977ddba0daca7fba5190f67ba56ccdc1b3f31308972236c2e4776", { - "isCompressed": true, - "isPrivkey": true, - "chain": "regtest" + "chain": "regtest", + "isCompressed": false, + "isPrivkey": true } ], [ - "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", - "76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac", + "cPisAUdLvqqAr6MYtXnrWvgvyUAwuNyuTvZkDGw6miPhZdaiSDNH", + "3fdfec1371cedcdb8c190ca6ff8ad603f817edc0d93c2a687c7b36dd66e70f2a", { - "isPrivkey": false, - "chain": "main" + "chain": "regtest", + "isCompressed": true, + "isPrivkey": true } ], [ - "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", - "a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587", + "bc1qvyq0cc6rahyvsazfdje0twl7ez82ndmuac2lhv", + "00146100fc6343edc8c874496cb2f5bbfec88ea9b77c", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", - "76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac", + "bc1qyucykdlhp62tezs0hagqury402qwhk589q80tqs5myh3rxq34nwqhkdhv7", + "002027304b37f70e94bc8a0fbf500e0c957a80ebda87280ef58214d92f119811acdc", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", - "a914c579342c2c4c9220205e2cdc285617040c924a0a87", + "bc1p83n3au0rjylefxq2nc2xh2y4jzz4pm6zxj4mw5pagdjjr2a9f36s6jjnnu", + "51203c671ef1e3913f94980a9e146ba895908550ef4234abb7503d436521aba54c75", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", - "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", + "bc1z2rksukkjr8", + "520250ed", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "main", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", - "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4", + "tb1qcrh3yqn4nlleplcez2yndq2ry8h9ncg3qh7n54", + "0014c0ef1202759fff90ff19128936814321ee59e111", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", - "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", + "tb1quyl9ujpgwr2chdzdnnalen48sup245vdfnh2jxhsuq3yx80rrwlq5hqfe4", + "0020e13e5e482870d58bb44d9cfbfccea78702aad18d4ceea91af0e022431de31bbe", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", - "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9", + "tb1p35n52jy6xkm4wd905tdy8qtagrn73kqdz73xe4zxpvq9t3fp50aqk3s6gz", + "51208d2745489a35b75734afa2da43817d40e7e8d80d17a26cd4460b0055c521a3fa", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", - "76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac", + "tb1rgv5m6uvdk3kc7qsuz0c79v88ycr5w4wa", + "53104329bd718db46d8f021c13f1e2b0e726", { + "chain": "test", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", - "a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87", + "tb1q3vya2h5435jkugq2few7dmktlrwq4ejmfaw7kr", + "00148b09d55e958d256e200a4e5de6eecbf8dc0ae65b", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", - "76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac", + "tb1qxkhrl2s6ttrclckldruea0e8anhrehffl8xv7t0pdyrzm08v2hyqy408nf", + "002035ae3faa1a5ac78fe2df68f99ebf27ecee3cdd29f9cccf2de169062dbcec55c8", { + "chain": "signet", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", - "a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087", + "tb1pae5um27ahn8n73pgexe3kcwlp8dhswpn684h2k2w6t9a7w3eq65qephd5y", + "5120ee69cdabddbccf3f4428c9b31b61df09db783833d1eb75594ed2cbdf3a3906a8", { + "chain": "signet", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", - "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", + "tb1rx9n9g37az8mu236e5jpxdt0m67y4fuq8rhs0ss3djnm0kscfrwvq0ntlyg", + "532031665447dd11f7c54759a48266adfbd78954f0071de0f8422d94f6fb43091b98", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "signet", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", - "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c", + "bcrt1qdavt4j2sd7dlhqsavtnfxvzppw6k7qy97tmnu9", + "00146f58bac9506f9bfb821d62e69330410bb56f0085", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", - "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", + "bcrt1qan8gntac7z7me2ejt4hpru42ad2f759fmy0m3ejvs98656znv7eqga4uhv", + "0020ecce89afb8f0bdbcab325d6e11f2aaeb549f50a9d91fb8e64c814faa685367b2", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", - "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69", + "bcrt1pfwxjqvtt4tcxrtdluukfmy2dv7xd2qzdfy6kajv5nwn4yam3wxkq3553uh", + "51204b8d20316baaf061adbfe72c9d914d678cd5004d49356ec9949ba752777171ac", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", - "76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac", + "bcrt1sx6p8njlx7h9mc2agz4yg82dzne23050ncq72cneeecez2pst8mahn8xecsf8g6hzx94420", + "6028368279cbe6f5cbbc2ba8154883a9a29e5517d1f3c03cac4f39ce3225060b3efb799cd9c412746ae2", { + "chain": "regtest", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", - "a914188f91a931947eddd7432d6e614387e32b24470987", + "1FjL87pn8ky6Vbavd1ZHeChRXtoxwRGCRd", + "76a914a19331b7b2627e663e25a7b001e4c0dcc5e21bc788ac", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isPrivkey": false } ], [ - "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", - "76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac", + "3BZECeAH8gSKkjrTx8PwMrNQBLG18yHpvf", + "a9146c382dcdf5b284760c8e3fead91f7422cd76aa8787", { - "isPrivkey": false, - "chain": "test" + "chain": "main", + "isPrivkey": false } ], [ - "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", - "a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387", + "n4YNbYuFdPwFrxSP8sjHFbAhUbLMUiY9jE", + "76a914fc8f9851f3c1e4719cd0b8e4816dd4e88c72e52888ac", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isPrivkey": false } ], [ - "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", - "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", + "2NAeQVZayzVFAtgeC3iYJsjpjWDmsDph71A", + "a914bedc797342c03fd7a346c4c7857ca03d467013b687", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false } ], [ - "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", - "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af", + "mnCBpkNMJEJLehgdEkzSo2eioniyJMxLpZ", + "76a914493c455551e48a1423263b62b127b436106a685488ac", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "signet", + "isPrivkey": false } ], [ - "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", - "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + "2N5sNHomeNJDZv67AcFx9ES7FBZY4jx9KDA", + "a9148a776a0f34d56b63e7c595f2b205dbe1c393617a87", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "signet", + "isPrivkey": false } ], [ - "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", - "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", + "mfhE6jAUwjUDNZhaX1PAsDTKfneQF2Nshc", + "76a91401f15a4cc063dae4f4d56b89bfbc8bcc9ae5387c88ac", { - "isCompressed": false, - "isPrivkey": true, - "chain": "regtest" + "chain": "regtest", + "isPrivkey": false } ], [ - "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", - "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef", + "2MxNm1VHyVU4RuP3u1c1v5aQLk2dQjwy1Qk", + "a91438456f7c076356abadcc67b92ad777eb20fb9f8887", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "regtest", + "isPrivkey": false } ], [ - "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", - "76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac", + "5HsL2nZuEebU5nM3RxNVQD9GcAnvNMahqQskf4fkqHe54zwd14e", + "06e8649790a90615a46d22dd762e0c42615336745356c2e16147c0f3d46b40d5", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isCompressed": false, + "isPrivkey": true } ], [ - "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", - "a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987", + "KwuVvu6hsuEMHrfFWJQV64tRrWX3QzqHH18JuAHYqYV6dqBvNKxd", + "147804bf8a0dfff35939a611c7f5a60ac107f33f33d6059f273d2079ab1d90f2", { - "isPrivkey": false, - "chain": "main" + "chain": "main", + "isCompressed": true, + "isPrivkey": true } ], [ - "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", - "76a914261f83568a098a8638844bd7aeca039d5f2352c088ac", + "921M1RNxghFcsVGqAJksQVbSgx36Yz4u6vebfz1wDujNvgNt93B", + "3777b341c45e2a9b9bf6bfb71dc7d129f64f1b9406ed4f93ade8f56065f1b732", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isCompressed": false, + "isPrivkey": true } ], [ - "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", - "a914e930e1834a4d234702773951d627cce82fbb5d2e87", + "cNEnbfF2fcxmmCLWqMAaq6fxJvVkwMbyU3kCbpQznz4Z1j6TZDGb", + "1397b0d4a03e1ab2c54dd9af99ce1ecbfb90c80a58886da95e1181a55703d96b", { - "isPrivkey": false, - "chain": "test" + "chain": "test", + "isCompressed": true, + "isPrivkey": true } ], [ - "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", - "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", + "93BcpCMKPmFCuY8bqS4k3HFrhJ1Afxi4uSsEeJFvX86GYW7PC7W", + "d27d1b6ef55ca2e4d475b5276f2dbb85f7a6459dceeb89c67b776fd3bb974452", { + "chain": "signet", "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", - "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3", + "cUtwbyxoL1owPxUafgH2meEpydeywjhnTYv2mJaFHHchz39AaEgy", + "da3ed4ef1647e1733ec076919cab6156077ed9532e7c365acc425747e198b3e1", { + "chain": "signet", "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "isPrivkey": true } ], [ - "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", - "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", + "927zPWny2SiNaUmHF5NnGQXQWDwbByfFzXGgu88j91ZoutSosvE", + "468e0284f230153db8687d8ec23db079a5b67d72ca04174b3867b13e4ea9945e", { + "chain": "regtest", "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", - "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de", + "cRez45VGSp5EXNqm89K3NJJPSKKapJg5Kbw3atxr2337x2gtgYed", + "798d87586cffbe8c545ab374454e403b1eb831501ebe89f3c3b02f3137bd7b46", { + "chain": "regtest", "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "isPrivkey": true } ], [ - "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", - "76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac", + "bc1qhxt04s5xnpy0kxw4x99n5hpdf5pmtzpqs52es2", + "0014b996fac2869848fb19d5314b3a5c2d4d03b58820", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", - "a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87", + "bc1qgc9ljrvdf2e0zg9rmmq86xklqwfys7r6wptjlacdgrcdc7sa6ggqu4rrxf", + "0020460bf90d8d4ab2f120a3dec07d1adf039248787a70572ff70d40f0dc7a1dd210", { + "chain": "main", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "myoqcgYiehufrsnnkqdqbp69dddVDMopJu", - "76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac", + "bc1pve739yap4uxjvfk0jrey69078u0gasm2nwvv483ec6zkzulgw9xqu4w9fd", + "5120667d1293a1af0d2626cf90f24d15fe3f1e8ec36a9b98ca9e39c6856173e8714c", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", - "a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87", + "bc1zmjtqxkzs89", + "5202dc96", { + "chain": "main", "isPrivkey": false, - "chain": "test" + "tryCaseFlip": true } ], [ - "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", - "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", + "tb1ql4k5ayv7p7w0t0ge7tpntgpkgw53g2payxkszr", + "0014fd6d4e919e0f9cf5bd19f2c335a03643a914283d", { - "isCompressed": false, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", - "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd", + "tb1q9jx3x2qqdpempxrcfgyrkjd5fzeacaqj4ua7cs7fe2sfd2wdaueq5wn26y", + "00202c8d1328006873b098784a083b49b448b3dc7412af3bec43c9caa096a9cdef32", { - "isCompressed": true, - "isPrivkey": true, - "chain": "main" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", - "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", + "tb1pdswckwd9ym5yf5eyzg8j4jjwnzla8y0tf9cp7aasfkek0u29sz9qfr00yf", + "51206c1d8b39a526e844d324120f2aca4e98bfd391eb49701f77b04db367f145808a", { - "isCompressed": false, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", - "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c", + "tb1r0ecpfxg2udhtc556gqrpwwhk4sw3f0kc", + "53107e7014990ae36ebc529a4006173af6ac", { - "isCompressed": true, - "isPrivkey": true, - "chain": "test" + "chain": "test", + "isPrivkey": false, + "tryCaseFlip": true } ], [ - "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", - "76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac", + "tb1q6mwf89hnqhlu8txjgjfs4s7p93ugffn3k062ll", + "0014d6dc9396f305ffc3acd244930ac3c12c7884a671", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", - "a9145ece0cadddc415b1980f001785947120acdb36fc87", + "tb1qafrjalu4d73dql0czau9j6z422434kef235mzljf48ckd5xz3sys09jm97", + "0020ea472eff956fa2d07df8177859685552ab1adb295469b17e49a9f166d0c28c09", { + "chain": "signet", "isPrivkey": false, - "chain": "main" + "tryCaseFlip": true } ], [ - "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", - "0014751e76e8199196d454941c45d1b3a323f1433bd6", + "tb1pwst9qszjrhuv2e7as0flcq9gm698v6gdxzz9e87p07s8rssdx3zqklm3vf", + "512074165040521df8c567dd83d3fc00a8de8a76690d30845c9fc17fa071c20d3444", { + "chain": "signet", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080", - "0014751e76e8199196d454941c45d1b3a323f1433bd6", + "tb1r3ss76jtsuxe8c8c8lxsehnpak55ylrgr345pww076l536ahjr6jsydamx3", + "53208c21ed4970e1b27c1f07f9a19bcc3db5284f8d038d681739fed7e91d76f21ea5", { + "chain": "signet", "isPrivkey": false, - "chain": "regtest", "tryCaseFlip": true } ], [ - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", - "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", + "bcrt1q65nhlm4hf2ptg3t264al57p7wjxj2c3s6kyt83", + "0014d5277feeb74a82b4456ad57bfa783e748d256230", { + "chain": "regtest", "isPrivkey": false, - "chain": "test", "tryCaseFlip": true } ], [ - "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx", - "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6", + "bcrt1qawvc90lpytw3z3k9etdx54l0exq5f5sqfzu5e45kjnl6slwayeeqx2dyac", + "0020eb9982bfe122dd1146c5cada6a57efc98144d20048b94cd69694ffa87ddd2672", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bc1sw50qa3jx3s", - "6002751e", + "bcrt1p39a4s4vdcw9kqa8w2t0rp7aj8kfxyw7mce5sk5d70x6wnnmpvt7skf2kxy", + "5120897b58558dc38b6074ee52de30fbb23d92623bdbc6690b51be79b4e9cf6162fd", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", - "5210751e76e8199196d454941c45d1b3a323", + "bcrt1s489d9fhmyel0vzfqsrmew4x7r80asuqesm5hgqacy35daflcyufh3j8cgdtflvt99ph05m", + "6028a9cad2a6fb267ef6092080f79754de19dfd8701986e97403b82468dea7f8271378c8f843569fb165", { + "chain": "regtest", "isPrivkey": false, - "chain": "main", "tryCaseFlip": true } ], [ - "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", - "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "1G9A9j6W8TLuh6dEeVwWeyibK1Uc5MfVFV", + "76a914a614da54daacdb8861f451a0b7e3c27cdf8a099e88ac", + { + "chain": "main", + "isPrivkey": false + } + ], + [ + "33GA3ZXbw5o5HeUrBEaqkWXFYYZmdxGRRP", + "a914113ca1afeb49ff3abf176ffa19c2a2b4df19712a87", + { + "chain": "main", + "isPrivkey": false + } + ], + [ + "mwgS2HRbjyfYxFnR1nF9VKLvmdgMfFBmGq", + "76a914b14ce7070b53cb0e4b5b5f6e253e876990aeca2e88ac", { - "isPrivkey": false, "chain": "test", - "tryCaseFlip": true + "isPrivkey": false } ], [ - "bcrt1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvseswlauz7", - "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "2MwBVrJQ76BdaGD76CTmou8cZzQYLpe4NqU", + "a9142b2c149cde619eae3d7fe995243b76a3417541aa87", { - "isPrivkey": false, - "chain": "regtest", - "tryCaseFlip": true + "chain": "test", + "isPrivkey": false + } + ], + [ + "mfnJ8tEkqKNFE5YaHTXFxyHk2mnDK2fvDh", + "76a91402e6cd77e649ad8b281271f158fc964ca3f66cb088ac", + { + "chain": "signet", + "isPrivkey": false + } + ], + [ + "2My83D67ir7K8PPzeT6mE2oth3ZwNTVRS9F", + "a9144074d84d32ff62da7b1b3c61925b934bfeb34b0587", + { + "chain": "signet", + "isPrivkey": false } ] ] diff --git a/src/test/scala/fr/acinq/bitcoin/scala/Bech32Spec.scala b/src/test/scala/fr/acinq/bitcoin/scala/Bech32Spec.scala index 80703d2e..08d5ff05 100644 --- a/src/test/scala/fr/acinq/bitcoin/scala/Bech32Spec.scala +++ b/src/test/scala/fr/acinq/bitcoin/scala/Bech32Spec.scala @@ -4,18 +4,27 @@ import org.scalatest.FunSuite import scodec.bits._ /** - * Created by fabrice on 19/04/17. - */ + * Created by fabrice on 19/04/17. + */ class Bech32Spec extends FunSuite { test("valid checksums") { val inputs = Seq( + // Bech32 "A12UEL5L", "a12uel5l", "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", - "?1ezyfcl" + "?1ezyfcl", + // Bech32m + "A1LQFN3A", + "a1lqfn3a", + "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", + "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", + "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", + "split1checkupstagehandshakeupstreamerranterredcaperredlc445v", + "?1v759aa" ) val outputs = inputs.map(Bech32.decode) assert(outputs.length == inputs.length) @@ -23,14 +32,34 @@ class Bech32Spec extends FunSuite { test("invalid checksums") { val inputs = Seq( + // Bech32 " 1nwldj5", "\u007f1axkwrx", + "\u00801eym55h", "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", "pzry9x0s0muk", "1pzry9x0s0muk", "x1b4n0q5v", "li1dgmt3", - "de1lg7wt\u00ff" + "de1lg7wt\u00ff", + "A1G7SGD8", + "10a06t8", + "1qzzfhee", + // Bech32m + "\u00201xj0phk", + "\u007F1g6xzxy", + "\u00801vctc34", + "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4", + "qyrz8wqd2c9m", + "1qyrz8wqd2c9m", + "y1b0jsk6g", + "lt1igcx5c0", + "in1muywd", + "mm1crxm3i", + "au1s5cgom", + "M1VUXWEZ", + "16plkw9", + "1p2gdwpf" ) inputs.map(address => { @@ -44,10 +73,12 @@ class Bech32Spec extends FunSuite { val inputs = Seq( "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4" -> "0014751e76e8199196d454941c45d1b3a323f1433bd6", "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7" -> "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262", - "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx" -> "8128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6", - "BC1SW50QA3JX3S" -> "9002751e", - "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj" -> "8210751e76e8199196d454941c45d1b3a323", - "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy" -> "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433" + "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y" -> "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6", + "BC1SW50QGDZ25J" -> "6002751e", + "bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs" -> "5210751e76e8199196d454941c45d1b3a323", + "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy" -> "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c" -> "5120000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433", + "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0" -> "512079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ) inputs.map { case (address, bin) => @@ -58,12 +89,15 @@ class Bech32Spec extends FunSuite { test("create addresses") { assert(Bech32.encodeWitnessAddress("bc", 0, hex"751e76e8199196d454941c45d1b3a323f1433bd6") == "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4".toLowerCase) + assert(Bech32.encodeWitnessAddress("bc", 1, hex"79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") == "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0") assert(Bech32.encodeWitnessAddress("tb", 0, hex"1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262") == "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7") assert(Bech32.encodeWitnessAddress("tb", 0, hex"000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433") == "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy") + assert(Bech32.encodeWitnessAddress("tb", 1, hex"000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433") == "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c") } test("reject invalid addresses") { val addresses = Seq( + // Bech32 "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", @@ -75,7 +109,22 @@ class Bech32Spec extends FunSuite { "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du", "tb1pw508d6qejxtdg4y5r3zarqfsj6c3", "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", - "bc1gmk9yu" + "bc1gmk9yu", + // Bech32m + "tc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq5zuyut", + "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd", + "tb1z0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqglt7rf", + "BC1S0XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ54WELL", + "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kemeawh", + "tb1q0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq24jc47", + "bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4", + "BC130XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ7ZWS8R", + "bc1pw5dgrnzv", + "bc1pw5dgrnzv", + "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zgeav", + "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47Zagq", + "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf", + "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j" ) addresses.map(address => { intercept[Exception] { @@ -83,4 +132,10 @@ class Bech32Spec extends FunSuite { } }) } + + test("encode and decode BIP86 taproot addresses") { + val script = Script.parse(hex"5120eceb3f3cdbad5bda395a32910ff6195a89cc5ec7fbf34705512da6f81963b156") + val witnessProgram = script(1).asInstanceOf[OP_PUSHDATA].data + assert(Bech32.encodeWitnessAddress("bcrt", 1, witnessProgram) == "bcrt1pan4n70xm44da5w26x2gslaset2yuchk8l0e5wp239kn0sxtrk9tql9wc8z") + } }