mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-06-18 21:01:22 +02:00
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille) 119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille) ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille) 32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille) Pull request description: This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting. This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic. Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
This commit is contained in:
commit
b225010a80
@ -105,6 +105,7 @@ BITCOIN_CORE_H = \
|
|||||||
indirectmap.h \
|
indirectmap.h \
|
||||||
init.h \
|
init.h \
|
||||||
key.h \
|
key.h \
|
||||||
|
key_io.h \
|
||||||
keystore.h \
|
keystore.h \
|
||||||
dbwrapper.h \
|
dbwrapper.h \
|
||||||
limitedmap.h \
|
limitedmap.h \
|
||||||
@ -327,6 +328,7 @@ libbitcoin_common_a_SOURCES = \
|
|||||||
core_read.cpp \
|
core_read.cpp \
|
||||||
core_write.cpp \
|
core_write.cpp \
|
||||||
key.cpp \
|
key.cpp \
|
||||||
|
key_io.cpp \
|
||||||
keystore.cpp \
|
keystore.cpp \
|
||||||
netaddress.cpp \
|
netaddress.cpp \
|
||||||
netbase.cpp \
|
netbase.cpp \
|
||||||
|
@ -9,13 +9,13 @@ TEST_SRCDIR = test
|
|||||||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||||
|
|
||||||
JSON_TEST_FILES = \
|
JSON_TEST_FILES = \
|
||||||
test/data/script_tests.json \
|
|
||||||
test/data/base58_keys_valid.json \
|
|
||||||
test/data/base58_encode_decode.json \
|
test/data/base58_encode_decode.json \
|
||||||
test/data/base58_keys_invalid.json \
|
test/data/key_io_valid.json \
|
||||||
|
test/data/key_io_invalid.json \
|
||||||
|
test/data/script_tests.json \
|
||||||
|
test/data/sighash.json \
|
||||||
test/data/tx_invalid.json \
|
test/data/tx_invalid.json \
|
||||||
test/data/tx_valid.json \
|
test/data/tx_valid.json
|
||||||
test/data/sighash.json
|
|
||||||
|
|
||||||
RAW_TEST_FILES =
|
RAW_TEST_FILES =
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ BITCOIN_TESTS =\
|
|||||||
test/DoS_tests.cpp \
|
test/DoS_tests.cpp \
|
||||||
test/getarg_tests.cpp \
|
test/getarg_tests.cpp \
|
||||||
test/hash_tests.cpp \
|
test/hash_tests.cpp \
|
||||||
|
test/key_io_tests.cpp \
|
||||||
test/key_tests.cpp \
|
test/key_tests.cpp \
|
||||||
test/limitedmap_tests.cpp \
|
test/limitedmap_tests.cpp \
|
||||||
test/dbwrapper_tests.cpp \
|
test/dbwrapper_tests.cpp \
|
||||||
|
232
src/base58.cpp
232
src/base58.cpp
@ -4,20 +4,12 @@
|
|||||||
|
|
||||||
#include <base58.h>
|
#include <base58.h>
|
||||||
|
|
||||||
#include <bech32.h>
|
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <script/script.h>
|
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <utilstrencodings.h>
|
|
||||||
|
|
||||||
#include <boost/variant/apply_visitor.hpp>
|
|
||||||
#include <boost/variant/static_visitor.hpp>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
/** All alphanumeric characters except for "0", "I", "O", and "l" */
|
/** All alphanumeric characters except for "0", "I", "O", and "l" */
|
||||||
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
@ -151,227 +143,3 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
|
|||||||
{
|
{
|
||||||
return DecodeBase58Check(str.c_str(), vchRet);
|
return DecodeBase58Check(str.c_str(), vchRet);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBase58Data::CBase58Data()
|
|
||||||
{
|
|
||||||
vchVersion.clear();
|
|
||||||
vchData.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
|
|
||||||
{
|
|
||||||
vchVersion = vchVersionIn;
|
|
||||||
vchData.resize(nSize);
|
|
||||||
if (!vchData.empty())
|
|
||||||
memcpy(vchData.data(), pdata, nSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
|
|
||||||
{
|
|
||||||
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> vchTemp;
|
|
||||||
bool rc58 = DecodeBase58Check(psz, vchTemp);
|
|
||||||
if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
|
|
||||||
vchData.clear();
|
|
||||||
vchVersion.clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
|
|
||||||
vchData.resize(vchTemp.size() - nVersionBytes);
|
|
||||||
if (!vchData.empty())
|
|
||||||
memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
|
|
||||||
memory_cleanse(vchTemp.data(), vchTemp.size());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBase58Data::SetString(const std::string& str)
|
|
||||||
{
|
|
||||||
return SetString(str.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CBase58Data::ToString() const
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> vch = vchVersion;
|
|
||||||
vch.insert(vch.end(), vchData.begin(), vchData.end());
|
|
||||||
return EncodeBase58Check(vch);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CBase58Data::CompareTo(const CBase58Data& b58) const
|
|
||||||
{
|
|
||||||
if (vchVersion < b58.vchVersion)
|
|
||||||
return -1;
|
|
||||||
if (vchVersion > b58.vchVersion)
|
|
||||||
return 1;
|
|
||||||
if (vchData < b58.vchData)
|
|
||||||
return -1;
|
|
||||||
if (vchData > b58.vchData)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
class DestinationEncoder : public boost::static_visitor<std::string>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const CChainParams& m_params;
|
|
||||||
|
|
||||||
public:
|
|
||||||
DestinationEncoder(const CChainParams& params) : m_params(params) {}
|
|
||||||
|
|
||||||
std::string operator()(const CKeyID& id) const
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> 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<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
|
||||||
data.insert(data.end(), id.begin(), id.end());
|
|
||||||
return EncodeBase58Check(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator()(const WitnessV0KeyHash& id) const
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> data = {0};
|
|
||||||
ConvertBits<8, 5, true>(data, id.begin(), id.end());
|
|
||||||
return bech32::Encode(m_params.Bech32HRP(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator()(const WitnessV0ScriptHash& id) const
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> data = {0};
|
|
||||||
ConvertBits<8, 5, true>(data, id.begin(), id.end());
|
|
||||||
return bech32::Encode(m_params.Bech32HRP(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator()(const WitnessUnknown& id) const
|
|
||||||
{
|
|
||||||
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
std::vector<unsigned char> data = {(unsigned char)id.version};
|
|
||||||
ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
|
|
||||||
return bech32::Encode(m_params.Bech32HRP(), data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string operator()(const CNoDestination& no) const { return {}; }
|
|
||||||
};
|
|
||||||
|
|
||||||
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> data;
|
|
||||||
uint160 hash;
|
|
||||||
if (DecodeBase58Check(str, data)) {
|
|
||||||
// base58-encoded Bitcoin addresses.
|
|
||||||
// Public-key-hash-addresses have version 0 (or 111 testnet).
|
|
||||||
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
|
||||||
const std::vector<unsigned char>& 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 5 (or 196 testnet).
|
|
||||||
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
|
||||||
const std::vector<unsigned char>& 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.clear();
|
|
||||||
auto bech = bech32::Decode(str);
|
|
||||||
if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
|
|
||||||
// Bech32 decoding
|
|
||||||
int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
|
|
||||||
// The rest of the symbols are converted witness program bytes.
|
|
||||||
if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
|
|
||||||
if (version == 0) {
|
|
||||||
{
|
|
||||||
WitnessV0KeyHash keyid;
|
|
||||||
if (data.size() == keyid.size()) {
|
|
||||||
std::copy(data.begin(), data.end(), keyid.begin());
|
|
||||||
return keyid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
WitnessV0ScriptHash scriptid;
|
|
||||||
if (data.size() == scriptid.size()) {
|
|
||||||
std::copy(data.begin(), data.end(), scriptid.begin());
|
|
||||||
return scriptid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CNoDestination();
|
|
||||||
}
|
|
||||||
if (version > 16 || data.size() < 2 || data.size() > 40) {
|
|
||||||
return CNoDestination();
|
|
||||||
}
|
|
||||||
WitnessUnknown unk;
|
|
||||||
unk.version = version;
|
|
||||||
std::copy(data.begin(), data.end(), unk.program);
|
|
||||||
unk.length = data.size();
|
|
||||||
return unk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return CNoDestination();
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void CBitcoinSecret::SetKey(const CKey& vchSecret)
|
|
||||||
{
|
|
||||||
assert(vchSecret.IsValid());
|
|
||||||
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
|
|
||||||
if (vchSecret.IsCompressed())
|
|
||||||
vchData.push_back(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
CKey CBitcoinSecret::GetKey()
|
|
||||||
{
|
|
||||||
CKey ret;
|
|
||||||
assert(vchData.size() >= 32);
|
|
||||||
ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBitcoinSecret::IsValid() const
|
|
||||||
{
|
|
||||||
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
|
|
||||||
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
|
|
||||||
return fExpectedFormat && fCorrectVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBitcoinSecret::SetString(const char* pszSecret)
|
|
||||||
{
|
|
||||||
return CBase58Data::SetString(pszSecret) && IsValid();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBitcoinSecret::SetString(const std::string& strSecret)
|
|
||||||
{
|
|
||||||
return SetString(strSecret.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string EncodeDestination(const CTxDestination& dest)
|
|
||||||
{
|
|
||||||
return boost::apply_visitor(DestinationEncoder(Params()), dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
CTxDestination DecodeDestination(const std::string& str)
|
|
||||||
{
|
|
||||||
return DecodeDestination(str, Params());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
|
|
||||||
{
|
|
||||||
return IsValidDestination(DecodeDestination(str, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidDestinationString(const std::string& str)
|
|
||||||
{
|
|
||||||
return IsValidDestinationString(str, Params());
|
|
||||||
}
|
|
||||||
|
93
src/base58.h
93
src/base58.h
@ -14,12 +14,6 @@
|
|||||||
#ifndef BITCOIN_BASE58_H
|
#ifndef BITCOIN_BASE58_H
|
||||||
#define BITCOIN_BASE58_H
|
#define BITCOIN_BASE58_H
|
||||||
|
|
||||||
#include <chainparams.h>
|
|
||||||
#include <key.h>
|
|
||||||
#include <pubkey.h>
|
|
||||||
#include <script/standard.h>
|
|
||||||
#include <support/allocators/zeroafterfree.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -56,95 +50,12 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
|
|||||||
* Decode a base58-encoded string (psz) that includes a checksum into a byte
|
* Decode a base58-encoded string (psz) that includes a checksum into a byte
|
||||||
* vector (vchRet), return true if decoding is successful
|
* vector (vchRet), return true if decoding is successful
|
||||||
*/
|
*/
|
||||||
inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
|
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a base58-encoded string (str) that includes a checksum into a byte
|
* Decode a base58-encoded string (str) that includes a checksum into a byte
|
||||||
* vector (vchRet), return true if decoding is successful
|
* vector (vchRet), return true if decoding is successful
|
||||||
*/
|
*/
|
||||||
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
|
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for all base58-encoded data
|
|
||||||
*/
|
|
||||||
class CBase58Data
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
//! the version byte(s)
|
|
||||||
std::vector<unsigned char> vchVersion;
|
|
||||||
|
|
||||||
//! the actually encoded data
|
|
||||||
typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
|
|
||||||
vector_uchar vchData;
|
|
||||||
|
|
||||||
CBase58Data();
|
|
||||||
void SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize);
|
|
||||||
void SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend);
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool SetString(const char* psz, unsigned int nVersionBytes = 1);
|
|
||||||
bool SetString(const std::string& str);
|
|
||||||
std::string ToString() const;
|
|
||||||
int CompareTo(const CBase58Data& b58) const;
|
|
||||||
|
|
||||||
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; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A base58-encoded secret key
|
|
||||||
*/
|
|
||||||
class CBitcoinSecret : public CBase58Data
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void SetKey(const CKey& vchSecret);
|
|
||||||
CKey GetKey();
|
|
||||||
bool IsValid() const;
|
|
||||||
bool SetString(const char* pszSecret);
|
|
||||||
bool SetString(const std::string& strSecret);
|
|
||||||
|
|
||||||
CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
|
|
||||||
CBitcoinSecret() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void SetKey(const K &key) {
|
|
||||||
unsigned char vch[Size];
|
|
||||||
key.Encode(vch);
|
|
||||||
SetData(Params().Base58Prefix(Type), vch, vch+Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
K GetKey() {
|
|
||||||
K ret;
|
|
||||||
if (vchData.size() == Size) {
|
|
||||||
// If base58 encoded data does not hold an ext key, return a !IsValid() key
|
|
||||||
ret.Decode(vchData.data());
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBitcoinExtKeyBase(const K &key) {
|
|
||||||
SetKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
CBitcoinExtKeyBase(const std::string& strBase58c) {
|
|
||||||
SetString(strBase58c.c_str(), Params().Base58Prefix(Type).size());
|
|
||||||
}
|
|
||||||
|
|
||||||
CBitcoinExtKeyBase() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
|
|
||||||
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
|
|
||||||
|
|
||||||
std::string EncodeDestination(const CTxDestination& dest);
|
|
||||||
CTxDestination DecodeDestination(const std::string& str);
|
|
||||||
bool IsValidDestinationString(const std::string& str);
|
|
||||||
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
|
|
||||||
|
|
||||||
#endif // BITCOIN_BASE58_H
|
#endif // BITCOIN_BASE58_H
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
#include <config/bitcoin-config.h>
|
#include <config/bitcoin-config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <coins.h>
|
#include <coins.h>
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <policy/rbf.h>
|
#include <policy/rbf.h>
|
||||||
@ -563,12 +563,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
|
|||||||
for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
|
for (unsigned int kidx = 0; kidx < keysObj.size(); kidx++) {
|
||||||
if (!keysObj[kidx].isStr())
|
if (!keysObj[kidx].isStr())
|
||||||
throw std::runtime_error("privatekey not a std::string");
|
throw std::runtime_error("privatekey not a std::string");
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(keysObj[kidx].getValStr());
|
||||||
bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
|
if (!key.IsValid()) {
|
||||||
if (!fGood)
|
|
||||||
throw std::runtime_error("privatekey not valid");
|
throw std::runtime_error("privatekey not valid");
|
||||||
|
}
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
tempKeystore.AddKey(key);
|
tempKeystore.AddKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/standard.h>
|
#include <script/standard.h>
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#include <httprpc.h>
|
#include <httprpc.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <httpserver.h>
|
#include <httpserver.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
|
223
src/key_io.cpp
Normal file
223
src/key_io.cpp
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
// Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <key_io.h>
|
||||||
|
|
||||||
|
#include <base58.h>
|
||||||
|
#include <bech32.h>
|
||||||
|
#include <script/script.h>
|
||||||
|
#include <utilstrencodings.h>
|
||||||
|
|
||||||
|
#include <boost/variant/apply_visitor.hpp>
|
||||||
|
#include <boost/variant/static_visitor.hpp>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class DestinationEncoder : public boost::static_visitor<std::string>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const CChainParams& m_params;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DestinationEncoder(const CChainParams& params) : m_params(params) {}
|
||||||
|
|
||||||
|
std::string operator()(const CKeyID& id) const
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> 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<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
|
||||||
|
data.insert(data.end(), id.begin(), id.end());
|
||||||
|
return EncodeBase58Check(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const WitnessV0KeyHash& id) const
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data = {0};
|
||||||
|
ConvertBits<8, 5, true>(data, id.begin(), id.end());
|
||||||
|
return bech32::Encode(m_params.Bech32HRP(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const WitnessV0ScriptHash& id) const
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data = {0};
|
||||||
|
ConvertBits<8, 5, true>(data, id.begin(), id.end());
|
||||||
|
return bech32::Encode(m_params.Bech32HRP(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const WitnessUnknown& id) const
|
||||||
|
{
|
||||||
|
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::vector<unsigned char> data = {(unsigned char)id.version};
|
||||||
|
ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
|
||||||
|
return bech32::Encode(m_params.Bech32HRP(), data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string operator()(const CNoDestination& no) const { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
uint160 hash;
|
||||||
|
if (DecodeBase58Check(str, data)) {
|
||||||
|
// base58-encoded Bitcoin addresses.
|
||||||
|
// Public-key-hash-addresses have version 0 (or 111 testnet).
|
||||||
|
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
|
||||||
|
const std::vector<unsigned char>& 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 5 (or 196 testnet).
|
||||||
|
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
|
||||||
|
const std::vector<unsigned char>& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.clear();
|
||||||
|
auto bech = bech32::Decode(str);
|
||||||
|
if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
|
||||||
|
// Bech32 decoding
|
||||||
|
int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
|
||||||
|
// The rest of the symbols are converted witness program bytes.
|
||||||
|
if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
|
||||||
|
if (version == 0) {
|
||||||
|
{
|
||||||
|
WitnessV0KeyHash keyid;
|
||||||
|
if (data.size() == keyid.size()) {
|
||||||
|
std::copy(data.begin(), data.end(), keyid.begin());
|
||||||
|
return keyid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
WitnessV0ScriptHash scriptid;
|
||||||
|
if (data.size() == scriptid.size()) {
|
||||||
|
std::copy(data.begin(), data.end(), scriptid.begin());
|
||||||
|
return scriptid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CNoDestination();
|
||||||
|
}
|
||||||
|
if (version > 16 || data.size() < 2 || data.size() > 40) {
|
||||||
|
return CNoDestination();
|
||||||
|
}
|
||||||
|
WitnessUnknown unk;
|
||||||
|
unk.version = version;
|
||||||
|
std::copy(data.begin(), data.end(), unk.program);
|
||||||
|
unk.length = data.size();
|
||||||
|
return unk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CNoDestination();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CKey DecodeSecret(const std::string& str)
|
||||||
|
{
|
||||||
|
CKey key;
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
if (DecodeBase58Check(str, data)) {
|
||||||
|
const std::vector<unsigned char>& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory_cleanse(data.data(), data.size());
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncodeSecret(const CKey& key)
|
||||||
|
{
|
||||||
|
assert(key.IsValid());
|
||||||
|
std::vector<unsigned char> 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;
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
if (DecodeBase58Check(str, data)) {
|
||||||
|
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
|
||||||
|
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
|
||||||
|
key.Decode(data.data() + prefix.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncodeExtPubKey(const CExtPubKey& key)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
|
||||||
|
size_t size = data.size();
|
||||||
|
data.resize(size + BIP32_EXTKEY_SIZE);
|
||||||
|
key.Encode(data.data() + size);
|
||||||
|
std::string ret = EncodeBase58Check(data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CExtKey DecodeExtKey(const std::string& str)
|
||||||
|
{
|
||||||
|
CExtKey key;
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
if (DecodeBase58Check(str, data)) {
|
||||||
|
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
|
||||||
|
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
|
||||||
|
key.Decode(data.data() + prefix.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncodeExtKey(const CExtKey& key)
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
|
||||||
|
size_t size = data.size();
|
||||||
|
data.resize(size + BIP32_EXTKEY_SIZE);
|
||||||
|
key.Encode(data.data() + size);
|
||||||
|
std::string ret = EncodeBase58Check(data);
|
||||||
|
memory_cleanse(data.data(), data.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncodeDestination(const CTxDestination& dest)
|
||||||
|
{
|
||||||
|
return boost::apply_visitor(DestinationEncoder(Params()), dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTxDestination DecodeDestination(const std::string& str)
|
||||||
|
{
|
||||||
|
return DecodeDestination(str, Params());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
|
||||||
|
{
|
||||||
|
return IsValidDestination(DecodeDestination(str, params));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidDestinationString(const std::string& str)
|
||||||
|
{
|
||||||
|
return IsValidDestinationString(str, Params());
|
||||||
|
}
|
29
src/key_io.h
Normal file
29
src/key_io.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_KEYIO_H
|
||||||
|
#define BITCOIN_KEYIO_H
|
||||||
|
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <key.h>
|
||||||
|
#include <pubkey.h>
|
||||||
|
#include <script/standard.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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);
|
||||||
|
std::string EncodeExtPubKey(const CExtPubKey& extpubkey);
|
||||||
|
|
||||||
|
std::string EncodeDestination(const CTxDestination& dest);
|
||||||
|
CTxDestination DecodeDestination(const std::string& str);
|
||||||
|
bool IsValidDestinationString(const std::string& str);
|
||||||
|
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
|
||||||
|
|
||||||
|
#endif // BITCOIN_KEYIO_H
|
@ -7,10 +7,9 @@
|
|||||||
#include <qt/guiutil.h>
|
#include <qt/guiutil.h>
|
||||||
#include <qt/walletmodel.h>
|
#include <qt/walletmodel.h>
|
||||||
|
|
||||||
#include <base58.h>
|
#include <key_io.h>
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
|
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <qt/bitcoinaddressvalidator.h>
|
#include <qt/bitcoinaddressvalidator.h>
|
||||||
|
|
||||||
#include <base58.h>
|
#include <key_io.h>
|
||||||
|
|
||||||
/* Base58 characters are:
|
/* Base58 characters are:
|
||||||
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <wallet/coincontrol.h>
|
#include <wallet/coincontrol.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <validation.h> // For mempool
|
#include <validation.h> // For mempool
|
||||||
|
@ -9,7 +9,10 @@
|
|||||||
#include <qt/qvalidatedlineedit.h>
|
#include <qt/qvalidatedlineedit.h>
|
||||||
#include <qt/walletmodel.h>
|
#include <qt/walletmodel.h>
|
||||||
|
|
||||||
|
#include <base58.h>
|
||||||
|
#include <chainparams.h>
|
||||||
#include <primitives/transaction.h>
|
#include <primitives/transaction.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <qt/paymentrequestplus.h>
|
#include <qt/paymentrequestplus.h>
|
||||||
|
|
||||||
|
#include <script/script.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
#include <qt/paymentrequest.pb.h>
|
#include <qt/paymentrequest.pb.h>
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
#include <base58.h>
|
#include <amount.h>
|
||||||
|
#include <script/script.h>
|
||||||
|
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@
|
|||||||
#include <qt/guiutil.h>
|
#include <qt/guiutil.h>
|
||||||
#include <qt/optionsmodel.h>
|
#include <qt/optionsmodel.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <ui_interface.h>
|
#include <ui_interface.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
#include <qt/platformstyle.h>
|
#include <qt/platformstyle.h>
|
||||||
#include <qt/sendcoinsentry.h>
|
#include <qt/sendcoinsentry.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <wallet/coincontrol.h>
|
#include <wallet/coincontrol.h>
|
||||||
#include <validation.h> // mempool and minRelayTxFee
|
#include <validation.h> // mempool and minRelayTxFee
|
||||||
#include <ui_interface.h>
|
#include <ui_interface.h>
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include <qt/platformstyle.h>
|
#include <qt/platformstyle.h>
|
||||||
#include <qt/walletmodel.h>
|
#include <qt/walletmodel.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <validation.h> // For strMessageMagic
|
#include <validation.h> // For strMessageMagic
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <qt/test/paymentrequestdata.h>
|
#include <qt/test/paymentrequestdata.h>
|
||||||
|
|
||||||
#include <amount.h>
|
#include <amount.h>
|
||||||
|
#include <chainparams.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <script/standard.h>
|
#include <script/standard.h>
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <qt/transactiontablemodel.h>
|
#include <qt/transactiontablemodel.h>
|
||||||
#include <qt/transactionview.h>
|
#include <qt/transactionview.h>
|
||||||
#include <qt/walletmodel.h>
|
#include <qt/walletmodel.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#include <qt/paymentserver.h>
|
#include <qt/paymentserver.h>
|
||||||
#include <qt/transactionrecord.h>
|
#include <qt/transactionrecord.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <qt/transactionrecord.h>
|
#include <qt/transactionrecord.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <consensus/consensus.h>
|
#include <consensus/consensus.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <timedata.h>
|
#include <timedata.h>
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
#include <qt/sendcoinsdialog.h>
|
#include <qt/sendcoinsdialog.h>
|
||||||
#include <qt/transactiontablemodel.h>
|
#include <qt/transactiontablemodel.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <net.h> // for g_connman
|
#include <net.h> // for g_connman
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
#ifndef BITCOIN_QT_WALLETMODEL_H
|
#ifndef BITCOIN_QT_WALLETMODEL_H
|
||||||
#define BITCOIN_QT_WALLETMODEL_H
|
#define BITCOIN_QT_WALLETMODEL_H
|
||||||
|
|
||||||
|
#include <amount.h>
|
||||||
|
#include <key.h>
|
||||||
|
#include <serialize.h>
|
||||||
|
#include <script/standard.h>
|
||||||
|
|
||||||
#include <qt/paymentrequestplus.h>
|
#include <qt/paymentrequestplus.h>
|
||||||
#include <qt/walletmodeltransaction.h>
|
#include <qt/walletmodeltransaction.h>
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <amount.h>
|
#include <amount.h>
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
@ -13,6 +12,7 @@
|
|||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <miner.h>
|
#include <miner.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <crypto/ripemd160.h>
|
#include <crypto/ripemd160.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <httpserver.h>
|
#include <httpserver.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
@ -224,13 +224,10 @@ UniValue signmessagewithprivkey(const JSONRPCRequest& request)
|
|||||||
std::string strPrivkey = request.params[0].get_str();
|
std::string strPrivkey = request.params[0].get_str();
|
||||||
std::string strMessage = request.params[1].get_str();
|
std::string strMessage = request.params[1].get_str();
|
||||||
|
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(strPrivkey);
|
||||||
bool fGood = vchSecret.SetString(strPrivkey);
|
if (!key.IsValid()) {
|
||||||
if (!fGood)
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
||||||
CKey key = vchSecret.GetKey();
|
}
|
||||||
if (!key.IsValid())
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
|
|
||||||
|
|
||||||
CHashWriter ss(SER_GETHASH, 0);
|
CHashWriter ss(SER_GETHASH, 0);
|
||||||
ss << strMessageMagic;
|
ss << strMessageMagic;
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <coins.h>
|
#include <coins.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
@ -12,6 +11,7 @@
|
|||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <validationinterface.h>
|
#include <validationinterface.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <merkleblock.h>
|
#include <merkleblock.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <policy/policy.h>
|
#include <policy/policy.h>
|
||||||
@ -896,13 +896,9 @@ UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
|
|||||||
const UniValue& keys = request.params[1].get_array();
|
const UniValue& keys = request.params[1].get_array();
|
||||||
for (unsigned int idx = 0; idx < keys.size(); ++idx) {
|
for (unsigned int idx = 0; idx < keys.size(); ++idx) {
|
||||||
UniValue k = keys[idx];
|
UniValue k = keys[idx];
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(k.get_str());
|
||||||
if (!vchSecret.SetString(k.get_str())) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
|
||||||
}
|
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
if (!key.IsValid()) {
|
if (!key.IsValid()) {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
|
||||||
}
|
}
|
||||||
keystore.AddKey(key);
|
keystore.AddKey(key);
|
||||||
}
|
}
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
|
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <init.h>
|
#include <init.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
#include <ui_interface.h>
|
#include <ui_interface.h>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
#include <key_io.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <pubkey.h>
|
#include <pubkey.h>
|
||||||
#include <rpc/protocol.h>
|
#include <rpc/protocol.h>
|
||||||
|
@ -2,17 +2,10 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
|
|
||||||
#include <test/data/base58_encode_decode.json.h>
|
#include <test/data/base58_encode_decode.json.h>
|
||||||
#include <test/data/base58_keys_invalid.json.h>
|
|
||||||
#include <test/data/base58_keys_valid.json.h>
|
|
||||||
|
|
||||||
#include <key.h>
|
#include <base58.h>
|
||||||
#include <script/script.h>
|
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
#include <uint256.h>
|
|
||||||
#include <util.h>
|
|
||||||
#include <utilstrencodings.h>
|
#include <utilstrencodings.h>
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
@ -73,135 +66,4 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
|
|||||||
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
|
BOOST_CHECK_EQUAL_COLLECTIONS(result.begin(), result.end(), expected.begin(), expected.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Goal: check that parsed keys match test payload
|
|
||||||
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
|
|
||||||
{
|
|
||||||
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
|
|
||||||
CBitcoinSecret secret;
|
|
||||||
CTxDestination destination;
|
|
||||||
SelectParams(CBaseChainParams::MAIN);
|
|
||||||
|
|
||||||
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
|
||||||
UniValue test = tests[idx];
|
|
||||||
std::string strTest = test.write();
|
|
||||||
if (test.size() < 3) { // Allow for extra stuff (useful for comments)
|
|
||||||
BOOST_ERROR("Bad test: " << strTest);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string exp_base58string = test[0].get_str();
|
|
||||||
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
|
|
||||||
const UniValue &metadata = test[2].get_obj();
|
|
||||||
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
|
|
||||||
SelectParams(find_value(metadata, "chain").get_str());
|
|
||||||
bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool();
|
|
||||||
if (isPrivkey) {
|
|
||||||
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
|
|
||||||
// Must be valid private key
|
|
||||||
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
|
|
||||||
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
|
|
||||||
CKey privkey = secret.GetKey();
|
|
||||||
BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
|
|
||||||
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
|
|
||||||
|
|
||||||
// Private key must be invalid public key
|
|
||||||
destination = DecodeDestination(exp_base58string);
|
|
||||||
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
|
|
||||||
} else {
|
|
||||||
// Must be valid public key
|
|
||||||
destination = DecodeDestination(exp_base58string);
|
|
||||||
CScript script = GetScriptForDestination(destination);
|
|
||||||
BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
|
|
||||||
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
|
|
||||||
|
|
||||||
// Try flipped case version
|
|
||||||
for (char& c : exp_base58string) {
|
|
||||||
if (c >= 'a' && c <= 'z') {
|
|
||||||
c = (c - 'a') + 'A';
|
|
||||||
} else if (c >= 'A' && c <= 'Z') {
|
|
||||||
c = (c - 'A') + 'a';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
destination = DecodeDestination(exp_base58string);
|
|
||||||
BOOST_CHECK_MESSAGE(IsValidDestination(destination) == try_case_flip, "!IsValid case flipped:" + strTest);
|
|
||||||
if (IsValidDestination(destination)) {
|
|
||||||
script = GetScriptForDestination(destination);
|
|
||||||
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public key must be invalid private key
|
|
||||||
secret.SetString(exp_base58string);
|
|
||||||
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Goal: check that generated keys match test vectors
|
|
||||||
BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
|
|
||||||
{
|
|
||||||
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
|
|
||||||
|
|
||||||
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
|
||||||
UniValue test = tests[idx];
|
|
||||||
std::string strTest = test.write();
|
|
||||||
if (test.size() < 3) // Allow for extra stuff (useful for comments)
|
|
||||||
{
|
|
||||||
BOOST_ERROR("Bad test: " << strTest);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string exp_base58string = test[0].get_str();
|
|
||||||
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
|
|
||||||
const UniValue &metadata = test[2].get_obj();
|
|
||||||
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
|
|
||||||
SelectParams(find_value(metadata, "chain").get_str());
|
|
||||||
if (isPrivkey) {
|
|
||||||
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
|
|
||||||
CKey key;
|
|
||||||
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
|
|
||||||
assert(key.IsValid());
|
|
||||||
CBitcoinSecret secret;
|
|
||||||
secret.SetKey(key);
|
|
||||||
BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
|
|
||||||
} else {
|
|
||||||
CTxDestination dest;
|
|
||||||
CScript exp_script(exp_payload.begin(), exp_payload.end());
|
|
||||||
ExtractDestination(exp_script, dest);
|
|
||||||
std::string address = EncodeDestination(dest);
|
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(address, exp_base58string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectParams(CBaseChainParams::MAIN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Goal: check that base58 parsing code is robust against a variety of corrupted data
|
|
||||||
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
|
|
||||||
{
|
|
||||||
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
|
|
||||||
CBitcoinSecret secret;
|
|
||||||
CTxDestination destination;
|
|
||||||
|
|
||||||
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
|
||||||
UniValue test = tests[idx];
|
|
||||||
std::string strTest = test.write();
|
|
||||||
if (test.size() < 1) // Allow for extra stuff (useful for comments)
|
|
||||||
{
|
|
||||||
BOOST_ERROR("Bad test: " << strTest);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string exp_base58string = test[0].get_str();
|
|
||||||
|
|
||||||
// must be invalid as public and as private key
|
|
||||||
for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) {
|
|
||||||
SelectParams(chain);
|
|
||||||
destination = DecodeDestination(exp_base58string);
|
|
||||||
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
|
|
||||||
secret.SetString(exp_base58string);
|
|
||||||
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey in mainnet:" + strTest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <utilstrencodings.h>
|
#include <utilstrencodings.h>
|
||||||
@ -99,20 +99,12 @@ void RunTest(const TestVector &test) {
|
|||||||
pubkey.Encode(data);
|
pubkey.Encode(data);
|
||||||
|
|
||||||
// Test private key
|
// Test private key
|
||||||
CBitcoinExtKey b58key; b58key.SetKey(key);
|
BOOST_CHECK(EncodeExtKey(key) == derive.prv);
|
||||||
BOOST_CHECK(b58key.ToString() == derive.prv);
|
BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
|
||||||
|
|
||||||
CBitcoinExtKey b58keyDecodeCheck(derive.prv);
|
|
||||||
CExtKey checkKey = b58keyDecodeCheck.GetKey();
|
|
||||||
assert(checkKey == key); //ensure a base58 decoded key also matches
|
|
||||||
|
|
||||||
// Test public key
|
// Test public key
|
||||||
CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey);
|
BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
|
||||||
BOOST_CHECK(b58pubkey.ToString() == derive.pub);
|
BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
|
||||||
|
|
||||||
CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub);
|
|
||||||
CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey();
|
|
||||||
assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches
|
|
||||||
|
|
||||||
// Derive new keys
|
// Derive new keys
|
||||||
CExtKey keyNew;
|
CExtKey keyNew;
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#include <bloom.h>
|
#include <bloom.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <merkleblock.h>
|
#include <merkleblock.h>
|
||||||
#include <primitives/block.h>
|
#include <primitives/block.h>
|
||||||
#include <random.h>
|
#include <random.h>
|
||||||
@ -85,10 +85,7 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
|
|||||||
BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
|
BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
|
||||||
{
|
{
|
||||||
std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
|
std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(strSecret);
|
||||||
BOOST_CHECK(vchSecret.SetString(strSecret));
|
|
||||||
|
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
CPubKey pubkey = key.GetPubKey();
|
CPubKey pubkey = key.GetPubKey();
|
||||||
std::vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());
|
std::vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());
|
||||||
|
|
||||||
|
149
src/test/key_io_tests.cpp
Normal file
149
src/test/key_io_tests.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
// Copyright (c) 2011-2016 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <test/data/key_io_invalid.json.h>
|
||||||
|
#include <test/data/key_io_valid.json.h>
|
||||||
|
|
||||||
|
#include <key.h>
|
||||||
|
#include <key_io.h>
|
||||||
|
#include <script/script.h>
|
||||||
|
#include <utilstrencodings.h>
|
||||||
|
#include <test/test_bitcoin.h>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <univalue.h>
|
||||||
|
|
||||||
|
extern UniValue read_json(const std::string& jsondata);
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(key_io_tests, BasicTestingSetup)
|
||||||
|
|
||||||
|
// Goal: check that parsed keys match test payload
|
||||||
|
BOOST_AUTO_TEST_CASE(key_io_valid_parse)
|
||||||
|
{
|
||||||
|
UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
|
||||||
|
CKey privkey;
|
||||||
|
CTxDestination destination;
|
||||||
|
SelectParams(CBaseChainParams::MAIN);
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
||||||
|
UniValue test = tests[idx];
|
||||||
|
std::string strTest = test.write();
|
||||||
|
if (test.size() < 3) { // Allow for extra stuff (useful for comments)
|
||||||
|
BOOST_ERROR("Bad test: " << strTest);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string exp_base58string = test[0].get_str();
|
||||||
|
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
|
||||||
|
const UniValue &metadata = test[2].get_obj();
|
||||||
|
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
|
||||||
|
SelectParams(find_value(metadata, "chain").get_str());
|
||||||
|
bool try_case_flip = find_value(metadata, "tryCaseFlip").isNull() ? false : find_value(metadata, "tryCaseFlip").get_bool();
|
||||||
|
if (isPrivkey) {
|
||||||
|
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
|
||||||
|
// Must be valid private key
|
||||||
|
privkey = DecodeSecret(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
|
||||||
|
BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
|
||||||
|
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
|
||||||
|
|
||||||
|
// Private key must be invalid public key
|
||||||
|
destination = DecodeDestination(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
|
||||||
|
} else {
|
||||||
|
// Must be valid public key
|
||||||
|
destination = DecodeDestination(exp_base58string);
|
||||||
|
CScript script = GetScriptForDestination(destination);
|
||||||
|
BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
|
||||||
|
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
|
||||||
|
|
||||||
|
// Try flipped case version
|
||||||
|
for (char& c : exp_base58string) {
|
||||||
|
if (c >= 'a' && c <= 'z') {
|
||||||
|
c = (c - 'a') + 'A';
|
||||||
|
} else if (c >= 'A' && c <= 'Z') {
|
||||||
|
c = (c - 'A') + 'a';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
destination = DecodeDestination(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(IsValidDestination(destination) == try_case_flip, "!IsValid case flipped:" + strTest);
|
||||||
|
if (IsValidDestination(destination)) {
|
||||||
|
script = GetScriptForDestination(destination);
|
||||||
|
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public key must be invalid private key
|
||||||
|
privkey = DecodeSecret(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Goal: check that generated keys match test vectors
|
||||||
|
BOOST_AUTO_TEST_CASE(key_io_valid_gen)
|
||||||
|
{
|
||||||
|
UniValue tests = read_json(std::string(json_tests::key_io_valid, json_tests::key_io_valid + sizeof(json_tests::key_io_valid)));
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
||||||
|
UniValue test = tests[idx];
|
||||||
|
std::string strTest = test.write();
|
||||||
|
if (test.size() < 3) // Allow for extra stuff (useful for comments)
|
||||||
|
{
|
||||||
|
BOOST_ERROR("Bad test: " << strTest);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string exp_base58string = test[0].get_str();
|
||||||
|
std::vector<unsigned char> exp_payload = ParseHex(test[1].get_str());
|
||||||
|
const UniValue &metadata = test[2].get_obj();
|
||||||
|
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
|
||||||
|
SelectParams(find_value(metadata, "chain").get_str());
|
||||||
|
if (isPrivkey) {
|
||||||
|
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
|
||||||
|
CKey key;
|
||||||
|
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
|
||||||
|
assert(key.IsValid());
|
||||||
|
BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
|
||||||
|
} else {
|
||||||
|
CTxDestination dest;
|
||||||
|
CScript exp_script(exp_payload.begin(), exp_payload.end());
|
||||||
|
ExtractDestination(exp_script, dest);
|
||||||
|
std::string address = EncodeDestination(dest);
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL(address, exp_base58string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectParams(CBaseChainParams::MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Goal: check that base58 parsing code is robust against a variety of corrupted data
|
||||||
|
BOOST_AUTO_TEST_CASE(key_io_invalid)
|
||||||
|
{
|
||||||
|
UniValue tests = read_json(std::string(json_tests::key_io_invalid, json_tests::key_io_invalid + sizeof(json_tests::key_io_invalid))); // Negative testcases
|
||||||
|
CKey privkey;
|
||||||
|
CTxDestination destination;
|
||||||
|
|
||||||
|
for (unsigned int idx = 0; idx < tests.size(); idx++) {
|
||||||
|
UniValue test = tests[idx];
|
||||||
|
std::string strTest = test.write();
|
||||||
|
if (test.size() < 1) // Allow for extra stuff (useful for comments)
|
||||||
|
{
|
||||||
|
BOOST_ERROR("Bad test: " << strTest);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string exp_base58string = test[0].get_str();
|
||||||
|
|
||||||
|
// must be invalid as public and as private key
|
||||||
|
for (auto chain : { CBaseChainParams::MAIN, CBaseChainParams::TESTNET, CBaseChainParams::REGTEST }) {
|
||||||
|
SelectParams(chain);
|
||||||
|
destination = DecodeDestination(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey in mainnet:" + strTest);
|
||||||
|
privkey = DecodeSecret(exp_base58string);
|
||||||
|
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey in mainnet:" + strTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
|
||||||
#include <base58.h>
|
#include <key_io.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
@ -32,21 +32,16 @@ BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(key_test1)
|
BOOST_AUTO_TEST_CASE(key_test1)
|
||||||
{
|
{
|
||||||
CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1;
|
CKey key1 = DecodeSecret(strSecret1);
|
||||||
BOOST_CHECK( bsecret1.SetString (strSecret1));
|
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
|
||||||
BOOST_CHECK( bsecret2.SetString (strSecret2));
|
CKey key2 = DecodeSecret(strSecret2);
|
||||||
BOOST_CHECK( bsecret1C.SetString(strSecret1C));
|
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
|
||||||
BOOST_CHECK( bsecret2C.SetString(strSecret2C));
|
CKey key1C = DecodeSecret(strSecret1C);
|
||||||
BOOST_CHECK(!baddress1.SetString(strAddressBad));
|
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
|
||||||
|
CKey key2C = DecodeSecret(strSecret2C);
|
||||||
CKey key1 = bsecret1.GetKey();
|
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
|
||||||
BOOST_CHECK(key1.IsCompressed() == false);
|
CKey bad_key = DecodeSecret(strAddressBad);
|
||||||
CKey key2 = bsecret2.GetKey();
|
BOOST_CHECK(!bad_key.IsValid());
|
||||||
BOOST_CHECK(key2.IsCompressed() == false);
|
|
||||||
CKey key1C = bsecret1C.GetKey();
|
|
||||||
BOOST_CHECK(key1C.IsCompressed() == true);
|
|
||||||
CKey key2C = bsecret2C.GetKey();
|
|
||||||
BOOST_CHECK(key2C.IsCompressed() == true);
|
|
||||||
|
|
||||||
CPubKey pubkey1 = key1. GetPubKey();
|
CPubKey pubkey1 = key1. GetPubKey();
|
||||||
CPubKey pubkey2 = key2. GetPubKey();
|
CPubKey pubkey2 = key2. GetPubKey();
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <rpc/client.h>
|
#include <rpc/client.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <netbase.h>
|
#include <netbase.h>
|
||||||
|
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <rpc/safemode.h>
|
#include <rpc/safemode.h>
|
||||||
#include <rpc/server.h>
|
#include <rpc/server.h>
|
||||||
#include <wallet/init.h>
|
#include <wallet/init.h>
|
||||||
@ -147,13 +147,8 @@ UniValue importprivkey(const JSONRPCRequest& request)
|
|||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(strSecret);
|
||||||
bool fGood = vchSecret.SetString(strSecret);
|
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
||||||
|
|
||||||
if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
|
||||||
|
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
|
|
||||||
|
|
||||||
CPubKey pubkey = key.GetPubKey();
|
CPubKey pubkey = key.GetPubKey();
|
||||||
assert(key.VerifyPubKey(pubkey));
|
assert(key.VerifyPubKey(pubkey));
|
||||||
@ -554,9 +549,8 @@ UniValue importwallet(const JSONRPCRequest& request)
|
|||||||
boost::split(vstr, line, boost::is_any_of(" "));
|
boost::split(vstr, line, boost::is_any_of(" "));
|
||||||
if (vstr.size() < 2)
|
if (vstr.size() < 2)
|
||||||
continue;
|
continue;
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(vstr[0]);
|
||||||
if (vchSecret.SetString(vstr[0])) {
|
if (key.IsValid()) {
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
CPubKey pubkey = key.GetPubKey();
|
CPubKey pubkey = key.GetPubKey();
|
||||||
assert(key.VerifyPubKey(pubkey));
|
assert(key.VerifyPubKey(pubkey));
|
||||||
CKeyID keyid = pubkey.GetID();
|
CKeyID keyid = pubkey.GetID();
|
||||||
@ -659,7 +653,7 @@ UniValue dumpprivkey(const JSONRPCRequest& request)
|
|||||||
if (!pwallet->GetKey(keyid, vchSecret)) {
|
if (!pwallet->GetKey(keyid, vchSecret)) {
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
|
||||||
}
|
}
|
||||||
return CBitcoinSecret(vchSecret).ToString();
|
return EncodeSecret(vchSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -742,10 +736,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
|||||||
CExtKey masterKey;
|
CExtKey masterKey;
|
||||||
masterKey.SetMaster(key.begin(), key.size());
|
masterKey.SetMaster(key.begin(), key.size());
|
||||||
|
|
||||||
CBitcoinExtKey b58extkey;
|
file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n";
|
||||||
b58extkey.SetKey(masterKey);
|
|
||||||
|
|
||||||
file << "# extended private masterkey: " << b58extkey.ToString() << "\n\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
|
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
|
||||||
@ -755,7 +746,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
|
|||||||
std::string strLabel;
|
std::string strLabel;
|
||||||
CKey key;
|
CKey key;
|
||||||
if (pwallet->GetKey(keyid, key)) {
|
if (pwallet->GetKey(keyid, key)) {
|
||||||
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
|
file << strprintf("%s %s ", EncodeSecret(key), strTime);
|
||||||
if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
|
if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
|
||||||
file << strprintf("label=%s", strLabel);
|
file << strprintf("label=%s", strLabel);
|
||||||
} else if (keyid == masterKeyID) {
|
} else if (keyid == masterKeyID) {
|
||||||
@ -911,17 +902,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
|
|||||||
for (size_t i = 0; i < keys.size(); i++) {
|
for (size_t i = 0; i < keys.size(); i++) {
|
||||||
const std::string& privkey = keys[i].get_str();
|
const std::string& privkey = keys[i].get_str();
|
||||||
|
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(privkey);
|
||||||
bool fGood = vchSecret.SetString(privkey);
|
|
||||||
|
|
||||||
if (!fGood) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
|
||||||
}
|
|
||||||
|
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
|
|
||||||
if (!key.IsValid()) {
|
if (!key.IsValid()) {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
||||||
}
|
}
|
||||||
|
|
||||||
CPubKey pubkey = key.GetPubKey();
|
CPubKey pubkey = key.GetPubKey();
|
||||||
@ -1018,16 +1002,10 @@ UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, const int6
|
|||||||
const std::string& strPrivkey = keys[0].get_str();
|
const std::string& strPrivkey = keys[0].get_str();
|
||||||
|
|
||||||
// Checks.
|
// Checks.
|
||||||
CBitcoinSecret vchSecret;
|
CKey key = DecodeSecret(strPrivkey);
|
||||||
bool fGood = vchSecret.SetString(strPrivkey);
|
|
||||||
|
|
||||||
if (!fGood) {
|
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
|
||||||
}
|
|
||||||
|
|
||||||
CKey key = vchSecret.GetKey();
|
|
||||||
if (!key.IsValid()) {
|
if (!key.IsValid()) {
|
||||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
|
||||||
}
|
}
|
||||||
|
|
||||||
CPubKey pubKey = key.GetPubKey();
|
CPubKey pubKey = key.GetPubKey();
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <amount.h>
|
#include <amount.h>
|
||||||
#include <base58.h>
|
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <core_io.h>
|
#include <core_io.h>
|
||||||
#include <httpserver.h>
|
#include <httpserver.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <policy/feerate.h>
|
#include <policy/feerate.h>
|
||||||
#include <policy/fees.h>
|
#include <policy/fees.h>
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <wallet/wallet.h>
|
#include <wallet/wallet.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <checkpoints.h>
|
#include <checkpoints.h>
|
||||||
#include <chain.h>
|
#include <chain.h>
|
||||||
#include <wallet/coincontrol.h>
|
#include <wallet/coincontrol.h>
|
||||||
@ -14,6 +13,7 @@
|
|||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <wallet/init.h>
|
#include <wallet/init.h>
|
||||||
#include <key.h>
|
#include <key.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <keystore.h>
|
#include <keystore.h>
|
||||||
#include <validation.h>
|
#include <validation.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
#include <wallet/walletdb.h>
|
#include <wallet/walletdb.h>
|
||||||
|
|
||||||
#include <base58.h>
|
|
||||||
#include <consensus/tx_verify.h>
|
#include <consensus/tx_verify.h>
|
||||||
#include <consensus/validation.h>
|
#include <consensus/validation.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
|
#include <key_io.h>
|
||||||
#include <protocol.h>
|
#include <protocol.h>
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
#include <sync.h>
|
#include <sync.h>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user