aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorW. J. van der Laan <laanwj@protonmail.com>2021-04-23 09:53:37 +0200
committerW. J. van der Laan <laanwj@protonmail.com>2021-04-23 09:53:43 +0200
commit56311988bff14b0fa3d827c00c9d298d71ace211 (patch)
treeb12df9758b716ba173951463684475ca27b87f04
parentf1c3c53e5f94965c3a2c1376cb375257ece53989 (diff)
parentc0f85fd8503a6e6f66cb8659bd88deec92b96eec (diff)
downloadbitcoin-56311988bff14b0fa3d827c00c9d298d71ace211.tar.xz
Merge bitcoin/bitcoin#21470: BIP 350: Implement Bech32m and use it for v1+ segwit addresses (0.20 backport)
c0f85fd8503a6e6f66cb8659bd88deec92b96eec Backport invalid address tests (Pieter Wuille) c6709867d3614809c17d38bab5ac6772460c0599 naming nits (Fabian Jahr) 1a4e88e0e885cfcb91196840a958e7c9fa09c3b5 Use Bech32m encoding for v1+ segwit addresses (Pieter Wuille) cf18ac9665a13ea701f4410287e6ad10ae1f1c30 Add Bech32m test vectors (Pieter Wuille) 5f9537b2d9d1af80431870d77814d93f621e83cb Implement Bech32m encoding/decoding (Pieter Wuille) Pull request description: Backport of #20861 for 0.20. Also includes #21471. ACKs for top commit: jnewbery: utACK c0f85fd8503a6e6f66cb8659bd88deec92b96eec MarcoFalke: range-diff-only ACK c0f85fd850 🐔 Tree-SHA512: e87e52995cb9b555109bc500dba1e844993d881821d2001443b3de9e3ef9050ddb73deefa0c1af732418fa7355a86b875789887c9611c340713b3ad26809d58e
-rwxr-xr-xcontrib/testgen/gen_key_io_test_vectors.py70
-rw-r--r--doc/bips.md3
-rw-r--r--doc/release-notes-20861.md12
-rw-r--r--src/bech32.cpp52
-rw-r--r--src/bech32.h39
-rw-r--r--src/bench/bech32.cpp2
-rw-r--r--src/key_io.cpp22
-rw-r--r--src/test/bech32_tests.cpp58
-rw-r--r--src/test/data/key_io_invalid.json126
-rw-r--r--src/test/data/key_io_valid.json495
-rw-r--r--src/test/fuzz/bech32.cpp32
-rwxr-xr-xtest/functional/rpc_invalid_address_message.py84
-rw-r--r--test/functional/test_framework/segwit_addr.py53
-rwxr-xr-xtest/functional/test_runner.py1
-rwxr-xr-xtest/functional/wallet_labels.py1
15 files changed, 566 insertions, 484 deletions
diff --git a/contrib/testgen/gen_key_io_test_vectors.py b/contrib/testgen/gen_key_io_test_vectors.py
index a00acb1f41..c9a12c9237 100755
--- a/contrib/testgen/gen_key_io_test_vectors.py
+++ b/contrib/testgen/gen_key_io_test_vectors.py
@@ -16,7 +16,7 @@ from itertools import islice
from base58 import b58encode_chk, b58decode_chk, b58chars
import random
from binascii import b2a_hex
-from segwit_addr import bech32_encode, decode, convertbits, CHARSET
+from segwit_addr import bech32_encode, decode, convertbits, CHARSET, Encoding
# key types
PUBKEY_ADDRESS = 0
@@ -33,6 +33,7 @@ PRIVKEY_REGTEST = 239
OP_0 = 0x00
OP_1 = 0x51
OP_2 = 0x52
+OP_3 = 0x53
OP_16 = 0x60
OP_DUP = 0x76
OP_EQUAL = 0x87
@@ -45,6 +46,7 @@ script_prefix = (OP_HASH160, 20)
script_suffix = (OP_EQUAL,)
p2wpkh_prefix = (OP_0, 20)
p2wsh_prefix = (OP_0, 32)
+p2tr_prefix = (OP_1, 32)
metadata_keys = ['isPrivkey', 'chain', 'isCompressed', 'tryCaseFlip']
# templates for valid sequences
@@ -66,29 +68,39 @@ templates = [
]
# templates for valid bech32 sequences
bech32_templates = [
- # hrp, version, witprog_size, metadata, output_prefix
- ('bc', 0, 20, (False, 'main', None, True), p2wpkh_prefix),
- ('bc', 0, 32, (False, 'main', None, True), p2wsh_prefix),
- ('bc', 1, 2, (False, 'main', None, True), (OP_1, 2)),
- ('tb', 0, 20, (False, 'test', None, True), p2wpkh_prefix),
- ('tb', 0, 32, (False, 'test', None, True), p2wsh_prefix),
- ('tb', 2, 16, (False, 'test', None, True), (OP_2, 16)),
- ('bcrt', 0, 20, (False, 'regtest', None, True), p2wpkh_prefix),
- ('bcrt', 0, 32, (False, 'regtest', None, True), p2wsh_prefix),
- ('bcrt', 16, 40, (False, 'regtest', None, True), (OP_16, 40))
+ # hrp, version, witprog_size, metadata, encoding, output_prefix
+ ('bc', 0, 20, (False, 'main', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('bc', 0, 32, (False, 'main', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('bc', 1, 32, (False, 'main', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('bc', 2, 2, (False, 'main', None, True), Encoding.BECH32M, (OP_2, 2)),
+ ('tb', 0, 20, (False, 'test', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('tb', 0, 32, (False, 'test', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('tb', 1, 32, (False, 'test', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('tb', 3, 16, (False, 'test', None, True), Encoding.BECH32M, (OP_3, 16)),
+ ('bcrt', 0, 20, (False, 'regtest', None, True), Encoding.BECH32, p2wpkh_prefix),
+ ('bcrt', 0, 32, (False, 'regtest', None, True), Encoding.BECH32, p2wsh_prefix),
+ ('bcrt', 1, 32, (False, 'regtest', None, True), Encoding.BECH32M, p2tr_prefix),
+ ('bcrt', 16, 40, (False, 'regtest', None, True), Encoding.BECH32M, (OP_16, 40))
]
# templates for invalid bech32 sequences
bech32_ng_templates = [
- # hrp, version, witprog_size, invalid_bech32, invalid_checksum, invalid_char
- ('tc', 0, 20, False, False, False),
- ('tb', 17, 32, False, False, False),
- ('bcrt', 3, 1, False, False, False),
- ('bc', 15, 41, False, False, False),
- ('tb', 0, 16, False, False, False),
- ('bcrt', 0, 32, True, False, False),
- ('bc', 0, 16, True, False, False),
- ('tb', 0, 32, False, True, False),
- ('bcrt', 0, 20, False, False, True)
+ # hrp, version, witprog_size, encoding, invalid_bech32, invalid_checksum, invalid_char
+ ('tc', 0, 20, Encoding.BECH32, False, False, False),
+ ('bt', 1, 32, Encoding.BECH32M, False, False, False),
+ ('tb', 17, 32, Encoding.BECH32M, False, False, False),
+ ('bcrt', 3, 1, Encoding.BECH32M, False, False, False),
+ ('bc', 15, 41, Encoding.BECH32M, False, False, False),
+ ('tb', 0, 16, Encoding.BECH32, False, False, False),
+ ('bcrt', 0, 32, Encoding.BECH32, True, False, False),
+ ('bc', 0, 16, Encoding.BECH32, True, False, False),
+ ('tb', 0, 32, Encoding.BECH32, False, True, False),
+ ('bcrt', 0, 20, Encoding.BECH32, False, False, True),
+ ('bc', 0, 20, Encoding.BECH32M, False, False, False),
+ ('tb', 0, 32, Encoding.BECH32M, False, False, False),
+ ('bcrt', 0, 20, Encoding.BECH32M, False, False, False),
+ ('bc', 1, 32, Encoding.BECH32, False, False, False),
+ ('tb', 2, 16, Encoding.BECH32, False, False, False),
+ ('bcrt', 16, 20, Encoding.BECH32, False, False, False),
]
def is_valid(v):
@@ -128,8 +140,9 @@ def gen_valid_bech32_vector(template):
hrp = template[0]
witver = template[1]
witprog = bytearray(os.urandom(template[2]))
- dst_prefix = bytearray(template[4])
- rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ encoding = template[4]
+ dst_prefix = bytearray(template[5])
+ rv = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5))
return rv, dst_prefix + witprog
def gen_valid_vectors():
@@ -189,22 +202,23 @@ def gen_invalid_bech32_vector(template):
hrp = template[0]
witver = template[1]
witprog = bytearray(os.urandom(template[2]))
+ encoding = template[3]
if no_data:
- rv = bech32_encode(hrp, [])
+ rv = bech32_encode(encoding, hrp, [])
else:
data = [witver] + convertbits(witprog, 8, 5)
- if template[3] and not no_data:
+ if template[4] and not no_data:
if template[2] % 5 in {2, 4}:
data[-1] |= 1
else:
data.append(0)
- rv = bech32_encode(hrp, data)
+ rv = bech32_encode(encoding, hrp, data)
- if template[4]:
+ if template[5]:
i = len(rv) - random.randrange(1, 7)
rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:]
- if template[5]:
+ if template[6]:
i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4)
rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:]
diff --git a/doc/bips.md b/doc/bips.md
index b96862297f..793ff29a26 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -1,4 +1,4 @@
-BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**):
+BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.20.2**):
* [`BIP 9`](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki): The changes allowing multiple soft-forks to be deployed in parallel have been implemented since **v0.12.1** ([PR #7575](https://github.com/bitcoin/bitcoin/pull/7575))
* [`BIP 11`](https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki): Multisig outputs are standard since **v0.6.0** ([PR #669](https://github.com/bitcoin/bitcoin/pull/669)).
@@ -42,3 +42,4 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.19.0**):
* [`BIP 173`](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki): Bech32 addresses for native Segregated Witness outputs are supported as of **v0.16.0** ([PR 11167](https://github.com/bitcoin/bitcoin/pull/11167)). Bech32 addresses are generated by default as of **v0.20.0** ([PR 16884](https://github.com/bitcoin/bitcoin/pull/16884)).
* [`BIP 174`](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki): RPCs to operate on Partially Signed Bitcoin Transactions (PSBT) are present as of **v0.17.0** ([PR 13557](https://github.com/bitcoin/bitcoin/pull/13557)).
* [`BIP 176`](https://github.com/bitcoin/bips/blob/master/bip-0176.mediawiki): Bits Denomination [QT only] is supported as of **v0.16.0** ([PR 12035](https://github.com/bitcoin/bitcoin/pull/12035)).
+* [`BIP 350`](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki): Addresses for native v1+ segregated Witness outputs use Bech32m instead of Bech32 as of **v0.20.2** ([PR 20861](https://github.com/bitcoin/bitcoin/pull/20861)).
diff --git a/doc/release-notes-20861.md b/doc/release-notes-20861.md
new file mode 100644
index 0000000000..66c92699c3
--- /dev/null
+++ b/doc/release-notes-20861.md
@@ -0,0 +1,12 @@
+Updated RPCs
+------------
+
+- Due to [BIP 350](https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki)
+ being implemented, behavior for all RPCs that accept addresses is changed when
+ a native witness version 1 (or higher) is passed. These now require a Bech32m
+ encoding instead of a Bech32 one, and Bech32m encoding will be used for such
+ addresses in RPC output as well. No version 1 addresses should be created
+ for mainnet until consensus rules are adopted that give them meaning
+ (e.g. through [BIP 341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)).
+ Once that happens, Bech32m is expected to be used for them, so this shouldn't
+ affect any production systems, but may be observed on other networks.
diff --git a/src/bech32.cpp b/src/bech32.cpp
index 1e0471f110..288b14e023 100644
--- a/src/bech32.cpp
+++ b/src/bech32.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Pieter Wuille
+// Copyright (c) 2017, 2021 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -7,15 +7,18 @@
#include <assert.h>
+namespace bech32
+{
+
namespace
{
typedef std::vector<uint8_t> data;
-/** The Bech32 character set for encoding. */
+/** The Bech32 and Bech32m character set for encoding. */
const char* CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
-/** The Bech32 character set for decoding. */
+/** The Bech32 and Bech32m character set for decoding. */
const int8_t CHARSET_REV[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -27,6 +30,12 @@ const int8_t CHARSET_REV[128] = {
1, 0, 3, 16, 11, 28, 12, 14, 6, 4, 2, -1, -1, -1, -1, -1
};
+/* Determine the final constant to use for the specified encoding. */
+uint32_t EncodingConstant(Encoding encoding) {
+ assert(encoding == Encoding::BECH32 || encoding == Encoding::BECH32M);
+ return encoding == Encoding::BECH32 ? 1 : 0x2bc830a3;
+}
+
/** This function will compute what 6 5-bit values to XOR into the last 6 input values, in order to
* make the checksum 0. These 6 values are packed together in a single 30-bit integer. The higher
* bits correspond to earlier values. */
@@ -111,21 +120,24 @@ data ExpandHRP(const std::string& hrp)
}
/** Verify a checksum. */
-bool VerifyChecksum(const std::string& hrp, const data& values)
+Encoding VerifyChecksum(const std::string& hrp, const data& values)
{
// PolyMod computes what value to xor into the final values to make the checksum 0. However,
// if we required that the checksum was 0, it would be the case that appending a 0 to a valid
// list of values would result in a new valid list. For that reason, Bech32 requires the
- // resulting checksum to be 1 instead.
- return PolyMod(Cat(ExpandHRP(hrp), values)) == 1;
+ // resulting checksum to be 1 instead. In Bech32m, this constant was amended.
+ const uint32_t check = PolyMod(Cat(ExpandHRP(hrp), values));
+ if (check == EncodingConstant(Encoding::BECH32)) return Encoding::BECH32;
+ if (check == EncodingConstant(Encoding::BECH32M)) return Encoding::BECH32M;
+ return Encoding::INVALID;
}
/** Create a checksum. */
-data CreateChecksum(const std::string& hrp, const data& values)
+data CreateChecksum(Encoding encoding, const std::string& hrp, const data& values)
{
data enc = Cat(ExpandHRP(hrp), values);
enc.resize(enc.size() + 6); // Append 6 zeroes
- uint32_t mod = PolyMod(enc) ^ 1; // Determine what to XOR into those 6 zeroes.
+ uint32_t mod = PolyMod(enc) ^ EncodingConstant(encoding); // Determine what to XOR into those 6 zeroes.
data ret(6);
for (size_t i = 0; i < 6; ++i) {
// Convert the 5-bit groups in mod to checksum values.
@@ -136,16 +148,13 @@ data CreateChecksum(const std::string& hrp, const data& values)
} // namespace
-namespace bech32
-{
-
-/** Encode a Bech32 string. */
-std::string Encode(const std::string& hrp, const data& values) {
- // First ensure that the HRP is all lowercase. BIP-173 requires an encoder
- // to return a lowercase Bech32 string, but if given an uppercase HRP, the
+/** Encode a Bech32 or Bech32m string. */
+std::string Encode(Encoding encoding, const std::string& hrp, const data& values) {
+ // First ensure that the HRP is all lowercase. BIP-173 and BIP350 require an encoder
+ // to return a lowercase Bech32/Bech32m string, but if given an uppercase HRP, the
// result will always be invalid.
for (const char& c : hrp) assert(c < 'A' || c > 'Z');
- data checksum = CreateChecksum(hrp, values);
+ data checksum = CreateChecksum(encoding, hrp, values);
data combined = Cat(values, checksum);
std::string ret = hrp + '1';
ret.reserve(ret.size() + combined.size());
@@ -155,8 +164,8 @@ std::string Encode(const std::string& hrp, const data& values) {
return ret;
}
-/** Decode a Bech32 string. */
-std::pair<std::string, data> Decode(const std::string& str) {
+/** Decode a Bech32 or Bech32m string. */
+DecodeResult Decode(const std::string& str) {
bool lower = false, upper = false;
for (size_t i = 0; i < str.size(); ++i) {
unsigned char c = str[i];
@@ -183,10 +192,9 @@ std::pair<std::string, data> Decode(const std::string& str) {
for (size_t i = 0; i < pos; ++i) {
hrp += LowerCase(str[i]);
}
- if (!VerifyChecksum(hrp, values)) {
- return {};
- }
- return {hrp, data(values.begin(), values.end() - 6)};
+ Encoding result = VerifyChecksum(hrp, values);
+ if (result == Encoding::INVALID) return {};
+ return {result, std::move(hrp), data(values.begin(), values.end() - 6)};
}
} // namespace bech32
diff --git a/src/bech32.h b/src/bech32.h
index fb39cd352b..e9450ccc2b 100644
--- a/src/bech32.h
+++ b/src/bech32.h
@@ -1,13 +1,14 @@
-// Copyright (c) 2017 Pieter Wuille
+// Copyright (c) 2017, 2021 Pieter Wuille
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-// Bech32 is a string encoding format used in newer address types.
-// The output consists of a human-readable part (alphanumeric), a
-// separator character (1), and a base32 data section, the last
-// 6 characters of which are a checksum.
+// Bech32 and Bech32m are string encoding formats used in newer
+// address types. The outputs consist of a human-readable part
+// (alphanumeric), a separator character (1), and a base32 data
+// section, the last 6 characters of which are a checksum. The
+// module is namespaced under bech32 for historical reasons.
//
-// For more information, see BIP 173.
+// For more information, see BIP 173 and BIP 350.
#ifndef BITCOIN_BECH32_H
#define BITCOIN_BECH32_H
@@ -19,11 +20,29 @@
namespace bech32
{
-/** Encode a Bech32 string. If hrp contains uppercase characters, this will cause an assertion error. */
-std::string Encode(const std::string& hrp, const std::vector<uint8_t>& values);
+enum class Encoding {
+ INVALID, //!< Failed decoding
-/** Decode a Bech32 string. Returns (hrp, data). Empty hrp means failure. */
-std::pair<std::string, std::vector<uint8_t>> Decode(const std::string& str);
+ BECH32, //!< Bech32 encoding as defined in BIP173
+ BECH32M, //!< Bech32m encoding as defined in BIP350
+};
+
+/** Encode a Bech32 or Bech32m string. If hrp contains uppercase characters, this will cause an
+ * assertion error. Encoding must be one of BECH32 or BECH32M. */
+std::string Encode(Encoding encoding, const std::string& hrp, const std::vector<uint8_t>& values);
+
+struct DecodeResult
+{
+ Encoding encoding; //!< What encoding was detected in the result; Encoding::INVALID if failed.
+ std::string hrp; //!< The human readable part
+ std::vector<uint8_t> data; //!< The payload (excluding checksum)
+
+ DecodeResult() : encoding(Encoding::INVALID) {}
+ DecodeResult(Encoding enc, std::string&& h, std::vector<uint8_t>&& d) : encoding(enc), hrp(std::move(h)), data(std::move(d)) {}
+};
+
+/** Decode a Bech32 or Bech32m string. */
+DecodeResult Decode(const std::string& str);
} // namespace bech32
diff --git a/src/bench/bech32.cpp b/src/bench/bech32.cpp
index f2fc3999fe..88a5fd9055 100644
--- a/src/bench/bech32.cpp
+++ b/src/bench/bech32.cpp
@@ -18,7 +18,7 @@ static void Bech32Encode(benchmark::State& state)
tmp.reserve(1 + 32 * 8 / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { tmp.push_back(c); }, v.begin(), v.end());
while (state.KeepRunning()) {
- bech32::Encode("bc", tmp);
+ bech32::Encode(bech32::Encoding::BECH32, "bc", tmp);
}
}
diff --git a/src/key_io.cpp b/src/key_io.cpp
index d2f5be93f5..0cb4d0bf7c 100644
--- a/src/key_io.cpp
+++ b/src/key_io.cpp
@@ -44,7 +44,7 @@ public:
std::vector<unsigned char> data = {0};
data.reserve(33);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessV0ScriptHash& id) const
@@ -52,7 +52,7 @@ public:
std::vector<unsigned char> data = {0};
data.reserve(53);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.begin(), id.end());
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32, m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessUnknown& id) const
@@ -63,7 +63,7 @@ public:
std::vector<unsigned char> data = {(unsigned char)id.version};
data.reserve(1 + (id.length * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, id.program, id.program + id.length);
- return bech32::Encode(m_params.Bech32HRP(), data);
+ return bech32::Encode(bech32::Encoding::BECH32M, m_params.Bech32HRP(), data);
}
std::string operator()(const CNoDestination& no) const { return {}; }
@@ -91,13 +91,19 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
}
}
data.clear();
- auto bech = bech32::Decode(str);
- if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
+ const auto dec = bech32::Decode(str);
+ if ((dec.encoding == bech32::Encoding::BECH32 || dec.encoding == bech32::Encoding::BECH32M) && dec.data.size() > 0 && dec.hrp == params.Bech32HRP()) {
// Bech32 decoding
- int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
+ int version = dec.data[0]; // The first 5 bit symbol is the witness version (0-16)
+ if (version == 0 && dec.encoding != bech32::Encoding::BECH32) {
+ return CNoDestination();
+ }
+ if (version != 0 && dec.encoding != bech32::Encoding::BECH32M) {
+ return CNoDestination();
+ }
// The rest of the symbols are converted witness program bytes.
- data.reserve(((bech.second.size() - 1) * 5) / 8);
- if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin() + 1, bech.second.end())) {
+ data.reserve(((dec.data.size() - 1) * 5) / 8);
+ if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, dec.data.begin() + 1, dec.data.end())) {
if (version == 0) {
{
WitnessV0KeyHash keyid;
diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp
index a2098f4f56..2651e46430 100644
--- a/src/test/bech32_tests.cpp
+++ b/src/test/bech32_tests.cpp
@@ -10,7 +10,7 @@
BOOST_FIXTURE_TEST_SUITE(bech32_tests, BasicTestingSetup)
-BOOST_AUTO_TEST_CASE(bip173_testvectors_valid)
+BOOST_AUTO_TEST_CASE(bech32_testvectors_valid)
{
static const std::string CASES[] = {
"A12UEL5L",
@@ -22,15 +22,35 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_valid)
"?1ezyfcl",
};
for (const std::string& str : CASES) {
- auto ret = bech32::Decode(str);
- BOOST_CHECK(!ret.first.empty());
- std::string recode = bech32::Encode(ret.first, ret.second);
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32);
+ std::string recode = bech32::Encode(bech32::Encoding::BECH32, dec.hrp, dec.data);
BOOST_CHECK(!recode.empty());
BOOST_CHECK(CaseInsensitiveEqual(str, recode));
}
}
-BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid)
+BOOST_AUTO_TEST_CASE(bech32m_testvectors_valid)
+{
+ static const std::string CASES[] = {
+ "A1LQFN3A",
+ "a1lqfn3a",
+ "an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6",
+ "abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx",
+ "11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8",
+ "split1checkupstagehandshakeupstreamerranterredcaperredlc445v",
+ "?1v759aa"
+ };
+ for (const std::string& str : CASES) {
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::BECH32M);
+ std::string recode = bech32::Encode(bech32::Encoding::BECH32M, dec.hrp, dec.data);
+ BOOST_CHECK(!recode.empty());
+ BOOST_CHECK(CaseInsensitiveEqual(str, recode));
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bech32_testvectors_invalid)
{
static const std::string CASES[] = {
" 1nwldj5",
@@ -49,8 +69,32 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid)
"A12uEL5L",
};
for (const std::string& str : CASES) {
- auto ret = bech32::Decode(str);
- BOOST_CHECK(ret.first.empty());
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(bech32m_testvectors_invalid)
+{
+ static const std::string CASES[] = {
+ " 1xj0phk",
+ "\x7f""1g6xzxy",
+ "\x80""1vctc34",
+ "an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4",
+ "qyrz8wqd2c9m",
+ "1qyrz8wqd2c9m",
+ "y1b0jsk6g",
+ "lt1igcx5c0",
+ "in1muywd",
+ "mm1crxm3i",
+ "au1s5cgom",
+ "M1VUXWEZ",
+ "16plkw9",
+ "1p2gdwpf"
+ };
+ for (const std::string& str : CASES) {
+ const auto dec = bech32::Decode(str);
+ BOOST_CHECK(dec.encoding == bech32::Encoding::INVALID);
}
}
diff --git a/src/test/data/key_io_invalid.json b/src/test/data/key_io_invalid.json
index 9b52943ac6..376fa1ccdc 100644
--- a/src/test/data/key_io_invalid.json
+++ b/src/test/data/key_io_invalid.json
@@ -6,177 +6,147 @@
"x"
],
[
- "37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y"
+ "1KyjgD9vFKmFSysJPUqQdXT8Yy5r82D6y74dfsg1ANTteuHJuP2q1aP1WgGX3oetFRtatKVXxPU"
],
[
- "dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv"
+ "2CwgfUPJ6BCa16PuFjKeMzLJJUpqnXm9mCtoXVGiGN7s9dNCKfCN5SdT7cu4nMY5omWHPrQLAqYL"
],
[
- "MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S"
+ "grEx1jdq4kpgsvorxP5PRyjgbXpvAVpaL5HEcqpDmF6ZpwuqRbzHX64GZ9eUwoSTvmbQb9fnqnh"
],
[
- "rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf"
+ "7RSWWNt7pyiZkNnLTuocsLMM6e3c7Mvvq8phtaBVyhuceG37y9r"
],
[
- "4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq"
+ "7VXvPTB9ZdTRUS2W1KpcykSA1XHaVrfUGhKvWQXQLMVUNefmaLkF9DFC4fZJ5aMCxmj4HRQcLFGix"
],
[
- "7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb"
+ "91bBALqY4D1Mmz4vqnCwdGSB4U1sqnZPrKZ8aHENoT5irq6bB9Nc"
],
[
- "17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs"
+ "tc19jm4rn"
],
[
- "KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3"
+ "bt1py306q853jeddsuaasstjxjz6l9uehmx8kgpe94lvvwj85rah56asxg35e3"
],
[
- "7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th"
+ "tb13u87aul665v37upwmu9a4nh82rj9cv94x5tps52e39e6k56t2ryzqv9mkxa"
],
[
- "cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va"
+ "bcrt1rkqk977nr"
],
[
- "gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk"
+ "bc10v6wh2rtujsn9hnsyfzzsd9y3rx9n8xhue0agk7c8q9tv3lga7css5jku9rstle93e5fhc8dl"
],
[
- "emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs"
+ "tb1q9quwy0k48ne8ppmr7p0jhj6hks7smd7l"
],
[
- "7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo"
+ "bcrt1q5l6rmlw2et02krnfgl9uuxp8q30dktcjvuzsw7gyk2ykkkm2td0prkw9de"
],
[
- "1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso"
+ "bc1q5ezcdrt4qqmkcqz8n50hgww88gqzfx4m6"
],
[
- "31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq"
+ "tb1q5gcna4un84qevljj3wk6rvm97f8f00gwtcu7v258cvn880wkf7gqesasqn"
],
[
- "DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN"
+ "bcrt1qtevjqsc85md7pa0CQEnpvdx977juj30usufphy"
],
[
- "2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i"
+ "bc1qret0yy8cmhsh6vw87lxtzt7w0sk4026l5qrvy7"
],
[
- "7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos"
+ "tb1qnw0xfgkucr4ysapsj8gd0u40fpj05n8cn24unkql8mc4ckkcp0mqc7acjd"
],
[
- "1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu"
+ "bcrt1qu26l525vmxfv59gxm2r0c8alnkpzmat2mga2qw"
],
[
- "2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb"
+ "bc1prjkeqgknynar5tj6v76yn3u27rep8jf366kmhglq898yn3aczk9ss73nrl"
],
[
- "8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ"
+ "tb1zq0vsl9pta9uwh2txtrmxyedjtqcfkqt5"
],
[
- "163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ"
+ "bcrt1suvw5wa9elxy3a43ctljjn8avcmqpzwz5m4tycs"
],
[
- "2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu"
+ "gf7t7z22jkuKcEjc8gELEYau3NzgGFLtLNEdMpJKcVt6z7mmvEJHH37y36MNGSmriFaPAbGghdh"
],
[
- "461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU"
+ "mn9CPaeodb6L1CtJu1KaLtJhDbYL55Hxwe"
],
[
- "2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs"
+ "cTSecEa3nqxF4mgYkGrxRKeWLpXWng6nUgL4sVeAhrNbtdf1z8hz1VFesD492QWZ4JprpRW1Drr"
],
[
- "cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn"
+ "4UjQEEvAT4Y9a3mtLFjzhcVBBKz8NiqAMfGhMwaSKgMqatpGT3qWzKY2f9HedshfSaAa439Vn3yNc"
],
[
- "gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj"
+ "5ip19k2UhwhpHMK8ym6ZGnLA8J9JvHzv418AwohCMf3WrCfwLhG"
],
[
- "nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny"
+ "tc1qe7avhvpmn9le76kxlcvwl69ldm0n66gefjetyn"
],
[
- "L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc"
+ "bt1pz4l3ja200jyyhtaxvz4ffm3t33ares72745gwjspttzdllvmte5qs0kd5q"
],
[
- "7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ"
+ "tb13wthrv4wkvpxl57d0plyfqjxvzu9qmdzg7eldaeut2hmcpp02mw2q3ep6tw"
],
[
- "2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP"
+ "bcrt1rqg9chz23"
],
[
- "dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw"
+ "BC102A2J0QF2MX8926EQ3WZGDC45PXL4QN267673J7P7JMJ6VD0RDTAWVQ2ZFNP4JJAW85JXP080"
],
[
- "HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX"
+ "tb1qx0shsrwmrl57djkm0yyqdyp02cmpjmlw"
],
[
- "4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB"
+ "bcrt17capp7"
],
[
- "Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ"
+ "bc1qvgrlqspye3z2ufaekn7qygm7guqjx982l"
],
[
- "Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs"
+ "tb1qk8lfs3l8df9gkw69240g0ckg4ywmw9qvmcm0pltxt8udk9szrhxqkhd5n2"
],
[
- "6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ"
+ "bcrt1qKW6Cxkky8a7gyvmkw9p3v5l2gx8zgyjtjv7dl7"
],
[
- "giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4"
+ "bc1a8xfp7"
],
[
- "cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK"
+ "tb1dclvmr"
],
[
- "37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig"
+ "bcrt1q26vevm7x046n9h3jg6zsgyd3228ra25ck7jah2"
],
[
- "EsYbG4tWWWY45G31nox838qNdzksbPySWc"
+ "BC1PCCNQDKKS5ZQ0AC69MQYQXU8ADGSGE53UY3AXXHJYFDG77Y0WX9AQHEHRL7"
],
[
- "nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT"
+ "tb1zys2pfhe9fslxat85y7uc5e78uq7449ct"
],
[
- "cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx"
+ "bcrt1slnwcpwf88ffa708xpfkm6a5wsaq9me7y0fmvg3"
],
[
- "1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde"
+ "dhBi3wYUjrVsW1pA4XhLjdavSQYSnsECskAoZ1dqLnV8hCSxuo9EZ9tf4cCoxn7fnKgCoJK3mcE"
],
[
- "2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU"
+ "2UFHPygbpDdbzmQx688QnMqSunZi97Yn5T7DVBdKyTD7sCfGi5fi8r2ct92FNUZPMm1xswo8Ve8c"
],
[
- "ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf"
+ "2yAaXFzjninFv5dn3JnWQ5y9nYkK5ZCMAkDWr4Y9WUiCGa3UiYfs"
],
[
- "Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd"
+ "tc1qmfcz6l7gfwwt0tucqgtmhwlkgtd47a3urnjpt4"
],
[
- "2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED"
- ],
- [
- "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty"
- ],
- [
- "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5"
- ],
- [
- "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2"
- ],
- [
- "bc1rw5uspcuh"
- ],
- [
- "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90"
- ],
- [
- "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P"
- ],
- [
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7"
- ],
- [
- "bc1zw508d6qejxtdg4y5r3zarvaryvqyzf3du"
- ],
- [
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"
- ],
- [
- "bc1gmk9yu"
+ "bt1flep4g"
]
]
diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json
index 8418a6002d..eea78aab20 100644
--- a/src/test/data/key_io_valid.json
+++ b/src/test/data/key_io_valid.json
@@ -1,533 +1,438 @@
[
[
- "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
- "76a91465a16059864a2fdbc7c99a4723a8395bc6f188eb88ac",
+ "1LsN3xZdsNiSMiVc45AGBdhtkQZG53tKpx",
+ "76a914d9f0c2ae3652e96389b4481a510f0b2b96da1d0888ac",
{
- "isPrivkey": false,
- "chain": "main"
- }
- ],
- [
- "3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
- "a91474f209f6ea907e2ea48f74fae05782ae8a66525787",
- {
- "isPrivkey": false,
- "chain": "main"
- }
- ],
- [
- "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
- "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
- {
- "isPrivkey": false,
- "chain": "test"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
- "76a91453c0307d6851aa0ce7825ba883c6bd9ad242b48688ac",
+ "3MJLKTjYK8U2LSE5G8qH66P6cTkd2fbYKo",
+ "a914d7184dd5b2ac5ffa6b808271b51d39610ca2952187",
{
- "isPrivkey": false,
- "chain": "regtest"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
- "a9146349a418fc4578d10a372b54b45c280cc8c4382f87",
+ "mvAUuoN11iBG6xx7AiX3ifUV9WpDfmPa8u",
+ "76a914a0aab571f298b042bc9bce37d8a45f9d37e9c5ef88ac",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
- "eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
+ "2MsFPtk8t5LQw7nBpFmsCjf8r9e5vfMMdPX",
+ "a914000844921919a97eca8adb5b63c02ecf7dc212eb87",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
- "55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
+ "mjC3aAxQcm6QeeJJ81pnpX61xMMgUXuJUG",
+ "76a914284d017134105d53e712d7801def91cfe6b3b26088ac",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
- "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ "2N7sKNwAst83ARAqh1z5Ahrt1UieLQZARvc",
+ "a914a0653c424a38b1c7d43ccafb83c90e96da58149c87",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
- "36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
+ "5J8KazNMuftbk6azCPQb5YhuiQJddSUmJcyYMbSwo8wiUFNcNQJ",
+ "28f3200da1464c7a9d7456f03980471142a63bcf2bd65f87096694a10c20c6ee",
{
+ "chain": "main",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "regtest"
- }
- ],
- [
- "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
- "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
- {
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
- "b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
+ "L44JDntsb8mGGLLJXwoEtbYbH1Sf5PZTigvVcA18184sexkwG65w",
+ "cc04f03e141b18f3debe86edf6daaa2f1b84169515774c5489db97b5a2d09153",
{
+ "chain": "main",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "regtest"
- }
- ],
- [
- "1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
- "76a9146d23156cbbdcc82a5a47eee4c2c7c583c18b6bf488ac",
- {
- "isPrivkey": false,
- "chain": "main"
- }
- ],
- [
- "3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
- "a914fcc5460dd6e2487c7d75b1963625da0e8f4c597587",
- {
- "isPrivkey": false,
- "chain": "main"
- }
- ],
- [
- "n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
- "76a914f1d470f9b02370fdec2e6b708b08ac431bf7a5f788ac",
- {
- "isPrivkey": false,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
- "a914c579342c2c4c9220205e2cdc285617040c924a0a87",
- {
- "isPrivkey": false,
- "chain": "test"
- }
- ],
- [
- "5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
- "a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
+ "93A1NRTKmTeKHinsqaPDLqMnsrhZtdgNJJ4SxEB6n7mGtfxk4Bo",
+ "ced49a2c0d95a062b2da31cc3e04dbad74cf4f93a928c77fd32e8fcca0552926",
{
+ "chain": "test",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
- "7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
+ "cQmrxBnJjdhJFJo98LnNysqDaxUKWBQANYsArzrxsRZhKtaCAqkr",
+ "5f40e71ffb52d0c31786fb6018db39e964c7d5a6b946590461fd7b28e1c4571e",
{
+ "chain": "test",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
- "d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
+ "92kU7nc1yidzKyJdJGDNhNHvjD26KGB2JtTdKK7XyEvm7hWnb1m",
+ "9961f71b7f22fe502330464805548ac3f5391ff013b91d56608ca0d18e5d9e75",
{
+ "chain": "regtest",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
- "a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
+ "cSdQEjZBzGGsZT5td11rRJqcbQ3fvz8pVrM6rkKUuJLSUFwPEWTe",
+ "96936c11e60fc08e0fb288776368ad7d754eee11753c39bad4211a5b671c875d",
{
+ "chain": "regtest",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
- "76a9147987ccaa53d02c8873487ef919677cd3db7a691288ac",
+ "bc1qqsjhe0x35lnvcxhf0de0djyqj8gfxwc90g7w8u",
+ "001404257cbcd1a7e6cc1ae97b72f6c88091d0933b05",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
- "a91463bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb87",
+ "bc1qxdyx9mr8hp39mnjdamv5f4m9908nm98zv0tt34pzd0xhrkgnelcqjh32xa",
+ "0020334862ec67b8625dce4deed944d7652bcf3d94e263d6b8d4226bcd71d913cff0",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
- "76a914ef66444b5b17f14e8fae6e7e19b045a78c54fd7988ac",
+ "bc1p2g8z7e58vl5epg9x7en4m5e9x67ekastycnlucc2z2n3ucvmppxqnjtw5m",
+ "5120520e2f668767e990a0a6f6675dd32536bd9b760b2627fe630a12a71e619b084c",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
- "a914c3e55fceceaa4391ed2a9677f4a4d34eacd021a087",
+ "bc1zyczqag2mv2",
+ "52022604",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
- }
- ],
- [
- "5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
- "e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
- {
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
- "8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
+ "tb1qx3wv854zd2emkzfc83j2t2adzftkdq4kc0t05d",
+ "0014345cc3d2a26ab3bb09383c64a5abad12576682b6",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
- "44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
+ "tb1qgjr9pkgglh8sw4ksg406xfyl7n2rz5awa5uddeqgn4y96w9khf9s2awvsc",
+ "0020448650d908fdcf0756d0455fa3249ff4d43153aeed38d6e4089d485d38b6ba4b",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
- "d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
+ "tb1pqhdwj0m7xg6c95vn07qwce4hy5nmhmqvhayx5w8zvf2hye27vruswrc2t7",
+ "512005dae93f7e323582d1937f80ec66b72527bbec0cbf486a38e2625572655e60f9",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
- "76a914adc1cc2081a27206fae25792f28bbc55b831549d88ac",
+ "tb1rjfpgh7cnpkqfrq76ekkgucwdqgklltya",
+ "531092428bfb130d809183dacdac8e61cd02",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
- "a914188f91a931947eddd7432d6e614387e32b24470987",
+ "bcrt1qq6dlzfmth08txpj06gm0jj5qaw7j8jj8qlkwdu",
+ "0014069bf1276bbbceb3064fd236f94a80ebbd23ca47",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
- "76a9141694f5bc1a7295b600f40018a618a6ea48eeb49888ac",
+ "bcrt1q3708vp22qn6ezk47lx2g0ck3tvrm7s0dj7naajlxwegm4289gjlqcwwf29",
+ "00208f9e76054a04f5915abef99487e2d15b07bf41ed97a7decbe67651baa8e544be",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
- "a9143b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f387",
+ "bcrt1pdt8nx0wk2xmv0fv0tg9l4ps87nes44dwz8s7yd0xppnxv22k2lcsssg874",
+ "51206acf333dd651b6c7a58f5a0bfa8607f4f30ad5ae11e1e235e6086666295657f1",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
- "091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
+ "bcrt1sxs49j3ctsrqpvju8wtszynehlcmgx82hmhs6kckvkyzw24d3r6j29kf3gjmmpmxwx00n7m",
+ "6028342a59470b80c0164b8772e0224f37fe36831d57dde1ab62ccb104e555b11ea4a2d93144b7b0ecce",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "regtest",
+ "isPrivkey": false,
+ "tryCaseFlip": true
}
],
[
- "L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
- "ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
+ "1HYHMSsBJnA3tkACp8Yet1DEfbc63u4ku4",
+ "76a914b56c8ec8a6297b2804113ddabd34fb95c574fca788ac",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
- "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ "3BiJtoZKF93YdYARkHxDdCYbRzwWuN9Dwa",
+ "a9146defd6f293368f683654fefac42f0fe20add132f87",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
- "b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
+ "n2FK7HfSTMg8M5A4haEhSr92xUmRFsi5PS",
+ "76a914e3655c6d2ae661c1a2e3a84a8ebb3663d2a5478d88ac",
{
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "regtest"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
- "e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
+ "2NFiGy8rTrrNKtb7NHoWDpuPtJitNAg2KYr",
+ "a914f6707c684df7be7e37402fb86578b7d31bcff88387",
{
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "chain": "test",
+ "isPrivkey": false
}
],
[
- "1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
- "76a914c4c1b72491ede1eedaca00618407ee0b772cad0d88ac",
+ "mqvNPprrNJxRnN7aopLgcgzfuZFa9pZRNw",
+ "76a914721ef1357a0e3a55920e1cbbafabaa1f675befda88ac",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
- "a914f6fe69bcb548a829cce4c57bf6fff8af3a5981f987",
+ "2N1hdjsHKpLrbXFh1uFLoP8LF9ykukL8mfz",
+ "a9145cbfa5e24b2a9c85202c1a49d949cd202c9d24b087",
{
- "isPrivkey": false,
- "chain": "main"
+ "chain": "regtest",
+ "isPrivkey": false
}
],
[
- "mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
- "76a914261f83568a098a8638844bd7aeca039d5f2352c088ac",
+ "5JEgGYoTJ9dwkvhM1RBtTYHFCLKHYSsetvuusjT8jBRgxkLHbVw",
+ "376213ede0cff4e5a9a99dc62621849edd12e84e32e50b4c2fd872b2a90a539b",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "main",
+ "isCompressed": false,
+ "isPrivkey": true
}
],
[
- "2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
- "a914e930e1834a4d234702773951d627cce82fbb5d2e87",
+ "L4eTMSFgakGfGEv88oZfZTHPicfSpSRLmqkd5xUwM5mRvGdUNWcG",
+ "dd97572e04e485cb3459c25bd5673159e37a5dfce8f6683c03886cf52c766df0",
{
- "isPrivkey": false,
- "chain": "test"
+ "chain": "main",
+ "isCompressed": true,
+ "isPrivkey": true
}
],
[
- "5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
- "d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
+ "92Vw1zxCpQeadmn9oo3DcaAzYYATC8E4dxYWcLEpJvmLDGCTpV6",
+ "78605efe8bc054d0ee79eed107446856c3c359add661a5f450e9a34dcfd9c7a0",
{
+ "chain": "test",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
- "b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
+ "cNUakHTv7yJopxUZQ3cM5RC4VfMFkUdCAyQ9jtefhomhpyqpjKiL",
+ "1ab086b845c8776e6f86468b2d7cf782a5b81096274a10b5a21dbf2fbbb20cc6",
{
+ "chain": "test",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
+ "isPrivkey": true
}
],
[
- "91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
- "037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
+ "92KS5stuYsoRe4PsxD6DTQsL3HL8oicdVwgwKvJTBeLe9JbFsAV",
+ "60899bbfa276d9263c47b92d0f3508acb42810ce00f44de1e8cb0abd628aae13",
{
+ "chain": "regtest",
"isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
- "6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
+ "cTz7XPo8zzoemHZVoATACAE9L9jzrdJ8Fkkg7a2ZQ52p9gqAASCL",
+ "bf11771d24fd18daa0a4d9b379cecb9cc7c82177e66f233515351cc05b207007",
{
+ "chain": "regtest",
"isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "isPrivkey": true
}
],
[
- "19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
- "76a9145eadaf9bb7121f0f192561a5a62f5e5f5421029288ac",
+ "bc1q6xw4mq83zgpzyedqtpgh65u7psaarrz768pwsc",
+ "0014d19d5d80f112022265a058517d539e0c3bd18c5e",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
- "a9143f210e7277c899c3a155cc1c90f4106cbddeec6e87",
+ "bc1quncjnjmmk4tyxdypl80wqv90lc7qfksp3mcv8lr5zyg9e9y7pv8s09h58f",
+ "0020e4f129cb7bb556433481f9dee030affe3c04da018ef0c3fc7411105c949e0b0f",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
- "76a914c8a3c2a09a298592c3e180f02487cd91ba3400b588ac",
+ "bc1prf34k6kzuf7vugngsz36guj5ykknjt3l36ch5ykdgemuaflfzvhs45h9c3",
+ "51201a635b6ac2e27cce226880a3a4725425ad392e3f8eb17a12cd4677cea7e9132f",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
- "a91499b31df7c9068d1481b596578ddbb4d3bd90baeb87",
+ "bc1zaxgqtcvx3y",
+ "5202e990",
{
+ "chain": "main",
"isPrivkey": false,
- "chain": "test"
- }
- ],
- [
- "5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
- "c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
- {
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "main"
- }
- ],
- [
- "KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
- "07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
- {
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "main"
- }
- ],
- [
- "93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
- "ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
- {
- "isCompressed": false,
- "isPrivkey": true,
- "chain": "test"
- }
- ],
- [
- "cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
- "0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
- {
- "isCompressed": true,
- "isPrivkey": true,
- "chain": "test"
+ "tryCaseFlip": true
}
],
[
- "13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
- "76a9141ed467017f043e91ed4c44b4e8dd674db211c4e688ac",
+ "tb1q0xeygzklzdcke5fpae8dj4gp7favyg285gy3ez",
+ "001479b2440adf13716cd121ee4ed95501f27ac22147",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
- "a9145ece0cadddc415b1980f001785947120acdb36fc87",
+ "tb1qmrryvv8jl4cdkce3s856whutzrkfcd2lytv3rqwxkj23ktf9fzzqcylgum",
+ "0020d8c64630f2fd70db633181e9a75f8b10ec9c355f22d91181c6b4951b2d254884",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "main"
+ "tryCaseFlip": true
}
],
[
- "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
- "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "tb1pv5235wgguf7fu8ajjs0vfpzhgwvwdvxsu88mjrr82cp9esy6467sgt7uws",
+ "512065151a3908e27c9e1fb2941ec484574398e6b0d0e1cfb90c6756025cc09aaebd",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kygt080",
- "0014751e76e8199196d454941c45d1b3a323f1433bd6",
+ "tb1rzhkfz2she865pjqz2dqa3kv0lvfftkeu",
+ "531015ec912a17c9f540c8025341d8d98ffb",
{
+ "chain": "test",
"isPrivkey": false,
- "chain": "regtest",
"tryCaseFlip": true
}
],
[
- "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
- "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262",
+ "bcrt1qp09acyw3823sggs8uyq6yv2vpxe4lq8scuxmef",
+ "00140bcbdc11d13aa3042207e101a2314c09b35f80f0",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "test",
"tryCaseFlip": true
}
],
[
- "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx",
- "5128751e76e8199196d454941c45d1b3a323f1433bd6751e76e8199196d454941c45d1b3a323f1433bd6",
+ "bcrt1qlnpqh99rp80qn6jkgc0zs7acyc50erwp8eefr3zzkrj7ps739fzqzla273",
+ "0020fcc20b94a309de09ea56461e287bb82628fc8dc13e7291c442b0e5e0c3d12a44",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bc1sw50qa3jx3s",
- "6002751e",
+ "bcrt1p3zd30ugrjyl587qqyu48vqclt3yawauzw6pwt3cpkskvczrytywsjpyxnq",
+ "5120889b17f103913f43f800272a76031f5c49d777827682e5c701b42ccc0864591d",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj",
- "5210751e76e8199196d454941c45d1b3a323",
+ "bcrt1stgtmagdaa9dqf0rtsxszgcd232g62t43dvkqmmmpf7deqllv576373vc5k9fps08hq3hek",
+ "60285a17bea1bde95a04bc6b81a02461aa8a91a52eb16b2c0def614f9b907feca7b51f4598a58a90c1e7",
{
+ "chain": "regtest",
"isPrivkey": false,
- "chain": "main",
"tryCaseFlip": true
}
],
[
- "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy",
- "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ "1Au8D5w97THBxXDyjCn5o8UcUWHFgZeoWv",
+ "76a9146c94c780911ea77c43eee9dc7ce4cd5eeab1e2fa88ac",
{
- "isPrivkey": false,
- "chain": "test",
- "tryCaseFlip": true
+ "chain": "main",
+ "isPrivkey": false
}
],
[
- "bcrt1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvseswlauz7",
- "0020000000c4a5cad46221b2a187905e5266362b99d5e91c6ce24d165dab93e86433",
+ "3R2FhhgAE4fM6npLMavoBeedrnDJCN4Ho6",
+ "a914ffee4c4faa197a760f901d25880c56f9d635fc8987",
{
- "isPrivkey": false,
- "chain": "regtest",
- "tryCaseFlip": true
+ "chain": "main",
+ "isPrivkey": false
}
]
]
diff --git a/src/test/fuzz/bech32.cpp b/src/test/fuzz/bech32.cpp
index 8b91f9bc96..0ac1f02263 100644
--- a/src/test/fuzz/bech32.cpp
+++ b/src/test/fuzz/bech32.cpp
@@ -16,28 +16,28 @@
void test_one_input(const std::vector<uint8_t>& buffer)
{
const std::string random_string(buffer.begin(), buffer.end());
- const std::pair<std::string, std::vector<uint8_t>> r1 = bech32::Decode(random_string);
- if (r1.first.empty()) {
- assert(r1.second.empty());
+ const auto r1 = bech32::Decode(random_string);
+ if (r1.hrp.empty()) {
+ assert(r1.encoding == bech32::Encoding::INVALID);
+ assert(r1.data.empty());
} else {
- const std::string& hrp = r1.first;
- const std::vector<uint8_t>& data = r1.second;
- const std::string reencoded = bech32::Encode(hrp, data);
+ assert(r1.encoding != bech32::Encoding::INVALID);
+ const std::string reencoded = bech32::Encode(r1.encoding, r1.hrp, r1.data);
assert(CaseInsensitiveEqual(random_string, reencoded));
}
std::vector<unsigned char> input;
ConvertBits<8, 5, true>([&](unsigned char c) { input.push_back(c); }, buffer.begin(), buffer.end());
- const std::string encoded = bech32::Encode("bc", input);
- assert(!encoded.empty());
- const std::pair<std::string, std::vector<uint8_t>> r2 = bech32::Decode(encoded);
- if (r2.first.empty()) {
- assert(r2.second.empty());
- } else {
- const std::string& hrp = r2.first;
- const std::vector<uint8_t>& data = r2.second;
- assert(hrp == "bc");
- assert(data == input);
+ if (input.size() + 3 + 6 <= 90) {
+ // If it's possible to encode input in Bech32(m) without exceeding the 90-character limit:
+ for (auto encoding : {bech32::Encoding::BECH32, bech32::Encoding::BECH32M}) {
+ const std::string encoded = bech32::Encode(encoding, "bc", input);
+ assert(!encoded.empty());
+ const auto r2 = bech32::Decode(encoded);
+ assert(r2.encoding == encoding);
+ assert(r2.hrp == "bc");
+ assert(r2.data == input);
+ }
}
}
diff --git a/test/functional/rpc_invalid_address_message.py b/test/functional/rpc_invalid_address_message.py
new file mode 100755
index 0000000000..814f50c9e6
--- /dev/null
+++ b/test/functional/rpc_invalid_address_message.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test error messages for 'getaddressinfo' and 'validateaddress' RPC commands."""
+
+from test_framework.test_framework import BitcoinTestFramework
+
+from test_framework.util import assert_raises_rpc_error
+
+BECH32_VALID = 'bcrt1qtmp74ayg7p24uslctssvjm06q5phz4yrxucgnv'
+BECH32_INVALID_BECH32 = 'bcrt1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqdmchcc'
+BECH32_INVALID_BECH32M = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7k35mrzd'
+BECH32_INVALID_VERSION = 'bcrt130xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqynjegk'
+BECH32_INVALID_SIZE = 'bcrt1s0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav25430mtr'
+BECH32_INVALID_V0_SIZE = 'bcrt1qw508d6qejxtdg4y5r3zarvary0c5xw7kqqq5k3my'
+BECH32_INVALID_PREFIX = 'bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx'
+
+BASE58_VALID = 'mipcBbFg9gMiCh81Kj8tqqdgoZub1ZJRfn'
+BASE58_INVALID_PREFIX = '17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem'
+
+INVALID_ADDRESS = 'asfah14i8fajz0123f'
+
+class InvalidAddressErrorMessageTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def skip_test_if_missing_module(self):
+ self.skip_if_no_wallet()
+
+ def test_validateaddress(self):
+ node = self.nodes[0]
+
+ # Bech32
+ info = node.validateaddress(BECH32_INVALID_SIZE)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BECH32_INVALID_PREFIX)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BECH32_INVALID_BECH32)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BECH32_INVALID_BECH32M)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BECH32_INVALID_V0_SIZE)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BECH32_VALID)
+ assert info['isvalid']
+ assert 'error' not in info
+
+ # Base58
+ info = node.validateaddress(BASE58_INVALID_PREFIX)
+ assert not info['isvalid']
+
+ info = node.validateaddress(BASE58_VALID)
+ assert info['isvalid']
+ assert 'error' not in info
+
+ # Invalid address format
+ info = node.validateaddress(INVALID_ADDRESS)
+ assert not info['isvalid']
+
+ def test_getaddressinfo(self):
+ node = self.nodes[0]
+
+ assert_raises_rpc_error(-5, "Invalid address", node.getaddressinfo, BECH32_INVALID_SIZE)
+
+ assert_raises_rpc_error(-5, "Invalid address", node.getaddressinfo, BECH32_INVALID_PREFIX)
+
+ assert_raises_rpc_error(-5, "Invalid address", node.getaddressinfo, BASE58_INVALID_PREFIX)
+
+ assert_raises_rpc_error(-5, "Invalid address", node.getaddressinfo, INVALID_ADDRESS)
+
+ def run_test(self):
+ self.test_validateaddress()
+ self.test_getaddressinfo()
+
+
+if __name__ == '__main__':
+ InvalidAddressErrorMessageTest().main()
diff --git a/test/functional/test_framework/segwit_addr.py b/test/functional/test_framework/segwit_addr.py
index 02368e938f..817534a77a 100644
--- a/test/functional/test_framework/segwit_addr.py
+++ b/test/functional/test_framework/segwit_addr.py
@@ -2,10 +2,17 @@
# Copyright (c) 2017 Pieter Wuille
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Reference implementation for Bech32 and segwit addresses."""
-
+"""Reference implementation for Bech32/Bech32m and segwit addresses."""
+from enum import Enum
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
+BECH32_CONST = 1
+BECH32M_CONST = 0x2bc830a3
+
+class Encoding(Enum):
+ """Enumeration type to list the various supported encodings."""
+ BECH32 = 1
+ BECH32M = 2
def bech32_polymod(values):
@@ -27,38 +34,45 @@ def bech32_hrp_expand(hrp):
def bech32_verify_checksum(hrp, data):
"""Verify a checksum given HRP and converted data characters."""
- return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1
-
+ check = bech32_polymod(bech32_hrp_expand(hrp) + data)
+ if check == BECH32_CONST:
+ return Encoding.BECH32
+ elif check == BECH32M_CONST:
+ return Encoding.BECH32M
+ else:
+ return None
-def bech32_create_checksum(hrp, data):
+def bech32_create_checksum(encoding, hrp, data):
"""Compute the checksum values given HRP and data."""
values = bech32_hrp_expand(hrp) + data
- polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
+ const = BECH32M_CONST if encoding == Encoding.BECH32M else BECH32_CONST
+ polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ const
return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]
-def bech32_encode(hrp, data):
- """Compute a Bech32 string given HRP and data values."""
- combined = data + bech32_create_checksum(hrp, data)
+def bech32_encode(encoding, hrp, data):
+ """Compute a Bech32 or Bech32m string given HRP and data values."""
+ combined = data + bech32_create_checksum(encoding, hrp, data)
return hrp + '1' + ''.join([CHARSET[d] for d in combined])
def bech32_decode(bech):
- """Validate a Bech32 string, and determine HRP and data."""
+ """Validate a Bech32/Bech32m string, and determine HRP and data."""
if ((any(ord(x) < 33 or ord(x) > 126 for x in bech)) or
(bech.lower() != bech and bech.upper() != bech)):
- return (None, None)
+ return (None, None, None)
bech = bech.lower()
pos = bech.rfind('1')
if pos < 1 or pos + 7 > len(bech) or len(bech) > 90:
- return (None, None)
+ return (None, None, None)
if not all(x in CHARSET for x in bech[pos+1:]):
- return (None, None)
+ return (None, None, None)
hrp = bech[:pos]
data = [CHARSET.find(x) for x in bech[pos+1:]]
- if not bech32_verify_checksum(hrp, data):
- return (None, None)
- return (hrp, data[:-6])
+ encoding = bech32_verify_checksum(hrp, data)
+ if encoding is None:
+ return (None, None, None)
+ return (encoding, hrp, data[:-6])
def convertbits(data, frombits, tobits, pad=True):
@@ -86,7 +100,7 @@ def convertbits(data, frombits, tobits, pad=True):
def decode(hrp, addr):
"""Decode a segwit address."""
- hrpgot, data = bech32_decode(addr)
+ encoding, hrpgot, data = bech32_decode(addr)
if hrpgot != hrp:
return (None, None)
decoded = convertbits(data[1:], 5, 8, False)
@@ -96,12 +110,15 @@ def decode(hrp, addr):
return (None, None)
if data[0] == 0 and len(decoded) != 20 and len(decoded) != 32:
return (None, None)
+ if (data[0] == 0 and encoding != Encoding.BECH32) or (data[0] != 0 and encoding != Encoding.BECH32M):
+ return (None, None)
return (data[0], decoded)
def encode(hrp, witver, witprog):
"""Encode a segwit address."""
- ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
+ encoding = Encoding.BECH32 if witver == 0 else Encoding.BECH32M
+ ret = bech32_encode(encoding, hrp, [witver] + convertbits(witprog, 8, 5))
if decode(hrp, ret) == (None, None):
return None
return ret
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 9f885ae4b0..17395c8357 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -221,6 +221,7 @@ BASE_SCRIPTS = [
'rpc_getaddressinfo_label_deprecation.py',
'rpc_getdescriptorinfo.py',
'rpc_help.py',
+ 'rpc_invalid_address_message.py',
'feature_help.py',
'feature_shutdown.py',
'framework_test_script.py',
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 337d2e55d9..05ec754bcc 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -133,6 +133,7 @@ class WalletLabelsTest(BitcoinTestFramework):
# in the label. This is a no-op.
change_label(node, labels[2].addresses[0], labels[2], labels[2])
+
class Label:
def __init__(self, name):
# Label name