Skip to content

Commit

Permalink
WASM + python bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
l2xl committed Jun 9, 2024
1 parent e9a86cb commit 3dab612
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 6 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,7 @@ dist/
/guix-build-*

/ci/scratch/

.idea/
build/
build_clion/
19 changes: 19 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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],[
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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])
Expand Down
4 changes: 4 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include <common/args.h>
#include <consensus/params.h>
#include <deploymentinfo.h>
#ifndef __EMSCRIPTEN__
#include <logging.h>
#endif
#include <tinyformat.h>
#include <util/chaintype.h>
#include <util/strencodings.h>
Expand Down Expand Up @@ -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;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/coins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include <coins.h>

#include <consensus/consensus.h>
#ifndef __EMSCRIPTEN__
#include <logging.h>
#endif
#include <random.h>
#include <util/trace.h>

Expand Down Expand Up @@ -361,7 +363,9 @@ static bool ExecuteBackedWrapper(Func func, const std::vector<std::function<void
for (const auto& f : err_callbacks) {
f();
}
#ifndef __EMSCRIPTEN__
LogPrintf("Error reading from database: %s\n", e.what());
#endif
// Starting the shutdown sequence and returning false to the caller would be
// interpreted as 'entry not found' (as opposed to unable to read data), and
// could lead to invalid interpretation. Just exit immediately, as we can't
Expand Down
4 changes: 4 additions & 0 deletions src/core_write.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ std::string EncodeHexTx(const CTransaction& tx)
return HexStr(ssTx);
}

#ifndef LIMITED_API

void ScriptToUniv(const CScript& script, UniValue& out, bool include_hex, bool include_address, const SigningProvider* provider)
{
CTxDestination address;
Expand Down Expand Up @@ -267,3 +269,5 @@ void TxToUniv(const CTransaction& tx, const uint256& block_hash, UniValue& entry
entry.pushKV("hex", EncodeHexTx(tx)); // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
}
}

#endif
2 changes: 2 additions & 0 deletions src/primitives/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ Txid CMutableTransaction::GetHash() const
return Txid::FromUint256((HashWriter{} << TX_NO_WITNESS(*this)).GetHash());
}

const int32_t CTransaction::CURRENT_VERSION = 2;

bool CTransaction::ComputeHasWitness() const
{
return std::any_of(vin.begin(), vin.end(), [](const auto& input) {
Expand Down
2 changes: 1 addition & 1 deletion src/primitives/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ class CTransaction
{
public:
// Default transaction version.
static const int32_t CURRENT_VERSION=2;
static const int32_t CURRENT_VERSION;

// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not
Expand Down
36 changes: 32 additions & 4 deletions src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
#include <crypto/chacha20.h>
#include <crypto/sha256.h>
#include <crypto/sha512.h>
#ifndef LIMITED_API
#include <logging.h>
#endif
#include <randomenv.h>
#include <span.h>
#include <support/allocators/secure.h>
Expand All @@ -23,7 +25,9 @@
#include <array>
#include <cmath>
#include <cstdlib>
#ifndef __EMSCRIPTEN__
#include <thread>
#endif

#ifdef WIN32
#include <windows.h>
Expand All @@ -33,7 +37,7 @@
#include <sys/time.h>
#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 <sys/random.h>
#endif

Expand All @@ -44,9 +48,26 @@
#include <sys/auxv.h>
#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();
}

Expand All @@ -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();
Expand Down Expand Up @@ -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
Expand All @@ -106,6 +130,7 @@ static void ReportHardwareRand()
LogPrintf("Using RdRand as an additional entropy source\n");
}
}
#endif

/** Read 64 bits of entropy using rdrand.
*
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions src/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@

#include <bit>
#include <cassert>
#ifndef __EMSCRIPTEN__
#include <chrono>
#endif
#include <cstdint>
#include <limits>
#include <vector>
Expand Down Expand Up @@ -97,6 +99,7 @@ D GetRandomDuration(typename std::common_type<D>::type max) noexcept
constexpr auto GetRandMicros = GetRandomDuration<std::chrono::microseconds>;
constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;

#ifndef __EMSCRIPTEN__
/**
* Return a timestamp in the future sampled from an exponential distribution
* (https://en.wikipedia.org/wiki/Exponential_distribution). This distribution
Expand All @@ -107,6 +110,7 @@ constexpr auto GetRandMillis = GetRandomDuration<std::chrono::milliseconds>;
* is the average interval between events.
* */
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval);
#endif

uint256 GetRandHash() noexcept;

Expand Down
4 changes: 3 additions & 1 deletion src/randomenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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, ".");
Expand All @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/support/allocators/secure.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H
#define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H

#ifndef __EMSCRIPTEN__
#include <support/lockedpool.h>
#endif
#include <support/cleanse.h>

#include <memory>
Expand All @@ -26,19 +28,27 @@ struct secure_allocator {

T* allocate(std::size_t n)
{
#ifndef __EMSCRIPTEN__
T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
if (!allocation) {
throw std::bad_alloc();
}
return allocation;
#else
return std::allocator<T>::allocate(n);
#endif
}

void deallocate(T* p, std::size_t n)
{
if (p != nullptr) {
memory_cleanse(p, sizeof(T) * n);
}
#ifndef __EMSCRIPTEN__
LockedPoolManager::Instance().free(p);
#else
std::allocator<T>::deallocate(p, n);
#endif
}

template <typename U>
Expand Down

0 comments on commit 3dab612

Please sign in to comment.