diff --git a/src/neuralnet/beacon.cpp b/src/neuralnet/beacon.cpp index f7d5513ddc..d6f548cdcf 100644 --- a/src/neuralnet/beacon.cpp +++ b/src/neuralnet/beacon.cpp @@ -36,7 +36,7 @@ uint256 HashBeaconPayload(const BeaconPayload& payload) //! \return \c true if the supplied beacon contract matches an active beacon. //! This updates the matched beacon with a new timestamp. //! -bool TryRenewal(BeaconRegistry::BeaconMap beacons, const BeaconPayload& payload) +bool TryRenewal(BeaconRegistry::BeaconMap& beacons, const BeaconPayload& payload) { auto beacon_pair_iter = beacons.find(payload.m_cpid); @@ -276,6 +276,19 @@ bool BeaconRegistry::ContainsActive(const Cpid& cpid) const return ContainsActive(cpid, GetAdjustedTime()); } +std::vector BeaconRegistry::FindPendingKeys(const Cpid& cpid) const +{ + std::vector found; + + for (const auto& beacon_pair : m_pending) { + if (beacon_pair.second.m_cpid == cpid) { + found.emplace_back(beacon_pair.first); + } + } + + return found; +} + void BeaconRegistry::Add(Contract contract) { BeaconPayload payload = contract.CopyPayloadAs(); diff --git a/src/neuralnet/beacon.h b/src/neuralnet/beacon.h index b4b16d432e..4b15fc88e8 100644 --- a/src/neuralnet/beacon.h +++ b/src/neuralnet/beacon.h @@ -433,6 +433,20 @@ class BeaconRegistry : public IContractHandler //! bool ContainsActive(const Cpid& cpid) const; + //! + //! \brief Look up the key IDs of pending beacons for the specified CPID. + //! + //! The wallet matches key IDs returned by this method to determine whether + //! it contains private keys for pending beacons so that it can skip beacon + //! advertisement if it submitted one recently. + //! + //! \param cpid CPID of the beacons to find results for. + //! + //! \return The set of RIPEMD-160 hashes of the keys for the beacons that + //! match the supplied CPID. + //! + std::vector FindPendingKeys(const Cpid& cpid) const; + //! //! \brief Determine whether a beacon contract is valid. //! diff --git a/src/neuralnet/researcher.cpp b/src/neuralnet/researcher.cpp index b9c2253e7d..2c3407c7cd 100644 --- a/src/neuralnet/researcher.cpp +++ b/src/neuralnet/researcher.cpp @@ -323,6 +323,25 @@ bool CheckBeaconPrivateKey(const CWallet* const wallet, const CPubKey& public_ke return true; } +//! +//! \brief Determine whether the wallet contains a key for a pending beacon. +//! +//! \param beacons Fetches pending beacon keys IDs. +//! \param cpid CPID to look up pending beacons for. +//! +//! \return \c true if the a pending beacon exists for the supplied CPID. +//! +bool DetectPendingBeacon(const BeaconRegistry& beacons, const Cpid cpid) +{ + for (const auto& key_id : beacons.FindPendingKeys(cpid)) { + if (pwalletMain->HaveKey(key_id)) { + return true; + } + } + + return false; +} + //! //! \brief Generate a new beacon key pair. //! @@ -883,14 +902,20 @@ AdvertiseBeaconResult Researcher::AdvertiseBeacon() // if (last_advertised_height >= (nBestHeight - 5)) { LogPrintf("ERROR: %s: Beacon awaiting confirmation already", __func__); - return BeaconError::TOO_SOON; + return BeaconError::PENDING; } - const BeaconOption current_beacon = GetBeaconRegistry().Try(*cpid); + const BeaconRegistry& beacons = GetBeaconRegistry(); + const BeaconOption current_beacon = beacons.Try(*cpid); AdvertiseBeaconResult result(BeaconError::NONE); if (!current_beacon) { + if (DetectPendingBeacon(beacons, *cpid)) { + LogPrintf("%s: Beacon awaiting verification already", __func__); + return BeaconError::PENDING; + } + result = SendNewBeacon(*cpid); } else { result = RenewBeacon(*cpid, *current_beacon); diff --git a/src/neuralnet/researcher.h b/src/neuralnet/researcher.h index 3524ef9783..2273325cfd 100644 --- a/src/neuralnet/researcher.h +++ b/src/neuralnet/researcher.h @@ -199,7 +199,7 @@ enum class BeaconError MISSING_KEY, //!< Beacon private key missing or invalid. NO_CPID, //!< No valid CPID detected (investor mode). NOT_NEEDED, //!< Beacon exists for the CPID. No renewal needed. - TOO_SOON, //!< Not enough time elapsed for pending advertisement. + PENDING, //!< Not enough time elapsed for pending advertisement. TX_FAILED, //!< Beacon contract transacton failed to send. WALLET_LOCKED, //!< Wallet not fully unlocked. }; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 7d904fc24b..6355cb388c 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -660,7 +660,7 @@ UniValue advertisebeacon(const UniValue& params, bool fHelp) throw JSONRPCError( RPC_INVALID_REQUEST, "An active beacon already exists for this CPID"); - case NN::BeaconError::TOO_SOON: + case NN::BeaconError::PENDING: throw JSONRPCError( RPC_INVALID_REQUEST, "A beacon advertisement is already pending for this CPID"); @@ -729,7 +729,7 @@ UniValue revokebeacon(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_REQUEST, "No active beacon for CPID"); case NN::BeaconError::NOT_NEEDED: throw JSONRPCError(RPC_INTERNAL_ERROR, "Unexpected error occurred"); - case NN::BeaconError::TOO_SOON: + case NN::BeaconError::PENDING: throw JSONRPCError(RPC_INTERNAL_ERROR, "Unexpected error occurred"); case NN::BeaconError::TX_FAILED: throw JSONRPCError(