Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error on alias duplicat in mempool when looking up the address. #246

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/primitives/referral.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,6 @@ inline void SerializeReferral(const RefType& ref, Stream& s)
}
}

typedef std::shared_ptr<const Referral> ReferralRef;

template <typename Ref>
static inline ReferralRef MakeReferralRef(Ref&& referralIn)
{
Expand Down
22 changes: 15 additions & 7 deletions src/refmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,21 @@ int ReferralTxMemPool::Expire(int64_t time) {
}

namespace {
class ReferralIdVisitor : public boost::static_visitor<ReferralRef>
class ReferralIdVisitor : public boost::static_visitor<ReferralRefs>
{
private:
const ReferralTxMemPool *mempool;
public:
explicit ReferralIdVisitor(const ReferralTxMemPool *mempool_in): mempool{mempool_in} {}

template <typename T>
ReferralRef operator()(const T &id) const {
ReferralRefs operator()(const std::string &id) const {
return mempool->Get(id);
}

template <typename T>
ReferralRefs operator()(const T &id) const {
return {mempool->Get(id)};
}
};
}

Expand All @@ -232,14 +236,18 @@ ReferralRef ReferralTxMemPool::Get(const Address& address) const
return it != mapRTx.get<referral_address>().end() ? it->GetSharedEntryValue() : nullptr;
}

ReferralRef ReferralTxMemPool::Get(const std::string& alias) const
ReferralRefs ReferralTxMemPool::Get(const std::string& alias) const
{
LOCK(cs);
auto it = mapRTx.get<referral_alias>().find(alias);
return it != mapRTx.get<referral_alias>().end() ? it->GetSharedEntryValue() : nullptr;
auto range = mapRTx.get<referral_alias>().equal_range(alias);
ReferralRefs refs;
for(auto it = range.first ; it != range.second; it++) {
refs.push_back(it->GetSharedEntryValue());
}
return refs;
}

ReferralRef ReferralTxMemPool::Get(const ReferralId& referral_id) const
ReferralRefs ReferralTxMemPool::Get(const ReferralId& referral_id) const
{
return boost::apply_visitor(ReferralIdVisitor(this), referral_id);
}
Expand Down
4 changes: 2 additions & 2 deletions src/refmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ class ReferralTxMemPool
ReferralRef Get(const Address& address) const;

/** Get referral by alias */
ReferralRef Get(const std::string& alias) const;
ReferralRefs Get(const std::string& alias) const;

/** Get referral by id - hash, address or alias */
ReferralRef Get(const ReferralId& referral_id) const;
ReferralRefs Get(const ReferralId& referral_id) const;

/** Find all referrals with given alias */
std::pair<RefAliasIter, RefAliasIter> Find(const std::string& alias) const;
Expand Down
1 change: 1 addition & 0 deletions src/script/standard.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class CNoDestination {
* A CTxDestination is the internal data type encoded in a merit address
*/
using CTxDestination = boost::variant<CNoDestination, CKeyID, CScriptID, CParamScriptID>;
using CTxDestinations = std::vector<CTxDestination>;

/** returns a numberical type based on destination */
char AddressTypeFromDestination(const CTxDestination&);
Expand Down
64 changes: 52 additions & 12 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include <atomic>
#include <sstream>
#include <numeric>
#include <stdexcept>

#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/join.hpp>
Expand Down Expand Up @@ -5180,7 +5181,7 @@ bool CheckAddressConfirmed(const CMeritAddress& addr, bool checkMempool)
return maybe_hash ? CheckAddressConfirmed(*maybe_hash, addr.GetType(), checkMempool) : false;
}

CTxDestination LookupDestination(const std::string& address)
CTxDestinations LookupDestinations(const std::string& address)
{
assert(prefviewdb);

Expand All @@ -5189,38 +5190,77 @@ CTxDestination LookupDestination(const std::string& address)
// check if address is a valid destionation => it's an address
// otherwise try to get referral by alias and get it's address
if (IsValidDestination(dest)) {
return dest;
return {dest};
}

// Get referral by alias from cache
auto cached_referral = prefviewdb->GetReferral(address);
if (cached_referral) {
return CMeritAddress{cached_referral->addressType, cached_referral->GetAddress()}.Get();
return {CMeritAddress{cached_referral->addressType, cached_referral->GetAddress()}.Get()};
}

// Get referral by alias from cache
auto mempool_referral = mempoolReferral.Get(address);
if (mempool_referral) {
return CMeritAddress{mempool_referral->addressType, mempool_referral->GetAddress()}.Get();
auto mempool_referrals = mempoolReferral.Get(address);
if (!mempool_referrals.empty()) {
CTxDestinations dests;
for(const auto& ref: mempool_referrals) {
dests.push_back(CMeritAddress{ref->addressType, ref->GetAddress()}.Get());
}
return dests;
}

// if dest is not a valid festination and
// we have no referrals assosiated with this alias
// return decoded dest
return dest;
return {dest};
}

const referral::ReferralRef LookupReferral(referral::ReferralId& referral_id)
CTxDestination LookupDestination(const std::string& address)
{
auto mempool_referral = mempoolReferral.Get(referral_id);
assert(prefviewdb);

if (mempool_referral) {
return mempool_referral;
auto dests = LookupDestinations(address);
if(dests.size() > 1) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • space /pedantic

std::stringstream s;
s << "There are multiple destinations found with the alias " << address << std::endl;
s << "The conflicting destinations are..." << std::endl;
for(const auto d : dests) {
s << '\t' << CMeritAddress{d}.ToString() << std::endl;
}
throw std::runtime_error{s.str()};
}

return dests.empty() ? CTxDestination{} : dests.front();
}

const referral::ReferralRefs LookupReferrals(referral::ReferralId& referral_id)
{
auto cached_referral = prefviewdb->GetReferral(referral_id);

return cached_referral ? MakeReferralRef(*cached_referral) : nullptr;
if(cached_referral) {
return {MakeReferralRef(*cached_referral)};
}

return mempoolReferral.Get(referral_id);
}

const referral::ReferralRef LookupReferral(referral::ReferralId& referral_id)
{
auto mempool_referrals = LookupReferrals(referral_id);
if(mempool_referrals.size() > 1) {
std::stringstream s;
s << "There are multiple referrals found with the id specified" << std::endl;
s << "The conflicting referrals are..." << std::endl;
for(const auto ref : mempool_referrals) {
s << "\tid:"
<< ref->GetHash().GetHex()
<< " address: "
<< CMeritAddress{ref->addressType, ref->GetAddress()}.ToString()
<< std::endl;
}
throw std::runtime_error{s.str()};
}
return mempool_referrals.empty() ? nullptr : mempool_referrals.front();
}

bool IsWitnessCommitment(const CTxOut& out)
Expand Down
12 changes: 12 additions & 0 deletions src/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,12 +577,24 @@ bool CheckAddressConfirmed(const uint160&, char addr_type, bool checkMempool = t
/** Check that an address is valid and ready to use */
bool CheckAddressConfirmed(const CMeritAddress& addr, bool checkMempool = true);


/**
* Try to decide if the address is an alias or an address.
* If it is an alias, lookup the address.
*
* It is possible to return multiple destinations if the alias is found in the
* mempool and there are conflicts
*/
CTxDestinations LookupDestinations(const std::string& address);

/**
* Try to decide if the address is an alias or an address.
* If it is an alias, lookup the address.
*/
CTxDestination LookupDestination(const std::string& address);

const referral::ReferralRefs LookupReferrals(referral::ReferralId& referral_id);

const referral::ReferralRef LookupReferral(referral::ReferralId& referral_id);

/** When there are blocks in the active chain with missing data, rewind the chainstate and remove them from the block index */
Expand Down