mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 20:42:59 +01:00
Merge pull request #5152 from vijaydasmp/bp21_14
backport: Merge bitcoin#18814, 18781
This commit is contained in:
commit
596f26a195
@ -14,16 +14,14 @@
|
|||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#endif
|
#endif
|
||||||
#include <logging.h> // for LogPrintf()
|
#include <logging.h> // for LogPrintf()
|
||||||
|
#include <randomenv.h>
|
||||||
|
#include <support/allocators/secure.h>
|
||||||
#include <sync.h> // for Mutex
|
#include <sync.h> // for Mutex
|
||||||
#include <util/time.h> // for GetTimeMicros()
|
#include <util/time.h> // for GetTimeMicros()
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <randomenv.h>
|
|
||||||
|
|
||||||
#include <support/allocators/secure.h>
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
@ -582,16 +580,6 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max) noexcept
|
|
||||||
{
|
|
||||||
return std::chrono::microseconds{GetRand(duration_max.count())};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept
|
|
||||||
{
|
|
||||||
return std::chrono::milliseconds{GetRand(duration_max.count())};
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
|
void GetRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::FAST); }
|
||||||
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
|
void GetStrongRandBytes(unsigned char* buf, int num) noexcept { ProcRand(buf, num, RNGLevel::SLOW); }
|
||||||
void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
|
void RandAddPeriodic() noexcept { ProcRand(nullptr, 0, RNGLevel::PERIODIC); }
|
||||||
|
16
src/random.h
16
src/random.h
@ -70,9 +70,21 @@
|
|||||||
* Thread-safe.
|
* Thread-safe.
|
||||||
*/
|
*/
|
||||||
void GetRandBytes(unsigned char* buf, int num) noexcept;
|
void GetRandBytes(unsigned char* buf, int num) noexcept;
|
||||||
|
/** Generate a uniform random integer in the range [0..range). Precondition: range > 0 */
|
||||||
uint64_t GetRand(uint64_t nMax) noexcept;
|
uint64_t GetRand(uint64_t nMax) noexcept;
|
||||||
std::chrono::microseconds GetRandMicros(std::chrono::microseconds duration_max) noexcept;
|
/** Generate a uniform random duration in the range [0..max). Precondition: max.count() > 0 */
|
||||||
std::chrono::milliseconds GetRandMillis(std::chrono::milliseconds duration_max) noexcept;
|
template <typename D>
|
||||||
|
D GetRandomDuration(typename std::common_type<D>::type max) noexcept
|
||||||
|
// Having the compiler infer the template argument from the function argument
|
||||||
|
// is dangerous, because the desired return value generally has a different
|
||||||
|
// type than the function argument. So std::common_type is used to force the
|
||||||
|
// call site to specify the type of the return value.
|
||||||
|
{
|
||||||
|
assert(max.count() > 0);
|
||||||
|
return D{GetRand(max.count())};
|
||||||
|
};
|
||||||
|
constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
|
||||||
|
constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
|
||||||
int GetRandInt(int nMax) noexcept;
|
int GetRandInt(int nMax) noexcept;
|
||||||
uint256 GetRandHash() noexcept;
|
uint256 GetRandHash() noexcept;
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ static std::string rpcWarmupStatus GUARDED_BY(g_rpc_warmup_mutex) = "RPC server
|
|||||||
/* Timer-creating functions */
|
/* Timer-creating functions */
|
||||||
static RPCTimerInterface* timerInterface = nullptr;
|
static RPCTimerInterface* timerInterface = nullptr;
|
||||||
/* Map of name to timer. */
|
/* Map of name to timer. */
|
||||||
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers;
|
static Mutex g_deadline_timers_mutex;
|
||||||
|
static std::map<std::string, std::unique_ptr<RPCTimerBase> > deadlineTimers GUARDED_BY(g_deadline_timers_mutex);
|
||||||
static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler, std::multimap<std::string, std::vector<UniValue>> mapPlatformRestrictions);
|
static bool ExecuteCommand(const CRPCCommand& command, const JSONRPCRequest& request, UniValue& result, bool last_handler, std::multimap<std::string, std::vector<UniValue>> mapPlatformRestrictions);
|
||||||
|
|
||||||
// Any commands submitted by this user will have their commands filtered based on the mapPlatformRestrictions
|
// Any commands submitted by this user will have their commands filtered based on the mapPlatformRestrictions
|
||||||
@ -330,7 +331,7 @@ void InterruptRPC()
|
|||||||
void StopRPC()
|
void StopRPC()
|
||||||
{
|
{
|
||||||
LogPrint(BCLog::RPC, "Stopping RPC\n");
|
LogPrint(BCLog::RPC, "Stopping RPC\n");
|
||||||
deadlineTimers.clear();
|
WITH_LOCK(g_deadline_timers_mutex, deadlineTimers.clear());
|
||||||
DeleteAuthCookie();
|
DeleteAuthCookie();
|
||||||
g_rpcSignals.Stopped();
|
g_rpcSignals.Stopped();
|
||||||
}
|
}
|
||||||
@ -609,6 +610,7 @@ void RPCRunLater(const std::string& name, std::function<void()> func, int64_t nS
|
|||||||
{
|
{
|
||||||
if (!timerInterface)
|
if (!timerInterface)
|
||||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
|
||||||
|
LOCK(g_deadline_timers_mutex);
|
||||||
deadlineTimers.erase(name);
|
deadlineTimers.erase(name);
|
||||||
LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
|
LogPrint(BCLog::RPC, "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
|
||||||
deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
|
deadlineTimers.emplace(name, std::unique_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000)));
|
||||||
|
@ -28,6 +28,8 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
|
|||||||
for (int i = 10; i > 0; --i) {
|
for (int i = 10; i > 0; --i) {
|
||||||
BOOST_CHECK_EQUAL(GetRand(std::numeric_limits<uint64_t>::max()), uint64_t{10393729187455219830U});
|
BOOST_CHECK_EQUAL(GetRand(std::numeric_limits<uint64_t>::max()), uint64_t{10393729187455219830U});
|
||||||
BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits<int>::max()), int{769702006});
|
BOOST_CHECK_EQUAL(GetRandInt(std::numeric_limits<int>::max()), int{769702006});
|
||||||
|
BOOST_CHECK_EQUAL(GetRandMicros(std::chrono::hours{1}).count(), 2917185654);
|
||||||
|
BOOST_CHECK_EQUAL(GetRandMillis(std::chrono::hours{1}).count(), 2144374);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
constexpr SteadySeconds time_point{1s};
|
constexpr SteadySeconds time_point{1s};
|
||||||
@ -67,6 +69,8 @@ BOOST_AUTO_TEST_CASE(fastrandom_tests)
|
|||||||
for (int i = 10; i > 0; --i) {
|
for (int i = 10; i > 0; --i) {
|
||||||
BOOST_CHECK(GetRand(std::numeric_limits<uint64_t>::max()) != uint64_t{10393729187455219830U});
|
BOOST_CHECK(GetRand(std::numeric_limits<uint64_t>::max()) != uint64_t{10393729187455219830U});
|
||||||
BOOST_CHECK(GetRandInt(std::numeric_limits<int>::max()) != int{769702006});
|
BOOST_CHECK(GetRandInt(std::numeric_limits<int>::max()) != int{769702006});
|
||||||
|
BOOST_CHECK(GetRandMicros(std::chrono::hours{1}) != std::chrono::microseconds{2917185654});
|
||||||
|
BOOST_CHECK(GetRandMillis(std::chrono::hours{1}) != std::chrono::milliseconds{2144374});
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -108,7 +112,7 @@ BOOST_AUTO_TEST_CASE(stdrandom_test)
|
|||||||
BOOST_CHECK(x >= 3);
|
BOOST_CHECK(x >= 3);
|
||||||
BOOST_CHECK(x <= 9);
|
BOOST_CHECK(x <= 9);
|
||||||
|
|
||||||
std::vector<int> test{1,2,3,4,5,6,7,8,9,10};
|
std::vector<int> test{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
std::shuffle(test.begin(), test.end(), ctx);
|
std::shuffle(test.begin(), test.end(), ctx);
|
||||||
for (int j = 1; j <= 10; ++j) {
|
for (int j = 1; j <= 10; ++j) {
|
||||||
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
|
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
|
||||||
@ -118,7 +122,6 @@ BOOST_AUTO_TEST_CASE(stdrandom_test)
|
|||||||
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
|
BOOST_CHECK(std::find(test.begin(), test.end(), j) != test.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Test that Shuffle reaches every permutation with equal probability. */
|
/** Test that Shuffle reaches every permutation with equal probability. */
|
||||||
|
@ -1927,6 +1927,9 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
|
|||||||
CWallet* const pwallet = wallet.get();
|
CWallet* const pwallet = wallet.get();
|
||||||
|
|
||||||
int64_t nSleepTime;
|
int64_t nSleepTime;
|
||||||
|
int64_t relock_time;
|
||||||
|
// Prevent concurrent calls to walletpassphrase with the same wallet.
|
||||||
|
LOCK(pwallet->m_unlock_mutex);
|
||||||
{
|
{
|
||||||
LOCK(pwallet->cs_wallet);
|
LOCK(pwallet->cs_wallet);
|
||||||
|
|
||||||
@ -1975,7 +1978,7 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
|
|||||||
pwallet->TopUpKeyPool();
|
pwallet->TopUpKeyPool();
|
||||||
|
|
||||||
pwallet->nRelockTime = GetTime() + nSleepTime;
|
pwallet->nRelockTime = GetTime() + nSleepTime;
|
||||||
|
relock_time = pwallet->nRelockTime;
|
||||||
}
|
}
|
||||||
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
|
// rpcRunLater must be called without cs_wallet held otherwise a deadlock
|
||||||
// can occur. The deadlock would happen when RPCRunLater removes the
|
// can occur. The deadlock would happen when RPCRunLater removes the
|
||||||
@ -1986,9 +1989,11 @@ static UniValue walletpassphrase(const JSONRPCRequest& request)
|
|||||||
// wallet before the following callback is called. If a valid shared pointer
|
// wallet before the following callback is called. If a valid shared pointer
|
||||||
// is acquired in the callback then the wallet is still loaded.
|
// is acquired in the callback then the wallet is still loaded.
|
||||||
std::weak_ptr<CWallet> weak_wallet = wallet;
|
std::weak_ptr<CWallet> weak_wallet = wallet;
|
||||||
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet] {
|
pwallet->chain().rpcRunLater(strprintf("lockwallet(%s)", pwallet->GetName()), [weak_wallet, relock_time] {
|
||||||
if (auto shared_wallet = weak_wallet.lock()) {
|
if (auto shared_wallet = weak_wallet.lock()) {
|
||||||
LOCK(shared_wallet->cs_wallet);
|
LOCK(shared_wallet->cs_wallet);
|
||||||
|
// Skip if this is not the most recent rpcRunLater callback.
|
||||||
|
if (shared_wallet->nRelockTime != relock_time) return;
|
||||||
shared_wallet->Lock();
|
shared_wallet->Lock();
|
||||||
shared_wallet->nRelockTime = 0;
|
shared_wallet->nRelockTime = 0;
|
||||||
}
|
}
|
||||||
|
@ -965,8 +965,10 @@ public:
|
|||||||
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
std::vector<std::string> GetDestValues(const std::string& prefix) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
|
||||||
|
|
||||||
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
|
//! Holds a timestamp at which point the wallet is scheduled (externally) to be relocked. Caller must arrange for actual relocking to occur via Lock().
|
||||||
int64_t nRelockTime = 0;
|
int64_t nRelockTime GUARDED_BY(cs_wallet){0};
|
||||||
|
|
||||||
|
// Used to prevent concurrent calls to walletpassphrase RPC.
|
||||||
|
Mutex m_unlock_mutex;
|
||||||
bool Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnly = false, bool accept_no_keys = false);
|
bool Unlock(const SecureString& strWalletPassphrase, bool fForMixingOnly = false, bool accept_no_keys = false);
|
||||||
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
|
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
|
||||||
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
bool EncryptWallet(const SecureString& strWalletPassphrase);
|
||||||
|
Loading…
Reference in New Issue
Block a user