diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..5926df14b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = tab +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[{package.json,*.yml}] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..58b836ea9 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,29 @@ +name: CI +on: + push: + branches: + - master + pull_request: + types: + - opened + - reopened + - synchronize +jobs: + build-and-test: + name: Node.js ${{ matrix.node-version }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: + - 16 + - 14 + - 12 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build + - run: npm run test diff --git a/CMakeLists.txt b/CMakeLists.txt index c46462f0a..200abc626 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,6 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") project(MyMoneroCoreCpp) # -include_directories("build/boost/include") # must exist already - run bin/build-boost-emscripten.sh -# include_directories("src") include_directories("node_modules") # @@ -30,7 +28,7 @@ include_directories("${MONERO_SRC}/mnemonics") include_directories("${MONERO_SRC}/contrib/libsodium/include") # support sodium/… paths include_directories("${MONERO_SRC}/contrib/libsodium/include/sodium") # -# keeping test files in a separate source directory +# keeping test files in a separate source directory # file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/test_*.cpp) # set( @@ -108,29 +106,10 @@ set( ${MONERO_SRC}/contrib/libsodium/src/crypto_verify/verify.c ) -set(boost_DIR ${CMAKE_SOURCE_DIR}/build/boost) - -add_library(boost_chrono STATIC IMPORTED) -set_target_properties( - boost_chrono PROPERTIES IMPORTED_LOCATION - ${boost_DIR}/lib/libboost_chrono.a -) -add_library(boost_system STATIC IMPORTED) -set_target_properties( - boost_system PROPERTIES IMPORTED_LOCATION - ${boost_DIR}/lib/libboost_system.a -) -# -add_library(boost_thread STATIC IMPORTED) -set_target_properties( - boost_thread PROPERTIES IMPORTED_LOCATION - ${boost_DIR}/lib/libboost_thread.a -) # # set ( EMCC_LINKER_FLAGS__WASM - #unsure if the -I...boost..include is necessary here due to include above # # TODO? does EXPORT_NAME need to be the same for both targets? (or should it be set per-target with …_WASM, …_ASMJS?) "-Wall -std=c++11 \ @@ -151,7 +130,7 @@ set ( -Oz \ -s ALLOW_MEMORY_GROWTH=1 \ " - # • Disabling exception catching does not introduce silent failures + # • Disabling exception catching does not introduce silent failures # • Probably don't need PRECISE_F32 but wouldn't want to not use it # # @@ -167,23 +146,8 @@ set_target_properties(MyMoneroCoreCpp_WASM PROPERTIES LINK_FLAGS "${EMCC_LINKER_ # # set_target_properties(MyMoneroCoreCpp_WASM PROPERTIES SUFFIX ".html") # -# boost_atomic -# boost_date_time -# boost_filesystem -# boost_locale -# boost_program_options -# boost_regex -# boost_serialization -# boost_signals -# boost_timer -# boost_wserialization -# target_link_libraries( MyMoneroCoreCpp_WASM # - boost_chrono - boost_system - boost_thread - # ${log-lib} -) \ No newline at end of file +) diff --git a/README.md b/README.md index d9ad5bba7..eb9521300 100644 --- a/README.md +++ b/README.md @@ -26,19 +26,19 @@ All source code copyright © 2014-2018 by MyMonero. All rights reserved. This repository holds the Javascript source code for the Monero/CryptoNote cryptography and protocols, plus lightwallet functions which power the official [MyMonero](https://www.mymonero.com) apps. -There is also a chain of build scripts which is capable of building a JS module by transpiling a subset of Monero source code via emscripten, which relies upon static boost libs, for which there is also a script for building from source. +There is also a chain of build scripts which is capable of building a JS module by transpiling a subset of Monero source code via emscripten, which relies upon static boost libs, for which there is also a script for building from source. -It's possible to run your own lightweight (hosted) wallet server by using either OpenMonero or the lightweight wallet server which MyMonero has developed specially to be open-sourced for the Monero community (PR is in the process of being merged). However, MyMonero also offers highly optimized, high throughput, secure hosting for a nominal, scaling fee per active wallet per month to wallet app makers who would like to use this library, mymonero-core-js, to add hosted Monero wallets to their app. +It's possible to run your own lightweight (hosted) wallet server by using either OpenMonero or the lightweight wallet server which MyMonero has developed specially to be open-sourced for the Monero community (PR is in the process of being merged). However, MyMonero also offers highly optimized, high throughput, secure hosting for a nominal, scaling fee per active wallet per month to wallet app makers who would like to use this library, mymonero-core-js, to add hosted Monero wallets to their app. The benefit of offering a hosted wallet rather than requiring users to use a remote node is that scanning doesn't have to take place on the mobile device, so the user doesn't have to download the blockchain and scan on their device, or wait when they switch to a new device or come back to the app after a period of time. For more information, please reach out to Devin at [support@mymonero.com](support@mymonero.com). We work hard to support the growth of the Monero ecosystem, and will be happy to work with integrators on flexible pricing. -### Contents +### Contents -`monero_utils` contains Monero- and MyMonero-specific implementations, wrappers, and declarations, and the MyMonero JS and wasm (and asm.js fallback/polyfill) implementations for the underlying cryptography behind Monero. +`monero_utils` contains Monero- and MyMonero-specific implementations, wrappers, and declarations, and the MyMonero JS and wasm (and asm.js fallback/polyfill) implementations for the underlying cryptography behind Monero. `monero_utils/MyMoneroCoreCpp*` are produced by transpiling Monero core C++ code to JS via Emscripten (See *Building MyMoneroCoreCpp*). A Module instance is managed by `monero_utils/MyMoneroCoreBridge.js`. -Library integrators may use `MyMoneroCoreBridge` by `require("./monero_utils/MyMoneroCoreBridge")({}).then(function(coreBridge_instance) { })`. (This was formerly accessed via the now-deprecated `monero_utils/monero_utils`). You may also access this MyMoneroCoreBridge promise via the existing `index.js` property `monero_utils_promise` (the name has been kept the same for API stability). +Library integrators may use `MyMoneroCoreBridge` by `require("./monero_utils/MyMoneroCoreBridge")({}).then(function(coreBridge_instance) { })`. (This was formerly accessed via the now-deprecated `monero_utils/monero_utils`). You may also access this MyMoneroCoreBridge promise via the existing `index.js` property `monero_utils_promise` (the name has been kept the same for API stability). Many related utility functions and data structures are located throughout `monero_utils/`, `cryptonote_utils`, and `hostAPI`. Usage below. @@ -51,7 +51,7 @@ This readme is located at `README.md`, and the license is located at `LICENSE.tx If you would like to package this library to run in a standalone manner within, e.g. a webpage, similarly to how the old mymonero.com used this library, a script is provided to bundle everything for you. It's located at `bin/package_browser_js`. If you package the library in this manner, the resulting `mymonero-core.js` file can be included via a script tag. The index.js of the library will then be available as the global variable `mymonero_core_js`. -Alternatively you can bundle the contents in any other manner you prefer, including directly accessing them via your favorite module system. +Alternatively you can bundle the contents in any other manner you prefer, including directly accessing them via your favorite module system. ### `hostAPI` @@ -67,7 +67,7 @@ const endpointPath = "get_address_info" const parameters = net_service_utils.New_ParametersForWalletRequest(address, view_key__private) ``` -``` +``` monero_utils_promise.then(function(monero_utils) { response_parser_utils.Parsed_AddressTransactions__keyImageManaged( data, @@ -122,7 +122,7 @@ Functions: `formatMoneyFull`, `formatMoneyFullSymbol`, `formatMoney`, `formatMon ----- ### `monero_utils/monero_txParsing_utils` -Use these functions to derive additional state from transaction rows which were returned by a server and then parsed by `hostAPI`. +Use these functions to derive additional state from transaction rows which were returned by a server and then parsed by `hostAPI`. * `IsTransactionConfirmed(tx, blockchain_height)` * `IsTransactionUnlocked(tx, blockchain_height)` @@ -279,25 +279,30 @@ We often collaborate over IRC in #mymonero on Freenode. There's no need to build monero_utils/MyMoneroCoreCpp as a build is provided, but if you were for example interested in adding a C++ function, you could use the information in this section to transpile it to JS. +## Build everything in one go + +```bash +npm ci +npm run build +``` + +If this does not work for you, proceed with the steps below. + ## Building New WASM 1. Clone the repo `git clone https://github.com/mymonero/mymonero-core-js.git` 2. `cd mymonero-core-js` 3. Run `npm install` -4. Download Boost libraries -* `curl -LO https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz` or `wget https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz` - For Mac, you can verify the integrity of the archive by running `shasum -a 256 boost_1_76_0.tar.gz`. You should see the following hash: `7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca` -5. `mkdir -p contrib/boost-sdk` -6. `tar zxf boost_1_76_0.tar.gz -C contrib/boost-sdk --strip-components=1` -7. `rm -rf build && mkdir build` -8. `rm monero_utils/MyMoneroCoreCpp_*` +4. `rm -rf build && mkdir build` +5. `rm monero_utils/MyMoneroCoreCpp_*` ### Build boost emscripten -9. `npm run build:boost` +6. `npm run build:boost` ### Build MyMonero emscripten -10. `npm run build:emscripten` - * If you get '#error Including requires building with -std=c++11 or newer!' error, re-run step 10. - +7. `npm run build:emscripten` + * If you get '#error Including requires building with -std=c++11 or newer!' error, re-run step 7. + By following these instructions, new WASM library are generated and copied to the monero_utils folder @@ -318,7 +323,7 @@ There's no need to build monero_utils/MyMoneroCoreCpp as a build is provided, bu * luigi1111 -* Lucas Jones +* Lucas Jones * gutenye diff --git a/bin/archive-emcpp.sh b/bin/archive-emcpp.sh index 634ace087..856c2c072 100755 --- a/bin/archive-emcpp.sh +++ b/bin/archive-emcpp.sh @@ -1,5 +1,5 @@ -#!/bin/sh +#!/bin/sh -xe -bin/build-emcpp.sh && -cp build/MyMoneroCoreCpp_WASM.js monero_utils/; -cp build/MyMoneroCoreCpp_WASM.wasm monero_utils/; \ No newline at end of file +bin/build-emcpp.sh +cp build/MyMoneroCoreCpp_WASM.js monero_utils/ +cp build/MyMoneroCoreCpp_WASM.wasm monero_utils/ diff --git a/bin/build-all.sh b/bin/build-all.sh new file mode 100755 index 000000000..5e44cb72d --- /dev/null +++ b/bin/build-all.sh @@ -0,0 +1,7 @@ +#!/bin/sh -xe + +rm -rf build monero_utils/MyMoneroCoreCpp_* +mkdir -p build + +./bin/build-boost-emscripten.sh +./bin/archive-emcpp.sh diff --git a/bin/build-boost-emscripten.sh b/bin/build-boost-emscripten.sh index 7bfa5ac75..90e279a27 100755 --- a/bin/build-boost-emscripten.sh +++ b/bin/build-boost-emscripten.sh @@ -1,80 +1,11 @@ -#!/bin/sh - -PLATFORM="emscripten" - -SRC_DIR="contrib/boost-sdk" -INSTALL_DIR="build/boost" - -SRC_PATH="$(pwd)/$SRC_DIR" -INSTALL_PATH="$(pwd)/$INSTALL_DIR" -JAM_CONFIG_PATH="$(pwd)/configs/$PLATFORM.jam" - -if [ ! -d "$SRC_PATH" ]; then - echo "SOURCE NOT FOUND!" - exit 1 -fi +#!/bin/sh -xe if [ -z "$EMSCRIPTEN" ]; then echo "EMSCRIPTEN MUST BE DEFINED!" - exit -1 -fi - -cd $EMSCRIPTEN; ./embuilder.py build zlib - -# --- - -cd "$SRC_PATH" - -rm -rf bjam -rm -rf b2 -rm -rf project-config.jam -rm -rf bootstrap.log -rm -rf bin.v2 - -export NO_BZIP2=1 #bc it's supplied by emscripten but b2 will fail to find it - - -# --with-libraries=atomic,signals,timer,system,filesystem,thread,date_time,chrono,regex,serialization,program_options,locale \ - - -./bootstrap.sh \ - --with-libraries=system,thread,chrono \ -2>&1 - -if [ $? != 0 ]; then - echo "ERROR: boostrap FAILED!" - exit 1 -fi - -cat "$JAM_CONFIG_PATH" >> project-config.jam - -# --- -# Clean -rm -rf "$INSTALL_PATH" -mkdir "$INSTALL_PATH" - - -HOST_NCORES=$(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1) - - -# threading=single \ -./b2 -q -a -j$HOST_NCORES \ - toolset=clang-emscripten \ - link=static \ - optimization=space \ - variant=release \ - stage \ - --stagedir="$INSTALL_PATH" \ - 2>&1 - -unset NO_BZIP2 - -if [ $? != 0 ]; then - echo "ERROR: b2 FAILED!" - exit 1 + exit -1 fi -# --- +cd $EMSCRIPTEN -cd "$INSTALL_PATH" -ln -s "$SRC_PATH" include \ No newline at end of file +./embuilder.py build zlib +./embuilder.py build boost_headers diff --git a/bin/build-emcpp.sh b/bin/build-emcpp.sh index 1ff1306cc..45d8e9f6c 100755 --- a/bin/build-emcpp.sh +++ b/bin/build-emcpp.sh @@ -1,9 +1,12 @@ -#!/bin/sh +#!/bin/sh -xe -#EMCC_DEBUG=1 +#EMCC_DEBUG=1 -mkdir -p build && -cd build && -emcmake cmake .. && -emmake cmake --build . && -emmake make . \ No newline at end of file +HOST_NCORES=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 1) + +mkdir -p build +cd build + +emcmake cmake .. +emmake cmake --build . -j$HOST_NCORES +emmake make -j$HOST_NCORES . diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 000000000..9f96dd4ed --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,11 @@ +#!/bin/sh -xe + +docker \ + run \ + --rm \ + -i \ + -v $(pwd):/app \ + -w /app \ + -e EMSCRIPTEN=/emsdk/upstream/emscripten \ + emscripten/emsdk:3.0.1 \ + ./bin/build-all.sh diff --git a/package.json b/package.json index ecddb8630..b02a2a7e0 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,9 @@ "url": "git+https://github.com/mymonero/mymonero-core-js.git" }, "scripts": { - "build:boost": "docker run --rm -it -v $(pwd):/app -w /app -w /app -e EMSCRIPTEN=/emsdk/upstream/emscripten emscripten/emsdk ./bin/build-boost-emscripten.sh", - "build:emscripten": "docker run --rm -it -v $(pwd):/app -w /app -e EMSCRIPTEN=/emsdk/upstream/emscripten emscripten/emsdk ./bin/archive-emcpp.sh", + "build:boost": "docker run --rm -it -v $(pwd):/app -w /app -w /app -e EMSCRIPTEN=/emsdk/upstream/emscripten emscripten/emsdk:3.0.1 ./bin/build-boost-emscripten.sh", + "build:emscripten": "docker run --rm -it -v $(pwd):/app -w /app -e EMSCRIPTEN=/emsdk/upstream/emscripten emscripten/emsdk:3.0.1 ./bin/archive-emcpp.sh", + "build": "./bin/build.sh", "format": "find . -name '*.js*' | xargs prettier --write --config ./.prettierrc --config-precedence file-override", "test": "mocha", "install": "napa" diff --git a/test/monero_utils.spec.js b/test/monero_utils.spec.js index 6e99c73f8..90963f2ec 100644 --- a/test/monero_utils.spec.js +++ b/test/monero_utils.spec.js @@ -2,6 +2,8 @@ const mymonero = require("../"); const assert = require("assert"); +process.setMaxListeners(32); + var public_key = "904e49462268d771cc1649084c35aa1296bfb214880fe2e7f373620a3e2ba597"; var private_key = @@ -10,6 +12,7 @@ var private_key = var nettype = mymonero.nettype_utils.network_type.MAINNET; describe("cryptonote_utils tests", function() { + this.timeout(16000); it("create_address aka address_and_keys_from_seed", async function() { const monero_utils = await require("../monero_utils/MyMoneroCoreBridge")({})