Browse Source
Arbitrary numbers of test vectors can be generated using the script `gen_base58_test_vectors.py`.0.8
Wladimir J. van der Laan
12 years ago
7 changed files with 1085 additions and 64 deletions
@ -0,0 +1 @@ |
|||||||
|
Utilities to generate test vectors for the data-driven Bitcoin tests |
@ -0,0 +1,104 @@ |
|||||||
|
''' |
||||||
|
Bitcoin base58 encoding and decoding. |
||||||
|
|
||||||
|
Based on https://bitcointalk.org/index.php?topic=1026.0 (public domain) |
||||||
|
''' |
||||||
|
import hashlib |
||||||
|
|
||||||
|
# for compatibility with following code... |
||||||
|
class SHA256: |
||||||
|
new = hashlib.sha256 |
||||||
|
|
||||||
|
if str != bytes: |
||||||
|
# Python 3.x |
||||||
|
def ord(c): |
||||||
|
return c |
||||||
|
def chr(n): |
||||||
|
return bytes( (n,) ) |
||||||
|
|
||||||
|
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' |
||||||
|
__b58base = len(__b58chars) |
||||||
|
b58chars = __b58chars |
||||||
|
|
||||||
|
def b58encode(v): |
||||||
|
""" encode v, which is a string of bytes, to base58. |
||||||
|
""" |
||||||
|
long_value = 0 |
||||||
|
for (i, c) in enumerate(v[::-1]): |
||||||
|
long_value += (256**i) * ord(c) |
||||||
|
|
||||||
|
result = '' |
||||||
|
while long_value >= __b58base: |
||||||
|
div, mod = divmod(long_value, __b58base) |
||||||
|
result = __b58chars[mod] + result |
||||||
|
long_value = div |
||||||
|
result = __b58chars[long_value] + result |
||||||
|
|
||||||
|
# Bitcoin does a little leading-zero-compression: |
||||||
|
# leading 0-bytes in the input become leading-1s |
||||||
|
nPad = 0 |
||||||
|
for c in v: |
||||||
|
if c == '\0': nPad += 1 |
||||||
|
else: break |
||||||
|
|
||||||
|
return (__b58chars[0]*nPad) + result |
||||||
|
|
||||||
|
def b58decode(v, length = None): |
||||||
|
""" decode v into a string of len bytes |
||||||
|
""" |
||||||
|
long_value = 0 |
||||||
|
for (i, c) in enumerate(v[::-1]): |
||||||
|
long_value += __b58chars.find(c) * (__b58base**i) |
||||||
|
|
||||||
|
result = bytes() |
||||||
|
while long_value >= 256: |
||||||
|
div, mod = divmod(long_value, 256) |
||||||
|
result = chr(mod) + result |
||||||
|
long_value = div |
||||||
|
result = chr(long_value) + result |
||||||
|
|
||||||
|
nPad = 0 |
||||||
|
for c in v: |
||||||
|
if c == __b58chars[0]: nPad += 1 |
||||||
|
else: break |
||||||
|
|
||||||
|
result = chr(0)*nPad + result |
||||||
|
if length is not None and len(result) != length: |
||||||
|
return None |
||||||
|
|
||||||
|
return result |
||||||
|
|
||||||
|
def checksum(v): |
||||||
|
"""Return 32-bit checksum based on SHA256""" |
||||||
|
return SHA256.new(SHA256.new(v).digest()).digest()[0:4] |
||||||
|
|
||||||
|
def b58encode_chk(v): |
||||||
|
"""b58encode a string, with 32-bit checksum""" |
||||||
|
return b58encode(v + checksum(v)) |
||||||
|
|
||||||
|
def b58decode_chk(v): |
||||||
|
"""decode a base58 string, check and remove checksum""" |
||||||
|
result = b58decode(v) |
||||||
|
if result is None: |
||||||
|
return None |
||||||
|
h3 = checksum(result[:-4]) |
||||||
|
if result[-4:] == checksum(result[:-4]): |
||||||
|
return result[:-4] |
||||||
|
else: |
||||||
|
return None |
||||||
|
|
||||||
|
def get_bcaddress_version(strAddress): |
||||||
|
""" Returns None if strAddress is invalid. Otherwise returns integer version of address. """ |
||||||
|
addr = b58decode_chk(strAddress) |
||||||
|
if addr is None or len(addr)!=21: return None |
||||||
|
version = addr[0] |
||||||
|
return ord(version) |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
# Test case (from http://gitorious.org/bitcoin/python-base58.git) |
||||||
|
assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') is 0 |
||||||
|
_ohai = 'o hai'.encode('ascii') |
||||||
|
_tmp = b58encode(_ohai) |
||||||
|
assert _tmp == 'DYB3oMS' |
||||||
|
assert b58decode(_tmp, 5) == _ohai |
||||||
|
print("Tests passed") |
@ -0,0 +1,126 @@ |
|||||||
|
#!/usr/bin/env python |
||||||
|
''' |
||||||
|
Generate valid and invalid base58 address and private key test vectors. |
||||||
|
|
||||||
|
Usage: |
||||||
|
gen_base58_test_vectors.py valid 50 > ../../src/test/data/base58_keys_valid.json |
||||||
|
gen_base58_test_vectors.py invalid 50 > ../../src/test/data/base58_keys_invalid.json |
||||||
|
''' |
||||||
|
# 2012 Wladimir J. van der Laan |
||||||
|
# Released under MIT License |
||||||
|
import os |
||||||
|
from itertools import islice |
||||||
|
from base58 import b58encode, b58decode, b58encode_chk, b58decode_chk, b58chars |
||||||
|
import random |
||||||
|
from binascii import b2a_hex |
||||||
|
|
||||||
|
# key types |
||||||
|
PUBKEY_ADDRESS = 0 |
||||||
|
SCRIPT_ADDRESS = 5 |
||||||
|
PUBKEY_ADDRESS_TEST = 111 |
||||||
|
SCRIPT_ADDRESS_TEST = 196 |
||||||
|
PRIVKEY = 128 |
||||||
|
PRIVKEY_TEST = 239 |
||||||
|
|
||||||
|
metadata_keys = ['isPrivkey', 'isTestnet', 'addrType', 'isCompressed'] |
||||||
|
# templates for valid sequences |
||||||
|
templates = [ |
||||||
|
# prefix, payload_size, suffix, metadata |
||||||
|
# None = N/A |
||||||
|
((PUBKEY_ADDRESS,), 20, (), (False, False, 'pubkey', None)), |
||||||
|
((SCRIPT_ADDRESS,), 20, (), (False, False, 'script', None)), |
||||||
|
((PUBKEY_ADDRESS_TEST,), 20, (), (False, True, 'pubkey', None)), |
||||||
|
((SCRIPT_ADDRESS_TEST,), 20, (), (False, True, 'script', None)), |
||||||
|
((PRIVKEY,), 32, (), (True, False, None, False)), |
||||||
|
((PRIVKEY,), 32, (1,), (True, False, None, True)), |
||||||
|
((PRIVKEY_TEST,), 32, (), (True, True, None, False)), |
||||||
|
((PRIVKEY_TEST,), 32, (1,), (True, True, None, True)) |
||||||
|
] |
||||||
|
|
||||||
|
def is_valid(v): |
||||||
|
'''Check vector v for validity''' |
||||||
|
result = b58decode_chk(v) |
||||||
|
if result is None: |
||||||
|
return False |
||||||
|
valid = False |
||||||
|
for template in templates: |
||||||
|
prefix = str(bytearray(template[0])) |
||||||
|
suffix = str(bytearray(template[2])) |
||||||
|
if result.startswith(prefix) and result.endswith(suffix): |
||||||
|
if (len(result) - len(prefix) - len(suffix)) == template[1]: |
||||||
|
return True |
||||||
|
return False |
||||||
|
|
||||||
|
def gen_valid_vectors(): |
||||||
|
'''Generate valid test vectors''' |
||||||
|
while True: |
||||||
|
for template in templates: |
||||||
|
prefix = str(bytearray(template[0])) |
||||||
|
payload = os.urandom(template[1]) |
||||||
|
suffix = str(bytearray(template[2])) |
||||||
|
rv = b58encode_chk(prefix + payload + suffix) |
||||||
|
assert is_valid(rv) |
||||||
|
metadata = dict([(x,y) for (x,y) in zip(metadata_keys,template[3]) if y is not None]) |
||||||
|
yield (rv, b2a_hex(payload), metadata) |
||||||
|
|
||||||
|
def gen_invalid_vector(template, corrupt_prefix, randomize_payload_size, corrupt_suffix): |
||||||
|
'''Generate possibly invalid vector''' |
||||||
|
if corrupt_prefix: |
||||||
|
prefix = os.urandom(1) |
||||||
|
else: |
||||||
|
prefix = str(bytearray(template[0])) |
||||||
|
|
||||||
|
if randomize_payload_size: |
||||||
|
payload = os.urandom(max(int(random.expovariate(0.5)), 50)) |
||||||
|
else: |
||||||
|
payload = os.urandom(template[1]) |
||||||
|
|
||||||
|
if corrupt_suffix: |
||||||
|
suffix = os.urandom(len(template[2])) |
||||||
|
else: |
||||||
|
suffix = str(bytearray(template[2])) |
||||||
|
|
||||||
|
return b58encode_chk(prefix + payload + suffix) |
||||||
|
|
||||||
|
def randbool(p = 0.5): |
||||||
|
'''Return True with P(p)''' |
||||||
|
return random.random() < p |
||||||
|
|
||||||
|
def gen_invalid_vectors(): |
||||||
|
'''Generate invalid test vectors''' |
||||||
|
# start with some manual edge-cases |
||||||
|
yield "", |
||||||
|
yield "x", |
||||||
|
while True: |
||||||
|
# kinds of invalid vectors: |
||||||
|
# invalid prefix |
||||||
|
# invalid payload length |
||||||
|
# invalid (randomized) suffix (add random data) |
||||||
|
# corrupt checksum |
||||||
|
for template in templates: |
||||||
|
val = gen_invalid_vector(template, randbool(0.2), randbool(0.2), randbool(0.2)) |
||||||
|
if random.randint(0,10)<1: # line corruption |
||||||
|
if randbool(): # add random character to end |
||||||
|
val += random.choice(b58chars) |
||||||
|
else: # replace random character in the middle |
||||||
|
n = random.randint(0, len(val)) |
||||||
|
val = val[0:n] + random.choice(b58chars) + val[n+1:] |
||||||
|
if not is_valid(val): |
||||||
|
yield val, |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
import sys, json |
||||||
|
iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors} |
||||||
|
try: |
||||||
|
uiter = iters[sys.argv[1]] |
||||||
|
except IndexError: |
||||||
|
uiter = gen_valid_vectors |
||||||
|
try: |
||||||
|
count = int(sys.argv[2]) |
||||||
|
except IndexError: |
||||||
|
count = 0 |
||||||
|
|
||||||
|
data = list(islice(uiter(), count)) |
||||||
|
json.dump(data, sys.stdout, sort_keys=True, indent=4) |
||||||
|
sys.stdout.write('\n') |
||||||
|
|
@ -1,87 +1,259 @@ |
|||||||
#include <boost/test/unit_test.hpp> |
#include <boost/test/unit_test.hpp> |
||||||
|
#include "json/json_spirit_reader_template.h" |
||||||
|
#include "json/json_spirit_writer_template.h" |
||||||
|
#include "json/json_spirit_utils.h" |
||||||
|
|
||||||
#include "base58.h" |
#include "base58.h" |
||||||
|
#include "util.h" |
||||||
|
|
||||||
|
using namespace json_spirit; |
||||||
|
extern Array read_json(const std::string& filename); |
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(base58_tests) |
BOOST_AUTO_TEST_SUITE(base58_tests) |
||||||
|
|
||||||
// TODO:
|
// Goal: test low-level base58 encoding functionality
|
||||||
// EncodeBase58Check
|
BOOST_AUTO_TEST_CASE(base58_EncodeBase58) |
||||||
// DecodeBase58Check
|
{ |
||||||
// CBase58Data
|
Array tests = read_json("base58_encode_decode.json"); |
||||||
// bool SetString(const char* psz)
|
|
||||||
// bool SetString(const std::string& str)
|
BOOST_FOREACH(Value& tv, tests) |
||||||
// std::string ToString() const
|
{ |
||||||
// int CompareTo(const CBase58Data& b58) const
|
Array test = tv.get_array(); |
||||||
// bool operator==(const CBase58Data& b58) const
|
std::string strTest = write_string(tv, false); |
||||||
// bool operator<=(const CBase58Data& b58) const
|
if (test.size() < 2) // Allow for extra stuff (useful for comments)
|
||||||
// bool operator>=(const CBase58Data& b58) const
|
{ |
||||||
// bool operator< (const CBase58Data& b58) const
|
BOOST_ERROR("Bad test: " << strTest); |
||||||
// bool operator> (const CBase58Data& b58) const
|
continue; |
||||||
|
} |
||||||
// CBitcoinAddress
|
std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str()); |
||||||
// bool SetHash160(const uint160& hash160)
|
std::string base58string = test[1].get_str(); |
||||||
// bool SetPubKey(const std::vector<unsigned char>& vchPubKey)
|
BOOST_CHECK_MESSAGE( |
||||||
// bool IsValid() const
|
EncodeBase58(&sourcedata[0], &sourcedata[sourcedata.size()]) == base58string, |
||||||
// CBitcoinAddress()
|
strTest); |
||||||
// CBitcoinAddress(uint160 hash160In)
|
} |
||||||
// CBitcoinAddress(const std::vector<unsigned char>& vchPubKey)
|
} |
||||||
// CBitcoinAddress(const std::string& strAddress)
|
|
||||||
// CBitcoinAddress(const char* pszAddress)
|
// Goal: test low-level base58 decoding functionality
|
||||||
// uint160 GetHash160() const
|
BOOST_AUTO_TEST_CASE(base58_DecodeBase58) |
||||||
|
{ |
||||||
#define U(x) (reinterpret_cast<const unsigned char*>(x)) |
Array tests = read_json("base58_encode_decode.json"); |
||||||
static struct { |
std::vector<unsigned char> result; |
||||||
const unsigned char *data; |
|
||||||
int size; |
BOOST_FOREACH(Value& tv, tests) |
||||||
} vstrIn[] = { |
{ |
||||||
{U(""), 0}, |
Array test = tv.get_array(); |
||||||
{U("\x61"), 1}, |
std::string strTest = write_string(tv, false); |
||||||
{U("\x62\x62\x62"), 3}, |
if (test.size() < 2) // Allow for extra stuff (useful for comments)
|
||||||
{U("\x63\x63\x63"), 3}, |
{ |
||||||
{U("\x73\x69\x6d\x70\x6c\x79\x20\x61\x20\x6c\x6f\x6e\x67\x20\x73\x74\x72\x69\x6e\x67"), 20}, |
BOOST_ERROR("Bad test: " << strTest); |
||||||
{U("\x00\xeb\x15\x23\x1d\xfc\xeb\x60\x92\x58\x86\xb6\x7d\x06\x52\x99\x92\x59\x15\xae\xb1\x72\xc0\x66\x47"), 25}, |
continue; |
||||||
{U("\x51\x6b\x6f\xcd\x0f"), 5}, |
} |
||||||
{U("\xbf\x4f\x89\x00\x1e\x67\x02\x74\xdd"), 9}, |
std::vector<unsigned char> expected = ParseHex(test[0].get_str()); |
||||||
{U("\x57\x2e\x47\x94"), 4}, |
std::string base58string = test[1].get_str(); |
||||||
{U("\xec\xac\x89\xca\xd9\x39\x23\xc0\x23\x21"), 10}, |
BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest); |
||||||
{U("\x10\xc8\x51\x1e"), 4}, |
BOOST_CHECK_MESSAGE(result.size() == expected.size() && std::equal(result.begin(), result.end(), expected.begin()), strTest); |
||||||
{U("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"), 10}, |
} |
||||||
|
|
||||||
|
BOOST_CHECK(!DecodeBase58("invalid", result)); |
||||||
|
} |
||||||
|
|
||||||
|
// Visitor to check address type
|
||||||
|
class TestAddrTypeVisitor : public boost::static_visitor<bool> |
||||||
|
{ |
||||||
|
private: |
||||||
|
std::string exp_addrType; |
||||||
|
public: |
||||||
|
TestAddrTypeVisitor(const std::string &exp_addrType) : exp_addrType(exp_addrType) { } |
||||||
|
bool operator()(const CKeyID &id) const |
||||||
|
{ |
||||||
|
return (exp_addrType == "pubkey"); |
||||||
|
} |
||||||
|
bool operator()(const CScriptID &id) const |
||||||
|
{ |
||||||
|
return (exp_addrType == "script"); |
||||||
|
} |
||||||
|
bool operator()(const CNoDestination &no) const |
||||||
|
{ |
||||||
|
return (exp_addrType == "none"); |
||||||
|
} |
||||||
}; |
}; |
||||||
|
|
||||||
const char *vstrOut[] = { |
// Visitor to check address payload
|
||||||
"", |
class TestPayloadVisitor : public boost::static_visitor<bool> |
||||||
"2g", |
{ |
||||||
"a3gV", |
private: |
||||||
"aPEr", |
std::vector<unsigned char> exp_payload; |
||||||
"2cFupjhnEsSn59qHXstmK2ffpLv2", |
public: |
||||||
"1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L", |
TestPayloadVisitor(std::vector<unsigned char> &exp_payload) : exp_payload(exp_payload) { } |
||||||
"ABnLTmg", |
bool operator()(const CKeyID &id) const |
||||||
"3SEo3LWLoPntC", |
{ |
||||||
"3EFU7m", |
uint160 exp_key(exp_payload); |
||||||
"EJDM8drfXA6uyA", |
return exp_key == id; |
||||||
"Rt5zm", |
} |
||||||
"1111111111" |
bool operator()(const CScriptID &id) const |
||||||
|
{ |
||||||
|
uint160 exp_key(exp_payload); |
||||||
|
return exp_key == id; |
||||||
|
} |
||||||
|
bool operator()(const CNoDestination &no) const |
||||||
|
{ |
||||||
|
return exp_payload.size() == 0; |
||||||
|
} |
||||||
}; |
}; |
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(base58_EncodeBase58) |
// Goal: check that parsed keys match test payload
|
||||||
|
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) |
||||||
{ |
{ |
||||||
for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++) |
Array tests = read_json("base58_keys_valid.json"); |
||||||
|
std::vector<unsigned char> result; |
||||||
|
CBitcoinSecret secret; |
||||||
|
CBitcoinAddress addr; |
||||||
|
// Save global state
|
||||||
|
bool fTestNet_stored = fTestNet; |
||||||
|
|
||||||
|
BOOST_FOREACH(Value& tv, tests) |
||||||
{ |
{ |
||||||
BOOST_CHECK_EQUAL(EncodeBase58(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size), vstrOut[i]); |
Array test = tv.get_array(); |
||||||
|
std::string strTest = write_string(tv, false); |
||||||
|
if (test.size() < 3) // Allow for extra stuff (useful for comments)
|
||||||
|
{ |
||||||
|
BOOST_ERROR("Bad test: " << strTest); |
||||||
|
continue; |
||||||
|
} |
||||||
|
std::string exp_base58string = test[0].get_str(); |
||||||
|
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str()); |
||||||
|
const Object &metadata = test[2].get_obj(); |
||||||
|
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); |
||||||
|
bool isTestnet = find_value(metadata, "isTestnet").get_bool(); |
||||||
|
fTestNet = isTestnet; // Override testnet flag
|
||||||
|
if(isPrivkey) |
||||||
|
{ |
||||||
|
bool isCompressed = find_value(metadata, "isCompressed").get_bool(); |
||||||
|
// Must be valid private key
|
||||||
|
// Note: CBitcoinSecret::SetString tests isValid, whereas CBitcoinAddress does not!
|
||||||
|
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest); |
||||||
|
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest); |
||||||
|
bool fCompressedOut = false; |
||||||
|
CSecret privkey = secret.GetSecret(fCompressedOut); |
||||||
|
BOOST_CHECK_MESSAGE(fCompressedOut == isCompressed, "compressed mismatch:" + strTest); |
||||||
|
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest); |
||||||
|
|
||||||
|
// Private key must be invalid public key
|
||||||
|
addr.SetString(exp_base58string); |
||||||
|
BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid privkey as pubkey:" + strTest); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
std::string exp_addrType = find_value(metadata, "addrType").get_str(); // "script" or "pubkey"
|
||||||
|
// Must be valid public key
|
||||||
|
BOOST_CHECK_MESSAGE(addr.SetString(exp_base58string), "SetString:" + strTest); |
||||||
|
BOOST_CHECK_MESSAGE(addr.IsValid(), "!IsValid:" + strTest); |
||||||
|
BOOST_CHECK_MESSAGE(addr.IsScript() == (exp_addrType == "script"), "isScript mismatch" + strTest); |
||||||
|
CTxDestination dest = addr.Get(); |
||||||
|
BOOST_CHECK_MESSAGE(boost::apply_visitor(TestAddrTypeVisitor(exp_addrType), dest), "addrType mismatch" + strTest); |
||||||
|
|
||||||
|
// Public key must be invalid private key
|
||||||
|
secret.SetString(exp_base58string); |
||||||
|
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); |
||||||
|
} |
||||||
} |
} |
||||||
|
// Restore global state
|
||||||
|
fTestNet = fTestNet_stored; |
||||||
} |
} |
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(base58_DecodeBase58) |
// Goal: check that generated keys match test vectors
|
||||||
|
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) |
||||||
{ |
{ |
||||||
|
Array tests = read_json("base58_keys_valid.json"); |
||||||
std::vector<unsigned char> result; |
std::vector<unsigned char> result; |
||||||
for (unsigned int i=0; i<sizeof(vstrIn)/sizeof(vstrIn[0]); i++) |
// Save global state
|
||||||
|
bool fTestNet_stored = fTestNet; |
||||||
|
|
||||||
|
BOOST_FOREACH(Value& tv, tests) |
||||||
{ |
{ |
||||||
std::vector<unsigned char> expected(vstrIn[i].data, vstrIn[i].data + vstrIn[i].size); |
Array test = tv.get_array(); |
||||||
BOOST_CHECK(DecodeBase58(vstrOut[i], result)); |
std::string strTest = write_string(tv, false); |
||||||
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); |
if (test.size() < 3) // Allow for extra stuff (useful for comments)
|
||||||
|
{ |
||||||
|
BOOST_ERROR("Bad test: " << strTest); |
||||||
|
continue; |
||||||
|
} |
||||||
|
std::string exp_base58string = test[0].get_str(); |
||||||
|
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str()); |
||||||
|
const Object &metadata = test[2].get_obj(); |
||||||
|
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); |
||||||
|
bool isTestnet = find_value(metadata, "isTestnet").get_bool(); |
||||||
|
fTestNet = isTestnet; // Override testnet flag
|
||||||
|
if(isPrivkey) |
||||||
|
{ |
||||||
|
bool isCompressed = find_value(metadata, "isCompressed").get_bool(); |
||||||
|
CBitcoinSecret secret; |
||||||
|
secret.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed); |
||||||
|
BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
std::string exp_addrType = find_value(metadata, "addrType").get_str(); |
||||||
|
CTxDestination dest; |
||||||
|
if(exp_addrType == "pubkey") |
||||||
|
{ |
||||||
|
dest = CKeyID(uint160(exp_payload)); |
||||||
|
} |
||||||
|
else if(exp_addrType == "script") |
||||||
|
{ |
||||||
|
dest = CScriptID(uint160(exp_payload)); |
||||||
|
} |
||||||
|
else if(exp_addrType == "none") |
||||||
|
{ |
||||||
|
dest = CNoDestination(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
BOOST_ERROR("Bad addrtype: " << strTest); |
||||||
|
continue; |
||||||
|
} |
||||||
|
CBitcoinAddress addrOut; |
||||||
|
BOOST_CHECK_MESSAGE(boost::apply_visitor(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest); |
||||||
|
BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Visiting a CNoDestination must fail
|
||||||
|
CBitcoinAddress dummyAddr; |
||||||
|
CTxDestination nodest = CNoDestination(); |
||||||
|
BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest)); |
||||||
|
|
||||||
|
// Restore global state
|
||||||
|
fTestNet = fTestNet_stored; |
||||||
|
} |
||||||
|
|
||||||
|
// Goal: check that base58 parsing code is robust against a variety of corrupted data
|
||||||
|
BOOST_AUTO_TEST_CASE(base58_keys_invalid) |
||||||
|
{ |
||||||
|
Array tests = read_json("base58_keys_invalid.json"); // Negative testcases
|
||||||
|
std::vector<unsigned char> result; |
||||||
|
CBitcoinSecret secret; |
||||||
|
CBitcoinAddress addr; |
||||||
|
|
||||||
|
BOOST_FOREACH(Value& tv, tests) |
||||||
|
{ |
||||||
|
Array test = tv.get_array(); |
||||||
|
std::string strTest = write_string(tv, false); |
||||||
|
if (test.size() < 1) // Allow for extra stuff (useful for comments)
|
||||||
|
{ |
||||||
|
BOOST_ERROR("Bad test: " << strTest); |
||||||
|
continue; |
||||||
|
} |
||||||
|
std::string exp_base58string = test[0].get_str(); |
||||||
|
|
||||||
|
// must be invalid as public and as private key
|
||||||
|
addr.SetString(exp_base58string); |
||||||
|
BOOST_CHECK_MESSAGE(!addr.IsValid(), "IsValid pubkey:" + strTest); |
||||||
|
secret.SetString(exp_base58string); |
||||||
|
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest); |
||||||
} |
} |
||||||
BOOST_CHECK(!DecodeBase58("invalid", result)); |
|
||||||
} |
} |
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END() |
BOOST_AUTO_TEST_SUITE_END() |
||||||
|
|
||||||
|
@ -0,0 +1,14 @@ |
|||||||
|
[ |
||||||
|
["", ""], |
||||||
|
["61", "2g"], |
||||||
|
["626262", "a3gV"], |
||||||
|
["636363", "aPEr"], |
||||||
|
["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], |
||||||
|
["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"], |
||||||
|
["516b6fcd0f", "ABnLTmg"], |
||||||
|
["bf4f89001e670274dd", "3SEo3LWLoPntC"], |
||||||
|
["572e4794", "3EFU7m"], |
||||||
|
["ecac89cad93923c02321", "EJDM8drfXA6uyA"], |
||||||
|
["10c8511e", "Rt5zm"], |
||||||
|
["00000000000000000000", "1111111111"] |
||||||
|
] |
@ -0,0 +1,152 @@ |
|||||||
|
[ |
||||||
|
[ |
||||||
|
"" |
||||||
|
], |
||||||
|
[ |
||||||
|
"x" |
||||||
|
], |
||||||
|
[ |
||||||
|
"37qgekLpCCHrQuSjvX3fs496FWTGsHFHizjJAs6NPcR47aefnnCWECAhHV6E3g4YN7u7Yuwod5Y" |
||||||
|
], |
||||||
|
[ |
||||||
|
"dzb7VV1Ui55BARxv7ATxAtCUeJsANKovDGWFVgpTbhq9gvPqP3yv" |
||||||
|
], |
||||||
|
[ |
||||||
|
"MuNu7ZAEDFiHthiunm7dPjwKqrVNCM3mAz6rP9zFveQu14YA8CxExSJTHcVP9DErn6u84E6Ej7S" |
||||||
|
], |
||||||
|
[ |
||||||
|
"rPpQpYknyNQ5AEHuY6H8ijJJrYc2nDKKk9jjmKEXsWzyAQcFGpDLU2Zvsmoi8JLR7hAwoy3RQWf" |
||||||
|
], |
||||||
|
[ |
||||||
|
"4Uc3FmN6NQ6zLBK5QQBXRBUREaaHwCZYsGCueHauuDmJpZKn6jkEskMB2Zi2CNgtb5r6epWEFfUJq" |
||||||
|
], |
||||||
|
[ |
||||||
|
"7aQgR5DFQ25vyXmqZAWmnVCjL3PkBcdVkBUpjrjMTcghHx3E8wb" |
||||||
|
], |
||||||
|
[ |
||||||
|
"17QpPprjeg69fW1DV8DcYYCKvWjYhXvWkov6MJ1iTTvMFj6weAqW7wybZeH57WTNxXVCRH4veVs" |
||||||
|
], |
||||||
|
[ |
||||||
|
"KxuACDviz8Xvpn1xAh9MfopySZNuyajYMZWz16Dv2mHHryznWUp3" |
||||||
|
], |
||||||
|
[ |
||||||
|
"7nK3GSmqdXJQtdohvGfJ7KsSmn3TmGqExug49583bDAL91pVSGq5xS9SHoAYL3Wv3ijKTit65th" |
||||||
|
], |
||||||
|
[ |
||||||
|
"cTivdBmq7bay3RFGEBBuNfMh2P1pDCgRYN2Wbxmgwr4ki3jNUL2va" |
||||||
|
], |
||||||
|
[ |
||||||
|
"gjMV4vjNjyMrna4fsAr8bWxAbwtmMUBXJS3zL4NJt5qjozpbQLmAfK1uA3CquSqsZQMpoD1g2nk" |
||||||
|
], |
||||||
|
[ |
||||||
|
"emXm1naBMoVzPjbk7xpeTVMFy4oDEe25UmoyGgKEB1gGWsK8kRGs" |
||||||
|
], |
||||||
|
[ |
||||||
|
"7VThQnNRj1o3Zyvc7XHPRrjDf8j2oivPTeDXnRPYWeYGE4pXeRJDZgf28ppti5hsHWXS2GSobdqyo" |
||||||
|
], |
||||||
|
[ |
||||||
|
"1G9u6oCVCPh2o8m3t55ACiYvG1y5BHewUkDSdiQarDcYXXhFHYdzMdYfUAhfxn5vNZBwpgUNpso" |
||||||
|
], |
||||||
|
[ |
||||||
|
"31QQ7ZMLkScDiB4VyZjuptr7AEc9j1SjstF7pRoLhHTGkW4Q2y9XELobQmhhWxeRvqcukGd1XCq" |
||||||
|
], |
||||||
|
[ |
||||||
|
"DHqKSnpxa8ZdQyH8keAhvLTrfkyBMQxqngcQA5N8LQ9KVt25kmGN" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2LUHcJPbwLCy9GLH1qXmfmAwvadWw4bp4PCpDfduLqV17s6iDcy1imUwhQJhAoNoN1XNmweiJP4i" |
||||||
|
], |
||||||
|
[ |
||||||
|
"7USRzBXAnmck8fX9HmW7RAb4qt92VFX6soCnts9s74wxm4gguVhtG5of8fZGbNPJA83irHVY6bCos" |
||||||
|
], |
||||||
|
[ |
||||||
|
"1DGezo7BfVebZxAbNT3XGujdeHyNNBF3vnficYoTSp4PfK2QaML9bHzAMxke3wdKdHYWmsMTJVu" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2D12DqDZKwCxxkzs1ZATJWvgJGhQ4cFi3WrizQ5zLAyhN5HxuAJ1yMYaJp8GuYsTLLxTAz6otCfb" |
||||||
|
], |
||||||
|
[ |
||||||
|
"8AFJzuTujXjw1Z6M3fWhQ1ujDW7zsV4ePeVjVo7D1egERqSW9nZ" |
||||||
|
], |
||||||
|
[ |
||||||
|
"163Q17qLbTCue8YY3AvjpUhotuaodLm2uqMhpYirsKjVqnxJRWTEoywMVY3NbBAHuhAJ2cF9GAZ" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2MnmgiRH4eGLyLc9eAqStzk7dFgBjFtUCtu" |
||||||
|
], |
||||||
|
[ |
||||||
|
"461QQ2sYWxU7H2PV4oBwJGNch8XVTYYbZxU" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2UCtv53VttmQYkVU4VMtXB31REvQg4ABzs41AEKZ8UcB7DAfVzdkV9JDErwGwyj5AUHLkmgZeobs" |
||||||
|
], |
||||||
|
[ |
||||||
|
"cSNjAsnhgtiFMi6MtfvgscMB2Cbhn2v1FUYfviJ1CdjfidvmeW6mn" |
||||||
|
], |
||||||
|
[ |
||||||
|
"gmsow2Y6EWAFDFE1CE4Hd3Tpu2BvfmBfG1SXsuRARbnt1WjkZnFh1qGTiptWWbjsq2Q6qvpgJVj" |
||||||
|
], |
||||||
|
[ |
||||||
|
"nksUKSkzS76v8EsSgozXGMoQFiCoCHzCVajFKAXqzK5on9ZJYVHMD5CKwgmX3S3c7M1U3xabUny" |
||||||
|
], |
||||||
|
[ |
||||||
|
"L3favK1UzFGgdzYBF2oBT5tbayCo4vtVBLJhg2iYuMeePxWG8SQc" |
||||||
|
], |
||||||
|
[ |
||||||
|
"7VxLxGGtYT6N99GdEfi6xz56xdQ8nP2dG1CavuXx7Rf2PrvNMTBNevjkfgs9JmkcGm6EXpj8ipyPZ" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2mbZwFXF6cxShaCo2czTRB62WTx9LxhTtpP" |
||||||
|
], |
||||||
|
[ |
||||||
|
"dB7cwYdcPSgiyAwKWL3JwCVwSk6epU2txw" |
||||||
|
], |
||||||
|
[ |
||||||
|
"HPhFUhUAh8ZQQisH8QQWafAxtQYju3SFTX" |
||||||
|
], |
||||||
|
[ |
||||||
|
"4ctAH6AkHzq5ioiM1m9T3E2hiYEev5mTsB" |
||||||
|
], |
||||||
|
[ |
||||||
|
"Hn1uFi4dNexWrqARpjMqgT6cX1UsNPuV3cHdGg9ExyXw8HTKadbktRDtdeVmY3M1BxJStiL4vjJ" |
||||||
|
], |
||||||
|
[ |
||||||
|
"Sq3fDbvutABmnAHHExJDgPLQn44KnNC7UsXuT7KZecpaYDMU9Txs" |
||||||
|
], |
||||||
|
[ |
||||||
|
"6TqWyrqdgUEYDQU1aChMuFMMEimHX44qHFzCUgGfqxGgZNMUVWJ" |
||||||
|
], |
||||||
|
[ |
||||||
|
"giqJo7oWqFxNKWyrgcBxAVHXnjJ1t6cGoEffce5Y1y7u649Noj5wJ4mmiUAKEVVrYAGg2KPB3Y4" |
||||||
|
], |
||||||
|
[ |
||||||
|
"cNzHY5e8vcmM3QVJUcjCyiKMYfeYvyueq5qCMV3kqcySoLyGLYUK" |
||||||
|
], |
||||||
|
[ |
||||||
|
"37uTe568EYc9WLoHEd9jXEvUiWbq5LFLscNyqvAzLU5vBArUJA6eydkLmnMwJDjkL5kXc2VK7ig" |
||||||
|
], |
||||||
|
[ |
||||||
|
"EsYbG4tWWWY45G31nox838qNdzksbPySWc" |
||||||
|
], |
||||||
|
[ |
||||||
|
"nbuzhfwMoNzA3PaFnyLcRxE9bTJPDkjZ6Rf6Y6o2ckXZfzZzXBT" |
||||||
|
], |
||||||
|
[ |
||||||
|
"cQN9PoxZeCWK1x56xnz6QYAsvR11XAce3Ehp3gMUdfSQ53Y2mPzx" |
||||||
|
], |
||||||
|
[ |
||||||
|
"1Gm3N3rkef6iMbx4voBzaxtXcmmiMTqZPhcuAepRzYUJQW4qRpEnHvMojzof42hjFRf8PE2jPde" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2TAq2tuN6x6m233bpT7yqdYQPELdTDJn1eU" |
||||||
|
], |
||||||
|
[ |
||||||
|
"ntEtnnGhqPii4joABvBtSEJG6BxjT2tUZqE8PcVYgk3RHpgxgHDCQxNbLJf7ardf1dDk2oCQ7Cf" |
||||||
|
], |
||||||
|
[ |
||||||
|
"Ky1YjoZNgQ196HJV3HpdkecfhRBmRZdMJk89Hi5KGfpfPwS2bUbfd" |
||||||
|
], |
||||||
|
[ |
||||||
|
"2A1q1YsMZowabbvta7kTy2Fd6qN4r5ZCeG3qLpvZBMzCixMUdkN2Y4dHB1wPsZAeVXUGD83MfRED" |
||||||
|
] |
||||||
|
] |
@ -0,0 +1,452 @@ |
|||||||
|
[ |
||||||
|
[ |
||||||
|
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i", |
||||||
|
"65a16059864a2fdbc7c99a4723a8395bc6f188eb", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou", |
||||||
|
"74f209f6ea907e2ea48f74fae05782ae8a665257", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs", |
||||||
|
"53c0307d6851aa0ce7825ba883c6bd9ad242b486", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br", |
||||||
|
"6349a418fc4578d10a372b54b45c280cc8c4382f", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr", |
||||||
|
"eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD", |
||||||
|
"55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko", |
||||||
|
"36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH", |
||||||
|
"b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ", |
||||||
|
"6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy", |
||||||
|
"fcc5460dd6e2487c7d75b1963625da0e8f4c5975", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ", |
||||||
|
"f1d470f9b02370fdec2e6b708b08ac431bf7a5f7", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", |
||||||
|
"c579342c2c4c9220205e2cdc285617040c924a0a", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc", |
||||||
|
"a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi", |
||||||
|
"7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj", |
||||||
|
"d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN", |
||||||
|
"a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv", |
||||||
|
"7987ccaa53d02c8873487ef919677cd3db7a6912", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks", |
||||||
|
"63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk", |
||||||
|
"ef66444b5b17f14e8fae6e7e19b045a78c54fd79", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2NB72XtkjpnATMggui83aEtPawyyKvnbX2o", |
||||||
|
"c3e55fceceaa4391ed2a9677f4a4d34eacd021a0", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9", |
||||||
|
"e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT", |
||||||
|
"8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo", |
||||||
|
"44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7", |
||||||
|
"d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu", |
||||||
|
"adc1cc2081a27206fae25792f28bbc55b831549d", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk", |
||||||
|
"188f91a931947eddd7432d6e614387e32b244709", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H", |
||||||
|
"1694f5bc1a7295b600f40018a618a6ea48eeb498", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN", |
||||||
|
"3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR", |
||||||
|
"091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8", |
||||||
|
"ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq", |
||||||
|
"b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA", |
||||||
|
"e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4", |
||||||
|
"c4c1b72491ede1eedaca00618407ee0b772cad0d", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y", |
||||||
|
"f6fe69bcb548a829cce4c57bf6fff8af3a5981f9", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6", |
||||||
|
"261f83568a098a8638844bd7aeca039d5f2352c0", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda", |
||||||
|
"e930e1834a4d234702773951d627cce82fbb5d2e", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg", |
||||||
|
"d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi", |
||||||
|
"b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys", |
||||||
|
"037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw", |
||||||
|
"6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r", |
||||||
|
"5eadaf9bb7121f0f192561a5a62f5e5f54210292", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3", |
||||||
|
"3f210e7277c899c3a155cc1c90f4106cbddeec6e", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"myoqcgYiehufrsnnkqdqbp69dddVDMopJu", |
||||||
|
"c8a3c2a09a298592c3e180f02487cd91ba3400b5", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C", |
||||||
|
"99b31df7c9068d1481b596578ddbb4d3bd90baeb", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4", |
||||||
|
"c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2", |
||||||
|
"07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV", |
||||||
|
"ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801", |
||||||
|
{ |
||||||
|
"isCompressed": false, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h", |
||||||
|
"0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c", |
||||||
|
{ |
||||||
|
"isCompressed": true, |
||||||
|
"isPrivkey": true, |
||||||
|
"isTestnet": true |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE", |
||||||
|
"1ed467017f043e91ed4c44b4e8dd674db211c4e6", |
||||||
|
{ |
||||||
|
"addrType": "pubkey", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
], |
||||||
|
[ |
||||||
|
"3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G", |
||||||
|
"5ece0cadddc415b1980f001785947120acdb36fc", |
||||||
|
{ |
||||||
|
"addrType": "script", |
||||||
|
"isPrivkey": false, |
||||||
|
"isTestnet": false |
||||||
|
} |
||||||
|
] |
||||||
|
] |
Loading…
Reference in new issue