Skip to content

Commit 1025440

Browse files
committed
Refactor: split CKeyID/CScriptID/CTxDestination from CBitcoinAddress
This introduces internal types: * CKeyID: reference (hash160) of a key * CScriptID: reference (hash160) of a script * CTxDestination: a boost::variant of the former two CBitcoinAddress is retrofitted to be a Base58 encoding of a CTxDestination. This allows all internal code to only use the internal types, and only have RPC and GUI depend on the base58 code. Furthermore, the header dependencies are a lot saner now. base58.h is at the top (right below rpc and gui) instead of at the bottom. For the rest: wallet -> script -> keystore -> key. Only keystore still requires a forward declaration of CScript. Solving that would require splitting script into two layers.
1 parent fd61d6f commit 1025440

26 files changed

+477
-339
lines changed

src/base58.h

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <vector>
2020
#include "bignum.h"
2121
#include "key.h"
22+
#include "script.h"
2223

2324
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
2425

@@ -258,6 +259,18 @@ class CBase58Data
258259
* Script-hash-addresses have version 5 (or 196 testnet).
259260
* The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
260261
*/
262+
class CBitcoinAddress;
263+
class CBitcoinAddressVisitor : public boost::static_visitor<bool>
264+
{
265+
private:
266+
CBitcoinAddress *addr;
267+
public:
268+
CBitcoinAddressVisitor(CBitcoinAddress *addrIn) : addr(addrIn) { }
269+
bool operator()(const CKeyID &id) const;
270+
bool operator()(const CScriptID &id) const;
271+
bool operator()(const CNoDestination &no) const;
272+
};
273+
261274
class CBitcoinAddress : public CBase58Data
262275
{
263276
public:
@@ -269,21 +282,19 @@ class CBitcoinAddress : public CBase58Data
269282
SCRIPT_ADDRESS_TEST = 196,
270283
};
271284

272-
bool SetHash160(const uint160& hash160)
273-
{
274-
SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &hash160, 20);
285+
bool Set(const CKeyID &id) {
286+
SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
275287
return true;
276288
}
277289

278-
void SetPubKey(const CPubKey& vchPubKey)
279-
{
280-
SetHash160(vchPubKey.GetID());
290+
bool Set(const CScriptID &id) {
291+
SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
292+
return true;
281293
}
282294

283-
bool SetScriptHash160(const uint160& hash160)
295+
bool Set(const CTxDestination &dest)
284296
{
285-
SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &hash160, 20);
286-
return true;
297+
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
287298
}
288299

289300
bool IsValid() const
@@ -315,27 +326,14 @@ class CBitcoinAddress : public CBase58Data
315326
}
316327
return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
317328
}
318-
bool IsScript() const
319-
{
320-
if (!IsValid())
321-
return false;
322-
if (fTestNet)
323-
return nVersion == SCRIPT_ADDRESS_TEST;
324-
return nVersion == SCRIPT_ADDRESS;
325-
}
326329

327330
CBitcoinAddress()
328331
{
329332
}
330333

331-
CBitcoinAddress(uint160 hash160In)
332-
{
333-
SetHash160(hash160In);
334-
}
335-
336-
CBitcoinAddress(const CPubKey& vchPubKey)
334+
CBitcoinAddress(const CTxDestination &dest)
337335
{
338-
SetPubKey(vchPubKey);
336+
Set(dest);
339337
}
340338

341339
CBitcoinAddress(const std::string& strAddress)
@@ -348,15 +346,58 @@ class CBitcoinAddress : public CBase58Data
348346
SetString(pszAddress);
349347
}
350348

351-
uint160 GetHash160() const
352-
{
353-
assert(vchData.size() == 20);
354-
uint160 hash160;
355-
memcpy(&hash160, &vchData[0], 20);
356-
return hash160;
349+
CTxDestination Get() const {
350+
if (!IsValid())
351+
return CNoDestination();
352+
switch (nVersion) {
353+
case PUBKEY_ADDRESS:
354+
case PUBKEY_ADDRESS_TEST: {
355+
uint160 id;
356+
memcpy(&id, &vchData[0], 20);
357+
return CKeyID(id);
358+
}
359+
case SCRIPT_ADDRESS:
360+
case SCRIPT_ADDRESS_TEST: {
361+
uint160 id;
362+
memcpy(&id, &vchData[0], 20);
363+
return CScriptID(id);
364+
}
365+
}
366+
return CNoDestination();
367+
}
368+
369+
bool GetKeyID(CKeyID &keyID) const {
370+
if (!IsValid())
371+
return false;
372+
switch (nVersion) {
373+
case PUBKEY_ADDRESS:
374+
case PUBKEY_ADDRESS_TEST: {
375+
uint160 id;
376+
memcpy(&id, &vchData[0], 20);
377+
keyID = CKeyID(id);
378+
return true;
379+
}
380+
default: return false;
381+
}
382+
}
383+
384+
bool IsScript() const {
385+
if (!IsValid())
386+
return false;
387+
switch (nVersion) {
388+
case SCRIPT_ADDRESS:
389+
case SCRIPT_ADDRESS_TEST: {
390+
return true;
391+
}
392+
default: return false;
393+
}
357394
}
358395
};
359396

397+
bool inline CBitcoinAddressVisitor::operator()(const CKeyID &id) const { return addr->Set(id); }
398+
bool inline CBitcoinAddressVisitor::operator()(const CScriptID &id) const { return addr->Set(id); }
399+
bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { return false; }
400+
360401
/** A base58-encoded secret key */
361402
class CBitcoinSecret : public CBase58Data
362403
{

0 commit comments

Comments
 (0)