Skip to content

Commit 32e69fa

Browse files
committed
Replace CBitcoinSecret with {Encode,Decode}Secret
1 parent ffc6e48 commit 32e69fa

File tree

9 files changed

+62
-118
lines changed

9 files changed

+62
-118
lines changed

src/base58.cpp

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -323,39 +323,35 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par
323323
}
324324
} // namespace
325325

326-
void CBitcoinSecret::SetKey(const CKey& vchSecret)
326+
CKey DecodeSecret(const std::string& str)
327327
{
328-
assert(vchSecret.IsValid());
329-
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
330-
if (vchSecret.IsCompressed())
331-
vchData.push_back(1);
328+
CKey key;
329+
std::vector<unsigned char> data;
330+
if (DecodeBase58Check(str, data)) {
331+
const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
332+
if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
333+
std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
334+
bool compressed = data.size() == 33 + privkey_prefix.size();
335+
key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
336+
}
337+
}
338+
memory_cleanse(data.data(), data.size());
339+
return key;
332340
}
333341

334-
CKey CBitcoinSecret::GetKey()
342+
std::string EncodeSecret(const CKey& key)
335343
{
336-
CKey ret;
337-
assert(vchData.size() >= 32);
338-
ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
344+
assert(key.IsValid());
345+
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
346+
data.insert(data.end(), key.begin(), key.end());
347+
if (key.IsCompressed()) {
348+
data.push_back(1);
349+
}
350+
std::string ret = EncodeBase58Check(data);
351+
memory_cleanse(data.data(), data.size());
339352
return ret;
340353
}
341354

342-
bool CBitcoinSecret::IsValid() const
343-
{
344-
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
345-
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
346-
return fExpectedFormat && fCorrectVersion;
347-
}
348-
349-
bool CBitcoinSecret::SetString(const char* pszSecret)
350-
{
351-
return CBase58Data::SetString(pszSecret) && IsValid();
352-
}
353-
354-
bool CBitcoinSecret::SetString(const std::string& strSecret)
355-
{
356-
return SetString(strSecret.c_str());
357-
}
358-
359355
std::string EncodeDestination(const CTxDestination& dest)
360356
{
361357
return boost::apply_visitor(DestinationEncoder(Params()), dest);

src/base58.h

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,21 +94,8 @@ class CBase58Data
9494
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
9595
};
9696

97-
/**
98-
* A base58-encoded secret key
99-
*/
100-
class CBitcoinSecret : public CBase58Data
101-
{
102-
public:
103-
void SetKey(const CKey& vchSecret);
104-
CKey GetKey();
105-
bool IsValid() const;
106-
bool SetString(const char* pszSecret);
107-
bool SetString(const std::string& strSecret);
108-
109-
CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
110-
CBitcoinSecret() {}
111-
};
97+
CKey DecodeSecret(const std::string& str);
98+
std::string EncodeSecret(const CKey& key);
11299

113100
template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
114101
{

src/bitcoin-tx.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -563,12 +563,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
563563
for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
564564
if (!keysObj[kidx].isStr())
565565
throw std::runtime_error("privatekey not a std::string");
566-
CBitcoinSecret vchSecret;
567-
bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
568-
if (!fGood)
566+
CKey key = DecodeSecret(keysObj[kidx].getValStr());
567+
if (!key.IsValid()) {
569568
throw std::runtime_error("privatekey not valid");
570-
571-
CKey key = vchSecret.GetKey();
569+
}
572570
tempKeystore.AddKey(key);
573571
}
574572

src/rpc/misc.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,10 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request)
224224
std::string strPrivkey = request.params[0].get_str();
225225
std::string strMessage = request.params[1].get_str();
226226

227-
CBitcoinSecret vchSecret;
228-
bool fGood = vchSecret.SetString(strPrivkey);
229-
if (!fGood)
227+
CKey key = DecodeSecret(strPrivkey);
228+
if (!key.IsValid()) {
230229
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
231-
CKey key = vchSecret.GetKey();
232-
if (!key.IsValid())
233-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
230+
}
234231

235232
CHashWriter ss(SER_GETHASH, 0);
236233
ss << strMessageMagic;

src/rpc/rawtransaction.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -896,13 +896,9 @@ UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
896896
const UniValue& keys = request.params[1].get_array();
897897
for (unsigned int idx = 0; idx < keys.size(); ++idx) {
898898
UniValue k = keys[idx];
899-
CBitcoinSecret vchSecret;
900-
if (!vchSecret.SetString(k.get_str())) {
901-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
902-
}
903-
CKey key = vchSecret.GetKey();
899+
CKey key = DecodeSecret(k.get_str());
904900
if (!key.IsValid()) {
905-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
901+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
906902
}
907903
keystore.AddKey(key);
908904
}

src/test/base58_tests.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
7777
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
7878
{
7979
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
80-
CBitcoinSecret secret;
80+
CKey privkey;
8181
CTxDestination destination;
8282
SelectParams(CBaseChainParams::MAIN);
8383

@@ -97,9 +97,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
9797
if (isPrivkey) {
9898
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
9999
// Must be valid private key
100-
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
101-
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
102-
CKey privkey = secret.GetKey();
100+
privkey = DecodeSecret(exp_base58string);
101+
BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
103102
BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
104103
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
105104

@@ -129,8 +128,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
129128
}
130129

131130
// Public key must be invalid private key
132-
secret.SetString(exp_base58string);
133-
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
131+
privkey = DecodeSecret(exp_base58string);
132+
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest);
134133
}
135134
}
136135
}
@@ -158,9 +157,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
158157
CKey key;
159158
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
160159
assert(key.IsValid());
161-
CBitcoinSecret secret;
162-
secret.SetKey(key);
163-
BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
160+
BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
164161
} else {
165162
CTxDestination dest;
166163
CScript exp_script(exp_payload.begin(), exp_payload.end());
@@ -179,7 +176,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
179176
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
180177
{
181178
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
182-
CBitcoinSecret secret;
179+
CKey privkey;
183180
CTxDestination destination;
184181

185182
for (unsigned int idx = 0; idx < tests.size(); idx++) {
@@ -197,8 +194,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
197194
SelectParams(chain);
198195
destination = DecodeDestination(exp_base58string);
199196
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
200-
secret.SetString(exp_base58string);
201-
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey in mainnet:" + strTest);
197+
privkey = DecodeSecret(exp_base58string);
198+
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey in mainnet:" + strTest);
202199
}
203200
}
204201
}

