From a9bb196fa7e706074927ec0be85769684e79de8e Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Tue, 24 Jan 2023 18:24:03 +0300 Subject: [PATCH 1/7] refactor: remove CSecret Rationale: With the recent move to libsecp256k1, most of the key managament code was refactored. This commit follows up on that by cleaning up the usages of CSecret for the removal of CBitcoinSecret altogether. Mostly based on upstream commit bitcoin/bitcoin@dfa23b94c24aae6466152fccbe896ba5dc0e97b4. --- src/base58.h | 22 ++++++++++------------ src/crypter.cpp | 4 ++-- src/crypter.h | 4 ++-- src/key.h | 3 --- src/keystore.cpp | 36 +++++++++++++++++------------------- src/keystore.h | 21 ++++++--------------- src/rpc/net.cpp | 8 ++------ src/rpc/rawtransaction.cpp | 5 +---- src/test/base58_tests.cpp | 10 ++++++---- src/test/key_tests.cpp | 34 ++++++++++++---------------------- src/wallet/rpcdump.cpp | 25 +++++++------------------ src/wallet/rpcwallet.cpp | 4 +--- src/wallet/wallet.cpp | 7 ++----- 13 files changed, 68 insertions(+), 115 deletions(-) diff --git a/src/base58.h b/src/base58.h index 214f021a0c..4d71e7c453 100644 --- a/src/base58.h +++ b/src/base58.h @@ -293,21 +293,19 @@ bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { class CBitcoinSecret : public CBase58Data { public: - void SetSecret(const CSecret& vchSecret, bool fCompressed) + void SetKey(const CKey& vchSecret) { - assert(vchSecret.size() == 32); - SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), &vchSecret[0], vchSecret.size()); - if (fCompressed) + assert(vchSecret.IsValid()); + SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), vchSecret.begin(), vchSecret.size()); + if (vchSecret.IsCompressed()) vchData.push_back(1); } - CSecret GetSecret(bool &fCompressedOut) + CKey GetKey() { - CSecret vchSecret; - vchSecret.resize(32); - memcpy(&vchSecret[0], &vchData[0], 32); - fCompressedOut = vchData.size() == 33; - return vchSecret; + CKey ret; + ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1); + return ret; } bool IsValid() const @@ -338,9 +336,9 @@ class CBitcoinSecret : public CBase58Data return SetString(strSecret.c_str()); } - CBitcoinSecret(const CSecret& vchSecret, bool fCompressed) + CBitcoinSecret(const CKey& vchSecret) { - SetSecret(vchSecret, fCompressed); + SetKey(vchSecret); } CBitcoinSecret() diff --git a/src/crypter.cpp b/src/crypter.cpp index fab1defe50..29e6a88573 100644 --- a/src/crypter.cpp +++ b/src/crypter.cpp @@ -114,7 +114,7 @@ bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingM } -bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) +bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) { CCrypter cKeyCrypter; std::vector chIV(WALLET_CRYPTO_KEY_SIZE); @@ -124,7 +124,7 @@ bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, con return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext); } -bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext) +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) { CCrypter cKeyCrypter; std::vector chIV(WALLET_CRYPTO_KEY_SIZE); diff --git a/src/crypter.h b/src/crypter.h index d3f1be407c..9bdb51def4 100644 --- a/src/crypter.h +++ b/src/crypter.h @@ -120,8 +120,8 @@ class CCrypter }; -bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext); -bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector &vchCiphertext, const uint256& nIV, CSecret &vchPlaintext); +bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext); +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector &vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext); bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key); #endif // BITCOIN_CRYPTER_H diff --git a/src/key.h b/src/key.h index d87ddeb2f5..069f85b45b 100644 --- a/src/key.h +++ b/src/key.h @@ -25,9 +25,6 @@ class key_error : public std::runtime_error // secure_allocator is defined in allocators.h // CPrivKey is a serialized private key, with all parameters included (279 bytes) typedef std::vector > CPrivKey; -// CSecret is a serialization of just the secret parameter (32 bytes) -typedef std::vector > CSecret; - /** An encapsulated private key. */ class CKey diff --git a/src/keystore.cpp b/src/keystore.cpp index 5fb35a8202..f1bc00d90d 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -15,13 +15,14 @@ bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const return true; } -bool CBasicKeyStore::AddKey(const CKey& key) +bool CKeyStore::AddKey(const CKey &key) { + return AddKeyPubKey(key, key.GetPubKey()); +} + +bool CBasicKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) { - CSecret secret(key.begin(), key.end()); - { - LOCK(cs_KeyStore); - mapKeys[key.GetPubKey().GetID()] = make_pair(secret, key.IsCompressed()); - } + LOCK(cs_KeyStore); + mapKeys[pubkey.GetID()] = key; return true; } @@ -133,23 +134,22 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn) return true; } -bool CCryptoKeyStore::AddKey(const CKey& key) +bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey) { { LOCK(cs_KeyStore); if (!IsCrypted()) - return CBasicKeyStore::AddKey(key); + return CBasicKeyStore::AddKeyPubKey(key, pubkey); if (IsLocked()) return false; std::vector vchCryptedSecret; - CPubKey vchPubKey = key.GetPubKey(); - CSecret secret(key.begin(), key.end()); - if (!EncryptSecret(vMasterKey, secret, vchPubKey.GetHash(), vchCryptedSecret)) + CKeyingMaterial vchSecret(key.begin(), key.end()); + if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret)) return false; - if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret)) + if (!AddCryptedKey(pubkey, vchCryptedSecret)) return false; } return true; @@ -180,7 +180,7 @@ bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const { const CPubKey& vchPubKey = mi->second.first; const std::vector& vchCryptedSecret = mi->second.second; - CSecret vchSecret; + CKeyingMaterial vchSecret; if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret)) return false; if (vchSecret.size() != 32) @@ -219,13 +219,11 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn) fUseCrypto = true; for(KeyMap::value_type& mKey : mapKeys) { - CKey key; - key.Set(mKey.second.first.begin(), mKey.second.first.end(), mKey.second.second); - if (!key.IsValid()) - return false; - const CPubKey vchPubKey = key.GetPubKey(); + const CKey &key = mKey.second; + CPubKey vchPubKey = key.GetPubKey(); + CKeyingMaterial vchSecret(key.begin(), key.end()); std::vector vchCryptedSecret; - if (!EncryptSecret(vMasterKeyIn, mKey.second.first, vchPubKey.GetHash(), vchCryptedSecret)) + if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret)) return false; if (!AddCryptedKey(vchPubKey, vchCryptedSecret)) return false; diff --git a/src/keystore.h b/src/keystore.h index cb6ab524a3..c6eea7343d 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -22,7 +22,8 @@ class CKeyStore virtual ~CKeyStore() {} // Add a key to the store. - virtual bool AddKey(const CKey& key) =0; + virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0; + virtual bool AddKey(const CKey &key); // Check whether a key corresponding to a given address is present in the store. virtual bool HaveKey(const CKeyID &address) const =0; @@ -34,19 +35,9 @@ class CKeyStore virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; - - virtual bool GetSecret(const CKeyID &address, CSecret& vchSecret, bool &fCompressed) const - { - CKey key; - if (!GetKey(address, key)) - return false; - fCompressed = key.IsCompressed(); - vchSecret.assign(key.begin(), key.end()); - return true; - } }; -typedef std::map > KeyMap; +typedef std::map KeyMap; typedef std::map ScriptMap; /** Basic key store, that keeps keys in an address->secret map */ @@ -57,7 +48,7 @@ class CBasicKeyStore : public CKeyStore ScriptMap mapScripts; public: - bool AddKey(const CKey& key); + bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); bool HaveKey(const CKeyID &address) const { bool result; @@ -87,7 +78,7 @@ class CBasicKeyStore : public CKeyStore KeyMap::const_iterator mi = mapKeys.find(address); if (mi != mapKeys.end()) { - keyOut.Set(mi->second.first.begin(), mi->second.first.end(), mi->second.second); + keyOut = mi->second; return true; } } @@ -151,7 +142,7 @@ class CCryptoKeyStore : public CBasicKeyStore bool Lock(); virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret); - bool AddKey(const CKey& key); + bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); bool HaveKey(const CKeyID &address) const { { diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index 13127761d3..d11e3cdc02 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -524,9 +524,7 @@ UniValue sendalert(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); } - bool fCompressed; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); + key = vchSecret.GetKey(); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); @@ -610,9 +608,7 @@ UniValue sendalert2(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); } - bool fCompressed; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); + key = vchSecret.GetKey(); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index ef570f9da7..41f12ed7c5 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -1766,10 +1766,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) bool fGood = vchSecret.SetString(k.get_str()); if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key"); - CKey key; - bool fCompressed; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); + CKey key = vchSecret.GetKey(); tempKeystore.AddKey(key); } } diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index 895c30e81c..feeb3fcfb0 100755 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -154,9 +154,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse) // 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); + 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 @@ -206,8 +205,11 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen) 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.SetSecret(CSecret(exp_payload.begin(), exp_payload.end()), isCompressed); + secret.SetKey(key); BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest); } else diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 0ad8b9679b..4fea1ee34c 100755 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -34,34 +34,24 @@ BOOST_AUTO_TEST_CASE(key_test1) BOOST_CHECK( bsecret2C.SetString(strSecret2C)); BOOST_CHECK(!baddress1.SetString(strAddressBad)); - bool fCompressed; - CSecret secret1 = bsecret1.GetSecret (fCompressed); - BOOST_CHECK(fCompressed == false); - CSecret secret2 = bsecret2.GetSecret (fCompressed); - BOOST_CHECK(fCompressed == false); - CSecret secret1C = bsecret1C.GetSecret(fCompressed); - BOOST_CHECK(fCompressed == true); - CSecret secret2C = bsecret2C.GetSecret(fCompressed); - BOOST_CHECK(fCompressed == true); - - BOOST_CHECK(secret1 == secret1C); - BOOST_CHECK(secret2 == secret2C); - - CKey key1, key2, key1C, key2C; - key1.Set(secret1.begin(), secret1.end(), false); - key2.Set(secret2.begin(), secret2.end(), false); - key1C.Set(secret1.begin(), secret1.end(), true); - key2C.Set(secret2.begin(), secret2.end(), true); + 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(key1C.IsCompressed() == true); CPubKey pubkey1 = key1. GetPubKey(); CPubKey pubkey2 = key2. GetPubKey(); CPubKey pubkey1C = key1C.GetPubKey(); CPubKey pubkey2C = key2C.GetPubKey(); - BOOST_CHECK(addr1.Get() == CTxDestination(key1.GetPubKey().GetID())); - BOOST_CHECK(addr2.Get() == CTxDestination(key2.GetPubKey().GetID())); - BOOST_CHECK(addr1C.Get() == CTxDestination(key1C.GetPubKey().GetID())); - BOOST_CHECK(addr2C.Get() == CTxDestination(key2C.GetPubKey().GetID())); + BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID())); + BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID())); + BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID())); + BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID())); for (int n=0; n<16; n++) { diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index b229dc7880..853b78abaf 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -130,13 +130,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key."); } - bool fCompressed; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); - - if (!key.IsValid()) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key."); - } + key = vchSecret.GetKey(); if (fWalletUnlockStakingOnly) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); @@ -216,10 +210,7 @@ UniValue importwallet(const UniValue& params, bool fHelp) if (!vchSecret.SetString(vstr[0])) continue; - bool fCompressed; - CKey key; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); + CKey key = vchSecret.GetKey(); CKeyID keyid = key.GetPubKey().GetID(); if (pwalletMain->HaveKey(keyid)) { @@ -305,9 +296,8 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) CKeyID keyID; if (!address.GetKeyID(keyID)) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); - CSecret vchSecret; - bool fCompressed; - if (!pwalletMain->GetSecret(keyID, vchSecret, fCompressed)) + CKey vchSecret; + if (!pwalletMain->GetKey(keyID, vchSecret)) throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); @@ -317,14 +307,14 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); - result.pushKV("private_key", CBitcoinSecret(vchSecret, fCompressed).ToString()); + result.pushKV("private_key", CBitcoinSecret(vchSecret).ToString()); result.pushKV("private_key_hex", HexStr(key_out.GetPrivKey())); result.pushKV("public_key_hex", HexStr(key_out.GetPubKey())); return result; } - return CBitcoinSecret(vchSecret, fCompressed).ToString(); + return CBitcoinSecret(vchSecret).ToString(); } UniValue dumpwallet(const UniValue& params, bool fHelp) @@ -397,8 +387,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) CKey key; if (pwalletMain->GetKey(keyid, key)) { - CSecret secret(key.begin(), key.end()); - file << strprintf("%s %s ", CBitcoinSecret(secret, key.IsCompressed()).ToString(), strTime); + file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime); if (pwalletMain->mapAddressBook.count(keyid)) { file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid])); } else if (keyid == masterKeyID) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 17b5b96fe4..4c9800c8b3 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2731,9 +2731,7 @@ UniValue sethdseed(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); } - bool fCompressed; - CSecret secret = vchSecret.GetSecret(fCompressed); - key.Set(secret.begin(), secret.end(), fCompressed); + key = vchSecret.GetKey(); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index df01975f35..d140f5fd44 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2994,8 +2994,7 @@ std::vector> CWallet::GetAllPrivateKe } else { - CSecret secret(vchSecret.begin(), vchSecret.end()); - CBitcoinSecret privateKey(secret, vchSecret.IsCompressed()); + CBitcoinSecret privateKey(vchSecret); res.push_back(std::make_pair(address, privateKey)); } } @@ -3020,16 +3019,14 @@ std::vector> CWallet::GetAllPrivateKe else { CKey vchSecret; - //CSecret vchSecret; if (!GetKey(keyID, vchSecret)) { LogPrintf("GetAllPrivateKeys: During Private Key Backup, Private key for address %s is not known", keyID.ToString()); } else { - CSecret secret(vchSecret.begin(), vchSecret.end()); CBitcoinAddress address(keyID); - CBitcoinSecret privateKey(secret, vchSecret.IsCompressed()); + CBitcoinSecret privateKey(vchSecret); res.push_back(std::make_pair(address, privateKey)); } } From d3823e0201fff69e87611f32a9b2800ff208f0a4 Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Tue, 24 Jan 2023 19:03:24 +0300 Subject: [PATCH 2/7] rpc,wallet: remove backupprivatekeys and related utils Rationale: This RPC method is a relic of past that's better replaced by the dumpwallet/importwallet combo. This commit removes them for the CBitcoinSecret removal. --- src/gridcoin/backup.cpp | 26 ---------------- src/gridcoin/backup.h | 1 - src/rpc/blockchain.cpp | 25 --------------- src/rpc/server.cpp | 1 - src/rpc/server.h | 1 - src/wallet/wallet.cpp | 68 ----------------------------------------- src/wallet/wallet.h | 1 - 7 files changed, 123 deletions(-) diff --git a/src/gridcoin/backup.cpp b/src/gridcoin/backup.cpp index de5456fb26..1e63af065a 100644 --- a/src/gridcoin/backup.cpp +++ b/src/gridcoin/backup.cpp @@ -336,29 +336,3 @@ bool GRC::MaintainBackups(fs::path wallet_backup_path, std::vector return true; } -bool GRC::BackupPrivateKeys(const CWallet& wallet, std::string& sTarget, std::string& sErrors) -{ - if (wallet.IsLocked() || fWalletUnlockStakingOnly) - { - sErrors = "Wallet needs to be fully unlocked to backup private keys."; - return false; - } - fs::path PrivateKeysTarget = GetBackupFilename("keys.dat"); - fs::create_directories(PrivateKeysTarget.parent_path()); - sTarget = PrivateKeysTarget.string(); - fsbridge::ofstream myBackup; - myBackup.open(PrivateKeysTarget); - std::string sError; - for(const auto& keyPair : wallet.GetAllPrivateKeys(sError)) - { - if (!sError.empty()) - { - sErrors = sError; - return false; - } - myBackup << "Address: " << keyPair.first.ToString() << ", Secret: " << keyPair.second.ToString() << std::endl; - } - LogPrintf("BackupPrivateKeys: Backup made to %s", PrivateKeysTarget.string()); - myBackup.close(); - return true; -} diff --git a/src/gridcoin/backup.h b/src/gridcoin/backup.h index 082f5c4657..f7aba4ee32 100644 --- a/src/gridcoin/backup.h +++ b/src/gridcoin/backup.h @@ -23,7 +23,6 @@ bool BackupConfigFile(const std::string& strDest); bool MaintainBackups(fs::path wallet_backup_path, std::vector backup_file_type, unsigned int retention_by_num, unsigned int retention_by_days, std::vector& files_removed); bool BackupWallet(const CWallet& wallet, const std::string& strDest); -bool BackupPrivateKeys(const CWallet& wallet, std::string& sTarget, std::string& sErrors); } #endif // GRIDCOIN_BACKUP_H diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 32ee83380c..f57b3cce80 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1081,31 +1081,6 @@ UniValue getblocksbatch(const UniValue& params, bool fHelp) return result; } -UniValue backupprivatekeys(const UniValue& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "backupprivatekeys\n" - "\n" - "Backup wallet private keys to file (Wallet must be fully unlocked!)\n"); - - string sErrors; - string sTarget; - UniValue res(UniValue::VOBJ); - - bool bBackupPrivateKeys = GRC::BackupPrivateKeys(*pwalletMain, sTarget, sErrors); - - if (!bBackupPrivateKeys) - res.pushKV("error", sErrors); - - else - res.pushKV("location", sTarget); - - res.pushKV("result", bBackupPrivateKeys); - - return res; -} - UniValue rainbymagnitude(const UniValue& params, bool fHelp) { if (fHelp || (params.size() < 2 || params.size() > 4)) diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index a483355d62..c45f5ac51b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -288,7 +288,6 @@ static const CRPCCommand vRPCCommands[] = // Wallet commands { "addmultisigaddress", &addmultisigaddress, cat_wallet }, { "addredeemscript", &addredeemscript, cat_wallet }, - { "backupprivatekeys", &backupprivatekeys, cat_wallet }, { "backupwallet", &backupwallet, cat_wallet }, { "burn", &burn, cat_wallet }, { "checkwallet", &checkwallet, cat_wallet }, diff --git a/src/rpc/server.h b/src/rpc/server.h index a4b6f2d571..e1ae8b6874 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -103,7 +103,6 @@ extern std::vector ParseHexV(const UniValue& v, std::string strNa // Wallet extern UniValue addmultisigaddress(const UniValue& params, bool fHelp); extern UniValue addredeemscript(const UniValue& params, bool fHelp); -extern UniValue backupprivatekeys(const UniValue& params, bool fHelp); extern UniValue backupwallet(const UniValue& params, bool fHelp); extern UniValue burn(const UniValue& params, bool fHelp); extern UniValue checkwallet(const UniValue& params, bool fHelp); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d140f5fd44..05447d924a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2966,74 +2966,6 @@ void CWallet::GetAllReserveKeys(set& setAddress) const } } -std::vector> CWallet::GetAllPrivateKeys(std::string& sError) const -{ - CWalletDB walletdb(strWalletFile); - - LOCK2(cs_main, cs_wallet); - - std::vector> res; - // Get Private Keys from mapAddressBook - for (auto const& item : mapAddressBook) - { - const CBitcoinAddress& address = item.first; - isminetype fMine = ::IsMine(*this, address.Get()); - if (fMine != ISMINE_NO) - { - CKeyID keyID; - if (!address.GetKeyID(keyID)) - { - LogPrintf("GetAllPrivateKeys: During private key backup, Address %s does not refer to a key", address.ToString()); - } - else - { - CKey vchSecret; - if (!GetKey(keyID, vchSecret)) - { - LogPrintf("GetAllPrivateKeys: During private key backup, Private key for address %s is not known", address.ToString()); - } - else - { - CBitcoinSecret privateKey(vchSecret); - res.push_back(std::make_pair(address, privateKey)); - } - } - } - } - // Get Private Keys from KeyPool - for (auto const& id : setKeyPool) - { - CKeyPool keypool; - if (!walletdb.ReadPool(id, keypool)) - { - // Important to know. - sError = "GetAllPrivateKeys: Failed to read pool"; - } - assert(keypool.vchPubKey.IsValid()); - CKeyID keyID = keypool.vchPubKey.GetID(); - - if (!HaveKey(keyID)) - { - LogPrintf("GetAllPrivateKeys: Unknown key in key pool"); - } - else - { - CKey vchSecret; - if (!GetKey(keyID, vchSecret)) - { - LogPrintf("GetAllPrivateKeys: During Private Key Backup, Private key for address %s is not known", keyID.ToString()); - } - else - { - CBitcoinAddress address(keyID); - CBitcoinSecret privateKey(vchSecret); - res.push_back(std::make_pair(address, privateKey)); - } - } - } - return res; -} - void CWallet::UpdatedTransaction(const uint256 &hashTx) { { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index beed549c93..4561c802d7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -286,7 +286,6 @@ class CWallet : public CCryptoKeyStore bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true); int64_t GetOldestKeyPoolTime(); void GetAllReserveKeys(std::set& setAddress) const; - std::vector> GetAllPrivateKeys(std::string& sError) const; std::set< std::set > GetAddressGroupings(); From 0ba0fcc2b5416628b9954bedf31920d4e0cb2dbb Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Tue, 24 Jan 2023 19:48:20 +0300 Subject: [PATCH 3/7] refactor: replace CBitcoinSecret with Encode/DecodeSecret Rationale: This commit replaces the usages of CBitcoinSecret with new utility methods. This moves base58.h/cpp towards more of a pure utility and moves us closer to upstream. Loosely based on bitcoin/bitcoin@32e69fa0df8fc1cfc8ac4f8381bc54b8f33e1c38. --- src/base58.h | 57 ----------- src/chainparams.cpp | 4 +- src/key_io.cpp | 31 ++++++ src/key_io.h | 3 + src/rpc/net.cpp | 16 +-- src/rpc/rawtransaction.cpp | 10 +- src/test/base58_tests.cpp | 196 ------------------------------------- src/test/key_tests.cpp | 26 +++-- src/wallet/rpcdump.cpp | 23 ++--- src/wallet/rpcwallet.cpp | 11 +-- src/wallet/wallet.cpp | 2 +- 11 files changed, 67 insertions(+), 312 deletions(-) diff --git a/src/base58.h b/src/base58.h index 4d71e7c453..dd4f686116 100644 --- a/src/base58.h +++ b/src/base58.h @@ -289,61 +289,4 @@ bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); } bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; } -/** A base58-encoded secret key */ -class CBitcoinSecret : public CBase58Data -{ -public: - void SetKey(const CKey& vchSecret) - { - assert(vchSecret.IsValid()); - SetData(128 + (fTestNet ? CBitcoinAddress::PUBKEY_ADDRESS_TEST : CBitcoinAddress::PUBKEY_ADDRESS), vchSecret.begin(), vchSecret.size()); - if (vchSecret.IsCompressed()) - vchData.push_back(1); - } - - CKey GetKey() - { - CKey ret; - ret.Set(&vchData[0], &vchData[32], vchData.size() > 32 && vchData[32] == 1); - return ret; - } - - bool IsValid() const - { - bool fExpectTestNet = false; - switch(nVersion) - { - case (128 + CBitcoinAddress::PUBKEY_ADDRESS): - break; - - case (128 + CBitcoinAddress::PUBKEY_ADDRESS_TEST): - fExpectTestNet = true; - break; - - default: - return false; - } - return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1)); - } - - bool SetString(const char* pszSecret) - { - return CBase58Data::SetString(pszSecret) && IsValid(); - } - - bool SetString(const std::string& strSecret) - { - return SetString(strSecret.c_str()); - } - - CBitcoinSecret(const CKey& vchSecret) - { - SetKey(vchSecret); - } - - CBitcoinSecret() - { - } -}; - #endif diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 53d8ca56d8..a2d2d8d790 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -102,7 +102,7 @@ class CMainParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,62); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,85); - base58Prefixes[SECRET_KEY] = std::vector(1,0); // TODO: What should be the exact value here? 128 + PUBKEY_ADDRESS as 4 bytes? + base58Prefixes[SECRET_KEY] = std::vector(1,190); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; @@ -213,7 +213,7 @@ class CTestNetParams : public CChainParams { base58Prefixes[PUBKEY_ADDRESS] = std::vector(1,111); base58Prefixes[SCRIPT_ADDRESS] = std::vector(1,196); - base58Prefixes[SECRET_KEY] = std::vector(1,0); // TODO: What should be the exact value here? 128 + PUBKEY_ADDRESS as 4 bytes? + base58Prefixes[SECRET_KEY] = std::vector(1,239); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; diff --git a/src/key_io.cpp b/src/key_io.cpp index 414996e37e..e8cca8b5dc 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -12,6 +12,37 @@ #include #include +CKey DecodeSecret(const std::string& str) +{ + CKey key; + std::vector data; + if (DecodeBase58Check(str, data, 34)) { + const std::vector& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY); + if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) && + std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) { + bool compressed = data.size() == 33 + privkey_prefix.size(); + key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed); + } + } + if (!data.empty()) { + memory_cleanse(data.data(), data.size()); + } + return key; +} + +std::string EncodeSecret(const CKey& key) +{ + assert(key.IsValid()); + std::vector data = Params().Base58Prefix(CChainParams::SECRET_KEY); + data.insert(data.end(), key.begin(), key.end()); + if (key.IsCompressed()) { + data.push_back(1); + } + std::string ret = EncodeBase58Check(data); + memory_cleanse(data.data(), data.size()); + return ret; +} + CExtPubKey DecodeExtPubKey(const std::string& str) { CExtPubKey key; diff --git a/src/key_io.h b/src/key_io.h index 248366894e..9c1b9701cc 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -12,6 +12,9 @@ #include +CKey DecodeSecret(const std::string& str); +std::string EncodeSecret(const CKey& key); + CExtKey DecodeExtKey(const std::string& str); std::string EncodeExtKey(const CExtKey& extkey); CExtPubKey DecodeExtPubKey(const std::string& str); diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index d11e3cdc02..77a4f96e64 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -518,13 +518,7 @@ UniValue sendalert(const UniValue& params, bool fHelp) sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector((unsigned char*)&sMsg.begin()[0], (unsigned char*)&sMsg.end()[0]); - CBitcoinSecret vchSecret; - - if (!vchSecret.SetString(params[0].get_str())) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); - } - - key = vchSecret.GetKey(); + key = DecodeSecret(params[0].get_str()); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); @@ -602,13 +596,7 @@ UniValue sendalert2(const UniValue& params, bool fHelp) sMsg << (CUnsignedAlert)alert; alert.vchMsg = vector((unsigned char*)&sMsg.begin()[0], (unsigned char*)&sMsg.end()[0]); - CBitcoinSecret vchSecret; - - if (!vchSecret.SetString(params[0].get_str())) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); - } - - key = vchSecret.GetKey(); + key = DecodeSecret(params[0].get_str()); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 41f12ed7c5..54e404a707 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -17,6 +17,7 @@ #include "gridcoin/support/block_finder.h" #include "gridcoin/tx_message.h" #include "gridcoin/voting/payloads.h" +#include #include "node/blockstorage.h" #include "policy/policy.h" #include "policy/fees.h" @@ -1762,11 +1763,10 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp) for (unsigned int idx = 0; idx < keys.size(); idx++) { UniValue k = keys[idx]; - CBitcoinSecret vchSecret; - bool fGood = vchSecret.SetString(k.get_str()); - if (!fGood) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY,"Invalid private key"); - CKey key = vchSecret.GetKey(); + CKey key = DecodeSecret(k.get_str()); + if (!key.IsValid()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); + } tempKeystore.AddKey(key); } } diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp index feeb3fcfb0..dee72293c1 100755 --- a/src/test/base58_tests.cpp +++ b/src/test/base58_tests.cpp @@ -8,8 +8,6 @@ #include #include #include -#include -#include #include @@ -80,198 +78,4 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58) BOOST_CHECK(!DecodeBase58Check(std::string("3vQB7B6MrGQZaxCuFg4oh\00IOl", 26), result)); } -// Visitor to check address type -class TestAddrTypeVisitor -{ -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"); - } -}; - -// Visitor to check address payload -class TestPayloadVisitor -{ -private: - std::vector exp_payload; -public: - TestPayloadVisitor(std::vector &exp_payload) : exp_payload(exp_payload) { } - bool operator()(const CKeyID &id) const - { - uint160 exp_key(exp_payload); - return exp_key == id; - } - bool operator()(const CScriptID &id) const - { - uint160 exp_key(exp_payload); - return CScriptID(exp_key) == id; - } - bool operator()(const CNoDestination &no) const - { - return exp_payload.size() == 0; - } -}; - -// 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))); - std::vector result; - CBitcoinSecret secret; - CBitcoinAddress addr; - // Save global state - bool fTestNet_stored = fTestNet; - 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 exp_payload = ParseHex(test[1].get_str()); - const UniValue &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); - 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 - 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(std::visit(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; -} - -// 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))); - std::vector result; - // Save global state - bool fTestNet_stored = fTestNet; - 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 exp_payload = ParseHex(test[1].get_str()); - const UniValue &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(); - 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 - { - 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(std::visit(CBitcoinAddressVisitor(&addrOut), dest), "encode dest: " + strTest); - BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest + addrOut.ToString()); - } - } - - // Visiting a CNoDestination must fail - CBitcoinAddress dummyAddr; - CTxDestination nodest = CNoDestination(); - BOOST_CHECK(!std::visit(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) -{ - UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); - std::vector result; - CBitcoinSecret secret; - CBitcoinAddress addr; - 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 - 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_AUTO_TEST_SUITE_END() diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index 4fea1ee34c..e8f929062a 100755 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -4,6 +4,7 @@ #include #include "key.h" +#include #include "base58.h" #include "uint256.h" #include "util.h" @@ -27,21 +28,16 @@ BOOST_AUTO_TEST_SUITE(key_tests) 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(key1C.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/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 853b78abaf..e4021e2200 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -9,7 +9,6 @@ #include "rpc/server.h" #include "rpc/protocol.h" #include "node/ui_interface.h" -#include "base58.h" #include #include @@ -123,15 +122,13 @@ UniValue importprivkey(const UniValue& params, bool fHelp) if (params.size() > 2) fRescan = params[2].get_bool(); - CBitcoinSecret vchSecret; - CKey key; + CKey key = DecodeSecret(strSecret); - if (!vchSecret.SetString(strSecret)) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key."); + if (!key.IsValid()) + { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); } - key = vchSecret.GetKey(); - if (fWalletUnlockStakingOnly) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); @@ -206,11 +203,11 @@ UniValue importwallet(const UniValue& params, bool fHelp) boost::split(vstr, line, boost::is_any_of(" ")); if (vstr.size() < 2) continue; - CBitcoinSecret vchSecret; - if (!vchSecret.SetString(vstr[0])) + + CKey key = DecodeSecret(vstr[0]); + if (!key.IsValid()) continue; - CKey key = vchSecret.GetKey(); CKeyID keyid = key.GetPubKey().GetID(); if (pwalletMain->HaveKey(keyid)) { @@ -307,14 +304,14 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); - result.pushKV("private_key", CBitcoinSecret(vchSecret).ToString()); + result.pushKV("private_key", EncodeSecret(vchSecret)); result.pushKV("private_key_hex", HexStr(key_out.GetPrivKey())); result.pushKV("public_key_hex", HexStr(key_out.GetPubKey())); return result; } - return CBitcoinSecret(vchSecret).ToString(); + return EncodeSecret(vchSecret); } UniValue dumpwallet(const UniValue& params, bool fHelp) @@ -387,7 +384,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) CKey key; if (pwalletMain->GetKey(keyid, key)) { - file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime); + file << strprintf("%s %s ", EncodeSecret(key), strTime); if (pwalletMain->mapAddressBook.count(keyid)) { file << strprintf("label=%s", EncodeDumpString(pwalletMain->mapAddressBook[keyid])); } else if (keyid == masterKeyID) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4c9800c8b3..bea4ebbf3f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3,12 +3,12 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. +#include #include "version.h" #include "txdb.h" #include "rpc/server.h" #include "rpc/protocol.h" #include "init.h" -#include "base58.h" #include "streams.h" #include "util.h" #include "gridcoin/backup.h" @@ -2724,14 +2724,7 @@ UniValue sethdseed(const UniValue& params, bool fHelp) if (params[1].isNull()) { master_pub_key = pwalletMain->GenerateNewHDMasterKey(); } else { - CKey key; - CBitcoinSecret vchSecret; - - if (!vchSecret.SetString(params[1].get_str())) { - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); - } - - key = vchSecret.GetKey(); + CKey key = DecodeSecret(params[1].get_str()); if (!key.IsValid()) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key"); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 05447d924a..827e0da8b2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4,12 +4,12 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "chainparams.h" +#include #include "txdb.h" #include "wallet/wallet.h" #include "wallet/walletdb.h" #include "crypter.h" #include "node/ui_interface.h" -#include "base58.h" #include "wallet/coincontrol.h" #include #include From 838c3269525f08e0f8a8738d7461d56a61ffa85f Mon Sep 17 00:00:00 2001 From: div72 Date: Thu, 6 Jun 2024 15:01:53 +0300 Subject: [PATCH 4/7] refactor: remove CBitcoinAddress/CBase58Data Rationale: With the recent libsecp256k1 port, most of the key code has been moved much close to upstream. This commit is the last step on also moving key IO code closer to the upstream. This changes also enable us to use bech32 addresses without much hassle. The changes were also loosely done to drop the CBase58Data class which was not chain agnostic in order to support other chains. (Like regtest.) --- src/base58.h | 229 ------------------ src/gridcoin/beacon.cpp | 23 +- src/gridcoin/beacon.h | 3 +- src/gridcoin/contract/message.cpp | 4 +- src/gridcoin/quorum.cpp | 16 +- src/gridcoin/scraper/scraper.cpp | 43 ++-- src/gridcoin/scraper/scraper.h | 2 +- src/gridcoin/scraper/scraper_net.cpp | 13 +- src/gridcoin/scraper/scraper_registry.cpp | 48 ++-- src/gridcoin/scraper/scraper_registry.h | 12 +- src/gridcoin/sidestake.cpp | 26 +- src/gridcoin/sidestake.h | 6 +- src/gridcoin/voting/builders.cpp | 47 ++-- src/key_io.cpp | 104 ++++++++ src/key_io.h | 7 + src/main.h | 1 - src/miner.cpp | 20 +- src/qt/addresstablemodel.cpp | 30 +-- src/qt/coincontroldialog.cpp | 2 +- ...nsolidateunspentwizardselectinputspage.cpp | 2 +- src/qt/researcher/researchermodel.cpp | 4 +- .../researcher/researcherwizardpoolpage.cpp | 4 +- src/qt/sendcoinsdialog.cpp | 16 +- src/qt/sidestaketablemodel.cpp | 15 +- src/qt/signverifymessagedialog.cpp | 22 +- src/qt/transactiondesc.cpp | 12 +- src/qt/transactionrecord.cpp | 12 +- src/qt/walletmodel.cpp | 16 +- src/rpc/blockchain.cpp | 46 ++-- src/rpc/client.cpp | 2 +- src/rpc/mining.cpp | 4 +- src/rpc/protocol.cpp | 2 +- src/rpc/rawtransaction.cpp | 52 ++-- src/rpc/server.cpp | 3 +- src/script.cpp | 4 + src/script.h | 4 +- src/test/gridcoin/beacon_tests.cpp | 45 ++-- src/test/gridcoin/scraper_registry_tests.cpp | 48 ++-- src/test/gridcoin/superblock_tests.cpp | 3 +- src/test/key_tests.cpp | 17 +- src/test/rpc_tests.cpp | 15 +- src/validation.cpp | 20 +- src/validation.h | 3 +- src/wallet/rpcdump.cpp | 21 +- src/wallet/rpcwallet.cpp | 138 +++++------ src/wallet/wallet.cpp | 17 +- src/wallet/wallet.h | 2 +- src/wallet/walletdb.cpp | 2 +- src/wallet/walletdb.h | 2 +- 49 files changed, 508 insertions(+), 681 deletions(-) diff --git a/src/base58.h b/src/base58.h index dd4f686116..d085f5e778 100644 --- a/src/base58.h +++ b/src/base58.h @@ -60,233 +60,4 @@ std::string EncodeBase58Check(const std::vector& vchIn); [[nodiscard]] bool DecodeBase58Check(const std::string& str, std::vector& vchRet, int max_ret_len = std::numeric_limits::max() - 4); - -/** Base class for all base58-encoded data */ -class CBase58Data -{ -protected: - // the version byte - unsigned char nVersion; - - // the actually encoded data - std::vector vchData; - - CBase58Data() - { - nVersion = 0; - vchData.clear(); - } - - ~CBase58Data() - { - // zero the memory, as it may contain sensitive data - if (!vchData.empty()) - memory_cleanse(&vchData[0], vchData.size()); - } - - void SetData(int nVersionIn, const void* pdata, size_t nSize) - { - nVersion = nVersionIn; - vchData.resize(nSize); - if (!vchData.empty()) - memcpy(&vchData[0], pdata, nSize); - } - - void SetData(int nVersionIn, const unsigned char *pbegin, const unsigned char *pend) - { - SetData(nVersionIn, (void*)pbegin, pend - pbegin); - } - -public: - bool SetString(const char* psz) - { - std::vector vchTemp; - if (!DecodeBase58Check(psz, vchTemp)) - { - vchData.clear(); - nVersion = 0; - return false; - } - nVersion = vchTemp[0]; - vchData.resize(vchTemp.size() - 1); - if (!vchData.empty()) - memcpy(&vchData[0], &vchTemp[1], vchData.size()); - memory_cleanse(&vchTemp[0], vchTemp.size()); - return true; - } - - bool SetString(const std::string& str) - { - return SetString(str.c_str()); - } - - std::string ToString() const - { - std::vector vch(1, nVersion); - vch.insert(vch.end(), vchData.begin(), vchData.end()); - return EncodeBase58Check(vch); - } - - int CompareTo(const CBase58Data& b58) const - { - if (nVersion < b58.nVersion) return -1; - if (nVersion > b58.nVersion) return 1; - if (vchData < b58.vchData) return -1; - if (vchData > b58.vchData) return 1; - return 0; - } - - bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; } - bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; } - bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; } - bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; } - bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } -}; - -/** base58-encoded addresses. - * Public-key-hash-addresses have version 25 (or 111 testnet). - * The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. - * Script-hash-addresses have version 85 (or 196 testnet). - * The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. - */ -class CBitcoinAddress; -class CBitcoinAddressVisitor -{ -private: - CBitcoinAddress *addr; -public: - CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { } - bool operator()(const CKeyID &id) const; - bool operator()(const CScriptID &id) const; - bool operator()(const CNoDestination &no) const; -}; - -class CBitcoinAddress : public CBase58Data -{ -public: - enum - { - //Base58Gridcoin: - PUBKEY_ADDRESS = 62, // Gridcoin Research addresses start with R - 62, (Classic Starts with G: 37) - SCRIPT_ADDRESS = 85, - PUBKEY_ADDRESS_TEST = 111, - SCRIPT_ADDRESS_TEST = 196, - }; - - bool Set(const CKeyID &id) { - SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20); - return true; - } - - bool Set(const CScriptID &id) { - SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20); - return true; - } - - bool Set(const CTxDestination &dest) - { - return std::visit(CBitcoinAddressVisitor(this), dest); - } - - bool IsValid() const - { - unsigned int nExpectedSize = 20; - bool fExpectTestNet = false; - switch(nVersion) - { - case PUBKEY_ADDRESS: - nExpectedSize = 20; // Hash of public key - fExpectTestNet = false; - break; - case SCRIPT_ADDRESS: - nExpectedSize = 20; // Hash of CScript - fExpectTestNet = false; - break; - - case PUBKEY_ADDRESS_TEST: - nExpectedSize = 20; - fExpectTestNet = true; - break; - case SCRIPT_ADDRESS_TEST: - nExpectedSize = 20; - fExpectTestNet = true; - break; - - default: - return false; - } - return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize; - } - - CBitcoinAddress() - { - } - - CBitcoinAddress(const CTxDestination &dest) - { - Set(dest); - } - - CBitcoinAddress(const std::string& strAddress) - { - SetString(strAddress); - } - - CBitcoinAddress(const char* pszAddress) - { - SetString(pszAddress); - } - - CTxDestination Get() const { - if (!IsValid()) - return CNoDestination(); - switch (nVersion) { - case PUBKEY_ADDRESS: - case PUBKEY_ADDRESS_TEST: { - uint160 id; - memcpy(&id, &vchData[0], 20); - return CKeyID(id); - } - case SCRIPT_ADDRESS: - case SCRIPT_ADDRESS_TEST: { - uint160 id; - memcpy(&id, &vchData[0], 20); - return CScriptID(id); - } - } - return CNoDestination(); - } - - bool GetKeyID(CKeyID &keyID) const { - if (!IsValid()) - return false; - switch (nVersion) { - case PUBKEY_ADDRESS: - case PUBKEY_ADDRESS_TEST: { - uint160 id; - memcpy(&id, &vchData[0], 20); - keyID = CKeyID(id); - return true; - } - default: return false; - } - } - - bool IsScript() const { - if (!IsValid()) - return false; - switch (nVersion) { - case SCRIPT_ADDRESS: - case SCRIPT_ADDRESS_TEST: { - return true; - } - default: return false; - } - } -}; - -bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); } -bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); } -bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; } - #endif diff --git a/src/gridcoin/beacon.cpp b/src/gridcoin/beacon.cpp index 3fdcfc9e61..e629e18b32 100644 --- a/src/gridcoin/beacon.cpp +++ b/src/gridcoin/beacon.cpp @@ -2,7 +2,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include +#include #include "logging.h" #include "main.h" #include "gridcoin/beacon.h" @@ -105,7 +106,7 @@ bool Beacon::WellFormed() const std::pair Beacon::KeyValueToString() const { - return std::make_pair(m_cpid.ToString(), GetAddress().ToString()); + return std::make_pair(m_cpid.ToString(), EncodeDestination(GetAddress())); } std::string Beacon::StatusToString() const @@ -184,9 +185,9 @@ CKeyID Beacon::GetId() const return m_public_key.GetID(); } -CBitcoinAddress Beacon::GetAddress() const +CTxDestination Beacon::GetAddress() const { - return CBitcoinAddress(CTxDestination(m_public_key.GetID())); + return CTxDestination(m_public_key.GetID()); } std::string Beacon::GetVerificationCode() const @@ -209,7 +210,7 @@ std::string Beacon::ToString() const { return EncodeBase64( "0;0;" // Unused: [CPIDv2];[nonce]; - + GetAddress().ToString() + + EncodeDestination(GetAddress()) + ";" + HexStr(m_public_key)); } @@ -429,7 +430,7 @@ bool BeaconRegistry::TryRenewal(Beacon_ptr& current_beacon_ptr, int& height, con "contracts in the same block get stored/replayed.", __func__, renewal.m_cpid.ToString(), - renewal.GetAddress().ToString(), + EncodeDestination(renewal.GetAddress()), renewal.m_hash.GetHex()); } @@ -498,7 +499,7 @@ void BeaconRegistry::Add(const ContractContext& ctx) "contracts in the same block get stored/replayed.", __func__, historical.m_cpid.ToString(), - historical.GetAddress().ToString(), + EncodeDestination(historical.GetAddress()), historical.m_hash.GetHex()); } m_beacons[payload.m_cpid] = m_beacon_db.find(ctx.m_tx.GetHash())->second; @@ -530,7 +531,7 @@ void BeaconRegistry::Add(const ContractContext& ctx) "contracts in the same block get stored/replayed.", __func__, pending.m_cpid.ToString(), - pending.GetAddress().ToString(), + EncodeDestination(pending.GetAddress()), pending.m_hash.GetHex()); } @@ -1072,7 +1073,7 @@ void BeaconRegistry::ActivatePending( LogPrint(LogFlags::BEACON, "INFO: %s: Activating beacon for cpid %s, address %s, hash %s.", __func__, activated_beacon.m_cpid.ToString(), - activated_beacon.GetAddress().ToString(), + EncodeDestination(activated_beacon.GetAddress()), activated_beacon.m_hash.GetHex()); m_beacon_db.insert(activated_beacon.m_hash, height, activated_beacon); @@ -1108,7 +1109,7 @@ void BeaconRegistry::ActivatePending( LogPrint(LogFlags::BEACON, "INFO: %s: Marking pending beacon expired for cpid %s, address %s, hash %s.", __func__, pending_beacon.m_cpid.ToString(), - pending_beacon.GetAddress().ToString(), + EncodeDestination(pending_beacon.GetAddress()), pending_beacon.m_hash.GetHex()); // Insert the expired pending beacon into the db. @@ -1194,7 +1195,7 @@ void BeaconRegistry::Deactivate(const uint256 superblock_hash) pending_beacon_entry->second->m_hash.GetHex(), pending_beacon_entry->second->m_cpid.ToString(), superblock_hash.GetHex(), - pending_beacon_entry->second->GetAddress().ToString() + EncodeDestination(pending_beacon_entry->second->GetAddress()) ); } } diff --git a/src/gridcoin/beacon.h b/src/gridcoin/beacon.h index e97d1fd0f3..cc2d0333f0 100644 --- a/src/gridcoin/beacon.h +++ b/src/gridcoin/beacon.h @@ -17,7 +17,6 @@ #include #include -class CBitcoinAddress; class CTransaction; class CWallet; @@ -218,7 +217,7 @@ class Beacon //! //! \return Address produced from the beacon's public key. //! - CBitcoinAddress GetAddress() const; + CTxDestination GetAddress() const; //! //! \brief Get the code that the scrapers use to verify the beacon. diff --git a/src/gridcoin/contract/message.cpp b/src/gridcoin/contract/message.cpp index a08ff23e4f..b6bf70496f 100644 --- a/src/gridcoin/contract/message.cpp +++ b/src/gridcoin/contract/message.cpp @@ -27,7 +27,7 @@ namespace { //! bool SelectMasterInputOutput(CCoinControl& coin_control) { - const CTxDestination master_address = CWallet::MasterAddress(pindexBest->nHeight).Get(); + const CTxDestination master_address = CWallet::MasterAddress(pindexBest->nHeight); // Send change back to the master address: coin_control.destChange = master_address; @@ -86,7 +86,7 @@ bool CreateContractTx(CWalletTx& wtx_out, CReserveKey& reserve_key, CAmount burn coin_control_out.destChange = out_address; LogPrintf("INFO: %s: Change sent to %s for contract transaction per contractchangetoinputaddress setting.", - __func__, CBitcoinAddress(coin_control_out.destChange).ToString()); + __func__, EncodeDestination(coin_control_out.destChange)); } for (const auto& contract : wtx_out.vContracts) { diff --git a/src/gridcoin/quorum.cpp b/src/gridcoin/quorum.cpp index c0d04a4753..893677cd0a 100644 --- a/src/gridcoin/quorum.cpp +++ b/src/gridcoin/quorum.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include #include "chainparams.h" #include "main.h" #include "gridcoin/claim.h" @@ -253,7 +253,7 @@ class QuorumVote { public: const QuorumHash m_hash; //!< Hash of the superblock to vote for. - const CBitcoinAddress m_address; //!< Address of the voting wallet. + const CTxDestination m_address; //!< Address of the voting wallet. const CBlockIndex* const m_pindex; //!< Block that contains the vote. //! @@ -263,7 +263,7 @@ class QuorumVote //! \param address Default address of the voting wallet. //! \param pindex Block that contains the vote. //! - QuorumVote(QuorumHash hash, CBitcoinAddress address, const CBlockIndex* pindex) + QuorumVote(QuorumHash hash, CTxDestination address, const CBlockIndex* pindex) : m_hash(hash) , m_address(std::move(address)) , m_pindex(pindex) @@ -374,9 +374,9 @@ class LegacyConsensus return; } - CBitcoinAddress address(grc_address); + CTxDestination address = DecodeDestination(grc_address); - if (!address.IsValid()) { + if (!IsValidDestination(address)) { LogPrint(BCLog::LogFlags::VERBOSE, "Quorum::RecordVote: invalid address: %s HASH: %s", grc_address, @@ -509,7 +509,7 @@ class LegacyConsensus const int64_t min_height = last_height - STANDARD_LOOKBACK; PopularityMap popularity_map; - std::map addresses_seen; + std::map addresses_seen; for (const auto& vote_pair : reverse_iterate(m_votes)) { const int64_t vote_height = vote_pair.first; @@ -1557,9 +1557,9 @@ bool Quorum::ValidateSuperblockClaim( return ValidateSuperblock(superblock); } - const CBitcoinAddress address(claim.m_quorum_address); + const CTxDestination address = DecodeDestination(claim.m_quorum_address); - if (!address.IsValid()) { + if (!IsValidDestination(address)) { return error("ValidateSuperblockClaim(): " "invalid quorum address: %s", claim.m_quorum_address); } diff --git a/src/gridcoin/scraper/scraper.cpp b/src/gridcoin/scraper/scraper.cpp index d654f88d4a..0dfcb83578 100755 --- a/src/gridcoin/scraper/scraper.cpp +++ b/src/gridcoin/scraper/scraper.cpp @@ -442,7 +442,7 @@ bool ScraperSaveCScraperManifestToFiles(uint256 nManifestHash); * @param Key * @return bool true if successful */ -bool ScraperSendFileManifestContents(CBitcoinAddress& Address, CKey& Key); +bool ScraperSendFileManifestContents(CTxDestination& Address, CKey& Key); /** * @brief Sorts the inventory of CScraperManifests by scraper and orders by manifest time, which is important for * convergence determination @@ -1493,7 +1493,7 @@ void Scraper(bool bSingleShot) int64_t sbage = SuperblockAge(); int64_t nScraperThreadStartTime = GetAdjustedTime(); - CBitcoinAddress AddressOut; + CTxDestination AddressOut; CKey KeyOut; // These are to ensure thread-safety of these globals and keep the locking scope to a minimum. These will go away @@ -4116,7 +4116,7 @@ bool IsScraperAuthorized() return ALLOW_NONSCRAPER_NODE_STATS_DOWNLOAD; } -bool IsScraperAuthorizedToBroadcastManifests(CBitcoinAddress& AddressOut, CKey& KeyOut) +bool IsScraperAuthorizedToBroadcastManifests(CTxDestination& AddressOut, CKey& KeyOut) { AppCacheSection mScrapers = GetScrapersCache(); @@ -4138,23 +4138,22 @@ bool IsScraperAuthorizedToBroadcastManifests(CBitcoinAddress& AddressOut, CKey& { _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", "Entry in appcache is enabled."); - CBitcoinAddress address(sScraperAddressFromConfig); + CTxDestination address = DecodeDestination(sScraperAddressFromConfig); //CPubKey ScraperPubKey(ParseHex(sScraperAddressFromConfig)); - CKeyID KeyID; - address.GetKeyID(KeyID); + CKeyID* KeyID = std::get_if(&address); // ... and the address is valid... - if (address.IsValid()) + if (KeyID) { _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", "The address is valid."); _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", - "(Doublecheck) The address is " + address.ToString()); + "(Doublecheck) The address is " + EncodeDestination(address)); // ... and it exists in the wallet... LOCK(pwalletMain->cs_wallet); - if (pwalletMain->GetKey(KeyID, KeyOut)) + if (pwalletMain->GetKey(*KeyID, KeyOut)) { // ... and the key returned from the wallet is valid and matches the provided public key... assert(KeyOut.IsValid()); @@ -4189,9 +4188,9 @@ bool IsScraperAuthorizedToBroadcastManifests(CBitcoinAddress& AddressOut, CKey& for (auto const& item : pwalletMain->mapAddressBook) { - const CBitcoinAddress& address = item.first; + const CTxDestination& address = item.first; - std::string sScraperAddress = address.ToString(); + std::string sScraperAddress = EncodeDestination(address); _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", "Checking address " + sScraperAddress); entry = mScrapers.find(sScraperAddress); @@ -4206,18 +4205,17 @@ bool IsScraperAuthorizedToBroadcastManifests(CBitcoinAddress& AddressOut, CKey& { _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", "AppCache entry enabled"); - CKeyID KeyID; - address.GetKeyID(KeyID); + const CKeyID* KeyID = std::get_if(&address); // ... and the address is valid... - if (address.IsValid()) + if (KeyID) { _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", "The address is valid."); _log(logattribute::INFO, "IsScraperAuthorizedToBroadcastManifests", - "(Doublecheck) The address is " + address.ToString()); + "(Doublecheck) The address is " + EncodeDestination(address)); // ... and it exists in the wallet... (It SHOULD here... it came from the map...) - if (pwalletMain->GetKey(KeyID, KeyOut)) + if (pwalletMain->GetKey(*KeyID, KeyOut)) { // ... and the key returned from the wallet is valid ... assert(KeyOut.IsValid()); @@ -4264,11 +4262,10 @@ EXCLUSIVE_LOCKS_REQUIRED(CScraperManifest::cs_mapManifest) CKeyID ManifestKeyID = PubKey.GetID(); - CBitcoinAddress ManifestAddress; - ManifestAddress.Set(ManifestKeyID); + CTxDestination ManifestAddress(ManifestKeyID); // This is the address corresponding to the manifest public key, and is the scraper ID key in the outer map. - std::string sManifestAddress = ManifestAddress.ToString(); + std::string sManifestAddress = EncodeDestination(ManifestAddress); const auto& iScraper = mMapCSManifestBinnedByScraper.find(sManifestAddress); @@ -4411,7 +4408,7 @@ unsigned int ScraperDeleteUnauthorizedCScraperManifests() return nDeleted; } -bool ScraperSendFileManifestContents(CBitcoinAddress& Address, CKey& Key) +bool ScraperSendFileManifestContents(CTxDestination& Address, CKey& Key) EXCLUSIVE_LOCKS_REQUIRED(cs_StructScraperFileManifest, CScraperManifest::cs_mapManifest) { // This "broadcasts" the current ScraperFileManifest contents to the network. @@ -4429,10 +4426,10 @@ EXCLUSIVE_LOCKS_REQUIRED(cs_StructScraperFileManifest, CScraperManifest::cs_mapM LOCK2(CSplitBlob::cs_mapParts, manifest->cs_manifest); // The manifest name is the authorized address of the scraper. - manifest->sCManifestName = Address.ToString(); + manifest->sCManifestName = EncodeDestination(Address); // Also store local sCManifestName, because the manifest will be std::moved by addManifest. - sCManifestName = Address.ToString(); + sCManifestName = EncodeDestination(Address); manifest->nTime = StructScraperFileManifest.timestamp; @@ -5802,7 +5799,7 @@ UniValue sendscraperfilemanifest(const UniValue& params, bool fHelp) "Send a CScraperManifest object from the current ScraperFileManifest.\n" ); - CBitcoinAddress AddressOut; + CTxDestination AddressOut; CKey KeyOut; bool ret; if (IsScraperAuthorizedToBroadcastManifests(AddressOut, KeyOut)) diff --git a/src/gridcoin/scraper/scraper.h b/src/gridcoin/scraper/scraper.h index f07c56f020..a32e543ba8 100644 --- a/src/gridcoin/scraper/scraper.h +++ b/src/gridcoin/scraper/scraper.h @@ -159,7 +159,7 @@ bool IsScraperAuthorized(); * modified to bypass this check, so messages sent will also be validated on receipt by the complement * to this function, IsManifestAuthorized(CKey& Key) in the CScraperManifest class. */ -bool IsScraperAuthorizedToBroadcastManifests(CBitcoinAddress& AddressOut, CKey& KeyOut); +bool IsScraperAuthorizedToBroadcastManifests(CTxDestination& AddressOut, CKey& KeyOut); /** * @brief Returns whether the scraper with the input public key at the input time has exceeded the maximum allowable * manifest publishing rate. This is a DoS function and is used to issue misbehavior points, which could result in banning diff --git a/src/gridcoin/scraper/scraper_net.cpp b/src/gridcoin/scraper/scraper_net.cpp index ccb46dc9f2..1b7f89687e 100644 --- a/src/gridcoin/scraper/scraper_net.cpp +++ b/src/gridcoin/scraper/scraper_net.cpp @@ -13,7 +13,7 @@ #include "rpc/server.h" #include "rpc/protocol.h" #ifdef SCRAPER_NET_PK_AS_ADDRESS -#include "base58.h" +#include #endif #include "gridcoin/appcache.h" #include "gridcoin/project.h" @@ -352,11 +352,10 @@ EXCLUSIVE_LOCKS_REQUIRED(CScraperManifest::cs_mapManifest) CKeyID ManifestKeyID = PubKey.GetID(); - CBitcoinAddress ManifestAddress; - ManifestAddress.Set(ManifestKeyID); + CTxDestination ManifestAddress(ManifestKeyID); // This is the address corresponding to the manifest public key. - std::string sManifestAddress = ManifestAddress.ToString(); + std::string sManifestAddress = EncodeDestination(ManifestAddress); AppCacheSectionExt mScrapersExtended = GetExtendedScrapersCache(); @@ -857,7 +856,7 @@ UniValue CScraperManifest::ToJson() const EXCLUSIVE_LOCKS_REQUIRED(CSplitBlob::c UniValue r(UniValue::VOBJ); #ifdef SCRAPER_NET_PK_AS_ADDRESS - r.pushKV("pubkey", CBitcoinAddress(pubkey.GetID()).ToString()); + r.pushKV("pubkey", EncodeDestination(pubkey.GetID())); #else r.pushKV("pubkey", pubkey.GetID().ToString()); #endif @@ -950,7 +949,7 @@ UniValue listmanifests(const UniValue& params, bool fHelp) else { #ifdef SCRAPER_NET_PK_AS_ADDRESS - subset.pushKV("scraper (manifest) address", CBitcoinAddress(manifest.pubkey.GetID()).ToString()); + subset.pushKV("scraper (manifest) address", EncodeDestination(manifest.pubkey.GetID())); #else subset.pushKV("scraper (manifest) pubkey", manifest.pubkey.GetID().ToString()); #endif @@ -973,7 +972,7 @@ UniValue listmanifests(const UniValue& params, bool fHelp) else { #ifdef SCRAPER_NET_PK_AS_ADDRESS - subset.pushKV("scraper (manifest) address", CBitcoinAddress(manifest.pubkey.GetID()).ToString()); + subset.pushKV("scraper (manifest) address", EncodeDestination(manifest.pubkey.GetID())); #else subset.pushKV("scraper (manifest) pubkey", manifest.pubkey.GetID().ToString()); #endif diff --git a/src/gridcoin/scraper/scraper_registry.cpp b/src/gridcoin/scraper/scraper_registry.cpp index 5a22fb11ad..aedf3e89b3 100644 --- a/src/gridcoin/scraper/scraper_registry.cpp +++ b/src/gridcoin/scraper/scraper_registry.cpp @@ -52,7 +52,7 @@ ScraperEntry::ScraperEntry(CKeyID key_id, Status status, int64_t tx_timestamp, u bool ScraperEntry::WellFormed() const { - return (CBitcoinAddress(m_key).IsValid() + return (IsValidDestination(m_key) && m_status != ScraperEntryStatus::UNKNOWN && m_status != ScraperEntryStatus::OUT_OF_BOUND); } @@ -64,7 +64,7 @@ CKeyID ScraperEntry::Key() const std::pair ScraperEntry::KeyValueToString() const { - return std::make_pair(CBitcoinAddress(m_key).ToString(), StatusToString()); + return std::make_pair(EncodeDestination(m_key), StatusToString()); } CKeyID ScraperEntry::GetId() const @@ -72,9 +72,9 @@ CKeyID ScraperEntry::GetId() const return m_key; } -CBitcoinAddress ScraperEntry::GetAddress() const +CTxDestination ScraperEntry::GetAddress() const { - return CBitcoinAddress(m_key); + return CTxDestination(m_key); } std::string ScraperEntry::StatusToString() const @@ -125,7 +125,7 @@ AppCacheEntryExt ScraperEntry::GetLegacyScraperEntry() { AppCacheEntryExt entry; - entry.value = CBitcoinAddress(m_key).ToString(); + entry.value = EncodeDestination(m_key); entry.timestamp = m_timestamp; entry.deleted = (m_status == ScraperEntryStatus::DELETED); @@ -186,11 +186,9 @@ ScraperEntryPayload::ScraperEntryPayload(const std::string& key, const std::stri { m_version = 1; - CBitcoinAddress address; + CTxDestination address = DecodeDestination(m_key); - address.SetString(m_key); - - if (!address.IsValid()) { + if (!IsValidDestination(address)) { error("%s: Error during initialization of ScraperEntryPayload from legacy format: key = %s, value = %s", __func__, key, @@ -198,7 +196,7 @@ ScraperEntryPayload::ScraperEntryPayload(const std::string& key, const std::stri return; } - address.GetKeyID(m_scraper_entry.m_key); + m_scraper_entry.m_key = std::get(address); if (ToLower(m_value) == "true") { m_scraper_entry.m_status = ScraperEntryStatus::AUTHORIZED; @@ -210,16 +208,13 @@ ScraperEntryPayload::ScraperEntryPayload(const std::string& key, const std::stri ScraperEntryPayload ScraperEntryPayload::Parse(const std::string& key, const std::string& value) { - CBitcoinAddress address; - - address.SetString(key); + CTxDestination address = DecodeDestination(key); + CKeyID* key_id = std::get_if(&address); - if (!address.IsValid()) { + if (!IsValidDestination(address) || !key_id) { return ScraperEntryPayload(); } - CKeyID key_id; - address.GetKeyID(key_id); ScraperEntryStatus scraper_entry_status = ScraperEntryStatus::UNKNOWN; if (ToLower(value) == "true") { @@ -229,7 +224,7 @@ ScraperEntryPayload ScraperEntryPayload::Parse(const std::string& key, const std scraper_entry_status = ScraperEntryStatus::NOT_AUTHORIZED; } - ScraperEntryPayload payload(1, ScraperEntry(key_id, scraper_entry_status)); + ScraperEntryPayload payload(1, ScraperEntry(*key_id, scraper_entry_status)); // The above constructor doesn't carry over the legacy K-V which we need. payload.m_key = key; payload.m_value = value; @@ -270,7 +265,7 @@ const AppCacheSectionExt ScraperRegistry::GetScrapersLegacyExt(const bool& autho for (const auto& entry : m_scrapers) { - std::string key = CBitcoinAddress(entry.first).ToString(); + std::string key = EncodeDestination(entry.first); switch (entry.second->m_status.Value()) { case ScraperEntryStatus::DELETED: @@ -383,8 +378,7 @@ void ScraperRegistry::AddDelete(const ContractContext& ctx) payload.m_scraper_entry.m_previous_hash = uint256 {}; } - CBitcoinAddress address; - address.Set(payload.m_scraper_entry.m_key); + CTxDestination address(payload.m_scraper_entry.m_key); LogPrint(LogFlags::SCRAPER, "INFO: %s: scraper entry add/delete: contract m_version = %u, payload " "m_version = %u, address for m_key = %s, m_timestamp = %" PRId64 ", " @@ -392,7 +386,7 @@ void ScraperRegistry::AddDelete(const ContractContext& ctx) __func__, ctx->m_version, payload.m_version, - address.ToString(), + EncodeDestination(address), payload.m_scraper_entry.m_timestamp, payload.m_scraper_entry.m_hash.ToString(), payload.m_scraper_entry.m_previous_hash.ToString(), @@ -407,7 +401,7 @@ void ScraperRegistry::AddDelete(const ContractContext& ctx) "db record already exists. This can be expected on a restart of the wallet to ensure " "multiple contracts in the same block get stored/replayed.", __func__, - historical.GetAddress().ToString(), + EncodeDestination(historical.GetAddress()), historical.m_hash.GetHex()); } @@ -441,14 +435,14 @@ void ScraperRegistry::Revert(const ContractContext& ctx) if (entry_to_revert == m_scrapers.end()) { error("%s: The scraper entry for address %s to revert was not found in the scraper entry map.", __func__, - entry_to_revert->second->GetAddress().ToString()); + EncodeDestination(entry_to_revert->second->GetAddress())); // If there is no record in the current m_scrapers map, then there is nothing to do here. This // should not occur. return; } - CBitcoinAddress address = entry_to_revert->second->GetAddress(); + CTxDestination address = entry_to_revert->second->GetAddress(); // If this is not a null hash, then there will be a prior entry to resurrect. uint256 resurrect_hash = entry_to_revert->second->m_previous_hash; @@ -459,7 +453,7 @@ void ScraperRegistry::Revert(const ContractContext& ctx) if (m_scrapers.erase(payload->m_scraper_entry.m_key) == 0) { error("%s: The scraper entry to erase during a scraper entry revert for address %s was not found.", __func__, - address.ToString()); + EncodeDestination(address)); // If the record to revert is not found in the m_scrapers map, no point in continuing. return; } @@ -468,7 +462,7 @@ void ScraperRegistry::Revert(const ContractContext& ctx) if (!m_scraper_db.erase(ctx.m_tx.GetHash())) { error("%s: The db entry to erase during a scraper entry revert for address %s was not found.", __func__, - address.ToString()); + EncodeDestination(address)); // Unlike the above we will keep going even if this record is not found, because it is identical to the // m_scrapers record above. This should not happen, because during contract adds and removes, entries are @@ -484,7 +478,7 @@ void ScraperRegistry::Revert(const ContractContext& ctx) if (resurrect_entry == m_scraper_db.end()) { error("%s: The prior entry to resurrect during a scraper entry ADD revert for address %s was not found.", __func__, - address.ToString()); + EncodeDestination(address)); return; } diff --git a/src/gridcoin/scraper/scraper_registry.h b/src/gridcoin/scraper/scraper_registry.h index 8256b7e11b..736b49513f 100644 --- a/src/gridcoin/scraper/scraper_registry.h +++ b/src/gridcoin/scraper/scraper_registry.h @@ -6,7 +6,7 @@ #define GRIDCOIN_SCRAPER_SCRAPER_REGISTRY_H #include "amount.h" -#include "base58.h" +#include #include "dbwrapper.h" #include "serialize.h" #include "gridcoin/scraper/fwd.h" @@ -136,9 +136,9 @@ class ScraperEntry //! //! \brief Return the address from the m_key. //! - //! \return \c CBitcoinAddress derived from the m_key. + //! \return \c CTxDestination derived from the m_key. //! - CBitcoinAddress GetAddress() const; + CTxDestination GetAddress() const; //! //! \brief Returns the string representation of the current scraper entry status @@ -346,11 +346,7 @@ class ScraperEntryPayload : public LegacyPayload //! std::string LegacyKeyString() const override { - CBitcoinAddress address; - - address.Set(m_scraper_entry.m_key); - - return address.ToString(); + return EncodeDestination(m_scraper_entry.m_key); } //! diff --git a/src/gridcoin/sidestake.cpp b/src/gridcoin/sidestake.cpp index 0c553d6eef..4b7509f8b8 100644 --- a/src/gridcoin/sidestake.cpp +++ b/src/gridcoin/sidestake.cpp @@ -235,7 +235,7 @@ LocalSideStake::LocalSideStake(CTxDestination destination, bool LocalSideStake::WellFormed() const { - return CBitcoinAddress(m_destination).IsValid() && m_allocation >= 0 && m_allocation <= 1; + return IsValidDestination(m_destination) && m_allocation >= 0 && m_allocation <= 1; } std::string LocalSideStake::StatusToString() const @@ -328,7 +328,7 @@ MandatorySideStake::MandatorySideStake(CTxDestination destination, bool MandatorySideStake::WellFormed() const { - return CBitcoinAddress(m_destination).IsValid() && m_allocation >= 0 && m_allocation <= 1; + return IsValidDestination(m_destination) && m_allocation >= 0 && m_allocation <= 1; } CTxDestination MandatorySideStake::Key() const @@ -338,7 +338,7 @@ CTxDestination MandatorySideStake::Key() const std::pair MandatorySideStake::KeyValueToString() const { - return std::make_pair(CBitcoinAddress(m_destination).ToString(), StatusToString()); + return std::make_pair(EncodeDestination(m_destination), StatusToString()); } std::string MandatorySideStake::StatusToString() const @@ -718,7 +718,7 @@ void SideStakeRegistry::AddDelete(const ContractContext& ctx) __func__, ctx->m_version, payload.m_version, - CBitcoinAddress(payload.m_entry.m_destination).ToString(), + EncodeDestination(payload.m_entry.m_destination), payload.m_entry.m_allocation.ToPercent(), payload.m_entry.m_timestamp, payload.m_entry.m_hash.ToString(), @@ -734,7 +734,7 @@ void SideStakeRegistry::AddDelete(const ContractContext& ctx) "the SideStake entry db record already exists. This can be expected on a restart " "of the wallet to ensure multiple contracts in the same block get stored/replayed.", __func__, - CBitcoinAddress(historical.m_destination).ToString(), + EncodeDestination(historical.m_destination), historical.m_allocation.ToPercent(), historical.m_hash.GetHex()); } @@ -796,7 +796,7 @@ void SideStakeRegistry::Revert(const ContractContext& ctx) if (entry_to_revert == m_mandatory_sidestake_entries.end()) { error("%s: The SideStake entry for key %s to revert was not found in the SideStake entry map.", __func__, - CBitcoinAddress(entry_to_revert->second->m_destination).ToString()); + EncodeDestination(entry_to_revert->second->m_destination)); // If there is no record in the current m_sidestake_entries map, then there is nothing to do here. This // should not occur. @@ -813,7 +813,7 @@ void SideStakeRegistry::Revert(const ContractContext& ctx) if (m_mandatory_sidestake_entries.erase(payload->m_entry.m_destination) == 0) { error("%s: The SideStake entry to erase during a SideStake entry revert for key %s was not found.", __func__, - CBitcoinAddress(key).ToString()); + EncodeDestination(key)); // If the record to revert is not found in the m_sidestake_entries map, no point in continuing. return; } @@ -822,7 +822,7 @@ void SideStakeRegistry::Revert(const ContractContext& ctx) if (!m_sidestake_db.erase(ctx.m_tx.GetHash())) { error("%s: The db entry to erase during a SideStake entry revert for key %s was not found.", __func__, - CBitcoinAddress(key).ToString()); + EncodeDestination(key)); // Unlike the above we will keep going even if this record is not found, because it is identical to the // m_sidestake_entries record above. This should not happen, because during contract adds and removes, @@ -838,7 +838,7 @@ void SideStakeRegistry::Revert(const ContractContext& ctx) if (resurrect_entry == m_sidestake_db.end()) { error("%s: The prior entry to resurrect during a SideStake entry ADD revert for key %s was not found.", __func__, - CBitcoinAddress(key).ToString()); + EncodeDestination(key)); return; } @@ -1021,8 +1021,8 @@ void SideStakeRegistry::LoadLocalSideStakesFromConfig() std::string sAllocation = std::get<1>(entry); std::string sDescription = std::get<2>(entry); - CBitcoinAddress address(sAddress); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(sAddress); + if (!IsValidDestination(address)) { LogPrintf("WARN: %s: ignoring sidestake invalid address %s.", __func__, sAddress); continue; @@ -1060,7 +1060,7 @@ void SideStakeRegistry::LoadLocalSideStakesFromConfig() break; } - LocalSideStake sidestake(address.Get(), + LocalSideStake sidestake(address, allocation, sDescription, LocalSideStake::LocalSideStakeStatus::ACTIVE); @@ -1117,7 +1117,7 @@ bool SideStakeRegistry::SaveLocalSideStakesToConfig() separator = ","; } - addresses += separator + CBitcoinAddress(iter.second->m_destination).ToString(); + addresses += separator + EncodeDestination(iter.second->m_destination); allocations += separator + ToString(iter.second->m_allocation.ToPercent()); descriptions += separator + iter.second->m_description; diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index d909e7f27a..54a324f400 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -5,7 +5,7 @@ #ifndef GRIDCOIN_SIDESTAKE_H #define GRIDCOIN_SIDESTAKE_H -#include "base58.h" +#include #include "gridcoin/contract/handler.h" #include "gridcoin/contract/payload.h" #include "gridcoin/contract/registry_db.h" @@ -572,7 +572,7 @@ class SideStakePayload : public IContractPayload "m_entry.StatusToString() = %s", __func__, valid, - CBitcoinAddress(m_entry.m_destination).ToString(), + EncodeDestination(m_entry.m_destination), m_entry.m_allocation.ToPercent(), m_entry.StatusToString() ); @@ -588,7 +588,7 @@ class SideStakePayload : public IContractPayload //! std::string LegacyKeyString() const override { - return CBitcoinAddress(m_entry.m_destination).ToString(); + return EncodeDestination(m_entry.m_destination); } //! diff --git a/src/gridcoin/voting/builders.cpp b/src/gridcoin/voting/builders.cpp index 529a883028..9611e1b40f 100644 --- a/src/gridcoin/voting/builders.cpp +++ b/src/gridcoin/voting/builders.cpp @@ -23,21 +23,6 @@ using namespace GRC; using LogFlags = BCLog::LogFlags; namespace { -//! -//! \brief Get the string representation of an output destination for logging. -//! -//! \param dest Destination to convert to an address string. -//! -//! \return Base58-encoded string of the address. -//! -std::string DestinationToAddressString(const CTxDestination dest) -{ - CBitcoinAddress address; - address.Set(dest); - - return address.ToString(); -} - //! //! \brief A set of outputs associated with an address for a voting claim. //! @@ -166,7 +151,7 @@ class CoinPicker void operator()(const CKeyID& keyId, const COutput& output) const { LogPrint(LogFlags::VOTE, " added output for address: %s", - DestinationToAddressString(keyId)); + EncodeDestination(keyId)); auto result_pair = m_by_address.emplace(keyId, keyId); AddressOutputs& address_outputs = result_pair.first->second; @@ -184,7 +169,7 @@ class CoinPicker { // Voting does not support redemption script outputs yet. LogPrint(LogFlags::VOTE, " skipped script address: %s", - DestinationToAddressString(scriptId)); + EncodeDestination(scriptId)); } private: @@ -219,14 +204,14 @@ class CoinPicker // if (txo.tx->vout[txo.i].nValue < COIN) { LogPrint(LogFlags::VOTE, " skipped < 1 GRC outputs for: %s", - DestinationToAddressString(dest)); + EncodeDestination(dest)); break; // The input set is sorted so the rest are too small. } if (!txo.tx->IsTrusted() || !txo.tx->IsConfirmed()) { LogPrint(LogFlags::VOTE, " skipped unconfirmed output for %s", - DestinationToAddressString(dest)); + EncodeDestination(dest)); continue; } @@ -302,7 +287,7 @@ class AddressClaimBuilder if (!m_wallet.GetPubKey(address_outputs.m_key_id, claim.m_public_key)) { error("%s: failed to fetch public key for address %s", __func__, - DestinationToAddressString(address_outputs.m_key_id)); + EncodeDestination(address_outputs.m_key_id)); return std::nullopt; } @@ -310,8 +295,8 @@ class AddressClaimBuilder LogPrint(BCLog::LogFlags::VOTE, "INFO: %s: building address claim for address_outputs.m_key_id %s, " "claim.m_public_key address %s.", __func__, - DestinationToAddressString(address_outputs.m_key_id), - DestinationToAddressString(claim.m_public_key.GetID())); + EncodeDestination(address_outputs.m_key_id), + EncodeDestination(claim.m_public_key.GetID())); // An address claim must submit outputs in ascending order. This // improves the performance of duplicate output validation: @@ -337,25 +322,25 @@ class AddressClaimBuilder if (!m_wallet.GetKey(key_id, private_key)) { return error("%s: failed to fetch private key for address %s", __func__, - DestinationToAddressString(key_id)); + EncodeDestination(key_id)); } if (!private_key.IsValid()) { return error("%s: invalid private key for address %s", __func__, - DestinationToAddressString(key_id)); + EncodeDestination(key_id)); } if (!claim.Sign(private_key, message)) { return error("%s: failed to sign address claim for address %s", __func__, - DestinationToAddressString(key_id)); + EncodeDestination(key_id)); } LogPrint(LogFlags::VOTE, "%s: signed address claim for address: %s", __func__, - DestinationToAddressString(key_id)); + EncodeDestination(key_id)); return true; } @@ -420,7 +405,7 @@ class BalanceClaimBuilder for (auto& address_claim : claim.m_address_claims) { LogPrint(BCLog::LogFlags::VOTE, "INFO: %s: signing claim address %s", __func__, - DestinationToAddressString(address_claim.m_public_key.GetID()) + EncodeDestination(address_claim.m_public_key.GetID()) ); if (!builder.SignClaim(address_claim, message)) { @@ -459,7 +444,7 @@ class BalanceClaimBuilder LogPrint(LogFlags::VOTE, "%s: trimmed output claim from %s", __func__, - DestinationToAddressString(address.m_key_id)); + EncodeDestination(address.m_key_id)); address.m_outpoints.pop_back(); bytes_estimate -= txo_bytes; @@ -467,7 +452,7 @@ class BalanceClaimBuilder if (address.m_outpoints.empty()) { LogPrint(LogFlags::VOTE, "%s: trimmed address claim %s", __func__, - DestinationToAddressString(address.m_key_id)); + EncodeDestination(address.m_key_id)); by_address.pop_back(); bytes_estimate -= address_claim_bytes; @@ -716,7 +701,7 @@ class PollClaimBuilder if (address.m_total_amount < POLL_REQUIRED_BALANCE) { LogPrint(LogFlags::VOTE, "%s: exceeded max outputs for %s", __func__, - DestinationToAddressString(address.m_key_id)); + EncodeDestination(address.m_key_id)); return false; } @@ -1225,7 +1210,7 @@ CWalletTx PollBuilder::BuildContractTx(CWallet* const pwallet, const uint32_t& c LogPrint(BCLog::LogFlags::VOTE, "INFO: %s: tx contract payload claim address %s, poll title %s.", __func__, - DestinationToAddressString(poll_payload.m_claim.m_address_claim.m_public_key.GetID()), + EncodeDestination(poll_payload.m_claim.m_address_claim.m_public_key.GetID()), poll_payload.m_poll.m_title ); diff --git a/src/key_io.cpp b/src/key_io.cpp index e8cca8b5dc..40cae5daf9 100644 --- a/src/key_io.cpp +++ b/src/key_io.cpp @@ -12,6 +12,83 @@ #include #include +namespace { +class DestinationEncoder +{ +private: + const CChainParams& m_params; + +public: + explicit DestinationEncoder(const CChainParams& params) : m_params(params) {} + + std::string operator()(const CKeyID& id) const + { + std::vector data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); + data.insert(data.end(), id.begin(), id.end()); + return EncodeBase58Check(data); + } + + std::string operator()(const CScriptID& id) const + { + std::vector data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); + data.insert(data.end(), id.begin(), id.end()); + return EncodeBase58Check(data); + } + + std::string operator()(const CNoDestination& no) const { return {}; } +}; + +CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, std::string& error_str, std::vector* error_locations) +{ + std::vector data; + uint160 hash; + error_str = ""; + + if (DecodeBase58Check(str, data, 21)) { + // base58-encoded Gridcoin addresses. + // Public-key-hash-addresses have version 62 (or 111 testnet). + // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key. + const std::vector& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); + if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) { + std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin()); + return CKeyID(hash); + } + // Script-hash-addresses have version 85 (or 196 testnet). + // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. + const std::vector& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); + if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) { + std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); + return CScriptID(hash); + } + + // If the prefix of data matches either the script or pubkey prefix, the length must have been wrong + if ((data.size() >= script_prefix.size() && + std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) || + (data.size() >= pubkey_prefix.size() && + std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin()))) { + error_str = "Invalid length for Base58 address (P2PKH or P2SH)"; + } else { + error_str = "Invalid or unsupported Base58-encoded address."; + } + return CNoDestination(); + } else { + // Try Base58 decoding without the checksum, using a much larger max length + if (!DecodeBase58(str, data, 100)) { + error_str = "Invalid Base58 encoding."; + } else { + error_str = "Invalid checksum or length of Base58 address (P2PKH or P2SH)"; + } + return CNoDestination(); + } + + + // Set error message if address can't be interpreted as Base58. + if (error_str.empty()) error_str = "Invalid address format"; + + return CNoDestination(); +} +} // namespace + CKey DecodeSecret(const std::string& str) { CKey key; @@ -89,3 +166,30 @@ std::string EncodeExtKey(const CExtKey& key) memory_cleanse(data.data(), data.size()); return ret; } + +std::string EncodeDestination(const CTxDestination& dest) +{ + return std::visit(DestinationEncoder(Params()), dest); +} + +CTxDestination DecodeDestination(const std::string& str, std::string& error_msg, std::vector* error_locations) +{ + return DecodeDestination(str, Params(), error_msg, error_locations); +} + +CTxDestination DecodeDestination(const std::string& str) +{ + std::string error_msg; + return DecodeDestination(str, error_msg); +} + +bool IsValidDestinationString(const std::string& str, const CChainParams& params) +{ + std::string error_msg; + return IsValidDestination(DecodeDestination(str, params, error_msg, nullptr)); +} + +bool IsValidDestinationString(const std::string& str) +{ + return IsValidDestinationString(str, Params()); +} diff --git a/src/key_io.h b/src/key_io.h index 9c1b9701cc..39e7d2d7b2 100644 --- a/src/key_io.h +++ b/src/key_io.h @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -20,4 +21,10 @@ std::string EncodeExtKey(const CExtKey& extkey); CExtPubKey DecodeExtPubKey(const std::string& str); std::string EncodeExtPubKey(const CExtPubKey& extpubkey); +std::string EncodeDestination(const CTxDestination& dest); +CTxDestination DecodeDestination(const std::string& str); +CTxDestination DecodeDestination(const std::string& str, std::string& error_msg, std::vector* error_locations = nullptr); +bool IsValidDestinationString(const std::string& str); +bool IsValidDestinationString(const std::string& str, const CChainParams& params); + #endif // BITCOIN_KEY_IO_H diff --git a/src/main.h b/src/main.h index 3afe3e45a5..e297464d9f 100644 --- a/src/main.h +++ b/src/main.h @@ -33,7 +33,6 @@ class CKeyItem; class CReserveKey; class COutPoint; class CAddress; -class CBitcoinAddress; class CInv; class CNode; class CTxMemPool; diff --git a/src/miner.cpp b/src/miner.cpp index 1d1e8a3f7f..58ce9e7ac9 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -192,9 +192,9 @@ bool CreateMRCRewards(CBlock &blocknew, std::mapnTime); if (beacon && mrc_outputs.size() <= output_limit) { - CBitcoinAddress beacon_address = beacon->GetAddress(); + CTxDestination beacon_address = beacon->GetAddress(); CScript script_beacon_key; - script_beacon_key.SetDestination(beacon_address.Get()); + script_beacon_key.SetDestination(beacon_address); // The net reward paid to the MRC beacon address is the requested research subsidy (reward) // minus the fees for the MRC. @@ -254,7 +254,7 @@ bool CreateMRCRewards(CBlock &blocknew, std::mapget()->GetDestination()); + CTxDestination address = iterSideStake->get()->GetDestination(); GRC::Allocation allocation = iterSideStake->get()->GetAllocation(); - if (!address.IsValid()) + if (!IsValidDestination(address)) { LogPrintf("WARN: SplitCoinStakeOutput: ignoring sidestake invalid address %s.", - address.ToString()); + EncodeDestination(address)); continue; } @@ -972,7 +972,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake { LogPrintf("WARN: SplitCoinStakeOutput: distribution %f too small to address %s.", CoinToDouble((allocation * nReward).ToCAmount()), - address.ToString() + EncodeDestination(address) ); continue; } @@ -987,7 +987,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake // Push to an output the (reward times the allocation) to the address, increment the accumulator for allocation, // decrement the remaining stake output value, and increment outputs used. - SideStakeScriptPubKey.SetDestination(address.Get()); + SideStakeScriptPubKey.SetDestination(address); // It is entirely possible that the coinstake could be from an address that is specified in one of the sidestake // entries if the sidestake address(es) are local to the staking wallet. There is no reason to sidestake in that @@ -1014,7 +1014,7 @@ void SplitCoinStakeOutput(CBlock &blocknew, int64_t &nReward, bool &fEnableStake LogPrintf("SplitCoinStakeOutput: create sidestake UTXO %i value %f to address %s", nOutputsUsed, CoinToDouble((allocation * nReward).ToCAmount()), - address.ToString() + EncodeDestination(address) ); SumAllocation += allocation; nRemainingStakeOutputValue -= nSideStake; @@ -1489,7 +1489,7 @@ void StakeMiner(CWallet *pwallet) __func__, i, FormatMoney(StakeBlock.vtx[1].vout[i].nValue), - CBitcoinAddress(destination).ToString()); + EncodeDestination(destination)); } } diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp index 7bb0d5d1b1..07026c9a73 100644 --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -3,7 +3,7 @@ #include "walletmodel.h" #include "wallet/wallet.h" -#include "base58.h" +#include #include "util.h" #include @@ -62,12 +62,12 @@ class AddressTablePriv LOCK(wallet->cs_wallet); for (auto const &item : wallet->mapAddressBook) { - const CBitcoinAddress& address = item.first; + const CTxDestination& address = item.first; const std::string& strName = item.second; - isminetype fMine = IsMine(*wallet, address.Get()); + isminetype fMine = IsMine(*wallet, address); cachedAddressTable.append(AddressTableEntry((fMine != ISMINE_NO) ? AddressTableEntry::Receiving : AddressTableEntry::Sending, QString::fromStdString(strName), - QString::fromStdString(address.ToString()))); + QString::fromStdString(EncodeDestination(address)))); } } // std::lower_bound() and std::upper_bound() require our cachedAddressTable list to be sorted in asc order @@ -222,7 +222,7 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, auto address_count = [this](const QVariant &value) { LOCK(wallet->cs_wallet); - return wallet->mapAddressBook.count(CBitcoinAddress(value.toString().toStdString()).Get()); + return wallet->mapAddressBook.count(DecodeDestination(value.toString().toStdString())); }; if (role == Qt::EditRole) @@ -236,11 +236,11 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, editStatus = NO_CHANGES; return false; } - wallet->SetAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get(), value.toString().toStdString()); + wallet->SetAddressBookName(DecodeDestination(rec->address.toStdString()), value.toString().toStdString()); break; case Address: // Do nothing, if old address == new address - if(CBitcoinAddress(rec->address.toStdString()) == CBitcoinAddress(value.toString().toStdString())) + if(DecodeDestination(rec->address.toStdString()) == DecodeDestination(value.toString().toStdString())) { editStatus = NO_CHANGES; return false; @@ -264,9 +264,9 @@ bool AddressTableModel::setData(const QModelIndex &index, const QVariant &value, { LOCK(wallet->cs_wallet); // Remove old entry - wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get()); + wallet->DelAddressBookName(DecodeDestination(rec->address.toStdString())); // Add new entry with new address - wallet->SetAddressBookName(CBitcoinAddress(value.toString().toStdString()).Get(), rec->label.toStdString()); + wallet->SetAddressBookName(DecodeDestination(value.toString().toStdString()), rec->label.toStdString()); } } break; @@ -342,7 +342,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con // Check for duplicate addresses { LOCK(wallet->cs_wallet); - if(wallet->mapAddressBook.count(CBitcoinAddress(strAddress).Get())) + if(wallet->mapAddressBook.count(DecodeDestination(strAddress))) { editStatus = DUPLICATE_ADDRESS; return QString(); @@ -365,7 +365,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con editStatus = KEY_GENERATION_FAILURE; return QString(); } - strAddress = CBitcoinAddress(newKey.GetID()).ToString(); + strAddress = EncodeDestination(newKey.GetID()); } else { @@ -375,7 +375,7 @@ QString AddressTableModel::addRow(const QString &type, const QString &label, con // Add entry { LOCK(wallet->cs_wallet); - wallet->SetAddressBookName(CBitcoinAddress(strAddress).Get(), strLabel); + wallet->SetAddressBookName(DecodeDestination(strAddress), strLabel); } return QString::fromStdString(strAddress); } @@ -392,7 +392,7 @@ bool AddressTableModel::removeRows(int row, int count, const QModelIndex &parent } { LOCK(wallet->cs_wallet); - wallet->DelAddressBookName(CBitcoinAddress(rec->address.toStdString()).Get()); + wallet->DelAddressBookName(DecodeDestination(rec->address.toStdString())); } return true; } @@ -403,8 +403,8 @@ QString AddressTableModel::labelForAddress(const QString &address) const { { LOCK(wallet->cs_wallet); - CBitcoinAddress address_parsed(address.toStdString()); - std::map::iterator mi = wallet->mapAddressBook.find(address_parsed.Get()); + CTxDestination address_parsed = DecodeDestination(address.toStdString()); + std::map::iterator mi = wallet->mapAddressBook.find(address_parsed); if (mi != wallet->mapAddressBook.end()) { return QString::fromStdString(mi->second); diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 17eaf4541a..38b14cce23 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -821,7 +821,7 @@ void CoinControlDialog::updateView() QString sAddress = ""; if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress)) { - sAddress = CBitcoinAddress(outputAddress).ToString().c_str(); + sAddress = EncodeDestination(outputAddress).c_str(); // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs if (!treeMode || (!(sAddress == sWalletAddress))) diff --git a/src/qt/consolidateunspentwizardselectinputspage.cpp b/src/qt/consolidateunspentwizardselectinputspage.cpp index bef140db0e..8e1702e074 100644 --- a/src/qt/consolidateunspentwizardselectinputspage.cpp +++ b/src/qt/consolidateunspentwizardselectinputspage.cpp @@ -582,7 +582,7 @@ void ConsolidateUnspentWizardSelectInputsPage::updateView() QString sAddress = ""; if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress)) { - sAddress = CBitcoinAddress(outputAddress).ToString().c_str(); + sAddress = EncodeDestination(outputAddress).c_str(); // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs if (!treeMode || (!(sAddress == sWalletAddress))) diff --git a/src/qt/researcher/researchermodel.cpp b/src/qt/researcher/researchermodel.cpp index 18a4f7bef4..1fe8ae8bc4 100644 --- a/src/qt/researcher/researchermodel.cpp +++ b/src/qt/researcher/researchermodel.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include #include "main.h" #include "gridcoin/beacon.h" #include "gridcoin/boinc.h" @@ -462,7 +462,7 @@ QString ResearcherModel::formatBeaconAddress() const return QString(); } - return QString::fromStdString(m_beacon->GetAddress().ToString()); + return QString::fromStdString(EncodeDestination(m_beacon->GetAddress())); } QString ResearcherModel::formatBeaconVerificationCode() const diff --git a/src/qt/researcher/researcherwizardpoolpage.cpp b/src/qt/researcher/researcherwizardpoolpage.cpp index 2185be6df2..07be71486e 100644 --- a/src/qt/researcher/researcherwizardpoolpage.cpp +++ b/src/qt/researcher/researcherwizardpoolpage.cpp @@ -2,7 +2,7 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include #include "key.h" #include "qt/decoration.h" #include "qt/forms/ui_researcherwizardpoolpage.h" @@ -105,7 +105,7 @@ void ResearcherWizardPoolPage::getNewAddress() } ui->addressLabel->setText( - QString::fromStdString(CBitcoinAddress(public_key.GetID()).ToString())); + QString::fromStdString(EncodeDestination(public_key.GetID()))); ui->copyToClipboardButton->setVisible(true); } diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index d813d868d4..126fbf7d11 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -349,8 +349,8 @@ bool SendCoinsDialog::handleURI(const QString &uri) // URI has to be valid if (GUIUtil::parseBitcoinURI(uri, &rv)) { - CBitcoinAddress address(rv.address.toStdString()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(rv.address.toStdString()); + if (!IsValidDestination(address)) return false; pasteEntry(rv); return true; @@ -509,7 +509,7 @@ void SendCoinsDialog::coinControlChangeChecked(int state) if (model) { if (state == Qt::Checked) - coinControl->destChange = CBitcoinAddress(ui->coinControlChangeEdit->text().toStdString()).Get(); + coinControl->destChange = DecodeDestination(ui->coinControlChangeEdit->text().toStdString()); else coinControl->destChange = CNoDestination(); } @@ -525,13 +525,13 @@ void SendCoinsDialog::coinControlChangeEdited(const QString & text) { if (model) { - coinControl->destChange = CBitcoinAddress(text.toStdString()).Get(); + coinControl->destChange = DecodeDestination(text.toStdString()); // label for the change address ui->coinControlChangeAddressLabel->setStyleSheet(QString()); if (text.isEmpty()) ui->coinControlChangeAddressLabel->setText(QString()); - else if (!CBitcoinAddress(text.toStdString()).IsValid()) + else if (!IsValidDestination(DecodeDestination(text.toStdString()))) { ui->coinControlChangeAddressLabel->setStyleSheet("QLabel{color:red;}"); ui->coinControlChangeAddressLabel->setText(tr("WARNING: Invalid Gridcoin address")); @@ -544,9 +544,9 @@ void SendCoinsDialog::coinControlChangeEdited(const QString & text) else { CPubKey pubkey; - CKeyID keyid; - CBitcoinAddress(text.toStdString()).GetKeyID(keyid); - if (model->getPubKey(keyid, pubkey)) + CTxDestination dest = DecodeDestination(text.toStdString()); + CKeyID* keyid = std::get_if(&dest); + if (keyid && model->getPubKey(*keyid, pubkey)) ui->coinControlChangeAddressLabel->setText(tr("(no label)")); else { diff --git a/src/qt/sidestaketablemodel.cpp b/src/qt/sidestaketablemodel.cpp index 018cb0977e..9b6411b2ed 100644 --- a/src/qt/sidestaketablemodel.cpp +++ b/src/qt/sidestaketablemodel.cpp @@ -154,7 +154,7 @@ QVariant SideStakeTableModel::data(const QModelIndex &index, int role) const if (role == Qt::DisplayRole) { switch (column) { case Address: - return QString::fromStdString(CBitcoinAddress(rec->GetDestination()).ToString()); + return QString::fromStdString(EncodeDestination(rec->GetDestination())); case Allocation: return QString().setNum(rec->GetAllocation().ToPercent(), 'f', 2) + QString("\%"); case Description: @@ -166,7 +166,7 @@ QVariant SideStakeTableModel::data(const QModelIndex &index, int role) const } else if (role == Qt::EditRole) { switch (column) { case Address: - return QString::fromStdString(CBitcoinAddress(rec->GetDestination()).ToString()); + return QString::fromStdString(EncodeDestination(rec->GetDestination())); case Allocation: return QString().setNum(rec->GetAllocation().ToPercent(), 'f', 2); case Description: @@ -342,19 +342,18 @@ QString SideStakeTableModel::addRow(const QString &address, const QString &alloc { GRC::SideStakeRegistry& registry = GRC::GetSideStakeRegistry(); - CBitcoinAddress sidestake_address; - sidestake_address.SetString(address.toStdString()); + CTxDestination sidestake_address = DecodeDestination(address.toStdString()); m_edit_status = OK; - if (!sidestake_address.IsValid()) { + if (!IsValidDestination(sidestake_address)) { m_edit_status = INVALID_ADDRESS; return QString(); } // Check for duplicate local sidestakes. Here we use the actual core sidestake registry rather than the // UI model. - std::vector core_local_sidestake = registry.Try(sidestake_address.Get(), GRC::SideStake::FilterFlag::LOCAL); + std::vector core_local_sidestake = registry.Try(sidestake_address, GRC::SideStake::FilterFlag::LOCAL); if (!core_local_sidestake.empty()) { m_edit_status = DUPLICATE_ADDRESS; @@ -393,14 +392,14 @@ QString SideStakeTableModel::addRow(const QString &address, const QString &alloc return QString(); } - registry.NonContractAdd(GRC::LocalSideStake(sidestake_address.Get(), + registry.NonContractAdd(GRC::LocalSideStake(sidestake_address, sidestake_allocation, sanitized_description, GRC::LocalSideStake::LocalSideStakeStatus::ACTIVE)); updateSideStakeTableModel(); - return QString::fromStdString(sidestake_address.ToString()); + return QString::fromStdString(EncodeDestination(sidestake_address)); } bool SideStakeTableModel::removeRows(int row, int count, const QModelIndex &parent) diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp index 1589c8dc38..fa09672981 100644 --- a/src/qt/signverifymessagedialog.cpp +++ b/src/qt/signverifymessagedialog.cpp @@ -2,7 +2,7 @@ #include "ui_signverifymessagedialog.h" #include "addressbookpage.h" -#include "base58.h" +#include #include "guiutil.h" #include "init.h" #include "main.h" @@ -102,16 +102,16 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() /* Clear old signature to ensure users don't get confused on error with an old signature displayed */ ui->signatureOutEdit_SM->clear(); - CBitcoinAddress addr(ui->addressInEdit_SM->text().toStdString()); - if (!addr.IsValid()) + CTxDestination addr = DecodeDestination(ui->addressInEdit_SM->text().toStdString()); + if (!IsValidDestination(addr)) { ui->addressInEdit_SM->setValid(false); ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); return; } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&addr); + if (!keyID) { ui->addressInEdit_SM->setValid(false); ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); @@ -128,7 +128,7 @@ void SignVerifyMessageDialog::on_signMessageButton_SM_clicked() } CKey key; - if (!pwalletMain->GetKey(keyID, key)) + if (!pwalletMain->GetKey(*keyID, key)) { ui->statusLabel_SM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_SM->setText(tr("Private key for the entered address is not available.")); @@ -185,16 +185,16 @@ void SignVerifyMessageDialog::on_addressBookButton_VM_clicked() void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked() { - CBitcoinAddress addr(ui->addressInEdit_VM->text().toStdString()); - if (!addr.IsValid()) + CTxDestination addr = DecodeDestination(ui->addressInEdit_VM->text().toStdString()); + if (!IsValidDestination(addr)) { ui->addressInEdit_VM->setValid(false); ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_VM->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); return; } - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&addr); + if (!keyID) { ui->addressInEdit_VM->setValid(false); ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); @@ -226,7 +226,7 @@ void SignVerifyMessageDialog::on_verifyMessageButton_VM_clicked() return; } - if (!(CBitcoinAddress(pubkey.GetID()) == addr)) + if (!(CTxDestination(pubkey.GetID()) == addr)) { ui->statusLabel_VM->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_VM->setText(QString("") + tr("Message verification failed.") + QString("")); diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index cca2f3ba28..e04bb67af0 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -7,7 +7,7 @@ #include "wallet/wallet.h" #include "txdb.h" #include "node/ui_interface.h" -#include "base58.h" +#include #include "bitcoingui.h" #include "util.h" @@ -71,7 +71,7 @@ std::string PubKeyToGRCAddress(const CScript& scriptPubKey) std::string grcaddress = ""; for (auto const& addr : addresses) - grcaddress = CBitcoinAddress(addr).ToString(); + grcaddress = EncodeDestination(addr); return grcaddress; } @@ -177,7 +177,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, unsigned int vo { strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + strHTML += GUIUtil::HtmlEscape(EncodeDestination(address)); if (!wallet->mapAddressBook[address].empty()) strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")"; @@ -203,7 +203,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, unsigned int vo strHTML += "" + tr("To") + ": "; - CTxDestination dest = CBitcoinAddress(strAddress).Get(); + CTxDestination dest = DecodeDestination(strAddress); if (wallet->mapAddressBook.count(dest) && !wallet->mapAddressBook[dest].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[dest]) + " "; @@ -269,7 +269,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, unsigned int vo if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " "; - strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + strHTML += GUIUtil::HtmlEscape(EncodeDestination(address)); strHTML += "
"; } } @@ -395,7 +395,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, unsigned int vo CTxDestination address; if (ExtractDestination(vout.scriptPubKey, address)) - strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); + strHTML += QString::fromStdString(EncodeDestination(address)); strHTML += " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, vout.nValue); strHTML += " IsMine=" + ((wallet->IsMine(vout) != ISMINE_NO) ? tr("true") : tr("false")) + ""; diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1fc5af5a19..b841940cb5 100755 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -1,6 +1,6 @@ #include "transactionrecord.h" #include "wallet/wallet.h" -#include "base58.h" +#include #include /* Return positive answer if transaction should be shown in list. */ @@ -88,7 +88,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * if (ExtractDestination(txout.scriptPubKey, address)) { - sub.address = CBitcoinAddress(address).ToString(); + sub.address = EncodeDestination(address); } // Generated (proof-of-work) @@ -121,7 +121,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // The coinstake HAS to be from an address. if(ExtractDestination(wtx.vout[1].scriptPubKey, address)) { - sub.address = CBitcoinAddress(address).ToString(); + sub.address = EncodeDestination(address); } // Here we add up all of the outputs, whether they are ours (the stake return with @@ -173,7 +173,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * if (ExtractDestination(wtx.vout[t].scriptPubKey, address)) { - sub.address = CBitcoinAddress(address).ToString(); + sub.address = EncodeDestination(address); } int64_t nValue = wtx.vout[t].nValue; @@ -205,7 +205,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * { // Received by Bitcoin Address sub.type = TransactionRecord::RecvWithAddress; - sub.address = CBitcoinAddress(address).ToString(); + sub.address = EncodeDestination(address); } else { @@ -281,7 +281,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * { // Sent to Bitcoin Address sub.type = TransactionRecord::SendToAddress; - sub.address = CBitcoinAddress(address).ToString(); + sub.address = EncodeDestination(address); } else { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index f8c8e167a9..8c0c688b66 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -6,7 +6,7 @@ #include "node/ui_interface.h" #include "wallet/wallet.h" -#include "base58.h" +#include #include "util.h" #include "gridcoin/tx_message.h" @@ -174,8 +174,8 @@ void WalletModel::updateAddressBook(const QString &address, const QString &label bool WalletModel::validateAddress(const QString &address) { - CBitcoinAddress addressParsed(address.toStdString()); - return addressParsed.IsValid(); + CTxDestination addressParsed = DecodeDestination(address.toStdString()); + return IsValidDestination(addressParsed); } WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList &recipients, const CCoinControl *coinControl) @@ -242,7 +242,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList > vecSend; for (const SendCoinsRecipient& rcp : recipients) { CScript scriptPubKey; - scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); + scriptPubKey.SetDestination(DecodeDestination(rcp.address.toStdString())); vecSend.push_back(std::make_pair(scriptPubKey, rcp.amount)); } @@ -273,7 +273,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QListcs_wallet); @@ -361,9 +361,9 @@ static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStor static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status) { - LogPrintf("NotifyAddressBookChanged %s %s isMine=%i status=%i", CBitcoinAddress(address).ToString(), label, isMine, status); + LogPrintf("NotifyAddressBookChanged %s %s isMine=%i status=%i", EncodeDestination(address), label, isMine, status); QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, - Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())), + Q_ARG(QString, QString::fromStdString(EncodeDestination(address))), Q_ARG(QString, QString::fromStdString(label)), Q_ARG(bool, isMine), Q_ARG(int, status)); @@ -501,7 +501,7 @@ void WalletModel::listCoins(std::map >& mapCoins) CTxDestination address; if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; - mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); + mapCoins[EncodeDestination(address).c_str()].push_back(out); } } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f57b3cce80..69d73a2a39 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1156,7 +1156,7 @@ UniValue rainbymagnitude(const UniValue& params, bool fHelp) const int64_t now = GetAdjustedTime(); // Time to calculate beacon expiration from //------- CPID -------------- beacon address -- Mag --- payment - suppressed - std::map> mCPIDRain; + std::map> mCPIDRain; for (const auto& entry : mScraperConvergedStats) { @@ -1184,7 +1184,7 @@ UniValue rainbymagnitude(const UniValue& params, bool fHelp) // Zero mag CPIDs do not get paid. if (!dCPIDMag) continue; - CBitcoinAddress address; + CTxDestination address; // If the beacon is active get the address and insert an entry into the map for payment, // otherwise skip. @@ -1241,7 +1241,7 @@ UniValue rainbymagnitude(const UniValue& params, bool fHelp) { // Make it easier to read. const GRC::Cpid& cpid = iter.first; - const CBitcoinAddress& address = std::get<0>(iter.second); + const CTxDestination& address = std::get<0>(iter.second); const double& magnitude = std::get<1>(iter.second); // This is not a const reference on purpose because it has to be renormalized. @@ -1254,18 +1254,18 @@ UniValue rainbymagnitude(const UniValue& params, bool fHelp) payment = roundint64((double) payment * (double) amount / (double) total_amount_1st_pass); CScript scriptPubKey; - scriptPubKey.SetDestination(address.Get()); + scriptPubKey.SetDestination(address); LogPrint(BCLog::LogFlags::VERBOSE, "INFO: %s: cpid = %s. address = %s, magnitude = %.2f, " "payment = %s, dust_suppressed = %u", - __func__, cpid.ToString(), address.ToString(), magnitude, ValueFromAmount(payment).getValStr(), suppressed); + __func__, cpid.ToString(), EncodeDestination(address), magnitude, ValueFromAmount(payment).getValStr(), suppressed); if (output_details) { UniValue detail_entry(UniValue::VOBJ); detail_entry.pushKV("cpid", cpid.ToString()); - detail_entry.pushKV("address", address.ToString()); + detail_entry.pushKV("address", EncodeDestination(address)); detail_entry.pushKV("magnitude", magnitude); detail_entry.pushKV("amount", ValueFromAmount(payment)); detail_entry.pushKV("suppressed", suppressed); @@ -1537,7 +1537,7 @@ UniValue beaconreport(const UniValue& params, bool fHelp) if (active_only && beacon_pair.second->Expired(now)) continue; entry.pushKV("cpid", beacon_pair.first.ToString()); - entry.pushKV("address", beacon_pair.second->GetAddress().ToString()); + entry.pushKV("address", EncodeDestination(beacon_pair.second->GetAddress())); entry.pushKV("timestamp", beacon_pair.second->m_timestamp); entry.pushKV("hash", beacon_pair.second->m_hash.GetHex()); entry.pushKV("prev_beacon_hash", beacon_pair.second->m_previous_hash.GetHex()); @@ -1656,14 +1656,12 @@ UniValue pendingbeaconreport(const UniValue& params, bool fHelp) { UniValue entry(UniValue::VOBJ); - CBitcoinAddress address; const CKeyID& key_id = pending_beacon_pair.first; - - address.Set(key_id); + CTxDestination address(key_id); entry.pushKV("cpid", pending_beacon_pair.second->m_cpid.ToString()); entry.pushKV("key_id", pending_beacon_pair.first.ToString()); - entry.pushKV("address", address.ToString()); + entry.pushKV("address", EncodeDestination(address)); entry.pushKV("timestamp", pending_beacon_pair.second->m_timestamp); results.push_back(entry); @@ -1715,7 +1713,7 @@ UniValue beaconstatus(const UniValue& params, bool fHelp) entry.pushKV("expired", beacon->Expired(now)); entry.pushKV("renewable", beacon->Renewable(now)); entry.pushKV("timestamp", TimestampToHRDate(beacon->m_timestamp)); - entry.pushKV("address", beacon->GetAddress().ToString()); + entry.pushKV("address", EncodeDestination(beacon->GetAddress())); entry.pushKV("public_key", HexStr(beacon->m_public_key)); entry.pushKV("private_key_available", beacon->WalletHasPrivateKey(pwalletMain)); entry.pushKV("magnitude", GRC::Quorum::GetMagnitude(*cpid).Floating()); @@ -1733,7 +1731,7 @@ UniValue beaconstatus(const UniValue& params, bool fHelp) entry.pushKV("expired", beacon_ptr->Expired(now)); entry.pushKV("renewable", false); entry.pushKV("timestamp", TimestampToHRDate(beacon_ptr->m_timestamp)); - entry.pushKV("address", beacon_ptr->GetAddress().ToString()); + entry.pushKV("address", EncodeDestination(beacon_ptr->GetAddress())); entry.pushKV("public_key", HexStr(beacon_ptr->m_public_key)); entry.pushKV("private_key_available", beacon_ptr->WalletHasPrivateKey(pwalletMain)); entry.pushKV("magnitude", 0); @@ -2387,15 +2385,13 @@ UniValue addkey(const UniValue& params, bool fHelp) std::string status_string = ToLower(params[3].get_str()); GRC::ScraperEntryStatus status = GRC::ScraperEntryStatus::UNKNOWN; - CBitcoinAddress scraper_address; - if (!scraper_address.SetString(params[2].get_str())) { + CTxDestination scraper_address = DecodeDestination(params[2].get_str()); + if (!IsValidDestination(scraper_address)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Address specified for the scraper is invalid."); } if (block_v13_enabled) { // Contract version will be 3. - CKeyID key_id; - - scraper_address.GetKeyID(key_id); + CKeyID key_id = std::get(scraper_address); if (action == GRC::ContractAction::ADD) { if (status_string == "false") { @@ -2430,7 +2426,7 @@ UniValue addkey(const UniValue& params, bool fHelp) contract = GRC::MakeContract( contract_version, action, - scraper_address.ToString(), + EncodeDestination(scraper_address), status_string); } break; @@ -2447,8 +2443,8 @@ UniValue addkey(const UniValue& params, bool fHelp) case GRC::ContractType::SIDESTAKE: { if (block_v13_enabled) { - CBitcoinAddress sidestake_address; - if (!sidestake_address.SetString(params[2].get_str())) { + CTxDestination sidestake_address = DecodeDestination(params[2].get_str()); + if (!IsValidDestination(sidestake_address)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Address specified for the sidestake is invalid."); } @@ -2474,7 +2470,7 @@ UniValue addkey(const UniValue& params, bool fHelp) contract_version, // Contract version number (3+) action, // Contract action uint32_t {1}, // Contract payload version number - sidestake_address.Get(), // Sidestake destination + sidestake_address, // Sidestake destination allocation, // Sidestake allocation description, // Sidestake description GRC::MandatorySideStake::MandatorySideStakeStatus::MANDATORY // sidestake status @@ -2618,9 +2614,9 @@ UniValue listscrapers(const UniValue& params, bool fHelp) for (const auto& scraper : GRC::GetScraperRegistry().Scrapers()) { UniValue entry(UniValue::VOBJ); - CBitcoinAddress address(scraper.first); + CTxDestination address(scraper.first); - entry.pushKV("scraper_address", address.ToString()); + entry.pushKV("scraper_address", EncodeDestination(address)); entry.pushKV("current_scraper_entry_tx_hash", scraper.second->m_hash.ToString()); if (scraper.second->m_previous_hash.IsNull()) { entry.pushKV("previous_scraper_entry_tx_hash", "null"); @@ -2689,7 +2685,7 @@ UniValue listmandatorysidestakes(const UniValue& params, bool fHelp) for (const auto& sidestake : GRC::GetSideStakeRegistry().ActiveSideStakeEntries(GRC::SideStake::FilterFlag::MANDATORY, false)) { UniValue entry(UniValue::VOBJ); - entry.pushKV("mandatory_sidestake_entry_address", CBitcoinAddress(sidestake->GetDestination()).ToString()); + entry.pushKV("mandatory_sidestake_entry_address", EncodeDestination(sidestake->GetDestination())); entry.pushKV("mandatory_sidestake_entry_allocation", sidestake->GetAllocation().ToPercent()); entry.pushKV("mandatory_sidestake_entry_tx_hash", sidestake->GetHash().ToString()); if (sidestake->GetPreviousHash().IsNull()) { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 9724c04aa9..f99bc02991 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -6,7 +6,7 @@ #include "init.h" #include "sync.h" #include "node/ui_interface.h" -#include "base58.h" +#include #include "protocol.h" #include "client.h" #include "server.h" diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index be24b0b100..23c318c659 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -117,7 +117,7 @@ UniValue getstakinginfo(const UniValue& params, bool fHelp) // sidestakes are always included. for (const auto& alloc : vSideStakeAlloc) { - sidestakingalloc.pushKV("address", CBitcoinAddress(alloc->GetDestination()).ToString()); + sidestakingalloc.pushKV("address", EncodeDestination(alloc->GetDestination())); sidestakingalloc.pushKV("allocation_pct", alloc->GetAllocation().ToPercent()); sidestakingalloc.pushKV("status", alloc->StatusToString()); @@ -213,7 +213,7 @@ UniValue getlaststake(const UniValue& params, bool fHelp) CTxDestination dest; if (ExtractDestination(stake_tx->vout[1].scriptPubKey, dest)) { - json.pushKV("address", CBitcoinAddress(dest).ToString()); + json.pushKV("address", EncodeDestination(dest)); } else { json.pushKV("address", ""); } diff --git a/src/rpc/protocol.cpp b/src/rpc/protocol.cpp index 804eba917b..c4f44923af 100644 --- a/src/rpc/protocol.cpp +++ b/src/rpc/protocol.cpp @@ -7,7 +7,7 @@ #include "sync.h" #include "node/ui_interface.h" #include "protocol.h" -#include "base58.h" +#include #include "wallet/db.h" #include "util.h" diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 54e404a707..509ea3a6f8 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -121,7 +121,7 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud UniValue a(UniValue::VARR); for (auto const& addr : addresses) - a.push_back(CBitcoinAddress(addr).ToString()); + a.push_back(EncodeDestination(addr)); out.pushKV("addresses", a); } @@ -253,7 +253,7 @@ UniValue SideStakePayloadToJson (const GRC::ContractPayload& payload) UniValue out(UniValue::VOBJ); - out.pushKV("address", CBitcoinAddress(sidestake.m_entry.m_destination).ToString()); + out.pushKV("address", EncodeDestination(sidestake.m_entry.m_destination)); out.pushKV("allocation", sidestake.m_entry.m_allocation.ToPercent()); out.pushKV("description", sidestake.m_entry.m_description); out.pushKV("status", sidestake.m_entry.StatusToString()); @@ -456,14 +456,14 @@ UniValue listunspent(const UniValue& params, bool fHelp) if (params.size() > 1) nMaxDepth = params[1].get_int(); - set setAddress; + set setAddress; if (params.size() > 2) { UniValue inputs = params[2].get_array(); for (unsigned int ix = 0; ix < inputs.size(); ix++) { - CBitcoinAddress address(inputs[ix].get_str()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(inputs[ix].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Gridcoin address: ")+inputs[ix].get_str()); if (setAddress.count(address)) throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+inputs[ix].get_str()); @@ -502,7 +502,7 @@ UniValue listunspent(const UniValue& params, bool fHelp) CTxDestination address; if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) { - entry.pushKV("address", CBitcoinAddress(address).ToString()); + entry.pushKV("address", EncodeDestination(address)); auto item = pwalletMain->mapAddressBook.find(address); @@ -567,7 +567,7 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) UniValue result(UniValue::VOBJ); std::string sAddress = params[0].get_str(); - CBitcoinAddress OptimizeAddress(sAddress); + CTxDestination OptimizeAddress = DecodeDestination(sAddress); int64_t nConsolidateLimit = 0; unsigned int nInputNumberLimit = GetMaxInputsForConsolidationTxn(); @@ -589,14 +589,14 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) // due to the size. nInputNumberLimit = std::min(nInputNumberLimit, GetMaxInputsForConsolidationTxn()); - if (!OptimizeAddress.IsValid()) + if (!IsValidDestination(OptimizeAddress)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Gridcoin address: ") + sAddress); } // Set the consolidation transaction address to the specified output address. CScript scriptDestPubKey; - scriptDestPubKey.SetDestination(OptimizeAddress.Get()); + scriptDestPubKey.SetDestination(OptimizeAddress); std::vector vecInputs; @@ -623,7 +623,7 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) // If the UTXO matches the consolidation address or all sweep_all_addresses is true then add to the inputs // map for consolidation. Note that the value of sweep_change is ignored and all change will be swept. - if (CBitcoinAddress(out_address) == OptimizeAddress || sweep_all_addresses) + if (out_address == OptimizeAddress || sweep_all_addresses) { mInputs.insert(std::make_pair(nOutValue, out)); } @@ -684,7 +684,7 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) // to the inputs map for consolidation. if (ExtractDestination(prev_ctxout.scriptPubKey, change_input_address)) { - if (CBitcoinAddress(change_input_address) == OptimizeAddress) + if (change_input_address == OptimizeAddress) { // Insert the ORIGINAL change UTXO into the input map for the consolidation. mInputs.insert(std::make_pair(nOutValue, out)); @@ -818,7 +818,7 @@ UniValue consolidateunspent(const UniValue& params, bool fHelp) CCoinControl coinControl; // Send the change back to the same address. - coinControl.destChange = OptimizeAddress.Get(); + coinControl.destChange = OptimizeAddress; if (!pwalletMain->CreateTransaction(vecSend, setCoins, wtxNew, reservekey, nFeeRequired, &coinControl)) { @@ -999,10 +999,10 @@ UniValue consolidatemsunspent(const UniValue& params, bool fHelp) if (nMaxValue < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Value must not be less than 0"); - CBitcoinAddress Address(sAddress); + CTxDestination Address = DecodeDestination(sAddress); // Check if the address is valid - if (!Address.IsValid()) + if (!IsValidDestination(Address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin Address"); { @@ -1020,7 +1020,7 @@ UniValue consolidatemsunspent(const UniValue& params, bool fHelp) txnouttype WhichType; vector vSolutions; - CSDest.SetDestination(Address.Get()); + CSDest.SetDestination(Address); // Solve the solutions for Destination script if (!Solver(CSDest, WhichType, vSolutions)) @@ -1149,7 +1149,7 @@ UniValue consolidatemsunspent(const UniValue& params, bool fHelp) continue; // If we found a match to multisig address do our work - if (CBitcoinAddress(txaddress) == Address) + if (txaddress == Address) { // Check if this output is already spent COutPoint dummy = COutPoint(tx.GetHash(), j); @@ -1207,7 +1207,7 @@ UniValue consolidatemsunspent(const UniValue& params, bool fHelp) // Make the output CScript scriptPubKey; - scriptPubKey.SetDestination(Address.Get()); + scriptPubKey.SetDestination(Address); CTxOut out(nOutput, scriptPubKey); @@ -1290,9 +1290,9 @@ UniValue scanforunspent(const UniValue& params, bool fHelp) if (nBlockEnd < 1 || nBlockEnd > nBestHeight || nBlockEnd <= nBlockStart) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block-end"); - CBitcoinAddress Address(sAddress); + CTxDestination Address = DecodeDestination(sAddress); - if (!Address.IsValid()) + if (!IsValidDestination(Address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin Address"); // Store as: TXID, VOUT, nValue, nHeight @@ -1340,7 +1340,7 @@ UniValue scanforunspent(const UniValue& params, bool fHelp) continue; // If we found a match to multisig address do our work - if (CBitcoinAddress(txaddress) == Address) + if (txaddress == Address) { // Check if this output is already spent COutPoint dummy = COutPoint(tx.GetHash(), j); @@ -1547,11 +1547,11 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) rawTx.vin.push_back(in); } - set setAddress; + set setAddress; vector addrList = sendTo.getKeys(); for (auto const& name_: addrList) { - CBitcoinAddress address(name_); + CTxDestination address = DecodeDestination(name_); if (name_ == "data") { std::vector data = ParseHexV(sendTo[name_],"Data"); @@ -1560,8 +1560,8 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) } else { - CBitcoinAddress address(name_); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(name_); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Gridcoin address: ")+name_); if (setAddress.count(address)) @@ -1569,7 +1569,7 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey; - scriptPubKey.SetDestination(address.Get()); + scriptPubKey.SetDestination(address); int64_t nAmount = AmountFromValue(sendTo[name_]); CTxOut out(nAmount, scriptPubKey); @@ -1631,7 +1631,7 @@ UniValue decodescript(const UniValue& params, bool fHelp) } ScriptPubKeyToJSON(script, r, false); - r.pushKV("p2sh", CBitcoinAddress(script.GetID()).ToString()); + r.pushKV("p2sh", EncodeDestination(script.GetID())); return r; } diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index c45f5ac51b..497c8bbd30 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -4,10 +4,11 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include "amount.h" +#include #include "init.h" #include "sync.h" +#include #include "node/ui_interface.h" -#include "base58.h" #include "server.h" #include "client.h" #include "protocol.h" diff --git a/src/script.cpp b/src/script.cpp index e81af2bfcf..2595d20daa 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1910,3 +1910,7 @@ void CScript::SetMultisig(int nRequired, const std::vector& keys) *this << key; *this << EncodeOP_N(keys.size()) << OP_CHECKMULTISIG; } + +bool IsValidDestination(const CTxDestination& dest) { + return dest.index() != 0; +} diff --git a/src/script.h b/src/script.h index c65169c25c..4d675b5c62 100644 --- a/src/script.h +++ b/src/script.h @@ -106,10 +106,12 @@ class CNoDestination { * * CNoDestination: no destination set * * CKeyID: TX_PUBKEYHASH destination * * CScriptID: TX_SCRIPTHASH destination - * A CTxDestination is the internal data type encoded in a CBitcoinAddress */ typedef std::variant CTxDestination; +/** Check whether a CTxDestination is a CNoDestination. */ +bool IsValidDestination(const CTxDestination& dest); + const char* GetTxnOutputType(txnouttype t); /** Script opcodes */ diff --git a/src/test/gridcoin/beacon_tests.cpp b/src/test/gridcoin/beacon_tests.cpp index 770cddb0d7..7c9f91b49a 100644 --- a/src/test/gridcoin/beacon_tests.cpp +++ b/src/test/gridcoin/beacon_tests.cpp @@ -2,9 +2,10 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include #include "dbwrapper.h" #include "gridcoin/beacon.h" +#include #include "rpc/blockchain.h" #include "test/data/testnet_beacon.bin.h" #include "test/data/mainnet_beacon.bin.h" @@ -71,9 +72,9 @@ struct TestKey //! //! \brief Create an address from the test public key. //! - static CBitcoinAddress Address() + static CTxDestination Address() { - return CBitcoinAddress(CTxDestination(KeyId())); + return CTxDestination(KeyId()); } //! @@ -210,7 +211,7 @@ class BeaconRegistryTest << "blockheight = " << ctx.m_pindex->nHeight << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) - << ", address = " << beacon->GetAddress().ToString() + << ", address = " << EncodeDestination(beacon->GetAddress()) << ", timestamp = " << beacon->m_timestamp << ", hash = " << beacon->m_hash.GetHex() << ", prev beacon hash = " << beacon->m_previous_hash.GetHex() @@ -230,7 +231,7 @@ class BeaconRegistryTest << "blockheight = " << ctx.m_pindex->nHeight << ", cpid = " << beacon->m_cpid.ToString() << ", public key = " << HexStr(beacon->m_public_key) - << ", address = " << beacon->GetAddress().ToString() + << ", address = " << EncodeDestination(beacon->GetAddress()) << ", timestamp = " << beacon->m_timestamp << ", hash = " << beacon->m_hash.GetHex() << ", prev beacon hash = " << beacon->m_previous_hash.GetHex() @@ -268,7 +269,7 @@ class BeaconRegistryTest << "blockheight = " << pindex->nHeight << ", cpid = " << activated_beacon->m_cpid.ToString() << ", public key = " << HexStr(activated_beacon->m_public_key) - << ", address = " << activated_beacon->GetAddress().ToString() + << ", address = " << EncodeDestination(activated_beacon->GetAddress()) << ", timestamp = " << activated_beacon->m_timestamp << ", hash = " << activated_beacon->m_hash.GetHex() << ", prev beacon hash = " << activated_beacon->m_previous_hash.GetHex() @@ -283,7 +284,7 @@ class BeaconRegistryTest << "blockheight = " << pindex->nHeight << ", cpid = " << iter->m_cpid.ToString() << ", public key = " << HexStr(iter->m_public_key) - << ", address = " << iter->GetAddress().ToString() + << ", address = " << EncodeDestination(iter->GetAddress()) << ", timestamp = " << iter->m_timestamp << ", hash = " << iter->m_hash.GetHex() << ", prev beacon hash = " << iter->m_previous_hash.GetHex() @@ -328,7 +329,7 @@ class BeaconRegistryTest std::cout << "init beacon db record: " << ", cpid = " << beacon_ptr->m_cpid.ToString() << ", public key = " << HexStr(beacon_ptr->m_public_key) - << ", address = " << beacon_ptr->GetAddress().ToString() + << ", address = " << EncodeDestination(beacon_ptr->GetAddress()) << ", timestamp = " << beacon_ptr->m_timestamp << ", hash = " << beacon_ptr->m_hash.GetHex() << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() @@ -379,7 +380,7 @@ class BeaconRegistryTest std::cout << "init beacon db record: " << ", cpid = " << beacon_ptr->m_cpid.ToString() << ", public key = " << HexStr(beacon_ptr->m_public_key) - << ", address = " << beacon_ptr->GetAddress().ToString() + << ", address = " << EncodeDestination(beacon_ptr->GetAddress()) << ", timestamp = " << beacon_ptr->m_timestamp << ", hash = " << beacon_ptr->m_hash.GetHex() << ", prev beacon hash = " << beacon_ptr->m_previous_hash.GetHex() @@ -431,7 +432,7 @@ class BeaconRegistryTest << "hash = " << hash.GetHex() << ", cpid = " << left.second->m_cpid.ToString() << ", public key = " << HexStr(left.second->m_public_key) - << ", address = " << left.second->GetAddress().ToString() + << ", address = " << EncodeDestination(left.second->GetAddress()) << ", timestamp = " << left.second->m_timestamp << ", hash = " << left.second->m_hash.GetHex() << ", prev beacon hash = " << left.second->m_previous_hash.GetHex() @@ -457,8 +458,8 @@ class BeaconRegistryTest std::cout << "init_beacon public key = " << HexStr(left_beacon_ptr->m_public_key) << ", reinit_beacon public key = " << HexStr(right_beacon_iter->second->m_public_key) << std::endl; - std::cout << "init_beacon address = " << left_beacon_ptr->GetAddress().ToString() - << ", reinit_beacon address = " << right_beacon_iter->second->GetAddress().ToString() << std::endl; + std::cout << "init_beacon address = " << EncodeDestination(left_beacon_ptr->GetAddress()) + << ", reinit_beacon address = " << EncodeDestination(right_beacon_iter->second->GetAddress()) << std::endl; std::cout << "init_beacon timestamp = " << left_beacon_ptr->m_timestamp << ", reinit_beacon timestamp = " << right_beacon_iter->second->m_timestamp << std::endl; @@ -493,7 +494,7 @@ class BeaconRegistryTest << "hash = " << hash.GetHex() << ", cpid = " << left.second->m_cpid.ToString() << ", public key = " << HexStr(left.second->m_public_key) - << ", address = " << left.second->GetAddress().ToString() + << ", address = " << EncodeDestination(left.second->GetAddress()) << ", timestamp = " << left.second->m_timestamp << ", hash = " << left.second->m_hash.GetHex() << ", prev beacon hash = " << left.second->m_previous_hash.GetHex() @@ -519,8 +520,8 @@ class BeaconRegistryTest std::cout << "reinit_beacon public key = " << HexStr(left_beacon_ptr->m_public_key) << ", init_beacon public key = " << HexStr(right_beacon_iter->second->m_public_key) << std::endl; - std::cout << "reinit_beacon address = " << left_beacon_ptr->GetAddress().ToString() - << ", init_beacon address = " << right_beacon_iter->second->GetAddress().ToString() << std::endl; + std::cout << "reinit_beacon address = " << EncodeDestination(left_beacon_ptr->GetAddress()) + << ", init_beacon address = " << EncodeDestination(right_beacon_iter->second->GetAddress()) << std::endl; std::cout << "reinit_beacon timestamp = " << left_beacon_ptr->m_timestamp << ", init_beacon timestamp = " << right_beacon_iter->second->m_timestamp << std::endl; @@ -557,7 +558,7 @@ class BeaconRegistryTest // You should be in the src directory for that, so the command would be ./test/test_gridcoin. std::cout << "init_beacon cpid = " << cpid.ToString() << ", public key = " << HexStr(beacon.m_public_key) - << ", address = " << beacon.GetAddress().ToString() + << ", address = " << EncodeDestination(beacon.GetAddress()) << ", timestamp = " << beacon.m_timestamp << ", hash = " << beacon.m_hash.GetHex() << ", prev beacon hash = " << beacon.m_previous_hash.GetHex() @@ -574,7 +575,7 @@ class BeaconRegistryTest // You should be in the src directory for that, so the command would be ./test/test_gridcoin. std::cout << "reinit beacon cpid = " << cpid.ToString() << ", public key = " << HexStr(beacon.m_public_key) - << ", address = " << beacon.GetAddress().ToString() + << ", address = " << EncodeDestination(beacon.GetAddress()) << ", timestamp = " << beacon.m_timestamp << ", hash = " << beacon.m_hash.GetHex() << ", prev beacon hash = " << beacon.m_previous_hash.GetHex() @@ -603,7 +604,7 @@ class BeaconRegistryTest << "hash = " << left.second.m_hash.GetHex() << ", cpid = " << left.second.m_cpid.ToString() << ", public key = " << HexStr(left.second.m_public_key) - << ", address = " << left.second.GetAddress().ToString() + << ", address = " << EncodeDestination(left.second.GetAddress()) << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() @@ -656,7 +657,7 @@ class BeaconRegistryTest << "hash = " << left.second.m_hash.GetHex() << ", cpid = " << left.second.m_cpid.ToString() << ", public key = " << HexStr(left.second.m_public_key) - << ", address = " << left.second.GetAddress().ToString() + << ", address = " << EncodeDestination(left.second.GetAddress()) << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() @@ -720,7 +721,7 @@ class BeaconRegistryTest << "hash = " << left_beacon.m_hash.GetHex() << ", cpid = " << left_beacon.m_cpid.ToString() << ", public key = " << HexStr(left_beacon.m_public_key) - << ", address = " << left_beacon.GetAddress().ToString() + << ", address = " << EncodeDestination(left_beacon.GetAddress()) << ", timestamp = " << left_beacon.m_timestamp << ", hash = " << left_beacon.m_hash.GetHex() << ", prev beacon hash = " << left_beacon.m_previous_hash.GetHex() @@ -775,7 +776,7 @@ class BeaconRegistryTest << "hash = " << left.second.m_hash.GetHex() << ", cpid = " << left.second.m_cpid.ToString() << ", public key = " << HexStr(left.second.m_public_key) - << ", address = " << left.second.GetAddress().ToString() + << ", address = " << EncodeDestination(left.second.GetAddress()) << ", timestamp = " << left.second.m_timestamp << ", hash = " << left.second.m_hash.GetHex() << ", prev beacon hash = " << left.second.m_previous_hash.GetHex() @@ -962,7 +963,7 @@ BOOST_AUTO_TEST_CASE(it_represents_itself_as_a_legacy_string) const std::string expected = EncodeBase64( "0;0;" - + TestKey::Address().ToString() + + EncodeDestination(TestKey::Address()) + ";" + HexStr(TestKey::Public())); diff --git a/src/test/gridcoin/scraper_registry_tests.cpp b/src/test/gridcoin/scraper_registry_tests.cpp index 1164ae068e..4465ccafda 100644 --- a/src/test/gridcoin/scraper_registry_tests.cpp +++ b/src/test/gridcoin/scraper_registry_tests.cpp @@ -15,10 +15,10 @@ void AddRemoveScraperEntryV1(const std::string& address, const std::string& valu GRC::ScraperRegistry& registry = GRC::GetScraperRegistry(); std::string status_string = ToLower(value); - CBitcoinAddress scraper_address; + CTxDestination scraper_address = DecodeDestination(address); // Assert if not a valid address. - assert(scraper_address.SetString(address)); + assert(IsValidDestination(scraper_address)); // Make sure the registry is reset. if (reset_registry) registry.Reset(); @@ -54,12 +54,8 @@ void AddRemoveScraperEntryV2(const std::string& address, const GRC::ScraperEntry { GRC::ScraperRegistry& registry = GRC::GetScraperRegistry(); - CBitcoinAddress scraper_address; - CKeyID key_id; - - scraper_address.SetString(address); - - scraper_address.GetKeyID(key_id); + CTxDestination scraper_address = DecodeDestination(address); + CKeyID key_id = std::get(scraper_address); // Make sure the registry is reset. if (reset_registry) registry.Reset(); @@ -119,11 +115,9 @@ BOOST_AUTO_TEST_CASE(scraper_entries_added_to_scraper_work_correctly_legacy) // Native format from legacy adds. for (const auto& entry : scraper_entries) { - CBitcoinAddress address; - address.SetString(entry); + CTxDestination address = DecodeDestination(entry); - CKeyID key_id; - address.GetKeyID(key_id); + CKeyID key_id = std::get(address); auto registry_entry = scraper_map.find(key_id); @@ -185,11 +179,9 @@ BOOST_AUTO_TEST_CASE(scraper_entry_deauthorize_and_delete_works_correctly_legacy // Native format from legacy adds. for (const auto& entry : scraper_entries) { - CBitcoinAddress address; - address.SetString(entry); + CTxDestination address = DecodeDestination(entry); - CKeyID key_id; - address.GetKeyID(key_id); + CKeyID key_id = std::get(address); auto registry_entry = scraper_map.find(key_id); @@ -254,11 +246,9 @@ BOOST_AUTO_TEST_CASE(scraper_entry_deauthorize_and_delete_works_correctly_legacy // Native format from legacy adds, deauthorize, and delete for active scraper map.. for (const auto& entry : scraper_entries) { - CBitcoinAddress address; - address.SetString(entry); + CTxDestination address = DecodeDestination(entry); - CKeyID key_id; - address.GetKeyID(key_id); + CKeyID key_id = std::get(address); auto registry_entry = scraper_map.find(key_id); @@ -385,11 +375,9 @@ BOOST_AUTO_TEST_CASE(scraper_entry_deauthorize_and_delete_works_correctly_native // Native format from native adds. for (const auto& entry : scraper_entries) { - CBitcoinAddress address; - address.SetString(entry); + CTxDestination address = DecodeDestination(entry); - CKeyID key_id; - address.GetKeyID(key_id); + CKeyID key_id = std::get(address); auto registry_entry = scraper_map.find(key_id); @@ -430,11 +418,9 @@ BOOST_AUTO_TEST_CASE(scraper_entry_deauthorize_and_delete_works_correctly_native GRC::Contract contract; - CBitcoinAddress address; - address.SetString("SLbdvKZHmtu49VUWm88rbcCo9DaC8Z2urV"); + CTxDestination address = DecodeDestination("SLbdvKZHmtu49VUWm88rbcCo9DaC8Z2urV"); - CKeyID key_id; - address.GetKeyID(key_id) + CKeyID key_id = std::get(address); ; contract = GRC::MakeContract( uint32_t {3}, // Contract version (pre v13) @@ -460,11 +446,9 @@ BOOST_AUTO_TEST_CASE(scraper_entry_deauthorize_and_delete_works_correctly_native // Native format from legacy adds, deauthorize, and delete for active scraper map.. for (const auto& entry : scraper_entries) { - CBitcoinAddress address; - address.SetString(entry); + CTxDestination address = DecodeDestination(entry); - CKeyID key_id; - address.GetKeyID(key_id); + CKeyID key_id = std::get(address); auto registry_entry = scraper_map.find(key_id); diff --git a/src/test/gridcoin/superblock_tests.cpp b/src/test/gridcoin/superblock_tests.cpp index eea417b628..0e4b92dc55 100644 --- a/src/test/gridcoin/superblock_tests.cpp +++ b/src/test/gridcoin/superblock_tests.cpp @@ -2,12 +2,13 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include "base58.h" +#include #include "compat/endian.h" #include #include "gridcoin/scraper/scraper_net.h" #include "gridcoin/superblock.h" #include "gridcoin/support/xml.h" +#include #include "streams.h" #include diff --git a/src/test/key_tests.cpp b/src/test/key_tests.cpp index e8f929062a..30218872a0 100755 --- a/src/test/key_tests.cpp +++ b/src/test/key_tests.cpp @@ -5,7 +5,6 @@ #include "key.h" #include -#include "base58.h" #include "uint256.h" #include "util.h" @@ -16,10 +15,10 @@ static const std::string strSecret1 ("7NUfsJVtS5TruQrAFpni4yqqvoQg2fNk5JHRh1vsJP static const std::string strSecret2 ("7PiDb7gCaHw7P7Jfayc3d6BioSj8NyzxDzNb94vYe7gGYq2ytYF"); static const std::string strSecret1C("V7o8Z2EW1ghZGLFyrRvkGZtaxTqVGLNy7yHVyd6m1m45gzwsUEci"); static const std::string strSecret2C("VDEvZaU25wjqAapyJxqgaHtKVzYwa2ankLEHgcKLepUKd4F7czq6"); -static const CBitcoinAddress addr1 ("SMDEt5x56GHokFwbpaYLNykBo1JwA3tC4E"); -static const CBitcoinAddress addr2 ("SC3N7xZ7NnoshVxFhAM6eFWq4YCSGMKkzn"); -static const CBitcoinAddress addr1C("SKkhuYMjyZueN4wGpY6pMMW5soPiEDhXe8"); -static const CBitcoinAddress addr2C("S9P852TD2PFqh9otrRYUL7rTheRddigULh"); +static const std::string addr1 ("SMDEt5x56GHokFwbpaYLNykBo1JwA3tC4E"); +static const std::string addr2 ("SC3N7xZ7NnoshVxFhAM6eFWq4YCSGMKkzn"); +static const std::string addr1C("SKkhuYMjyZueN4wGpY6pMMW5soPiEDhXe8"); +static const std::string addr2C("S9P852TD2PFqh9otrRYUL7rTheRddigULh"); static const string strAddressBad("1HV9Lc3sNHZxwj4Zk6fB38tEmBryq2cBiF"); @@ -44,10 +43,10 @@ BOOST_AUTO_TEST_CASE(key_test1) CPubKey pubkey1C = key1C.GetPubKey(); CPubKey pubkey2C = key2C.GetPubKey(); - BOOST_CHECK(addr1.Get() == CTxDestination(pubkey1.GetID())); - BOOST_CHECK(addr2.Get() == CTxDestination(pubkey2.GetID())); - BOOST_CHECK(addr1C.Get() == CTxDestination(pubkey1C.GetID())); - BOOST_CHECK(addr2C.Get() == CTxDestination(pubkey2C.GetID())); + BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID())); + BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID())); + BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID())); + BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID())); for (int n=0; n<16; n++) { diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp index 5be3fd616f..6eb9c8a14c 100644 --- a/src/test/rpc_tests.cpp +++ b/src/test/rpc_tests.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include @@ -38,18 +38,17 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig) const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4"; UniValue v; - CBitcoinAddress address; BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + CTxDestination address = DecodeDestination(v.get_str()); + BOOST_CHECK(std::holds_alternative(address)); BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + address = DecodeDestination(v.get_str()); + BOOST_CHECK(std::holds_alternative(address)); BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false)); - address.SetString(v.get_str()); - BOOST_CHECK(address.IsValid() && address.IsScript()); + address = DecodeDestination(v.get_str()); + BOOST_CHECK(std::holds_alternative(address)); BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error); BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error); diff --git a/src/validation.cpp b/src/validation.cpp index 5871f358d8..9fff54f614 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -227,7 +227,7 @@ CAmount GetValueIn(const CTransaction& tx, const MapPrevTx& inputs) bool HasMasterKeyInput(const CTransaction& tx, const MapPrevTx& inputs, int block_height) { - const CTxDestination master_address = CWallet::MasterAddress(block_height).Get(); + const CTxDestination master_address = CWallet::MasterAddress(block_height); for (const auto& input : tx.vin) { const CTxOut& prev_out = GetOutputFor(input, inputs); @@ -625,18 +625,18 @@ Fraction FoundationSideStakeAllocation() return Fraction(4, 5); } -CBitcoinAddress FoundationSideStakeAddress() { - CBitcoinAddress foundation_address; +CTxDestination FoundationSideStakeAddress() { + CTxDestination foundation_address; // If on testnet set foundation destination address to test wallet address if (fTestNet) { - foundation_address.SetString("mfiy9sc2QEZZCK3WMUMZjNfrdRA6gXzRhr"); + foundation_address = DecodeDestination("mfiy9sc2QEZZCK3WMUMZjNfrdRA6gXzRhr"); return foundation_address; } // Will get here if not on testnet. The below address is the current multisignature address for the foundation - foundation_address.SetString("bc3NA8e8E3EoTL1qhRmeprbjWcmuoZ26A2"); + foundation_address = DecodeDestination("bc3NA8e8E3EoTL1qhRmeprbjWcmuoZ26A2"); return foundation_address; } @@ -904,7 +904,7 @@ class ClaimValidator "actual_output = %" PRId64 ", required_output = %" PRId64, __func__, i, - CBitcoinAddress(output_destination).ToString(), + EncodeDestination(output_destination), actual_output, required_output); } @@ -980,7 +980,7 @@ class ClaimValidator } // The sidestake destination must match that specified by FoundationSideStakeAddress(). - if (foundation_sidestake_destination != FoundationSideStakeAddress().Get()) { + if (foundation_sidestake_destination != FoundationSideStakeAddress()) { error_out = "MRC Foundation sidestake destination is incorrect."; return error("%s: FAILED: foundation MRC sidestake destination does not match protocol", @@ -1352,9 +1352,9 @@ class ClaimValidator const GRC::BeaconOption beacon = GRC::GetBeaconRegistry().TryActive(*cpid, mrc_index->nTime); if (beacon) { - CBitcoinAddress beacon_address = beacon->GetAddress(); + CTxDestination beacon_address = beacon->GetAddress(); CScript script_beacon_key; - script_beacon_key.SetDestination(beacon_address.Get()); + script_beacon_key.SetDestination(beacon_address); // If an MRC fails validation no point in continuing. Return false immediately with an // appropriate DoS. @@ -1373,7 +1373,7 @@ class ClaimValidator CAmount coinstake_mrc_reward = 0; CScript mrc_beacon_script_public_key; - mrc_beacon_script_public_key.SetDestination(beacon->GetAddress().Get()); + mrc_beacon_script_public_key.SetDestination(beacon->GetAddress()); // Start at the first actual MRC output. The MRC outputs come last in the coinstake. // We must exclude the other outputs, because it is possible, and allowed, for a diff --git a/src/validation.h b/src/validation.h index 3564409a2e..c746e4e0b0 100644 --- a/src/validation.h +++ b/src/validation.h @@ -17,7 +17,6 @@ class CBlockHeader; namespace Consensus { struct Params; } -class CBitcoinAddress; namespace GRC { class MRC; } @@ -111,7 +110,7 @@ bool CheckBlockSignature(const CBlock& block); unsigned int GetCoinstakeOutputLimit(const int& block_version); unsigned int GetMandatorySideStakeOutputLimit(const int& block_version); Fraction FoundationSideStakeAllocation(); -CBitcoinAddress FoundationSideStakeAddress(); +CTxDestination FoundationSideStakeAddress(); unsigned int GetMRCOutputLimit(const int& block_version, bool include_foundation_sidestake); bool ValidateMRC(const GRC::Contract &contract, const CTransaction& tx, int& DoS); bool ValidateMRC(const CBlockIndex* mrc_last_pindex, const GRC::MRC& mrc); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index e4021e2200..8e8e85c216 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -211,7 +211,7 @@ UniValue importwallet(const UniValue& params, bool fHelp) CKeyID keyid = key.GetPubKey().GetID(); if (pwalletMain->HaveKey(keyid)) { - LogPrintf("Skipping import of %s (key already present)", CBitcoinAddress(keyid).ToString()); + LogPrintf("Skipping import of %s (key already present)", EncodeDestination(keyid)); continue; } int64_t nTime = DecodeDumpTime(vstr[1]); @@ -232,7 +232,7 @@ UniValue importwallet(const UniValue& params, bool fHelp) fLabel = true; } } - LogPrintf("Importing %s...", CBitcoinAddress(keyid).ToString()); + LogPrintf("Importing %s...", EncodeDestination(keyid)); if (!pwalletMain->AddKey(key)) { fGood = false; continue; @@ -281,26 +281,25 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp) EnsureWalletIsUnlocked(); - string strAddress = params[0].get_str(); - CBitcoinAddress address; - if (!address.SetString(strAddress)) + CTxDestination address = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); if (fWalletUnlockStakingOnly) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Wallet is unlocked for staking only."); LOCK2(cs_main, pwalletMain->cs_wallet); - CKeyID keyID; - if (!address.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&address); + if (!keyID) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to a key"); CKey vchSecret; - if (!pwalletMain->GetKey(keyID, vchSecret)) - throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known"); + if (!pwalletMain->GetKey(*keyID, vchSecret)) + throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + params[0].get_str() + " is not known"); if (params.size() == 2 && params[1].isBool() && params[1].get_bool()) { CKey key_out; - pwalletMain->GetKey(keyID, key_out); + pwalletMain->GetKey(*keyID, key_out); UniValue result(UniValue::VOBJ); @@ -380,7 +379,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp) for (std::vector >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) { const CKeyID &keyid = it->second; std::string strTime = EncodeDumpTime(it->first); - std::string strAddr = CBitcoinAddress(keyid).ToString(); + std::string strAddr = EncodeDestination(keyid); CKey key; if (pwalletMain->GetKey(keyid, key)) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index bea4ebbf3f..75214478b2 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -228,11 +228,11 @@ UniValue getnewaddress(const UniValue& params, bool fHelp) pwalletMain->SetAddressBookName(keyID, strAccount); - return CBitcoinAddress(keyID).ToString(); + return EncodeDestination(keyID); } -CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) EXCLUSIVE_LOCKS_REQUIRED(pwalletMain->cs_wallet) +CTxDestination GetAccountAddress(string strAccount, bool bForceNew=false) EXCLUSIVE_LOCKS_REQUIRED(pwalletMain->cs_wallet) { CWalletDB walletdb(pwalletMain->strWalletFile); @@ -267,7 +267,7 @@ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false) EXCLU walletdb.WriteAccount(strAccount, account); } - return CBitcoinAddress(account.vchPubKey.GetID()); + return CTxDestination(account.vchPubKey.GetID()); } UniValue getaccountaddress(const UniValue& params, bool fHelp) @@ -285,7 +285,7 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - ret = GetAccountAddress(strAccount).ToString(); + ret = EncodeDestination(GetAccountAddress(strAccount)); return ret; } @@ -300,8 +300,8 @@ UniValue setaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); string strAccount; @@ -309,14 +309,14 @@ UniValue setaccount(const UniValue& params, bool fHelp) strAccount = AccountFromValue(params[1]); // Detect when changing the account of an address that is the 'unused current key' of another account: - if (pwalletMain->mapAddressBook.count(address.Get())) + if (pwalletMain->mapAddressBook.count(address)) { - string strOldAccount = pwalletMain->mapAddressBook[address.Get()]; + string strOldAccount = pwalletMain->mapAddressBook[address]; if (address == GetAccountAddress(strOldAccount)) GetAccountAddress(strOldAccount, true); } - pwalletMain->SetAddressBookName(address.Get(), strAccount); + pwalletMain->SetAddressBookName(address, strAccount); return NullUniValue; } @@ -332,13 +332,13 @@ UniValue getaccount(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); string strAccount; - map::iterator mi = pwalletMain->mapAddressBook.find(address.Get()); + map::iterator mi = pwalletMain->mapAddressBook.find(address); if (mi != pwalletMain->mapAddressBook.end() && !mi->second.empty()) { strAccount = mi->second; } @@ -363,10 +363,10 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp) for (auto const& item : pwalletMain->mapAddressBook) { - const CBitcoinAddress& address = item.first; + const CTxDestination& address = item.first; const string& strName = item.second; if (strName == strAccount) - ret.push_back(address.ToString()); + ret.push_back(EncodeDestination(address)); } return ret; } @@ -388,8 +388,8 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(params[0].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); // Amount @@ -408,7 +408,7 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp) if (pwalletMain->IsLocked()) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoneyToDestination(address, nAmount, wtx); if (!strError.empty()) throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -435,11 +435,11 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp) for (auto const& address : grouping) { UniValue addressInfo(UniValue::VARR); - addressInfo.push_back(CBitcoinAddress(address).ToString()); + addressInfo.push_back(EncodeDestination(address)); addressInfo.push_back(ValueFromAmount(balances[address])); { - if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end()) - addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second); + if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) + addressInfo.push_back(pwalletMain->mapAddressBook.find(address)->second); } jsonGrouping.push_back(addressInfo); } @@ -463,16 +463,16 @@ UniValue signmessage(const UniValue& params, bool fHelp) string strAddress = params[0].get_str(); string strMessage = params[1].get_str(); - CBitcoinAddress addr(strAddress); - if (!addr.IsValid()) + CTxDestination addr = DecodeDestination(strAddress); + if (!IsValidDestination(addr)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&addr); + if (!keyID) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); CKey key; - if (!pwalletMain->GetKey(keyID, key)) + if (!pwalletMain->GetKey(*keyID, key)) throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); CDataStream ss(SER_GETHASH, 0); @@ -500,12 +500,12 @@ UniValue verifymessage(const UniValue& params, bool fHelp) LOCK(cs_main); - CBitcoinAddress addr(strAddress); - if (!addr.IsValid()) + CTxDestination addr = DecodeDestination(strAddress); + if (!IsValidDestination(addr)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address"); - CKeyID keyID; - if (!addr.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&addr); + if (!keyID) throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key"); bool fInvalid = false; @@ -522,7 +522,7 @@ UniValue verifymessage(const UniValue& params, bool fHelp) if (!pubkey.RecoverCompact(Hash(ss), vchSig)) return false; - return pubkey.GetID() == keyID; + return pubkey.GetID() == *keyID; } @@ -537,11 +537,11 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // Bitcoin address - CBitcoinAddress address = CBitcoinAddress(params[0].get_str()); + CTxDestination address = DecodeDestination(params[0].get_str()); CScript scriptPubKey; - if (!address.IsValid()) + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); - scriptPubKey.SetDestination(address.Get()); + scriptPubKey.SetDestination(address); if (IsMine(*pwalletMain,scriptPubKey) == ISMINE_NO) return ValueFromAmount(0); @@ -805,8 +805,7 @@ UniValue getbalancedetail(const UniValue& params, bool fHelp) { std::string addressStr; - CBitcoinAddress addr; - addressStr = addr.Set(r.destination) ? addr.ToString() : std::string {}; + addressStr = IsValidDestination(r.destination) ? EncodeDestination(r.destination) : std::string {}; nBalance += r.amount; @@ -825,8 +824,7 @@ UniValue getbalancedetail(const UniValue& params, bool fHelp) { std::string addressStr; - CBitcoinAddress addr; - addressStr = addr.Set(s.destination) ? addr.ToString() : std::string {}; + addressStr = IsValidDestination(s.destination) ? EncodeDestination(s.destination) : std::string {}; nBalance -= s.amount; @@ -954,8 +952,8 @@ UniValue sendfrom(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[1].get_str()); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(params[1].get_str()); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Gridcoin address"); int64_t nAmount = AmountFromValue(params[2]); @@ -981,7 +979,7 @@ UniValue sendfrom(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoneyToDestination(address, nAmount, wtx); if (!strError.empty()) throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -1020,15 +1018,15 @@ UniValue sendmany(const UniValue& params, bool fHelp) if (params.size() > 3 && !params[3].isNull() && !params[3].get_str().empty()) wtx.mapValue["comment"] = params[3].get_str(); - set setAddress; + set setAddress; vector > vecSend; vector addrList = sendTo.getKeys(); int64_t totalAmount = 0; for (auto const& name_: addrList) { - CBitcoinAddress address(name_); - if (!address.IsValid()) + CTxDestination address = DecodeDestination(name_); + if (!IsValidDestination(address)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Gridcoin address: ")+name_); if (setAddress.count(address)) @@ -1036,7 +1034,7 @@ UniValue sendmany(const UniValue& params, bool fHelp) setAddress.insert(address); CScript scriptPubKey; - scriptPubKey.SetDestination(address.Get()); + scriptPubKey.SetDestination(address); int64_t nAmount = AmountFromValue(sendTo[name_]); totalAmount += nAmount; @@ -1136,15 +1134,15 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp) const std::string& ks = keys[i].get_str(); // Case 1: Bitcoin address and we have full public key: - CBitcoinAddress address(ks); - if (address.IsValid()) + CTxDestination address = DecodeDestination(ks); + if (IsValidDestination(address)) { - CKeyID keyID; - if (!address.GetKeyID(keyID)) + CKeyID* keyID = std::get_if(&address); + if (!keyID) throw runtime_error( strprintf("%s does not refer to a key",ks)); CPubKey vchPubKey; - if (!pwalletMain->GetPubKey(keyID, vchPubKey)) + if (!pwalletMain->GetPubKey(*keyID, vchPubKey)) throw runtime_error( strprintf("no full public key for address %s",ks)); if (!vchPubKey.IsValid()) @@ -1174,7 +1172,7 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp) throw runtime_error("AddCScript() failed"); pwalletMain->SetAddressBookName(innerID, strAccount); - return CBitcoinAddress(innerID).ToString(); + return EncodeDestination(innerID); } UniValue addredeemscript(const UniValue& params, bool fHelp) @@ -1202,7 +1200,7 @@ UniValue addredeemscript(const UniValue& params, bool fHelp) throw runtime_error("AddCScript() failed"); pwalletMain->SetAddressBookName(innerID, strAccount); - return CBitcoinAddress(innerID).ToString(); + return EncodeDestination(innerID); } struct tallyitem @@ -1238,7 +1236,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) EXCLUSIVE_LOCKS_ fIncludeEmpty = params[1].get_bool(); // Tally - map mapTally; + map mapTally; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) { const CWalletTx& wtx = it->second; @@ -1276,9 +1274,9 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) EXCLUSIVE_LOCKS_ for (auto const& item : pwalletMain->mapAddressBook) { - const CBitcoinAddress& address = item.first; + const CTxDestination& address = item.first; const string& strAccount = item.second; - map::iterator it = mapTally.find(address); + map::iterator it = mapTally.find(address); if (it == mapTally.end() && !fIncludeEmpty) continue; @@ -1306,7 +1304,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts) EXCLUSIVE_LOCKS_ if (fIsWatchonly) { obj.pushKV("involvesWatchonly", true); } - obj.pushKV("address", address.ToString()); + obj.pushKV("address", EncodeDestination(address)); obj.pushKV("account", strAccount); obj.pushKV("amount", ValueFromAmount(nAmount)); obj.pushKV("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf)); @@ -1419,8 +1417,7 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp) std::string addressStr; - CBitcoinAddress addr; - addressStr = addr.Set(s.destination) ? addr.ToString() : std::string {}; + addressStr = IsValidDestination(s.destination) ? EncodeDestination(s.destination) : std::string {}; entry.pushKV("address", addressStr); @@ -1480,8 +1477,7 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp) std::string addressStr; - CBitcoinAddress addr; - addressStr = addr.Set(r.destination) ? addr.ToString() : std::string {}; + addressStr = IsValidDestination(r.destination) ? EncodeDestination(r.destination) : std::string {}; entry.pushKV("address", addressStr); @@ -2438,7 +2434,7 @@ class DescribeAddressVisitor obj.pushKV("hex", HexStr(subscript)); UniValue a(UniValue::VARR); for (auto const& addr : addresses) - a.push_back(CBitcoinAddress(addr).ToString()); + a.push_back(EncodeDestination(addr)); obj.pushKV("addresses", a); if (whichType == TX_MULTISIG) obj.pushKV("sigsrequired", nRequired); @@ -2456,15 +2452,14 @@ UniValue validateaddress(const UniValue& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); + CTxDestination dest = DecodeDestination(params[0].get_str()); + bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.pushKV("isvalid", isValid); if (isValid) { - CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); + string currentAddress = EncodeDestination(dest); ret.pushKV("address", currentAddress); bool fMine = IsMine(*pwalletMain, dest) != ISMINE_NO; ret.pushKV("ismine", fMine); @@ -2474,11 +2469,11 @@ UniValue validateaddress(const UniValue& params, bool fHelp) } if (pwalletMain->mapAddressBook.count(dest)) ret.pushKV("account", pwalletMain->mapAddressBook[dest]); - CKeyID keyID; - if (pwalletMain && address.GetKeyID(keyID) && pwalletMain->mapKeyMetadata.count(keyID) && !pwalletMain->mapKeyMetadata[keyID].hdKeypath.empty()) + CKeyID* keyID = std::get_if(&dest); + if (pwalletMain && keyID && pwalletMain->mapKeyMetadata.count(*keyID) && !pwalletMain->mapKeyMetadata[*keyID].hdKeypath.empty()) { - ret.pushKV("hdkeypath", pwalletMain->mapKeyMetadata[keyID].hdKeypath); - ret.pushKV("hdmasterkeyid", pwalletMain->mapKeyMetadata[keyID].hdMasterKeyID.GetHex()); + ret.pushKV("hdkeypath", pwalletMain->mapKeyMetadata[*keyID].hdKeypath); + ret.pushKV("hdmasterkeyid", pwalletMain->mapKeyMetadata[*keyID].hdMasterKeyID.GetHex()); } } return ret; @@ -2502,15 +2497,14 @@ UniValue validatepubkey(const UniValue& params, bool fHelp) bool isCompressed = pubKey.IsCompressed(); CKeyID keyID = pubKey.GetID(); - CBitcoinAddress address; - address.Set(keyID); + CTxDestination address(keyID); UniValue ret(UniValue::VOBJ); ret.pushKV("isvalid", isValid); if (isValid) { - CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); + CTxDestination dest = address; + string currentAddress = EncodeDestination(address); ret.pushKV("address", currentAddress); bool fMine = IsMine(*pwalletMain, dest) != ISMINE_NO; ret.pushKV("ismine", fMine); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 827e0da8b2..504532c160 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -55,12 +55,9 @@ struct CompareValueOnly // Class: CWallet // ----------------------------------------------------------------------------- -const CBitcoinAddress CWallet::MasterAddress(int height) +const CTxDestination CWallet::MasterAddress(int height) { - CBitcoinAddress master_address; - master_address.Set(CPubKey(Params().MasterKey(height)).GetID()); - - return master_address; + return CPubKey(Params().MasterKey(height)).GetID(); } CKey CWallet::MasterPrivateKey(int height) const @@ -208,7 +205,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) * these. Do not add them to the wallet and warn. */ if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { - std::string strAddr = CBitcoinAddress(redeemScript.GetID()).ToString(); + std::string strAddr = EncodeDestination(redeemScript.GetID()); LogPrintf("%s: Warning: This wallet contains a redeemScript of size %" PRIszu " which exceeds maximum size %i thus can never be redeemed. Do not use address %s.", __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr); return true; @@ -2136,7 +2133,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, // coin control: send change to custom address if (coinControl && !std::get_if(&coinControl->destChange)) { LogPrintf("INFO: %s: Setting custom change address: %s", __func__, - CBitcoinAddress(coinControl->destChange).ToString()); + EncodeDestination(coinControl->destChange)); scriptChange.SetDestination(coinControl->destChange); } else { // no coin control @@ -2155,7 +2152,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, } LogPrintf("INFO: %s: Sending change to input address %s", __func__, - CBitcoinAddress(change_address).ToString()); + EncodeDestination(change_address)); } } else { // send change to newly generated address // Note: We use a new key here to keep it from being obvious which side is the change. @@ -2469,7 +2466,7 @@ bool CWallet::SetAddressBookName(const CTxDestination& address, const string& st (fUpdated ? CT_UPDATED : CT_NEW) ); if (!fFileBacked) return false; - return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName); + return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName); } bool CWallet::DelAddressBookName(const CTxDestination& address) @@ -2484,7 +2481,7 @@ bool CWallet::DelAddressBookName(const CTxDestination& address) if (!fFileBacked) return false; - return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString()); + return CWalletDB(strWalletFile).EraseName(EncodeDestination(address)); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 4561c802d7..5bf9f9dcef 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -135,7 +135,7 @@ class CWallet : public CCryptoKeyStore //! //! \return Address as calculated from the master public key. //! - static const CBitcoinAddress MasterAddress(int height); + static const CTxDestination MasterAddress(int height); //! //! \brief Get the imported master private key used to sign administrative diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 305b412b4e..a1af5ad9de 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -227,7 +227,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, { string strAddress; ssKey >> strAddress; - ssValue >> pwallet->mapAddressBook[CBitcoinAddress(strAddress).Get()]; + ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)]; } else if (strType == "tx") { diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 3e35ccf163..dd48d6129b 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -7,7 +7,7 @@ #define BITCOIN_WALLET_WALLETDB_H #include "wallet/db.h" -#include "base58.h" +#include class CKeyPool; class CAccount; From 972a95d94e7dd94c4f2b8fb5817a6ee8e14998ad Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Wed, 22 Mar 2023 10:46:13 +0300 Subject: [PATCH 5/7] test: add key IO tests --- src/Makefile.test.include | 5 +- src/test/data/CMakeLists.txt | 4 +- ..._keys_invalid.json => key_io_invalid.json} | 0 ...se58_keys_valid.json => key_io_valid.json} | 0 src/test/key_io_tests.cpp | 149 ++++++++++++++++++ 5 files changed, 154 insertions(+), 4 deletions(-) rename src/test/data/{base58_keys_invalid.json => key_io_invalid.json} (100%) rename src/test/data/{base58_keys_valid.json => key_io_valid.json} (100%) create mode 100644 src/test/key_io_tests.cpp diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 53d41ea1a5..b6a8524f23 100755 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -8,9 +8,9 @@ TEST_SRCDIR = test TEST_BINARY=test/test_gridcoin$(EXEEXT) JSON_TEST_FILES = \ - test/data/base58_keys_valid.json \ test/data/base58_encode_decode.json \ - test/data/base58_keys_invalid.json \ + test/data/key_io_invalid.json \ + test/data/key_io_valid.json \ test/data/script_valid.json \ test/data/script_invalid.json \ test/data/tx_invalid.json \ @@ -59,6 +59,7 @@ GRIDCOIN_TESTS =\ test/gridcoin/sidestake_tests.cpp \ test/gridcoin/superblock_tests.cpp \ test/key_tests.cpp \ + test/key_io_tests.cpp \ test/merkle_tests.cpp \ test/mruset_tests.cpp \ test/multisig_tests.cpp \ diff --git a/src/test/data/CMakeLists.txt b/src/test/data/CMakeLists.txt index 784efde82a..9034d69b56 100644 --- a/src/test/data/CMakeLists.txt +++ b/src/test/data/CMakeLists.txt @@ -1,7 +1,7 @@ set(JSON_TEST_FILES - base58_keys_valid.json base58_encode_decode.json - base58_keys_invalid.json + key_io_invalid.json + key_io_valid.json script_valid.json script_invalid.json tx_invalid.json diff --git a/src/test/data/base58_keys_invalid.json b/src/test/data/key_io_invalid.json similarity index 100% rename from src/test/data/base58_keys_invalid.json rename to 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 similarity index 100% rename from src/test/data/base58_keys_valid.json rename to 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..5019c4eac9 --- /dev/null +++ b/src/test/key_io_tests.cpp @@ -0,0 +1,149 @@ +// Copyright (c) 2011-2023 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or https://opensource.org/licenses/mit-license.php. + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +UniValue read_json(const std::string& jsondata); + +BOOST_AUTO_TEST_SUITE(key_io_tests) + +// 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++) { + const 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(); + const std::vector 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(Span{privkey} == MakeByteSpan(exp_payload), "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; + script.SetDestination(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.SetDestination(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++) { + const 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 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()); + BOOST_CHECK(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++) { + const 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 (const auto& chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET }) { + 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() From 7f429dd1b515f8e759317d0497d41009b8927ee3 Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Wed, 22 Mar 2023 12:17:29 +0300 Subject: [PATCH 6/7] test: fix key_io_valid tests The second element of items of key_io_valid JSON array was pkhash or scripthash. This commit changes them to be proper serialized scripts as thats what the key_io_valid expects. isTestNet flags are also changed to a chain string. --- src/test/data/key_io_valid.json | 146 ++++++++++++++++---------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/test/data/key_io_valid.json b/src/test/data/key_io_valid.json index 9855ceeb0f..733c0fc61b 100644 --- a/src/test/data/key_io_valid.json +++ b/src/test/data/key_io_valid.json @@ -1,38 +1,38 @@ [ [ "SE8hQCjzRxWye3p7D4hdYeeYaNuGUMWKaV", - "B174A85C22C917563A4E8425082A9B2302691814", + "76a914b174a85c22c917563a4e8425082a9b230269181488ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bE9beycFciNiykheLUmSPn5txcsvAMvA8v", - "0F91EFD3FE4DC089C6E2F4E259705F3A37716733", + "a9140f91efd3fe4dc089c6e2f4e259705f3a3771673387", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mtocGjbyzLqgMjqnjsTXJB29DpF4Xycg8Q", - "91BFFE0E06D0B15F74896B1F3967307EF7C73B73", + "76a91491bffe0e06d0b15f74896b1f3967307ef7c73b7388ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ - "2Mua2yKphS8HcpmT15YTQ7crCey6sXohv9y", - "197EF56DD6D0BDEC3D9D8B09297FF02293400FEF", + "2Mua2yKphS8HcpmT15YTQ7crCey6sXohv9y", + "a914197ef56dd6d0bdec3d9d8b09297ff02293400fef87", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -41,7 +41,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -50,7 +50,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -59,7 +59,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -68,43 +68,43 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ "RxN1HEdC2HqHEAk469wN39mDXknG4Dp2ZX", - "0476FA5D10A4D4FEB6FE00146AC6E2AB503BB9B3", + "76a9140476fa5d10a4d4feb6fe00146ac6e2ab503bb9b388ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bJkYuAPAqyxJDAfFoSP8t4Sg5g7vfFEG5G", - "420EB2D228DBE7611D797BABFD720A198DCE488F", + "a914420eb2d228dbe7611d797babfd720a198dce488f87", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mmwJ4FJUQ5kez7F1hm7S7AY8vHuqg5fChS", - "466B3BF6CC306568A8E754A3455ECF0D216B8782", + "76a914466b3bf6cc306568a8e754a3455ecf0d216b878288ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ "2N5B1qtneGpC9cchdKw9nsGSG74yRv2desu", - "82D5B52C470B024BD9CBC6A03FA401C1302FC5A5", + "a91482d5b52c470b024bd9cbc6a03fa401c1302fc5a587", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -113,7 +113,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -122,7 +122,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -131,7 +131,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -140,43 +140,43 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ "S5GgFVTsorwKffDSsgZAFRHcV3sWNngz8z", - "503DE4A5E4DCCF882CC81A401653F9864E34B3EF", + "76a914503de4a5e4dccf882cc81a401653f9864e34b3ef88ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bbpiXYwBzX3JFdVvTmiKGwZb4tbU5mgkLU", - "FD5289882CCF46545266F122243B352A64AE9729", + "a914fd5289882ccf46545266f122243b352a64ae972987", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mwJ3qHbM193N6r2cJt3uNfCnGbun3dZiac", - "AD113A74A31FB178B87AA9C8338A15D9AE064821", + "76a914ad113a74a31fb178b87aa9c8338a15d9ae06482188ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ "2N7wZC6QBYmp24rQtyR17evyhuA3wj2LNow", - "A1326E08A14B3202D77B53635CB3736355103697", + "a914a1326e08a14b3202d77b53635cb373635510369787", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -185,7 +185,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -194,7 +194,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -203,7 +203,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -212,43 +212,43 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ "SGeyeAC18vCZdW3wrBr3fgtbzyax9zuoRT", - "CD1EF1EFC1F9E1720693B8AFBCE39A829C04F54E", + "76a914cd1ef1efc1f9e1720693b8afbce39a829c04f54e88ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bGDhyPqUcykcEXHP2h8umYWvyF6zhUkTH7", - "26492038BEA91C03B677BFCE591C9B84A033AEE3", + "a91426492038bea91c03b677bfce591c9b84a033aee387", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mfprNrD49kcdxQcmA4o2qLosLmg43ocm8Q", - "03628C3B3C51F1634E260C948E376E6479122489", + "76a91403628c3b3c51f1634e260c948e376e647912248988ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ "2N45K8B7KHgmZ8CufhvFX15jaidmYaTV7WK", - "76C982E8E14D3B61B55DA51DA0ED2E1C3CF634E0", + "a91476c982e8e14d3b61b55da51da0ed2e1c3cf634e087", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -257,7 +257,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -266,7 +266,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -275,7 +275,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -284,43 +284,43 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ "S4tBgEy9mYTex8g5mDVvBwnMo1uEKm8D8N", - "4BFCE3E6060BCC52B14158543478F898D89270D0", + "76a9144bfce3e6060bcc52b14158543478f898d89270d088ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bTp4nL6vhz5nvKJTt8gePcqXjkv1adUQKQ", - "A57205DA5628AF7BC2FC0796976D32E83C0A2168", + "a914a57205da5628af7bc2fc0796976d32e83c0a216887", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mrZd1vneUmE4YkPg4P6wWWDgvuev45qpAh", - "792A89FCFADFDFB5E0571A8A06B9B51F6D447483", + "76a914792a89fcfadfdfb5e0571a8a06b9b51f6d44748388ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ "2N1UMtU75Ua1cvDzAMCuhM1bQSGrU9j9NcG", - "5A3D02150EAF6F3FC5FAEE1964996525526D28D8", + "a9145a3d02150eaf6f3fc5faee1964996525526d28d887", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -329,7 +329,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -338,7 +338,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -347,7 +347,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -356,43 +356,43 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ "S7vE1RM32kdRyoA2x4nRnba86Z25JVaL6m", - "6D480B886118FB6E6D3FFC35B62F2C5BFD98DD2B", + "76a9146d480b886118fb6e6d3ffc35b62f2c5bfd98dd2b88ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "bDtPuxX6bY4j6hxF4w2gbUz1LPvS36MhQ9", - "0CB1E55B1E593DEEE37D75895576BD3CAB52430B2", + "a9140cb1e55b1e593deee37d75895576bd3cab52430b87", { "addrType": "script", "isPrivkey": false, - "isTestnet": false + "chain": "main" } ], [ "mjFCEneHB5n1pzE5ZinZV6uiqrcxHJRpUG", - "28E57CC2E23A4A20B22D0201A20C2A736E7C296B", + "76a91428e57cc2e23a4a20b22d0201a20c2a736e7c296b88ac", { "addrType": "pubkey", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ "2MybDkUBALd9Ga8X4DqWfzhbFdNzvUaQEYE", - "4598E00770AC4D4521DF3F847D0573C75071E47A", + "a9144598e00770ac4d4521df3f847d0573c75071e47a87", { "addrType": "script", "isPrivkey": false, - "isTestnet": true + "chain": "test" } ], [ @@ -401,7 +401,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -410,7 +410,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": false + "chain": "main" } ], [ @@ -419,7 +419,7 @@ { "isCompressed": false, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ], [ @@ -428,7 +428,7 @@ { "isCompressed": true, "isPrivkey": true, - "isTestnet": true + "chain": "test" } ] ] From cff5c14cc384d89c1439292d36bc8183db71e083 Mon Sep 17 00:00:00 2001 From: div72 <60045611+div72@users.noreply.github.com> Date: Wed, 22 Mar 2023 13:17:20 +0300 Subject: [PATCH 7/7] test: set chain to mainnet after testing in key_io_tests Rationale: Sadly some other tests depends on the chain being mainnet without actually setting it to mainnet themselves. Which leads to weird test suite failures. --- src/test/key_io_tests.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/key_io_tests.cpp b/src/test/key_io_tests.cpp index 5019c4eac9..8300aa04d2 100644 --- a/src/test/key_io_tests.cpp +++ b/src/test/key_io_tests.cpp @@ -78,6 +78,8 @@ BOOST_AUTO_TEST_CASE(key_io_valid_parse) BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest); } } + + SelectParams(CBaseChainParams::MAIN); } // Goal: check that generated keys match test vectors @@ -144,6 +146,8 @@ BOOST_AUTO_TEST_CASE(key_io_invalid) BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey in mainnet:" + strTest); } } + + SelectParams(CBaseChainParams::MAIN); } BOOST_AUTO_TEST_SUITE_END()