Changeset View
Changeset View
Standalone View
Standalone View
src/test/key_io_tests.cpp
- This file was copied from src/test/base58_tests.cpp.
// Copyright (c) 2011-2016 The Bitcoin Core developers | // Copyright (c) 2011-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#include <base58.h> | #include <test/data/key_io_invalid.json.h> | ||||
#include <test/data/key_io_valid.json.h> | |||||
#include <chainparams.h> // For Params() | #include <chainparams.h> | ||||
#include <key.h> | #include <key.h> | ||||
#include <key_io.h> | #include <key_io.h> | ||||
#include <script/script.h> | #include <script/script.h> | ||||
#include <uint256.h> | |||||
#include <util.h> | |||||
#include <utilstrencodings.h> | |||||
#include <test/data/base58_encode_decode.json.h> | |||||
#include <test/data/base58_keys_invalid.json.h> | |||||
#include <test/data/base58_keys_valid.json.h> | |||||
#include <test/jsonutil.h> | |||||
#include <test/test_bitcoin.h> | #include <test/test_bitcoin.h> | ||||
#include <utilstrencodings.h> | |||||
#include <univalue.h> | |||||
#include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||
BOOST_FIXTURE_TEST_SUITE(base58_tests, BasicTestingSetup) | #include <univalue.h> | ||||
// Goal: test low-level base58 encoding functionality | |||||
BOOST_AUTO_TEST_CASE(base58_EncodeBase58) { | |||||
UniValue tests = | |||||
read_json(std::string(json_tests::base58_encode_decode, | |||||
json_tests::base58_encode_decode + | |||||
sizeof(json_tests::base58_encode_decode))); | |||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | |||||
UniValue test = tests[idx]; | |||||
std::string strTest = test.write(); | |||||
// Allow for extra stuff (useful for comments) | |||||
if (test.size() < 2) { | |||||
BOOST_ERROR("Bad test: " << strTest); | |||||
continue; | |||||
} | |||||
std::vector<uint8_t> sourcedata = ParseHex(test[0].get_str()); | |||||
std::string base58string = test[1].get_str(); | |||||
BOOST_CHECK_MESSAGE( | |||||
EncodeBase58(sourcedata.data(), | |||||
sourcedata.data() + sourcedata.size()) == base58string, | |||||
strTest); | |||||
} | |||||
} | |||||
// Goal: test low-level base58 decoding functionality | extern UniValue read_json(const std::string &jsondata); | ||||
BOOST_AUTO_TEST_CASE(base58_DecodeBase58) { | |||||
UniValue tests = | |||||
read_json(std::string(json_tests::base58_encode_decode, | |||||
json_tests::base58_encode_decode + | |||||
sizeof(json_tests::base58_encode_decode))); | |||||
std::vector<uint8_t> result; | |||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | BOOST_FIXTURE_TEST_SUITE(key_io_tests, BasicTestingSetup) | ||||
UniValue test = tests[idx]; | |||||
std::string strTest = test.write(); | |||||
// Allow for extra stuff (useful for comments) | |||||
if (test.size() < 2) { | |||||
BOOST_ERROR("Bad test: " << strTest); | |||||
continue; | |||||
} | |||||
std::vector<uint8_t> expected = ParseHex(test[0].get_str()); | |||||
std::string base58string = test[1].get_str(); | |||||
BOOST_CHECK_MESSAGE(DecodeBase58(base58string, result), strTest); | |||||
BOOST_CHECK_MESSAGE( | |||||
result.size() == expected.size() && | |||||
std::equal(result.begin(), result.end(), expected.begin()), | |||||
strTest); | |||||
} | |||||
BOOST_CHECK(!DecodeBase58("invalid", result)); | |||||
// check that DecodeBase58 skips whitespace, but still fails with unexpected | |||||
// non-whitespace at the end. | |||||
BOOST_CHECK(!DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t a", result)); | |||||
BOOST_CHECK(DecodeBase58(" \t\n\v\f\r skip \r\f\v\n\t ", result)); | |||||
std::vector<uint8_t> expected = ParseHex("971a55"); | |||||
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), | |||||
expected.begin(), expected.end()); | |||||
} | |||||
// Goal: check that parsed keys match test payload | // Goal: check that parsed keys match test payload | ||||
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) { | BOOST_AUTO_TEST_CASE(key_io_valid_parse) { | ||||
UniValue tests = read_json(std::string( | UniValue tests = read_json(std::string( | ||||
json_tests::base58_keys_valid, | json_tests::key_io_valid, | ||||
json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); | json_tests::key_io_valid + sizeof(json_tests::key_io_valid))); | ||||
CKey privkey; | CKey privkey; | ||||
CTxDestination destination; | CTxDestination destination; | ||||
SelectParams(CBaseChainParams::MAIN); | SelectParams(CBaseChainParams::MAIN); | ||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
UniValue test = tests[idx]; | UniValue test = tests[idx]; | ||||
std::string strTest = test.write(); | std::string strTest = test.write(); | ||||
// Allow for extra stuff (useful for comments) | // Allow for extra stuff (useful for comments) | ||||
Show All 37 Lines | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
// Try flipped case version | // Try flipped case version | ||||
for (char &c : exp_base58string) { | for (char &c : exp_base58string) { | ||||
if (c >= 'a' && c <= 'z') { | if (c >= 'a' && c <= 'z') { | ||||
c = (c - 'a') + 'A'; | c = (c - 'a') + 'A'; | ||||
} else if (c >= 'A' && c <= 'Z') { | } else if (c >= 'A' && c <= 'Z') { | ||||
c = (c - 'A') + 'a'; | c = (c - 'A') + 'a'; | ||||
} | } | ||||
} | } | ||||
destination = DecodeDestination(exp_base58string, Params()); | destination = DecodeLegacyAddr(exp_base58string, Params()); | ||||
BOOST_CHECK_MESSAGE(IsValidDestination(destination) == | BOOST_CHECK_MESSAGE(IsValidDestination(destination) == | ||||
try_case_flip, | try_case_flip, | ||||
"!IsValid case flipped:" + strTest); | "!IsValid case flipped:" + strTest); | ||||
if (IsValidDestination(destination)) { | if (IsValidDestination(destination)) { | ||||
script = GetScriptForDestination(destination); | script = GetScriptForDestination(destination); | ||||
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); | BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); | ||||
} | } | ||||
// Public key must be invalid private key | // Public key must be invalid private key | ||||
privkey = DecodeSecret(exp_base58string); | privkey = DecodeSecret(exp_base58string); | ||||
BOOST_CHECK_MESSAGE(!privkey.IsValid(), | BOOST_CHECK_MESSAGE(!privkey.IsValid(), | ||||
"IsValid pubkey as privkey:" + strTest); | "IsValid pubkey as privkey:" + strTest); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Goal: check that generated keys match test vectors | // Goal: check that generated keys match test vectors | ||||
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) { | BOOST_AUTO_TEST_CASE(key_io_valid_gen) { | ||||
UniValue tests = read_json(std::string( | UniValue tests = read_json(std::string( | ||||
json_tests::base58_keys_valid, | json_tests::key_io_valid, | ||||
json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); | json_tests::key_io_valid + sizeof(json_tests::key_io_valid))); | ||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
UniValue test = tests[idx]; | UniValue test = tests[idx]; | ||||
std::string strTest = test.write(); | std::string strTest = test.write(); | ||||
// Allow for extra stuff (useful for comments) | // Allow for extra stuff (useful for comments) | ||||
if (test.size() < 3) { | if (test.size() < 3) { | ||||
BOOST_ERROR("Bad test: " << strTest); | BOOST_ERROR("Bad test: " << strTest); | ||||
continue; | continue; | ||||
Show All 10 Lines | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
assert(key.IsValid()); | assert(key.IsValid()); | ||||
BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, | BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, | ||||
"result mismatch: " + strTest); | "result mismatch: " + strTest); | ||||
} else { | } else { | ||||
CTxDestination dest; | CTxDestination dest; | ||||
CScript exp_script(exp_payload.begin(), exp_payload.end()); | CScript exp_script(exp_payload.begin(), exp_payload.end()); | ||||
ExtractDestination(exp_script, dest); | ExtractDestination(exp_script, dest); | ||||
std::string address = EncodeLegacyAddr(dest, Params()); | std::string address = EncodeLegacyAddr(dest, Params()); | ||||
BOOST_CHECK_EQUAL(address, exp_base58string); | BOOST_CHECK_EQUAL(address, exp_base58string); | ||||
} | } | ||||
} | } | ||||
SelectParams(CBaseChainParams::MAIN); | SelectParams(CBaseChainParams::MAIN); | ||||
} | } | ||||
// Goal: check that base58 parsing code is robust against a variety of corrupted | // Goal: check that base58 parsing code is robust against a variety of corrupted | ||||
// data | // data | ||||
BOOST_AUTO_TEST_CASE(base58_keys_invalid) { | BOOST_AUTO_TEST_CASE(key_io_invalid) { | ||||
// Negative testcases | // Negative testcases | ||||
UniValue tests = | UniValue tests = read_json(std::string( | ||||
read_json(std::string(json_tests::base58_keys_invalid, | json_tests::key_io_invalid, | ||||
json_tests::base58_keys_invalid + | json_tests::key_io_invalid + sizeof(json_tests::key_io_invalid))); | ||||
sizeof(json_tests::base58_keys_invalid))); | |||||
CKey privkey; | CKey privkey; | ||||
CTxDestination destination; | CTxDestination destination; | ||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
UniValue test = tests[idx]; | UniValue test = tests[idx]; | ||||
std::string strTest = test.write(); | std::string strTest = test.write(); | ||||
// Allow for extra stuff (useful for comments) | // Allow for extra stuff (useful for comments) | ||||
if (test.size() < 1) { | if (test.size() < 1) { | ||||
BOOST_ERROR("Bad test: " << strTest); | BOOST_ERROR("Bad test: " << strTest); | ||||
continue; | continue; | ||||
} | } | ||||
std::string exp_base58string = test[0].get_str(); | std::string exp_base58string = test[0].get_str(); | ||||
// must be invalid as public and as private key | // must be invalid as public and as private key | ||||
for (auto chain : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, | for (auto chain : {CBaseChainParams::MAIN, CBaseChainParams::TESTNET, | ||||
CBaseChainParams::REGTEST}) { | CBaseChainParams::REGTEST}) { | ||||
SelectParams(chain); | SelectParams(chain); | ||||
destination = DecodeLegacyAddr(exp_base58string, Params()); | destination = DecodeLegacyAddr(exp_base58string, Params()); | ||||
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), | BOOST_CHECK_MESSAGE(!IsValidDestination(destination), | ||||
"IsValid pubkey:" + strTest); | "IsValid pubkey in mainnet:" + strTest); | ||||
privkey = DecodeSecret(exp_base58string); | privkey = DecodeSecret(exp_base58string); | ||||
BOOST_CHECK_MESSAGE(!privkey.IsValid(), | BOOST_CHECK_MESSAGE(!privkey.IsValid(), | ||||
"IsValid privkey:" + strTest); | "IsValid privkey in mainnet:" + strTest); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |