diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-03-07 00:04:56 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2018-03-07 00:09:48 +0100 |
commit | b225010a808d475cbb53aeed484295f8dc8751c4 (patch) | |
tree | 5ec8bb2bca595b84f4386d7da8abcccacaa7f898 /src/test | |
parent | 29088b14ee4b3b3ef772af9ba3294fadd33a4d21 (diff) | |
parent | 92f1f8b3197c2ba3cf65556070509838098975a4 (diff) |
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)
Pull request description:
This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.
This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.
Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/base58_tests.cpp | 140 | ||||
-rw-r--r-- | src/test/bip32_tests.cpp | 18 | ||||
-rw-r--r-- | src/test/bloom_tests.cpp | 7 | ||||
-rw-r--r-- | src/test/data/key_io_invalid.json (renamed from src/test/data/base58_keys_invalid.json) | 0 | ||||
-rw-r--r-- | src/test/data/key_io_valid.json (renamed from src/test/data/base58_keys_valid.json) | 0 | ||||
-rw-r--r-- | src/test/key_io_tests.cpp | 149 | ||||
-rw-r--r-- | src/test/key_tests.cpp | 27 | ||||
-rw-r--r-- | src/test/rpc_tests.cpp | 2 |
8 files changed, 169 insertions, 174 deletions
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index a2d4f82695..f90d4f90cb 100644 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -2,17 +2,10 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include <base58.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 <key.h> -#include <script/script.h> +#include <base58.h> #include <test/test_bitcoin.h> -#include <uint256.h> -#include <util.h> #include <utilstrencodings.h> #include <univalue.h> @@ -73,135 +66,4 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end()); } -// Goal: check that parsed keys match test payload -BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) -{ - UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); - CBitcoinSecret secret; - CTxDestination destination; - SelectParams(CBaseChainParams::MAIN); - - for (unsigned int idx = 0; idx < tests.size(); idx++) { - UniValue test = tests[idx]; - std::string strTest = test.write(); - 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 UniValue &metadata = test[2].get_obj(); - bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); - SelectParams(find_value(metadata, "chain").get_str()); - bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool(); - if (isPrivkey) { - bool isCompressed = find_value(metadata, "isCompressed").get_bool(); - // Must be valid private key - BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest); - BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest); - CKey privkey = secret.GetKey(); - BOOST_CHECK_MESSAGE(privkey.IsCompressed() == 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 - destination = DecodeDestination(exp_base58string); - BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest); - } else { - // Must be valid public key - destination = DecodeDestination(exp_base58string); - CScript script = GetScriptForDestination(destination); - BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest); - BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); - - // Try flipped case version - for (char& c : exp_base58string) { - if (c >= 'a' && c <= 'z') { - c = (c - 'a') + 'A'; - } else if (c >= 'A' && c <= 'Z') { - c = (c - 'A') + 'a'; - } - } - destination = DecodeDestination(exp_base58string); - BOOST_CHECK_MESSAGE(IsValidDestination(destination) == try_case_flip, "!IsValid case flipped:" + strTest); - if (IsValidDestination(destination)) { - script = GetScriptForDestination(destination); - BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); - } - - // Public key must be invalid private key - secret.SetString(exp_base58string); - BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest); - } - } -} - -// Goal: check that generated keys match test vectors -BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) -{ - UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid))); - - for (unsigned int idx = 0; idx < tests.size(); idx++) { - UniValue test = tests[idx]; - std::string strTest = test.write(); - 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 UniValue &metadata = test[2].get_obj(); - bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); - SelectParams(find_value(metadata, "chain").get_str()); - if (isPrivkey) { - bool isCompressed = find_value(metadata, "isCompressed").get_bool(); - CKey key; - key.Set(exp_payload.begin(), exp_payload.end(), isCompressed); - assert(key.IsValid()); - CBitcoinSecret secret; - secret.SetKey(key); - BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest); - } else { - CTxDestination dest; - CScript exp_script(exp_payload.begin(), exp_payload.end()); - ExtractDestination(exp_script, dest); - std::string address = EncodeDestination(dest); - - BOOST_CHECK_EQUAL(address, exp_base58string); - } - } - - SelectParams(CBaseChainParams::MAIN); -} - - -// Goal: check that base58 parsing code is robust against a variety of corrupted data -BOOST_AUTO_TEST_CASE(base58_keys_invalid) -{ - UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases - CBitcoinSecret secret; - CTxDestination destination; - - for (unsigned int idx = 0; idx < tests.size(); idx++) { - UniValue test = tests[idx]; - std::string strTest = test.write(); - 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 - for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) { - SelectParams(chain); - destination = DecodeDestination(exp_base58string); - BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest); - secret.SetString(exp_base58string); - BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey in mainnet:" + strTest); - } - } -} - - BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 438ddc177d..3c9ff1877d 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -4,8 +4,8 @@ #include <boost/test/unit_test.hpp> -#include <base58.h> #include <key.h> +#include <key_io.h> #include <uint256.h> #include <util.h> #include <utilstrencodings.h> @@ -99,20 +99,12 @@ void RunTest(const TestVector &test) { pubkey.Encode(data); // Test private key - CBitcoinExtKey b58key; b58key.SetKey(key); - BOOST_CHECK(b58key.ToString() == derive.prv); - - CBitcoinExtKey b58keyDecodeCheck(derive.prv); - CExtKey checkKey = b58keyDecodeCheck.GetKey(); - assert(checkKey == key); //ensure a base58 decoded key also matches + BOOST_CHECK(EncodeExtKey(key) == derive.prv); + BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches // Test public key - CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey); - BOOST_CHECK(b58pubkey.ToString() == derive.pub); - - CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub); - CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey(); - assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches + BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub); + BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches // Derive new keys CExtKey keyNew; diff --git a/src/test/bloom_tests.cpp b/src/test/bloom_tests.cpp index af5533b109..73c8eb5168 100644 --- a/src/test/bloom_tests.cpp +++ b/src/test/bloom_tests.cpp @@ -4,9 +4,9 @@ #include <bloom.h> -#include <base58.h> #include <clientversion.h> #include <key.h> +#include <key_io.h> #include <merkleblock.h> #include <primitives/block.h> #include <random.h> @@ -85,10 +85,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak) BOOST_AUTO_TEST_CASE(bloom_create_insert_key) { std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"); - CBitcoinSecret vchSecret; - BOOST_CHECK(vchSecret.SetString(strSecret)); - - CKey key = vchSecret.GetKey(); + CKey key = DecodeSecret(strSecret); CPubKey pubkey = key.GetPubKey(); std::vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end()); diff --git a/src/test/data/base58_keys_invalid.json b/src/test/data/key_io_invalid.json index 2056c7491c..2056c7491c 100644 --- a/src/test/data/base58_keys_invalid.json +++ b/src/test/data/key_io_invalid.json diff --git a/src/test/data/base58_keys_valid.json b/src/test/data/key_io_valid.json index 8418a6002d..8418a6002d 100644 --- a/src/test/data/base58_keys_valid.json +++ b/src/test/data/key_io_valid.json diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp new file mode 100644 index 0000000000..1ac1e0015b --- /dev/null +++ b/src/test/key_io_tests.cpp @@ -0,0 +1,149 @@ +// Copyright (c) 2011-2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <test/data/key_io_invalid.json.h> +#include <test/data/key_io_valid.json.h> + +#include <key.h> +#include <key_io.h> +#include <script/script.h> +#include <utilstrencodings.h> +#include <test/test_bitcoin.h> + +#include <boost/test/unit_test.hpp> + +#include <univalue.h> + +extern UniValue read_json(const std::string& jsondata); + +BOOST_FIXTURE_TEST_SUITE(key_io_tests, BasicTestingSetup) + +// Goal: check that parsed keys match test payload +BOOST_AUTO_TEST_CASE(key_io_valid_parse) +{ + UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid))); + CKey privkey; + CTxDestination destination; + SelectParams(CBaseChainParams::MAIN); + + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + std::string strTest = test.write(); + 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 UniValue &metadata = test[2].get_obj(); + bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); + SelectParams(find_value(metadata, "chain").get_str()); + bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool(); + if (isPrivkey) { + bool isCompressed = find_value(metadata, "isCompressed").get_bool(); + // Must be valid private key + privkey = DecodeSecret(exp_base58string); + BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest); + BOOST_CHECK_MESSAGE(privkey.IsCompressed() == 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 + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest); + } else { + // Must be valid public key + destination = DecodeDestination(exp_base58string); + CScript script = GetScriptForDestination(destination); + BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest); + BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); + + // Try flipped case version + for (char& c : exp_base58string) { + if (c >= 'a' && c <= 'z') { + c = (c - 'a') + 'A'; + } else if (c >= 'A' && c <= 'Z') { + c = (c - 'A') + 'a'; + } + } + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(IsValidDestination(destination) == try_case_flip, "!IsValid case flipped:" + strTest); + if (IsValidDestination(destination)) { + script = GetScriptForDestination(destination); + BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload)); + } + + // Public key must be invalid private key + privkey = DecodeSecret(exp_base58string); + BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest); + } + } +} + +// Goal: check that generated keys match test vectors +BOOST_AUTO_TEST_CASE(key_io_valid_gen) +{ + UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid))); + + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + std::string strTest = test.write(); + 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 UniValue &metadata = test[2].get_obj(); + bool isPrivkey = find_value(metadata, "isPrivkey").get_bool(); + SelectParams(find_value(metadata, "chain").get_str()); + if (isPrivkey) { + bool isCompressed = find_value(metadata, "isCompressed").get_bool(); + CKey key; + key.Set(exp_payload.begin(), exp_payload.end(), isCompressed); + assert(key.IsValid()); + BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest); + } else { + CTxDestination dest; + CScript exp_script(exp_payload.begin(), exp_payload.end()); + ExtractDestination(exp_script, dest); + std::string address = EncodeDestination(dest); + + BOOST_CHECK_EQUAL(address, exp_base58string); + } + } + + SelectParams(CBaseChainParams::MAIN); +} + + +// Goal: check that base58 parsing code is robust against a variety of corrupted data +BOOST_AUTO_TEST_CASE(key_io_invalid) +{ + UniValue tests = read_json(std::string(json_tests::key_io_invalid, json_tests::key_io_invalid + sizeof(json_tests::key_io_invalid))); // Negative testcases + CKey privkey; + CTxDestination destination; + + for (unsigned int idx = 0; idx < tests.size(); idx++) { + UniValue test = tests[idx]; + std::string strTest = test.write(); + 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 + for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) { + SelectParams(chain); + destination = DecodeDestination(exp_base58string); + BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest); + privkey = DecodeSecret(exp_base58string); + BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey in mainnet:" + strTest); + } + } +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 55ee1ecf6b..64c57f0705 100644 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -4,7 +4,7 @@ #include <key.h> -#include <base58.h> +#include <key_io.h> #include <script/script.h> #include <uint256.h> #include <util.h> @@ -32,21 +32,16 @@ BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup) BOOST_AUTO_TEST_CASE(key_test1) { - CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1; - BOOST_CHECK( bsecret1.SetString (strSecret1)); - BOOST_CHECK( bsecret2.SetString (strSecret2)); - BOOST_CHECK( bsecret1C.SetString(strSecret1C)); - BOOST_CHECK( bsecret2C.SetString(strSecret2C)); - BOOST_CHECK(!baddress1.SetString(strAddressBad)); - - CKey key1 = bsecret1.GetKey(); - BOOST_CHECK(key1.IsCompressed() == false); - CKey key2 = bsecret2.GetKey(); - BOOST_CHECK(key2.IsCompressed() == false); - CKey key1C = bsecret1C.GetKey(); - BOOST_CHECK(key1C.IsCompressed() == true); - CKey key2C = bsecret2C.GetKey(); - BOOST_CHECK(key2C.IsCompressed() == true); + CKey key1 = DecodeSecret(strSecret1); + BOOST_CHECK(key1.IsValid() && !key1.IsCompressed()); + CKey key2 = DecodeSecret(strSecret2); + BOOST_CHECK(key2.IsValid() && !key2.IsCompressed()); + CKey key1C = DecodeSecret(strSecret1C); + BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed()); + CKey key2C = DecodeSecret(strSecret2C); + BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed()); + CKey bad_key = DecodeSecret(strAddressBad); + BOOST_CHECK(!bad_key.IsValid()); CPubKey pubkey1 = key1. GetPubKey(); CPubKey pubkey2 = key2. GetPubKey(); diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 108c1a063e..892e4f2dac 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -5,8 +5,8 @@ #include <rpc/server.h> #include <rpc/client.h> -#include <base58.h> #include <core_io.h> +#include <key_io.h> #include <netbase.h> #include <test/test_bitcoin.h> |