src/test/bloom_tests.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
8585
BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
8686
{
8787
std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
88-
CBitcoinSecret vchSecret;
89-
BOOST_CHECK(vchSecret.SetString(strSecret));
90-
91-
CKey key = vchSecret.GetKey();
88+
CKey key = DecodeSecret(strSecret);
9289
CPubKey pubkey = key.GetPubKey();
9390
std::vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());
9491

src/test/key_tests.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,16 @@ BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
3232

3333
BOOST_AUTO_TEST_CASE(key_test1)
3434
{
35-
CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1;
36-
BOOST_CHECK( bsecret1.SetString (strSecret1));
37-
BOOST_CHECK( bsecret2.SetString (strSecret2));
38-
BOOST_CHECK( bsecret1C.SetString(strSecret1C));
39-
BOOST_CHECK( bsecret2C.SetString(strSecret2C));
40-
BOOST_CHECK(!baddress1.SetString(strAddressBad));
41-
42-
CKey key1 = bsecret1.GetKey();
43-
BOOST_CHECK(key1.IsCompressed() == false);
44-
CKey key2 = bsecret2.GetKey();
45-
BOOST_CHECK(key2.IsCompressed() == false);
46-
CKey key1C = bsecret1C.GetKey();
47-
BOOST_CHECK(key1C.IsCompressed() == true);
48-
CKey key2C = bsecret2C.GetKey();
49-
BOOST_CHECK(key2C.IsCompressed() == true);
35+
CKey key1 = DecodeSecret(strSecret1);
36+
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
37+
CKey key2 = DecodeSecret(strSecret2);
38+
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
39+
CKey key1C = DecodeSecret(strSecret1C);
40+
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
41+
CKey key2C = DecodeSecret(strSecret2C);
42+
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
43+
CKey bad_key = DecodeSecret(strAddressBad);
44+
BOOST_CHECK(!bad_key.IsValid());
5045

5146
CPubKey pubkey1 = key1. GetPubKey();
5247
CPubKey pubkey2 = key2. GetPubKey();

src/wallet/rpcdump.cpp

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
147147
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
148148
}
149149

150-
CBitcoinSecret vchSecret;
151-
bool fGood = vchSecret.SetString(strSecret);
152-
153-
if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
154-
155-
CKey key = vchSecret.GetKey();
156-
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
150+
CKey key = DecodeSecret(strSecret);
151+
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
157152

158153
CPubKey pubkey = key.GetPubKey();
159154
assert(key.VerifyPubKey(pubkey));
@@ -554,9 +549,8 @@ UniValue importwallet(const JSONRPCRequest& request)
554549
boost::split(vstr, line, boost::is_any_of(" "));
555550
if (vstr.size() < 2)
556551
continue;
557-
CBitcoinSecret vchSecret;
558-
if (vchSecret.SetString(vstr[0])) {
559-
CKey key = vchSecret.GetKey();
552+
CKey key = DecodeSecret(vstr[0]);
553+
if (key.IsValid()) {
560554
CPubKey pubkey = key.GetPubKey();
561555
assert(key.VerifyPubKey(pubkey));
562556
CKeyID keyid = pubkey.GetID();
@@ -659,7 +653,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
659653
if (!pwallet->GetKey(keyid, vchSecret)) {
660654
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
661655
}
662-
return CBitcoinSecret(vchSecret).ToString();
656+
return EncodeSecret(vchSecret);
663657
}
664658

665659

@@ -755,7 +749,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
755749
std::string strLabel;
756750
CKey key;
757751
if (pwallet->GetKey(keyid, key)) {
758-
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
752+
file << strprintf("%s %s ", EncodeSecret(key), strTime);
759753
if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
760754
file << strprintf("label=%s", strLabel);
761755
} else if (keyid == masterKeyID) {
@@ -911,17 +905,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
911905
for (size_t i = 0; i < keys.size(); i++) {
912906
const std::string& privkey = keys[i].get_str();
913907

914-
CBitcoinSecret vchSecret;
915-
bool fGood = vchSecret.SetString(privkey);
916-
917-
if (!fGood) {
918-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
919-
}
920-
921-
CKey key = vchSecret.GetKey();
908+
CKey key = DecodeSecret(privkey);
922909

923910
if (!key.IsValid()) {
924-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
911+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
925912
}
926913

927914
CPubKey pubkey = key.GetPubKey();
@@ -1018,16 +1005,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
10181005
const std::string& strPrivkey = keys[0].get_str();
10191006

10201007
// Checks.
1021-
CBitcoinSecret vchSecret;
1022-
bool fGood = vchSecret.SetString(strPrivkey);
1008+
CKey key = DecodeSecret(strPrivkey);
10231009

1024-
if (!fGood) {
1025-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
1026-
}
1027-
1028-
CKey key = vchSecret.GetKey();
10291010
if (!key.IsValid()) {
1030-
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
1011+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
10311012
}
10321013

10331014
CPubKey pubKey = key.GetPubKey();

0 commit comments

Comments
 (0)