refactor: use scoped weak enum instead of bare values for address type

strong enums (enum class) cannot be converted implicitly to another
type, requiring you to either use a static_cast or use to_underlying,
which is a part of C++23, which this codebase doesn't support.

the idea of scoping a weak enum into a namespace is courtesy of
https://stackoverflow.com/a/46294875/13845753
This commit is contained in:
Kittywhiskers Van Gogh 2023-09-19 00:09:11 +05:30
parent 7bff85e031
commit 5faf29d318
6 changed files with 68 additions and 56 deletions

View File

@ -11,6 +11,16 @@
#include <chrono>
namespace AddressType {
enum AddressType {
P2PK = 1,
P2PKH = 1,
P2SH = 2,
UNKNOWN = 0
};
}; /* namespace AddressType */
struct CMempoolAddressDelta
{
std::chrono::seconds time;

View File

@ -14,6 +14,7 @@
#include <univalue.h>
#include <util/strencodings.h>
#include <addressindex.h>
#include <spentindex.h>
#include <evo/assetlocktx.h>
@ -215,9 +216,9 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
auto spentInfo = it->second;
in.pushKV("value", ValueFromAmount(spentInfo.satoshis));
in.pushKV("valueSat", spentInfo.satoshis);
if (spentInfo.addressType == 1) {
if (spentInfo.addressType == AddressType::P2PK) {
in.pushKV("address", EncodeDestination(PKHash(spentInfo.addressHash)));
} else if (spentInfo.addressType == 2) {
} else if (spentInfo.addressType == AddressType::P2SH) {
in.pushKV("address", EncodeDestination(ScriptHash(spentInfo.addressHash)));
}
}

View File

@ -595,9 +595,9 @@ static UniValue mnauth(const JSONRPCRequest& request)
static bool getAddressFromIndex(const int &type, const uint160 &hash, std::string &address)
{
if (type == 2) {
if (type == AddressType::P2SH) {
address = EncodeDestination(ScriptHash(hash));
} else if (type == 1) {
} else if (type == AddressType::P2PK) {
address = EncodeDestination(PKHash(hash));
} else {
return false;
@ -609,12 +609,12 @@ static bool getIndexKey(const std::string& str, uint160& hashBytes, int& type)
{
CTxDestination dest = DecodeDestination(str);
if (!IsValidDestination(dest)) {
type = 0;
type = AddressType::UNKNOWN;
return false;
}
const PKHash *pkhash = std::get_if<PKHash>(&dest);
const ScriptHash *scriptID = std::get_if<ScriptHash>(&dest);
type = pkhash ? 1 : 2;
type = pkhash ? AddressType::P2PK : AddressType::P2SH;
hashBytes = pkhash ? uint160(*pkhash) : uint160(*scriptID);
return true;
}
@ -623,7 +623,7 @@ static bool getAddressesFromParams(const UniValue& params, std::vector<std::pair
{
if (params[0].isStr()) {
uint160 hashBytes;
int type = 0;
int type{AddressType::UNKNOWN};
if (!getIndexKey(params[0].get_str(), hashBytes, type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
}
@ -640,7 +640,7 @@ static bool getAddressesFromParams(const UniValue& params, std::vector<std::pair
for (std::vector<UniValue>::iterator it = values.begin(); it != values.end(); ++it) {
uint160 hashBytes;
int type = 0;
int type{AddressType::UNKNOWN};
if (!getIndexKey(it->get_str(), hashBytes, type)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
}

View File

@ -6,10 +6,11 @@
#ifndef BITCOIN_SPENTINDEX_H
#define BITCOIN_SPENTINDEX_H
#include <uint256.h>
#include <addressindex.h>
#include <amount.h>
#include <script/script.h>
#include <serialize.h>
#include <uint256.h>
struct CSpentIndexKey {
uint256 txid;
@ -67,7 +68,7 @@ struct CSpentIndexValue {
inputIndex = 0;
blockHeight = 0;
satoshis = 0;
addressType = 0;
addressType = AddressType::UNKNOWN;
addressHash.SetNull();
}
@ -189,7 +190,7 @@ struct CAddressUnspentKey {
}
void SetNull() {
type = 0;
type = AddressType::UNKNOWN;
hashBytes.SetNull();
txhash.SetNull();
index = 0;
@ -279,7 +280,7 @@ struct CAddressIndexKey {
}
void SetNull() {
type = 0;
type = AddressType::UNKNOWN;
hashBytes.SetNull();
blockHeight = 0;
txindex = 0;
@ -318,7 +319,7 @@ struct CAddressIndexIteratorKey {
}
void SetNull() {
type = 0;
type = AddressType::UNKNOWN;
hashBytes.SetNull();
}
};
@ -355,7 +356,7 @@ struct CAddressIndexIteratorHeightKey {
}
void SetNull() {
type = 0;
type = AddressType::UNKNOWN;
hashBytes.SetNull();
blockHeight = 0;
}

View File

@ -476,19 +476,19 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC
const CTxOut &prevout = coin.out;
if (prevout.scriptPubKey.IsPayToScriptHash()) {
std::vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDeltaKey key(AddressType::P2SH, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
mapAddress.insert(std::make_pair(key, delta));
inserted.push_back(key);
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDeltaKey key(AddressType::P2PKH, uint160(hashBytes), txhash, j, 1);
CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
mapAddress.insert(std::make_pair(key, delta));
inserted.push_back(key);
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{prevout.scriptPubKey.data()+1, prevout.scriptPubKey.size() - 2})};
CMempoolAddressDeltaKey key(1, hashBytes, txhash, j, 1);
CMempoolAddressDeltaKey key(AddressType::P2PK, hashBytes, txhash, j, 1);
CMempoolAddressDelta delta(entry.GetTime(), prevout.nValue * -1, input.prevout.hash, input.prevout.n);
mapAddress.insert(std::make_pair(key, delta));
inserted.push_back(key);
@ -499,19 +499,19 @@ void CTxMemPool::addAddressIndex(const CTxMemPoolEntry &entry, const CCoinsViewC
const CTxOut &out = tx.vout[k];
if (out.scriptPubKey.IsPayToScriptHash()) {
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
CMempoolAddressDeltaKey key(2, uint160(hashBytes), txhash, k, 0);
CMempoolAddressDeltaKey key(AddressType::P2SH, uint160(hashBytes), txhash, k, 0);
mapAddress.insert(std::make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
inserted.push_back(key);
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
std::pair<addressDeltaMap::iterator,bool> ret;
CMempoolAddressDeltaKey key(1, uint160(hashBytes), txhash, k, 0);
CMempoolAddressDeltaKey key(AddressType::P2PKH, uint160(hashBytes), txhash, k, 0);
mapAddress.insert(std::make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
inserted.push_back(key);
} else if (out.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{out.scriptPubKey.data()+1, out.scriptPubKey.size() - 2})};
std::pair<addressDeltaMap::iterator,bool> ret;
CMempoolAddressDeltaKey key(1, hashBytes, txhash, k, 0);
CMempoolAddressDeltaKey key(AddressType::P2PK, hashBytes, txhash, k, 0);
mapAddress.insert(std::make_pair(key, CMempoolAddressDelta(entry.GetTime(), out.nValue)));
inserted.push_back(key);
}
@ -567,16 +567,16 @@ void CTxMemPool::addSpentIndex(const CTxMemPoolEntry &entry, const CCoinsViewCac
if (prevout.scriptPubKey.IsPayToScriptHash()) {
addressHash = uint160(std::vector<unsigned char> (prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
addressType = AddressType::P2SH;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
addressHash = uint160(std::vector<unsigned char> (prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
addressType = AddressType::P2PKH;
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
addressHash = Hash160(Span{prevout.scriptPubKey.data()+1, prevout.scriptPubKey.size() - 2});
addressType = 1;
addressType = AddressType::P2PK;
} else {
addressHash.SetNull();
addressType = 0;
addressType = AddressType::UNKNOWN;
}
CSpentIndexKey key = CSpentIndexKey(input.prevout.hash, input.prevout.n);

View File

@ -1711,24 +1711,24 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
// undo receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2SH, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
// undo unspent index
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(2, uint160(hashBytes), hash, k), CAddressUnspentValue()));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2SH, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
// undo receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PKH, uint160(hashBytes), pindex->nHeight, i, hash, k, false), out.nValue));
// undo unspent index
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, uint160(hashBytes), hash, k), CAddressUnspentValue()));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PKH, uint160(hashBytes), hash, k), CAddressUnspentValue()));
} else if (out.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{out.scriptPubKey.data()+1, out.scriptPubKey.size() - 2})};
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, hashBytes, pindex->nHeight, i, hash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, hashBytes, hash, k), CAddressUnspentValue()));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PK, hashBytes, pindex->nHeight, i, hash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PK, hashBytes, hash, k), CAddressUnspentValue()));
} else {
continue;
}
@ -1778,27 +1778,27 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
std::vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22);
// undo spending activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2SH, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(2, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2SH, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23);
// undo spending activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PKH, uint160(hashBytes), pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PKH, uint160(hashBytes), input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{prevout.scriptPubKey.data()+1, prevout.scriptPubKey.size()-2})};
// undo spending activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, hashBytes, pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PK, hashBytes, pindex->nHeight, i, hash, j, true), prevout.nValue * -1));
// restore unspent index
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PK, hashBytes, input.prevout.hash, input.prevout.n), CAddressUnspentValue(prevout.nValue, prevout.scriptPubKey, undoHeight)));
} else {
continue;
}
@ -2260,16 +2260,16 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
if (prevout.scriptPubKey.IsPayToScriptHash()) {
hashBytes = uint160(std::vector<unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
addressType = AddressType::P2SH;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
hashBytes = uint160(std::vector<unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
addressType = AddressType::P2PKH;
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
hashBytes = Hash160(Span{prevout.scriptPubKey.data()+1, prevout.scriptPubKey.size()-2});
addressType = 1;
addressType = AddressType::P2PK;
} else {
hashBytes.SetNull();
addressType = 0;
addressType = AddressType::UNKNOWN;
}
if (fAddressIndex && addressType > 0) {
@ -2326,24 +2326,24 @@ bool CChainState::ConnectBlock(const CBlock& block, BlockValidationState& state,
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
// record receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2SH, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2SH, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
// record receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PKH, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PKH, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else if (out.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{out.scriptPubKey.data()+1, out.scriptPubKey.size()-2})};
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, hashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, hashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PK, hashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PK, hashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else {
continue;
}
@ -4866,16 +4866,16 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i
if (prevout.scriptPubKey.IsPayToScriptHash()) {
hashBytes = uint160(std::vector<unsigned char>(prevout.scriptPubKey.begin()+2, prevout.scriptPubKey.begin()+22));
addressType = 2;
addressType = AddressType::P2SH;
} else if (prevout.scriptPubKey.IsPayToPublicKeyHash()) {
hashBytes = uint160(std::vector<unsigned char>(prevout.scriptPubKey.begin()+3, prevout.scriptPubKey.begin()+23));
addressType = 1;
addressType = AddressType::P2PKH;
} else if (prevout.scriptPubKey.IsPayToPublicKey()) {
hashBytes = Hash160(Span{prevout.scriptPubKey.data()+1, prevout.scriptPubKey.size()-2});
addressType = 1;
addressType = AddressType::P2PK;
} else {
hashBytes.SetNull();
addressType = 0;
addressType = AddressType::UNKNOWN;
}
if (fAddressIndex && addressType > 0) {
@ -4902,24 +4902,24 @@ bool CChainState::RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& i
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+2, out.scriptPubKey.begin()+22);
// record receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(2, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2SH, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(2, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2SH, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else if (out.scriptPubKey.IsPayToPublicKeyHash()) {
std::vector<unsigned char> hashBytes(out.scriptPubKey.begin()+3, out.scriptPubKey.begin()+23);
// record receiving activity
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PKH, uint160(hashBytes), pindex->nHeight, i, txhash, k, false), out.nValue));
// record unspent output
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PKH, uint160(hashBytes), txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else if (out.scriptPubKey.IsPayToPublicKey()) {
uint160 hashBytes{Hash160(Span{out.scriptPubKey.data()+1, out.scriptPubKey.size()-2})};
addressIndex.push_back(std::make_pair(CAddressIndexKey(1, hashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(1, hashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
addressIndex.push_back(std::make_pair(CAddressIndexKey(AddressType::P2PK, hashBytes, pindex->nHeight, i, txhash, k, false), out.nValue));
addressUnspentIndex.push_back(std::make_pair(CAddressUnspentKey(AddressType::P2PK, hashBytes, txhash, k), CAddressUnspentValue(out.nValue, out.scriptPubKey, pindex->nHeight)));
} else {
continue;
}