diff --git a/.gitignore b/.gitignore index f7bcbd145986d4..fa1f7102636679 100644 --- a/.gitignore +++ b/.gitignore @@ -149,3 +149,7 @@ dist/ /guix-build-* /ci/scratch/ + +.idea/ +build/ +build_clion/ \ No newline at end of file diff --git a/configure.ac b/configure.ac index be3e43c73e2f77..7947cb9d20cc63 100644 --- a/configure.ac +++ b/configure.ac @@ -99,6 +99,16 @@ esac dnl Require C++20 compiler (no GNU extensions) AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) +compiler_name=`basename "$CC"` +if test "x$compiler_name" = "xemcc"; then + with_emscripten=yes +else + with_emscripten=no +fi + +dnl check if additional link flags are required for std::filesystem +CHECK_FILESYSTEM + dnl Unless the user specified OBJCXX, force it to be the same as CXX. This ensures dnl that we get the same -std flags for both. m4_ifdef([AC_PROG_OBJCXX],[ @@ -296,6 +306,13 @@ AC_ARG_ENABLE([external-signer], [use_external_signer=$enableval], [use_external_signer=yes]) +AC_ARG_ENABLE([limited-api], + [AS_HELP_STRING([--enable-limited-api],[build just limited consensus API for libconsensus for limited architectures like WASM (default is no)])], + [enable_limited_api=$enableval], + [enable_limited_api=no]) + +AM_CONDITIONAL([LIMITED_API], [test "$enable_limited_api" = "yes"]) + AC_LANG_PUSH([C++]) dnl Always set -g -O2 in our CXXFLAGS. Autoconf will try and set CXXFLAGS to "-g -O2" by default, @@ -343,8 +360,10 @@ if test "$enable_debug" = "yes"; then [$CXXFLAG_WERROR]) AX_CHECK_PREPROC_FLAG([-DDEBUG], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG"], [], [$CXXFLAG_WERROR]) +if test "x$with_emscripten" != "xyes"; then AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKORDER], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKORDER"], [], [$CXXFLAG_WERROR]) AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKCONTENTION], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKCONTENTION"], [], [$CXXFLAG_WERROR]) +fi AX_CHECK_PREPROC_FLAG([-DRPC_DOC_CHECK], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DRPC_DOC_CHECK"], [], [$CXXFLAG_WERROR]) AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME], [DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"], [], [$CXXFLAG_WERROR]) AX_CHECK_COMPILE_FLAG([-ftrapv], [DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"], [], [$CXXFLAG_WERROR]) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 539578085b5add..f6ac4771446ee3 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -9,7 +9,9 @@ #include #include #include +#ifndef __EMSCRIPTEN__ #include +#endif #include #include #include @@ -89,7 +91,9 @@ void ReadRegTestArgs(const ArgsManager& args, CChainParams::RegTestOptions& opti if (vDeploymentParams[0] == VersionBitsDeploymentInfo[j].name) { options.version_bits_parameters[Consensus::DeploymentPos(j)] = vbparams; found = true; +#ifndef __EMSCRIPTEN__ LogPrintf("Setting version bits activation parameters for %s to start=%ld, timeout=%ld, min_activation_height=%d\n", vDeploymentParams[0], vbparams.start_time, vbparams.timeout, vbparams.min_activation_height); +#endif break; } } diff --git a/src/coins.cpp b/src/coins.cpp index b62653e0de9612..fe26ac3ce5574a 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -5,7 +5,9 @@ #include #include +#ifndef __EMSCRIPTEN__ #include +#endif #include #include @@ -361,7 +363,9 @@ static bool ExecuteBackedWrapper(Func func, const std::vector #include #include +#ifndef LIMITED_API #include +#endif #include #include #include @@ -23,7 +25,9 @@ #include #include #include +#ifndef __EMSCRIPTEN__ #include +#endif #ifdef WIN32 #include @@ -33,7 +37,7 @@ #include #endif -#if defined(HAVE_GETRANDOM) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX)) +#if defined(HAVE_GETRANDOM) || (defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) || defined(__EMSCRIPTEN__)) #include #endif @@ -44,9 +48,26 @@ #include #endif +#ifdef __EMSCRIPTEN__ +extern "C" double emscripten_get_now(void); +int64_t GetTimeMicros() +{ + union { + double fractional; + int64_t integer; + } value; + value.fractional = emscripten_get_now(); + + return value.integer; +} + +#endif + [[noreturn]] static void RandFailure() { +#ifndef LIMITED_API LogPrintf("Failed to read randomness, aborting\n"); +#endif std::abort(); } @@ -64,6 +85,8 @@ static inline int64_t GetPerformanceCounter() noexcept uint64_t r1 = 0, r2 = 0; __asm__ volatile ("rdtsc" : "=a"(r1), "=d"(r2)); // Constrain r1 to rax and r2 to rdx. return (r2 << 32) | r1; +#elif defined(__EMSCRIPTEN__) + return GetTimeMicros(); #else // Fall back to using standard library clock (usually microsecond or nanosecond precision) return std::chrono::high_resolution_clock::now().time_since_epoch().count(); @@ -95,6 +118,7 @@ static void InitHardwareRand() } } +#ifndef LIMITED_API static void ReportHardwareRand() { // This must be done in a separate function, as InitHardwareRand() may be indirectly called @@ -106,6 +130,7 @@ static void ReportHardwareRand() LogPrintf("Using RdRand as an additional entropy source\n"); } } +#endif /** Read 64 bits of entropy using rdrand. * @@ -322,7 +347,7 @@ static void Strengthen(const unsigned char (&seed)[32], SteadyClock::duration du memory_cleanse(buffer, sizeof(buffer)); } -#ifndef WIN32 +#if !defined(WIN32) && !defined(__EMSCRIPTEN__) /** Fallback: get 32 bytes of system entropy from /dev/urandom. The most * compatible way to get cryptographic randomness on UNIX-ish platforms. */ @@ -376,7 +401,7 @@ void GetOSRand(unsigned char *ent32) The function call is always successful. */ arc4random_buf(ent32, NUM_OS_RANDOM_BYTES); -#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) +#elif defined(HAVE_GETENTROPY_RAND) && defined(MAC_OSX) || defined(__EMSCRIPTEN__) if (getentropy(ent32, NUM_OS_RANDOM_BYTES) != 0) { RandFailure(); } @@ -572,8 +597,9 @@ static void SeedPeriodic(CSHA512& hasher, RNGState& rng) noexcept // Dynamic environment data (performance monitoring, ...) auto old_size = hasher.Size(); RandAddDynamicEnv(hasher); +#ifndef LIMITED_API LogPrint(BCLog::RAND, "Feeding %i bytes of dynamic environment data into RNG\n", hasher.Size() - old_size); - +#endif // Strengthen for 10 ms SeedStrengthen(hasher, rng, 10ms); } @@ -592,7 +618,9 @@ static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept // Static environment data RandAddStaticEnv(hasher); +#ifndef LIMITED_API LogPrint(BCLog::RAND, "Feeding %i bytes of environment data into RNG\n", hasher.Size() - old_size); +#endif // Strengthen for 100 ms SeedStrengthen(hasher, rng, 100ms); diff --git a/src/random.h b/src/random.h index f7c20ee4b038e4..2c253691b94b80 100644 --- a/src/random.h +++ b/src/random.h @@ -13,7 +13,9 @@ #include #include +#ifndef __EMSCRIPTEN__ #include +#endif #include #include #include @@ -97,6 +99,7 @@ D GetRandomDuration(typename std::common_type::type max) noexcept constexpr auto GetRandMicros = GetRandomDuration; constexpr auto GetRandMillis = GetRandomDuration; +#ifndef __EMSCRIPTEN__ /** * Return a timestamp in the future sampled from an exponential distribution * (https://en.wikipedia.org/wiki/Exponential_distribution). This distribution @@ -107,6 +110,7 @@ constexpr auto GetRandMillis = GetRandomDuration; * is the average interval between events. * */ std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval); +#endif uint256 GetRandHash() noexcept; diff --git a/src/randomenv.cpp b/src/randomenv.cpp index aeec959c28c61c..7792deace4e134 100644 --- a/src/randomenv.cpp +++ b/src/randomenv.cpp @@ -256,7 +256,7 @@ void RandAddDynamicEnv(CSHA512& hasher) hasher << std::chrono::steady_clock::now().time_since_epoch().count(); hasher << std::chrono::high_resolution_clock::now().time_since_epoch().count(); -#ifndef WIN32 +#if !defined(WIN32) && !defined(__EMSCRIPTEN__) // Current resource usage. struct rusage usage = {}; if (getrusage(RUSAGE_SELF, &usage) == 0) hasher << usage; @@ -398,6 +398,7 @@ void RandAddStaticEnv(CSHA512& hasher) hasher.Write((const unsigned char*)&name.machine, strlen(name.machine) + 1); } +#ifndef __EMSCRIPTEN__ /* Path and filesystem provided data */ AddPath(hasher, "/"); AddPath(hasher, "."); @@ -415,6 +416,7 @@ void RandAddStaticEnv(CSHA512& hasher) AddFile(hasher, "/etc/resolv.conf"); AddFile(hasher, "/etc/timezone"); AddFile(hasher, "/etc/localtime"); +#endif #endif // For MacOS/BSDs, gather data through sysctl instead of /proc. Not all of these diff --git a/src/support/allocators/secure.h b/src/support/allocators/secure.h index 4395567722e6ed..52bed4efdebc0a 100644 --- a/src/support/allocators/secure.h +++ b/src/support/allocators/secure.h @@ -6,7 +6,9 @@ #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H +#ifndef __EMSCRIPTEN__ #include +#endif #include #include @@ -26,11 +28,15 @@ struct secure_allocator { T* allocate(std::size_t n) { +#ifndef __EMSCRIPTEN__ T* allocation = static_cast(LockedPoolManager::Instance().alloc(sizeof(T) * n)); if (!allocation) { throw std::bad_alloc(); } return allocation; +#else + return std::allocator::allocate(n); +#endif } void deallocate(T* p, std::size_t n) @@ -38,7 +44,11 @@ struct secure_allocator { if (p != nullptr) { memory_cleanse(p, sizeof(T) * n); } +#ifndef __EMSCRIPTEN__ LockedPoolManager::Instance().free(p); +#else + std::allocator::deallocate(p, n); +#endif } template