diff --git a/.core/build b/.core/build new file mode 160000 index 00000000..9c9346d5 --- /dev/null +++ b/.core/build @@ -0,0 +1 @@ +Subproject commit 9c9346d5494688a78ea573f3bc0547ad12b9be2a diff --git a/.core/build.yaml b/.core/build.yaml new file mode 100644 index 00000000..dcbd4f69 --- /dev/null +++ b/.core/build.yaml @@ -0,0 +1,83 @@ +# Lethean Blockchain Build Configuration +# Used by: core compile + +version: 1 + +project: + name: blockchain + type: cpp + description: "Lethean Blockchain - SASE infrastructure chain" + version: "6.0.1" + +cpp: + standard: 17 + build_type: Release + static: false + + conan: + version: "2.21.0" + requires: + - zlib/1.3.1 + - boost/1.85.0 + - openssl/3.2.0 + - miniupnpc/2.2.5 + - jwt-cpp/0.7.1 + - oatpp/1.3.0.latest + - oatpp-swagger/1.3.0.latest + tool_requires: + - cmake/3.31.9 + options: + boost/*:without_test: true + registry: + url: http://forge.snider.dev:4000/api/packages/host-uk/conan + remote: conan_build + + cmake: + minimum_version: "3.16" + variables: + USE_CCACHE: "ON" + + options: + testnet: false + +targets: + - os: linux + arch: x86_64 + profile: gcc-linux-x86_64 + - os: linux + arch: arm64 + profile: gcc-linux-armv8 + - os: darwin + arch: arm64 + profile: apple-clang-armv8 + - os: darwin + arch: x86_64 + profile: apple-clang-x86_64 + - os: windows + arch: x86_64 + profile: msvc-194-x86_64 + +package: + generators: + - TGZ + - ZIP + - NSIS + - DEB + - RPM + vendor: Lethean + contact: support@lt.hn + website: https://lt.hn + +docker: + dockerfile: utils/docker/lthn-chain/Dockerfile + image: lthn/chain + platforms: + - linux/amd64 + tags: + - testnet + - "{{.Version}}" + build_args: + BUILD_THREADS: auto + BUILD_TESTNET: "1" + BUILD_STATIC: "0" + BUILD_TYPE: Release diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml new file mode 100755 index 00000000..778cd7bd --- /dev/null +++ b/.forgejo/workflows/build.yml @@ -0,0 +1,234 @@ +name: Build & Release + +on: + workflow_dispatch: + push: + branches: + - dev + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + FORGEJO_URL: ${{ github.server_url }} + +jobs: + # ────────────────────────────────────────────── + # Linux x86_64 — native build on snider-linux + # ────────────────────────────────────────────── + build-linux: + name: Linux x86_64 + runs-on: linux-native + env: + CPU_CORES: "24" + steps: + - name: Checkout + uses: https://code.forgejo.org/actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + submodules: false + + - name: Init submodules + run: | + git config --global url."${{ env.FORGEJO_URL }}/".insteadOf "http://forge.snider.dev:4000/" + git -c http.extraHeader="Authorization: token ${{ secrets.RELEASE_TOKEN }}" submodule update --init --recursive + git submodule foreach --recursive 'git fetch --tags origin 2>/dev/null || true' + + - name: Build dependencies + run: | + make build-deps \ + CPU_CORES=${{ env.CPU_CORES }} \ + CONAN_URL=${{ env.FORGEJO_URL }}/api/packages/host-uk/conan \ + CONAN_USER=claude \ + CONAN_PASSWORD=${{ secrets.RELEASE_TOKEN }} + + - name: Compile + run: | + make ${{ github.ref_name == 'main' && 'mainnet' || 'testnet' }} \ + CPU_CORES=${{ env.CPU_CORES }} \ + CONAN_URL=${{ env.FORGEJO_URL }}/api/packages/host-uk/conan \ + CONAN_USER=claude \ + CONAN_PASSWORD=${{ secrets.RELEASE_TOKEN }} + + - name: Upload artifacts + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: linux-x86_64 + path: build/packages/lethean-* + retention-days: 7 + + # ────────────────────────────────────────────── + # macOS ARM64 — native build on M3 Ultra + # ────────────────────────────────────────────── + build-macos: + name: macOS ARM64 + runs-on: macos-native + env: + CPU_CORES: "24" + steps: + - name: Checkout + uses: https://code.forgejo.org/actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + submodules: false + + - name: Init submodules + run: | + git config --global url."${{ env.FORGEJO_URL }}/".insteadOf "http://forge.snider.dev:4000/" + git -c http.extraHeader="Authorization: token ${{ secrets.RELEASE_TOKEN }}" submodule update --init --recursive + git submodule foreach --recursive 'git fetch --tags origin 2>/dev/null || true' + + - name: Build dependencies + run: | + export PATH="/opt/homebrew/bin:$PATH" + make build-deps \ + CPU_CORES=${{ env.CPU_CORES }} \ + CONAN_URL=${{ env.FORGEJO_URL }}/api/packages/host-uk/conan \ + CONAN_USER=claude \ + CONAN_PASSWORD=${{ secrets.RELEASE_TOKEN }} + + - name: Compile + run: | + export PATH="/opt/homebrew/bin:$PATH" + make ${{ github.ref_name == 'main' && 'mainnet' || 'testnet' }} \ + CPU_CORES=${{ env.CPU_CORES }} \ + CONAN_URL=${{ env.FORGEJO_URL }}/api/packages/host-uk/conan \ + CONAN_USER=claude \ + CONAN_PASSWORD=${{ secrets.RELEASE_TOKEN }} + + - name: Upload artifacts + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + name: macos-arm64 + path: build/packages/lethean-* + retention-days: 7 + + # ────────────────────────────────────────────── + # Aggregate artifacts and create release + # ────────────────────────────────────────────── + release: + name: Create Release + needs: [build-linux, build-macos] + runs-on: linux-native + steps: + - name: Checkout + uses: https://code.forgejo.org/actions/checkout@v4 + with: + fetch-depth: 1 + submodules: false + + - name: Download Linux artifacts + uses: https://code.forgejo.org/forgejo/download-artifact@v4 + with: + name: linux-x86_64 + path: artifacts/linux + + - name: Download macOS artifacts + uses: https://code.forgejo.org/forgejo/download-artifact@v4 + with: + name: macos-arm64 + path: artifacts/macos + + - name: List artifacts + run: find artifacts/ -type f | sort + + - name: Compute release tag + id: release + run: | + VERSION=$(grep '^BUILD_VERSION:=' Makefile | cut -d'=' -f2) + if [ "${{ github.ref_name }}" = "main" ]; then + TAG="v${VERSION}+${{ github.run_number }}" + PRERELEASE=false + TITLE="v${VERSION} (build ${{ github.run_number }})" + else + TAG="v${VERSION}-beta+${{ github.run_number }}" + PRERELEASE=true + TITLE="v${VERSION}-beta (build ${{ github.run_number }})" + fi + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT" + echo "title=${TITLE}" >> "$GITHUB_OUTPUT" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Create release + id: create_release + run: | + RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ + "${{ env.FORGEJO_URL }}/api/v1/repos/${{ github.repository }}/releases" \ + -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \ + -H "Content-Type: application/json" \ + -d "{ + \"tag_name\": \"${{ steps.release.outputs.tag }}\", + \"target_commitish\": \"${{ github.sha }}\", + \"name\": \"${{ steps.release.outputs.title }}\", + \"body\": \"Automated build from \`${{ github.ref_name }}\` branch (run #${{ github.run_number }})\n\n## Platforms\n- Linux x86_64\n- macOS ARM64 (Apple Silicon)\", + \"draft\": false, + \"prerelease\": ${{ steps.release.outputs.prerelease }} + }") + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | sed '$d') + if [ "$HTTP_CODE" -ge 400 ]; then + echo "Failed to create release (HTTP ${HTTP_CODE}):" + echo "$BODY" + exit 1 + fi + RELEASE_ID=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") + echo "id=${RELEASE_ID}" >> "$GITHUB_OUTPUT" + echo "Created release ID: ${RELEASE_ID}" + + - name: Upload release assets + run: | + for dir in artifacts/linux artifacts/macos; do + for file in "$dir"/lethean-*; do + [ -f "$file" ] || continue + FILENAME=$(basename "$file") + echo "Uploading: ${FILENAME}" + HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ + "${{ env.FORGEJO_URL }}/api/v1/repos/${{ github.repository }}/releases/${{ steps.create_release.outputs.id }}/assets?name=${FILENAME}" \ + -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@${file}") + if [ "$HTTP_CODE" -ge 400 ]; then + echo "Failed to upload ${FILENAME} (HTTP ${HTTP_CODE})" + exit 1 + fi + echo "Uploaded ${FILENAME} (HTTP ${HTTP_CODE})" + done + done + + - name: Prune old releases + run: | + TAG_PREFIX="${{ github.ref_name == 'main' && 'v6' || 'v6.*-beta' }}" + CURRENT_ID="${{ steps.create_release.outputs.id }}" + echo "Keeping release ${CURRENT_ID}, pruning older ${TAG_PREFIX} releases..." + PAGE=1 + while true; do + RELEASES=$(curl -s "${{ env.FORGEJO_URL }}/api/v1/repos/${{ github.repository }}/releases?limit=50&page=${PAGE}" \ + -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}") + COUNT=$(echo "$RELEASES" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0) + [ "$COUNT" = "0" ] && break + echo "$RELEASES" | python3 -c " + import sys, json, fnmatch + for r in json.load(sys.stdin): + rid = r['id'] + tag = r['tag_name'] + if rid == ${CURRENT_ID}: + continue + if fnmatch.fnmatch(tag, '${TAG_PREFIX}*'): + print(f'{rid} {tag}') + " | while read -r RID RTAG; do + echo "Deleting release ${RTAG} (id=${RID})" + curl -s -o /dev/null -X DELETE \ + "${{ env.FORGEJO_URL }}/api/v1/repos/${{ github.repository }}/releases/${RID}" \ + -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" + curl -s -o /dev/null -X DELETE \ + "${{ env.FORGEJO_URL }}/api/v1/repos/${{ github.repository }}/tags/${RTAG}" \ + -H "Authorization: token ${{ secrets.RELEASE_TOKEN }}" + done + PAGE=$((PAGE + 1)) + done + echo "Prune complete" diff --git a/.gitmodules b/.gitmodules index e522feeb..5c7489d2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,9 @@ [submodule "docs"] path = docs url = https://github.com/letheanVPN/documentation.git +[submodule "contrib/randomx"] + path = contrib/randomx + url = https://github.com/tevador/RandomX.git +[submodule ".core/build"] + path = .core/build + url = http://forge.snider.dev:4000/host-uk/build.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 08ec3bdc..da6e936c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) list(INSERT CMAKE_MODULE_PATH 0 - "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + "${CMAKE_CURRENT_SOURCE_DIR}/.core/build/cmake") if(POLICY CMP0043) cmake_policy(SET CMP0043 NEW) diff --git a/CMakePresets.json b/CMakePresets.json index 80247a7d..80a4f47e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -18,7 +18,7 @@ "cacheVariables": { "TESTNET": "ON", "CMAKE_BUILD_TYPE": "Release", - "CMAKE_PROJECT_TOP_LEVEL_INCLUDES":"cmake/ConanProvider.cmake" + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES":".core/build/cmake/ConanProvider.cmake" } }, { @@ -30,7 +30,7 @@ "cacheVariables": { "TESTNET": "OFF", "CMAKE_BUILD_TYPE": "Release", - "CMAKE_PROJECT_TOP_LEVEL_INCLUDES":"cmake/ConanProvider.cmake" + "CMAKE_PROJECT_TOP_LEVEL_INCLUDES":".core/build/cmake/ConanProvider.cmake" } } ], diff --git a/ConanPresets.json b/ConanPresets.json index 57065026..6e1749b3 100644 --- a/ConanPresets.json +++ b/ConanPresets.json @@ -4,6 +4,6 @@ "conan": {} }, "include": [ - "build/release/conan/build/debug/generators/CMakePresets.json" + "build/release/generators/CMakePresets.json" ] } \ No newline at end of file diff --git a/Makefile b/Makefile index e4391e7b..3d0ca4a5 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,15 @@ # Distributed under the MIT/X11 software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. -# ------------------------------------------------------------ -# Detect the number of logical CPU cores – works on Linux, -# macOS, BSD, and Windows (both cmd.exe and PowerShell). -# ------------------------------------------------------------ +# ============================================================ +# Build system from host-uk/build submodule +# ============================================================ +BUILD_SYS := .core/build +CMAKE_DIR := $(BUILD_SYS)/cmake -# Default to “unknown” – will be overwritten below. +# ============================================================ +# Project Configuration +# ============================================================ CPU_CORES := 1 TESTNET:= 0 STATIC:= 0 @@ -19,21 +22,22 @@ BUILD_FOLDER:=build/release PRESET_BUILD:=conan-release PRESET_CONFIGURE:=conan-release +# ------------------------------------------------------------ +# Detect the number of logical CPU cores – works on Linux, +# macOS, BSD, and Windows (both cmd.exe and PowerShell). +# ------------------------------------------------------------ UNAME_S := $(shell uname -s 2>/dev/null || echo Unknown) ifeq ($(UNAME_S),Linux) - # Linux: try nproc first, fall back to /proc CPU_CORES := $(shell nproc 2>/dev/null || \ grep -c ^processor /proc/cpuinfo 2>/dev/null || echo 1) endif ifeq ($(UNAME_S),Darwin) - # macOS: sysctl reports the number of logical CPUs CPU_CORES := $(shell sysctl -n hw.logicalcpu 2>/dev/null || echo 1) endif ifeq ($(filter %BSD,$(UNAME_S)),%BSD) - # *BSD: also sysctl, but the key differs on some variants CPU_CORES := $(shell sysctl -n hw.ncpu 2>/dev/null || echo 1) endif @@ -41,29 +45,27 @@ ifeq ($(OS),Windows_NT) PRESET_CONFIGURE:=conan-default - # Prefer the environment variable that Windows sets for us. - # It works in both cmd.exe and PowerShell. CPU_CORES := $(NUMBER_OF_PROCESSORS) - # If for some reason the env var is empty, fall back to PowerShell. ifeq ($(CPU_CORES),) CPU_CORES := $(shell powershell -NoProfile -Command ^ "[Environment]::ProcessorCount") endif endif -# ----------------------------------------------------------------- -# Safety net – ensure we always have a positive integer. -# ----------------------------------------------------------------- +# Safety net CPU_CORES := $(or $(CPU_CORES),1) CPU_CORES := $(shell expr $(CPU_CORES) + 0 2>/dev/null || echo 1) CONAN_CPU_COUNT=$(CPU_CORES) -PROFILES :=$(patsubst cmake/profiles/%,%,$(wildcard cmake/profiles/*)) +# ============================================================ +# Paths — profiles and cmake modules from .build submodule +# ============================================================ +PROFILES :=$(patsubst $(CMAKE_DIR)/profiles/%,%,$(wildcard $(CMAKE_DIR)/profiles/*)) SORTED_PROFILES :=$(sort $(PROFILES)) CONAN_CACHE :=$(CURDIR)/build/sdk -CONAN_URL :=https://artifacts.host.uk.com/artifactory/api/conan/conan-build -CONAN_USER :=public -CONAN_PASSWORD :=Lethean1234 +CONAN_URL :=http://forge.snider.dev:4000/api/packages/host-uk/conan +CONAN_USER ?=$(shell echo $$CONAN_USER) +CONAN_PASSWORD ?=$(shell echo $$CONAN_PASSWORD) CONAN_EXECUTABLE :=$(CURDIR)/build/bin/conan CC_DOCKER_FILE ?=utils/docker/images/lthn-chain/Dockerfile SDK_PACKAGES_JSON :=$(wildcard utils/sdk/packages/*.json) @@ -111,10 +113,10 @@ docs: configure sdk: $(MAKE) -C utils/sdk $(filter-out $@,$(MAKECMDGOALS)) PACKAGE_VERSION=$(BUILD_VERSION) -# Rule for each profile +# Rule for each profile — uses .build/cmake/profiles/ $(PROFILES): conan-profile-detect @echo "Building profile: $@" - CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) install . -pr:h=cmake/profiles/$@ --build=missing -s build_type=$(BUILD_TYPE) + CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) install . -pr:h=$(CMAKE_DIR)/profiles/$@ --build=missing -s build_type=$(BUILD_TYPE) cmake -S . -B $(BUILD_FOLDER) -DCMAKE_TOOLCHAIN_FILE=$(BUILD_FOLDER)/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DSTATIC=$(STATIC) -DTESTNET=$(TESTNET) -DBUILD_VERSION=$(BUILD_VERSION) cmake --build $(BUILD_FOLDER) --config=$(BUILD_TYPE) --parallel=$(CPU_CORES) (cd $(BUILD_FOLDER) && cpack) @@ -128,10 +130,10 @@ help: @echo "" @echo "Available targets:" @printf " %-42s %s\n" "make clean" "Clean all build directories" - @printf " %-42s %s\n" "make get-conan" "Download and install conan locally" + @printf " %-42s %s\n" "make conan-get" "Download and install conan locally" @printf " %-42s %s\n" "make release" "Build release" - @printf " %-42s %s\n" "make static" "Build static release" - @printf " %-42s %s\n" "make debug" "Build debug" + @printf " %-42s %s\n" "make testnet" "Build testnet" + @printf " %-42s %s\n" "make mainnet" "Build mainnet" @printf " %-42s %s\n" "make test" "Build & run tests" @printf " %-42s %s\n" "make docs" "Builds offline documentation website" @printf " %-42s %s\n" "make docs-dev" "Runs local doc server, for editing/adding docs" @@ -161,17 +163,19 @@ test-debug: cmake --build build/test-debug --config=Debug --parallel=$(CPU_CORES) $(MAKE) test -# allowing this target to error quietly saves cross brwoser file detection +# Conan management — cmake modules from .build submodule conan-get: - cmake -P cmake/ConanGet.cmake + cmake -P $(CMAKE_DIR)/ConanGet.cmake +ifneq ($(CONAN_USER),) (CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) remote add conan_build $(CONAN_URL) && \ CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) remote login conan_build $(CONAN_USER) -p $(CONAN_PASSWORD)) || true +endif conan-upload: CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) upload "*" -r=conan_build --confirm conan-profile-detect: conan-get - cmake -P cmake/ConanProfileSetup.cmake + cmake -P $(CMAKE_DIR)/ConanProfileSetup.cmake docs-dev: configure @echo "Building Documentation" @@ -181,7 +185,7 @@ $(SDK_TARGETS): @# This is a proxy target. Handled by the 'sdk' rule. clean: - @cmake -P cmake/CleanBuild.cmake + @cmake -P $(CMAKE_DIR)/CleanBuild.cmake clean-build: clean rm -rf build @@ -189,5 +193,4 @@ clean-build: clean tags: ctags -R --sort=1 --c++-kinds=+p --fields=+iaS --extra=+q --language-force=C++ src contrib tests/gtest -.PHONY: all release upload-conan-cache docs docs-dev configure static static-release test test-release test-debug clean tags conan-profile-detect get-conan $(PROFILES) sdk $(SDK_TARGETS) -.PHONY: go-client \ No newline at end of file +.PHONY: all release upload-conan-cache docs docs-dev configure static static-release test test-release test-debug clean tags conan-profile-detect conan-get $(PROFILES) sdk $(SDK_TARGETS) diff --git a/cmake/CPackConfig.cmake b/cmake/CPackConfig.cmake deleted file mode 100644 index 9890ad10..00000000 --- a/cmake/CPackConfig.cmake +++ /dev/null @@ -1,88 +0,0 @@ - - -if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" OR CMAKE_BUILD_TYPE STREQUAL "") - set(CPACK_PACKAGE_NAME "${package_name}") - set(CPACK_PACKAGE_VENDOR "${package_vendor}") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${package_description}") - set(CPACK_PACKAGE_VERSION "${BUILD_VERSION}") - set(CPACK_PACKAGE_CONTACT "${package_contact}") - set(CPACK_PACKAGE_HOMEPAGE_URL "${package_website}") - - #set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local") # Linux/macOS default - #if(WIN32) - # set(CPACK_PACKAGING_INSTALL_PREFIX "C:/Program Files/${PROJECT_NAME}") - #endif() - - if(APPLE) - if("${package_macos_installer}" STREQUAL "DMG") - # set(CPACK_GENERATOR "DragNDrop") -# set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/resources/dmg_background.png") - # set(CPACK_DMG_VOLUME_NAME "${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION}") - # message(STATUS "Registered CPACK_GENERATOR: DragNDrop") - else () - # set(CPACK_GENERATOR "productbuild") - # set(CPACK_PRODUCTBUILD_IDENTIFIER "${package_macos_pkg_productbuild_identifier}") -# set(CPACK_PRODUCTBUILD_SIGNING_IDENTITY "Developer ID Installer: Your Company (TEAMID)") - # message(STATUS "Registered CPACK_GENERATOR: productbuild") - endif () - elseif(WIN32) - set(CPACK_GENERATOR "NSIS") - set(CPACK_NSIS_MODIFY_PATH ON) - set(CPACK_NSIS_HELP_LINK "https://lt.hn/getting-started/chain.html") - set(CPACK_NSIS_URL_INFO_ABOUT "https://lt.hn") - set(CPACK_NSIS_CONTACT "support@lt.hn") - set(CPACK_NSIS_UNINSTALL_NAME "Lethean CLI") - set(CPACK_NSIS_BRANDING_TEXT "Lethean Community") - set(CPACK_NSIS_MUI_FINISHPAGE_RUN "lethean-testnet-chain-node.exe") - - message(STATUS "Registered CPACK_GENERATOR: Inno exe") -# set(CPACK_WIX_PRODUCT_ICON "${CMAKE_SOURCE_DIR}/resources/windows_icon.ico") -# set(CPACK_WIX_LICENSE_RTF "${CMAKE_SOURCE_DIR}/LICENSE.rtf") -# set(CPACK_WIX_UPGRADE_GUID "D3F5A9C1-4B2E-4F5A-9C71-123456789ABC") # change once per major version - else() - set(CPACK_GENERATOR "DEB") - set(CPACK_GENERATOR "RPM") - message(STATUS "Registered CPACK_GENERATOR: deb") - set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${package_contact}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.28)") - set(CPACK_DEBIAN_PACKAGE_SECTION "utils") - set(CPACK_DEBIAN_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}") - # post‑install script (e.g., to register a systemd service) -# set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA -# "${CMAKE_SOURCE_DIR}/scripts/postinstall.sh") - endif() - - list(APPEND CPACK_GENERATOR "TXZ" "ZIP") - message(STATUS "Registered CPACK_GENERATOR: tgz") - message(STATUS "Registered CPACK_GENERATOR: zip") - set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) - set(CPACK_ARCHIVE_COMPONENT_INSTALL OFF) - set(CPACK_COMPONENTS_ALL) - set(CPACK_MONOLITHIC_INSTALL OFF) - set(CPACK_PACKAGE_CHECKSUM SHA256) - message(STATUS "Using SHA256 Checksums") - - set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt") - set(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md") - - set(CPACK_PACKAGE_DIRECTORY "${CMAKE_SOURCE_DIR}/build/packages") - - install(FILES README.md LICENSE.txt - DESTINATION "share/doc/${PROJECT_NAME}" - ) - - set(_arch "${CMAKE_SYSTEM_PROCESSOR}") - - if(_arch MATCHES "AMD64|x86_64") - set(_arch "x86_64") - elseif(_arch MATCHES "arm64|aarch64") - set(_arch "arm64") - endif() - - string(TOLOWER "${CMAKE_SYSTEM_NAME}" _sys_name_lc) - - set(CPACK_PACKAGE_FILE_NAME - "${package_name}-${CPACK_PACKAGE_VERSION}-${_sys_name_lc}-${_arch}") - - include(CPack) -endif() \ No newline at end of file diff --git a/cmake/CleanBuild.cmake b/cmake/CleanBuild.cmake deleted file mode 100644 index e9f3ab79..00000000 --- a/cmake/CleanBuild.cmake +++ /dev/null @@ -1,76 +0,0 @@ -# cmake/CleanBuild.cmake - -# Function to selectively clean the build directory. -# -# This function will remove most of the generated build files from the build -# directory, while preserving specific directories that contain downloaded -# tools or generated documentation. -# -# Golden Rules: -# - never delete build/ -# - never delete build/bin -# - never delete build/docs -# - never delete build/sdk (non cache) -# -# It will: -# - purge build files -# - clean up conan build files, cached sources can always remain. -function(selective_clean_build_dir) - if(EXISTS "${CMAKE_SOURCE_DIR}/build") - message(STATUS "Selectively cleaning build directory: ${CMAKE_SOURCE_DIR}/build") - - # List of top-level items in the build directory to keep. - set(golden_items - "${CMAKE_SOURCE_DIR}/build/.ccache" - "${CMAKE_SOURCE_DIR}/build/bin" - "${CMAKE_SOURCE_DIR}/build/docs" - "${CMAKE_SOURCE_DIR}/build/sdk" - ) - - # Get all top-level items in the build directory. - file(GLOB top_level_items "${CMAKE_SOURCE_DIR}/build/*") - - foreach(item ${top_level_items}) - list(FIND golden_items "${item}" is_golden) - if(is_golden STREQUAL "-1") - string(FIND "${item}" "${CMAKE_SOURCE_DIR}/build" is_prefixed) - if(is_prefixed EQUAL 0) - message(STATUS "Removing: ${item}") - if(IS_DIRECTORY "${item}") - file(REMOVE_RECURSE "${item}") - else() - file(REMOVE "${item}") - endif() - else() - message(WARNING "Safety check failed: Will not remove '${item}' because it is not prefixed with CMAKE_SOURCE_DIR/build.") - endif() - else() - message(STATUS "Keeping golden item: ${item}") - endif() - endforeach() - - message(STATUS "Selective clean complete.") - else() - message(STATUS "Build directory not found, skipping clean.") - endif() -endfunction() - -function(reset_conan_presets) - set(CONAN_PRESETS_FILE "${CMAKE_SOURCE_DIR}/ConanPresets.json") - - set(NEW_CONTENT [[{ - "version": 4, - "vendor": { - "conan": {} - }, - "include": [ - - ] -}]]) - message(STATUS "Resetting ${CONAN_PRESETS_FILE} to a clean state.") - file(WRITE "${CONAN_PRESETS_FILE}" "${NEW_CONTENT}") - message(STATUS "${CONAN_PRESETS_FILE} has been successfully reset.") -endfunction() - -selective_clean_build_dir() -reset_conan_presets() diff --git a/cmake/ConanGet.cmake b/cmake/ConanGet.cmake deleted file mode 100644 index 6110328e..00000000 --- a/cmake/ConanGet.cmake +++ /dev/null @@ -1,102 +0,0 @@ -# cmake/ConanGet.cmake - -# This module downloads and installs Conan if it's not found. - -# Set the Conan version -set(CONAN_VERSION 2.21.0) - -# Set the download URLs -set(CONAN_URL_MACOS_ARM "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-macos-arm64.tgz") -set(CONAN_URL_MACOS_INTEL "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-macos-x86_64.tgz") -set(CONAN_URL_WINDOWS_X86_64 "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-windows-x86_64.zip") -set(CONAN_URL_WINDOWS_ARM64 "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-windows-arm64.zip") -set(CONAN_URL_LINUX_X86_64 "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-linux-x86_64.tgz") -set(CONAN_URL_LINUX_AARCH64 "https://github.com/conan-io/conan/releases/download/${CONAN_VERSION}/conan-${CONAN_VERSION}-linux-aarch64.tgz") - -# Set the installation directory -if(NOT CMAKE_BINARY_DIR) - set(CMAKE_BINARY_DIR "${CONAN_INSTALL_DIR}") -endif() -if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - set(CONAN_INSTALL_DIR "${CMAKE_SOURCE_DIR}/build/bin") - set(CONAN_EXECUTABLE "${CMAKE_SOURCE_DIR}/build/bin/conan.exe") -else () - set(CONAN_INSTALL_DIR "${CMAKE_SOURCE_DIR}/build") - set(CONAN_EXECUTABLE "${CONAN_INSTALL_DIR}/bin/conan") -endif () -# Check if Conan is already installed -if(NOT EXISTS "${CONAN_EXECUTABLE}") - message(STATUS "Conan not found. Downloading and installing...") - - file(MAKE_DIRECTORY "${CONAN_INSTALL_DIR}") - - # Determine the processor architecture, with a fallback - if(CMAKE_HOST_SYSTEM_PROCESSOR) - set(HOST_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR}) - else() - cmake_host_system_information(RESULT HOST_PROCESSOR QUERY OS_PLATFORM) - endif() - - # Detect the operating system and architecture - message(STATUS "Detecting OS and architecture: ${HOST_PROCESSOR} on ${CMAKE_HOST_SYSTEM_NAME}") - if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - if(HOST_PROCESSOR MATCHES "arm64") - set(CONAN_URL ${CONAN_URL_MACOS_ARM}) - set(CONAN_ARCHIVE_TYPE "tgz") - else() - set(CONAN_URL ${CONAN_URL_MACOS_INTEL}) - set(CONAN_ARCHIVE_TYPE "tgz") - endif() - elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - if(HOST_PROCESSOR MATCHES "ARM64") - set(CONAN_URL ${CONAN_URL_WINDOWS_ARM64}) - set(CONAN_ARCHIVE_TYPE "zip") - else() - set(CONAN_URL ${CONAN_URL_WINDOWS_X86_64}) - set(CONAN_ARCHIVE_TYPE "zip") - endif() - elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") - if(HOST_PROCESSOR MATCHES "aarch64|arm64|ARM64") - set(CONAN_URL ${CONAN_URL_LINUX_AARCH64}) - set(CONAN_ARCHIVE_TYPE "tgz") - else() - set(CONAN_URL ${CONAN_URL_LINUX_X86_64}) - set(CONAN_ARCHIVE_TYPE "tgz") - endif() - else() - message(FATAL_ERROR "Unsupported operating system: ${CMAKE_HOST_SYSTEM_NAME}") - endif() - - # Download and extract Conan - set(CONAN_ARCHIVE "${CMAKE_BINARY_DIR}/conan.${CONAN_ARCHIVE_TYPE}") - - message(STATUS "Downloading ${CONAN_URL} to ${CONAN_ARCHIVE}") - file(DOWNLOAD "${CONAN_URL}" "${CONAN_ARCHIVE}" SHOW_PROGRESS) - - message(STATUS "Extracting ${CONAN_ARCHIVE} to ${CONAN_INSTALL_DIR}") - if(CONAN_ARCHIVE_TYPE STREQUAL "tgz") - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xzf "${CONAN_ARCHIVE}" - WORKING_DIRECTORY "${CONAN_INSTALL_DIR}" - RESULT_VARIABLE result - ) - elseif(CONAN_ARCHIVE_TYPE STREQUAL "zip") - # CMake -E tar can handle zip files - execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xf "${CONAN_ARCHIVE}" - WORKING_DIRECTORY "${CONAN_INSTALL_DIR}" - RESULT_VARIABLE result - ) - endif() - - if(NOT result EQUAL 0) - message(FATAL_ERROR "Failed to extract Conan archive.") - endif() - - # Clean up the archive - file(REMOVE "${CONAN_ARCHIVE}") - - message(STATUS "Conan installed successfully at ${CONAN_EXECUTABLE}") -else() - message(STATUS "Conan already installed at ${CONAN_EXECUTABLE}") -endif() diff --git a/cmake/ConanProfileSetup.cmake b/cmake/ConanProfileSetup.cmake deleted file mode 100644 index c6a0e803..00000000 --- a/cmake/ConanProfileSetup.cmake +++ /dev/null @@ -1,38 +0,0 @@ -set(CONAN_HOME "${CMAKE_SOURCE_DIR}/build/sdk") -set(DEFAULT_PROFILE "${CONAN_HOME}/profiles/default") -if(WIN32) - set(CONAN_EXECUTABLE "${CMAKE_SOURCE_DIR}/build/bin/conan.exe") -else() - set(CONAN_EXECUTABLE "${CMAKE_SOURCE_DIR}/build/bin/conan") -endif() -if(NOT EXISTS "${DEFAULT_PROFILE}") - message(STATUS "Conan default profile not found. Detecting a new one...") - set(ENV{CONAN_HOME} "${CONAN_HOME}") - execute_process( - COMMAND "${CONAN_EXECUTABLE}" profile detect --name=default --force - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" - RESULT_VARIABLE return_code - ) - unset(ENV{CONAN_HOME}) - - if(NOT return_code EQUAL 0) - message(FATAL_ERROR "Conan profile detection failed with exit code: ${return_code}") - endif() -endif() - -message(STATUS "Appending custom settings to Conan default profile...") - -set(CUSTOM_SETTINGS " -compiler.cppstd=17 -") - -#if(WIN32) -# message(STATUS "Windows detected. Appending static runtime setting.") -# string(APPEND CUSTOM_SETTINGS " -#compiler.runtime=static -#") -#endif() - -file(APPEND "${DEFAULT_PROFILE}" "${CUSTOM_SETTINGS}") - -message(STATUS "Conan profile setup is complete.") \ No newline at end of file diff --git a/cmake/ConanProvider.cmake b/cmake/ConanProvider.cmake deleted file mode 100644 index 036ede6e..00000000 --- a/cmake/ConanProvider.cmake +++ /dev/null @@ -1,698 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2024 JFrog -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -set(CONAN_MINIMUM_VERSION 2.0.5) - -# Create a new policy scope and set the minimum required cmake version so the -# features behind a policy setting like if(... IN_LIST ...) behaves as expected -# even if the parent project does not specify a minimum cmake version or a minimum -# version less than this module requires (e.g. 3.0) before the first project() call. -# (see: https://cmake.org/cmake/help/latest/variable/CMAKE_PROJECT_TOP_LEVEL_INCLUDES.html) -# -# The policy-affecting calls like cmake_policy(SET...) or `cmake_minimum_required` only -# affects the current policy scope, i.e. between the PUSH and POP in this case. -# -# https://cmake.org/cmake/help/book/mastering-cmake/chapter/Policies.html#the-policy-stack -cmake_policy(PUSH) -cmake_minimum_required(VERSION 3.24) - - -function(detect_os os os_api_level os_sdk os_subsystem os_version) - # it could be cross compilation - message(STATUS "CMake-Conan: cmake_system_name=${CMAKE_SYSTEM_NAME}") - if(CMAKE_SYSTEM_NAME AND NOT CMAKE_SYSTEM_NAME STREQUAL "Generic") - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(${os} Macos PARENT_SCOPE) - elseif(CMAKE_SYSTEM_NAME STREQUAL "QNX") - set(${os} Neutrino PARENT_SCOPE) - elseif(CMAKE_SYSTEM_NAME STREQUAL "CYGWIN") - set(${os} Windows PARENT_SCOPE) - set(${os_subsystem} cygwin PARENT_SCOPE) - elseif(CMAKE_SYSTEM_NAME MATCHES "^MSYS") - set(${os} Windows PARENT_SCOPE) - set(${os_subsystem} msys2 PARENT_SCOPE) - elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - # https://github.com/emscripten-core/emscripten/blob/4.0.6/cmake/Modules/Platform/Emscripten.cmake#L17C1-L17C34 - set(${os} Emscripten PARENT_SCOPE) - else() - set(${os} ${CMAKE_SYSTEM_NAME} PARENT_SCOPE) - endif() - if(CMAKE_SYSTEM_NAME STREQUAL "Android") - if(DEFINED ANDROID_PLATFORM) - string(REGEX MATCH "[0-9]+" _os_api_level ${ANDROID_PLATFORM}) - elseif(DEFINED CMAKE_SYSTEM_VERSION) - set(_os_api_level ${CMAKE_SYSTEM_VERSION}) - endif() - message(STATUS "CMake-Conan: android api level=${_os_api_level}") - set(${os_api_level} ${_os_api_level} PARENT_SCOPE) - endif() - if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS") - # CMAKE_OSX_SYSROOT contains the full path to the SDK for MakeFile/Ninja - # generators, but just has the original input string for Xcode. - if(NOT IS_DIRECTORY ${CMAKE_OSX_SYSROOT}) - set(_os_sdk ${CMAKE_OSX_SYSROOT}) - else() - if(CMAKE_OSX_SYSROOT MATCHES Simulator) - set(apple_platform_suffix simulator) - else() - set(apple_platform_suffix os) - endif() - if(CMAKE_OSX_SYSROOT MATCHES AppleTV) - set(_os_sdk "appletv${apple_platform_suffix}") - elseif(CMAKE_OSX_SYSROOT MATCHES iPhone) - set(_os_sdk "iphone${apple_platform_suffix}") - elseif(CMAKE_OSX_SYSROOT MATCHES Watch) - set(_os_sdk "watch${apple_platform_suffix}") - endif() - endif() - if(DEFINED os_sdk) - message(STATUS "CMake-Conan: cmake_osx_sysroot=${CMAKE_OSX_SYSROOT}") - set(${os_sdk} ${_os_sdk} PARENT_SCOPE) - endif() - if(DEFINED CMAKE_OSX_DEPLOYMENT_TARGET) - message(STATUS "CMake-Conan: cmake_osx_deployment_target=${CMAKE_OSX_DEPLOYMENT_TARGET}") - set(${os_version} ${CMAKE_OSX_DEPLOYMENT_TARGET} PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - - -function(detect_arch arch) - # CMAKE_OSX_ARCHITECTURES can contain multiple architectures, but Conan only supports one. - # Therefore this code only finds one. If the recipes support multiple architectures, the - # build will work. Otherwise, there will be a linker error for the missing architecture(s). - if(DEFINED CMAKE_OSX_ARCHITECTURES) - string(REPLACE " " ";" apple_arch_list "${CMAKE_OSX_ARCHITECTURES}") - list(LENGTH apple_arch_list apple_arch_count) - if(apple_arch_count GREATER 1) - message(WARNING "CMake-Conan: Multiple architectures detected, this will only work if Conan recipe(s) produce fat binaries.") - endif() - endif() - if(CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|tvOS|watchOS" AND NOT CMAKE_OSX_ARCHITECTURES STREQUAL "") - set(host_arch ${CMAKE_OSX_ARCHITECTURES}) - elseif(MSVC) - set(host_arch ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}) - else() - set(host_arch ${CMAKE_SYSTEM_PROCESSOR}) - endif() - if(host_arch MATCHES "aarch64|arm64|ARM64") - set(_arch armv8) - elseif(host_arch MATCHES "armv7|armv7-a|armv7l|ARMV7") - set(_arch armv7) - elseif(host_arch MATCHES armv7s) - set(_arch armv7s) - elseif(host_arch MATCHES "i686|i386|X86") - set(_arch x86) - elseif(host_arch MATCHES "AMD64|amd64|x86_64|x64") - set(_arch x86_64) - endif() - if(EMSCRIPTEN) - # https://github.com/emscripten-core/emscripten/blob/4.0.6/cmake/Modules/Platform/Emscripten.cmake#L294C1-L294C80 - set(_arch wasm) - endif() - message(STATUS "CMake-Conan: cmake_system_processor=${_arch}") - set(${arch} ${_arch} PARENT_SCOPE) -endfunction() - - -function(detect_cxx_standard cxx_standard) - set(${cxx_standard} ${CMAKE_CXX_STANDARD} PARENT_SCOPE) - if(CMAKE_CXX_EXTENSIONS) - set(${cxx_standard} "gnu${CMAKE_CXX_STANDARD}" PARENT_SCOPE) - endif() -endfunction() - - -macro(detect_gnu_libstdcxx) - # _conan_is_gnu_libstdcxx true if GNU libstdc++ - check_cxx_source_compiles(" - #include - #if !defined(__GLIBCXX__) && !defined(__GLIBCPP__) - static_assert(false); - #endif - int main(){}" _conan_is_gnu_libstdcxx) - - # _conan_gnu_libstdcxx_is_cxx11_abi true if C++11 ABI - check_cxx_source_compiles(" - #include - static_assert(sizeof(std::string) != sizeof(void*), \"using libstdc++\"); - int main () {}" _conan_gnu_libstdcxx_is_cxx11_abi) - - set(_conan_gnu_libstdcxx_suffix "") - if(_conan_gnu_libstdcxx_is_cxx11_abi) - set(_conan_gnu_libstdcxx_suffix "11") - endif() - unset (_conan_gnu_libstdcxx_is_cxx11_abi) -endmacro() - - -macro(detect_libcxx) - # _conan_is_libcxx true if LLVM libc++ - check_cxx_source_compiles(" - #include - #if !defined(_LIBCPP_VERSION) - static_assert(false); - #endif - int main(){}" _conan_is_libcxx) -endmacro() - - -function(detect_lib_cxx lib_cxx) - if(CMAKE_SYSTEM_NAME STREQUAL "Android") - message(STATUS "CMake-Conan: android_stl=${CMAKE_ANDROID_STL_TYPE}") - set(${lib_cxx} ${CMAKE_ANDROID_STL_TYPE} PARENT_SCOPE) - return() - endif() - - include(CheckCXXSourceCompiles) - - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - detect_gnu_libstdcxx() - set(${lib_cxx} "libstdc++${_conan_gnu_libstdcxx_suffix}" PARENT_SCOPE) - elseif(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") - set(${lib_cxx} "libc++" PARENT_SCOPE) - elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - # Check for libc++ - detect_libcxx() - if(_conan_is_libcxx) - set(${lib_cxx} "libc++" PARENT_SCOPE) - return() - endif() - - # Check for libstdc++ - detect_gnu_libstdcxx() - if(_conan_is_gnu_libstdcxx) - set(${lib_cxx} "libstdc++${_conan_gnu_libstdcxx_suffix}" PARENT_SCOPE) - return() - endif() - - # TODO: it would be an error if we reach this point - elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - # Do nothing - compiler.runtime and compiler.runtime_type - # should be handled separately: https://github.com/conan-io/cmake-conan/pull/516 - return() - else() - # TODO: unable to determine, ask user to provide a full profile file instead - endif() -endfunction() - - -function(detect_compiler compiler compiler_version compiler_runtime compiler_runtime_type) - if(DEFINED CMAKE_CXX_COMPILER_ID) - set(_compiler ${CMAKE_CXX_COMPILER_ID}) - set(_compiler_version ${CMAKE_CXX_COMPILER_VERSION}) - else() - if(NOT DEFINED CMAKE_C_COMPILER_ID) - message(FATAL_ERROR "C or C++ compiler not defined") - endif() - set(_compiler ${CMAKE_C_COMPILER_ID}) - set(_compiler_version ${CMAKE_C_COMPILER_VERSION}) - endif() - - message(STATUS "CMake-Conan: CMake compiler=${_compiler}") - message(STATUS "CMake-Conan: CMake compiler version=${_compiler_version}") - - if(_compiler MATCHES MSVC) - set(_compiler "msvc") - string(SUBSTRING ${MSVC_VERSION} 0 3 _compiler_version) - # Configure compiler.runtime and compiler.runtime_type settings for MSVC - if(CMAKE_MSVC_RUNTIME_LIBRARY) - set(_msvc_runtime_library ${CMAKE_MSVC_RUNTIME_LIBRARY}) - else() - set(_msvc_runtime_library MultiThreaded$<$:Debug>DLL) # default value documented by CMake - endif() - - set(_KNOWN_MSVC_RUNTIME_VALUES "") - list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded MultiThreadedDLL) - list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreadedDebug MultiThreadedDebugDLL) - list(APPEND _KNOWN_MSVC_RUNTIME_VALUES MultiThreaded$<$:Debug> MultiThreaded$<$:Debug>DLL) - - # only accept the 6 possible values, otherwise we don't don't know to map this - if(NOT _msvc_runtime_library IN_LIST _KNOWN_MSVC_RUNTIME_VALUES) - message(FATAL_ERROR "CMake-Conan: unable to map MSVC runtime: ${_msvc_runtime_library} to Conan settings") - endif() - - # Runtime is "dynamic" in all cases if it ends in DLL - if(_msvc_runtime_library MATCHES ".*DLL$") - set(_compiler_runtime "dynamic") - else() - set(_compiler_runtime "static") - endif() - message(STATUS "CMake-Conan: CMake compiler.runtime=${_compiler_runtime}") - - # Only define compiler.runtime_type when explicitly requested - # If a generator expression is used, let Conan handle it conditional on build_type - if(NOT _msvc_runtime_library MATCHES ":Debug>") - if(_msvc_runtime_library MATCHES "Debug") - set(_compiler_runtime_type "Debug") - else() - set(_compiler_runtime_type "Release") - endif() - message(STATUS "CMake-Conan: CMake compiler.runtime_type=${_compiler_runtime_type}") - endif() - - unset(_KNOWN_MSVC_RUNTIME_VALUES) - - elseif(_compiler MATCHES AppleClang) - set(_compiler "apple-clang") - string(REPLACE "." ";" VERSION_LIST ${_compiler_version}) - list(GET VERSION_LIST 0 _compiler_version) - elseif(_compiler MATCHES Clang) - set(_compiler "clang") - string(REPLACE "." ";" VERSION_LIST ${_compiler_version}) - list(GET VERSION_LIST 0 _compiler_version) - elseif(_compiler MATCHES GNU) - set(_compiler "gcc") - string(REPLACE "." ";" VERSION_LIST ${_compiler_version}) - list(GET VERSION_LIST 0 _compiler_version) - endif() - - message(STATUS "CMake-Conan: [settings] compiler=${_compiler}") - message(STATUS "CMake-Conan: [settings] compiler.version=${_compiler_version}") - if (_compiler_runtime) - message(STATUS "CMake-Conan: [settings] compiler.runtime=${_compiler_runtime}") - endif() - if (_compiler_runtime_type) - message(STATUS "CMake-Conan: [settings] compiler.runtime_type=${_compiler_runtime_type}") - endif() - - set(${compiler} ${_compiler} PARENT_SCOPE) - set(${compiler_version} ${_compiler_version} PARENT_SCOPE) - set(${compiler_runtime} ${_compiler_runtime} PARENT_SCOPE) - set(${compiler_runtime_type} ${_compiler_runtime_type} PARENT_SCOPE) -endfunction() - - -function(detect_build_type build_type) - get_property(multiconfig_generator GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(NOT multiconfig_generator) - # Only set when we know we are in a single-configuration generator - # Note: we may want to fail early if `CMAKE_BUILD_TYPE` is not defined - set(${build_type} ${CMAKE_BUILD_TYPE} PARENT_SCOPE) - endif() -endfunction() - - -macro(set_conan_compiler_if_appleclang lang command output_variable) - if(CMAKE_${lang}_COMPILER_ID STREQUAL "AppleClang") - execute_process(COMMAND xcrun --find ${command} - OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE) - cmake_path(GET _xcrun_out PARENT_PATH _xcrun_toolchain_path) - cmake_path(GET CMAKE_${lang}_COMPILER PARENT_PATH _compiler_parent_path) - if ("${_xcrun_toolchain_path}" STREQUAL "${_compiler_parent_path}") - set(${output_variable} "") - endif() - unset(_xcrun_out) - unset(_xcrun_toolchain_path) - unset(_compiler_parent_path) - endif() -endmacro() - - -macro(append_compiler_executables_configuration) - set(_conan_c_compiler "") - set(_conan_cpp_compiler "") - set(_conan_rc_compiler "") - set(_conan_compilers_list "") - if(CMAKE_C_COMPILER) - set(_conan_c_compiler "\"c\":\"${CMAKE_C_COMPILER}\"") - set_conan_compiler_if_appleclang(C cc _conan_c_compiler) - list(APPEND _conan_compilers_list ${_conan_c_compiler}) - else() - message(WARNING "CMake-Conan: The C compiler is not defined. " - "Please define CMAKE_C_COMPILER or enable the C language.") - endif() - if(CMAKE_CXX_COMPILER) - set(_conan_cpp_compiler "\"cpp\":\"${CMAKE_CXX_COMPILER}\"") - set_conan_compiler_if_appleclang(CXX c++ _conan_cpp_compiler) - list(APPEND _conan_compilers_list ${_conan_cpp_compiler}) - else() - message(WARNING "CMake-Conan: The C++ compiler is not defined. " - "Please define CMAKE_CXX_COMPILER or enable the C++ language.") - endif() - if(CMAKE_RC_COMPILER) - set(_conan_rc_compiler "\"rc\":\"${CMAKE_RC_COMPILER}\"") - list(APPEND _conan_compilers_list ${_conan_rc_compiler}) - # Not necessary to warn if RC not defined - endif() - if(NOT "x${_conan_compilers_list}" STREQUAL "x") - string(REPLACE ";" "," _conan_compilers_list "${_conan_compilers_list}") - string(APPEND profile "tools.build:compiler_executables={${_conan_compilers_list}}\n") - endif() - unset(_conan_c_compiler) - unset(_conan_cpp_compiler) - unset(_conan_rc_compiler) - unset(_conan_compilers_list) -endmacro() - - -function(detect_host_profile output_file) - detect_os(os os_api_level os_sdk os_subsystem os_version) - detect_arch(arch) - detect_compiler(compiler compiler_version compiler_runtime compiler_runtime_type) - detect_cxx_standard(compiler_cppstd) - detect_lib_cxx(compiler_libcxx) - detect_build_type(build_type) - - set(profile "") - string(APPEND profile "[settings]\n") - if(arch) - string(APPEND profile arch=${arch} "\n") - endif() - if(os) - string(APPEND profile os=${os} "\n") - endif() - if(os_api_level) - string(APPEND profile os.api_level=${os_api_level} "\n") - endif() - if(os_version) - string(APPEND profile os.version=${os_version} "\n") - endif() - if(os_sdk) - string(APPEND profile os.sdk=${os_sdk} "\n") - endif() - if(os_subsystem) - string(APPEND profile os.subsystem=${os_subsystem} "\n") - endif() - if(compiler) - string(APPEND profile compiler=${compiler} "\n") - endif() - if(compiler_version) - string(APPEND profile compiler.version=${compiler_version} "\n") - endif() - if(compiler_runtime) - string(APPEND profile compiler.runtime=${compiler_runtime} "\n") - endif() - if(compiler_runtime_type) - string(APPEND profile compiler.runtime_type=${compiler_runtime_type} "\n") - endif() - if(compiler_cppstd) - string(APPEND profile compiler.cppstd=${compiler_cppstd} "\n") - endif() - if(compiler_libcxx) - string(APPEND profile compiler.libcxx=${compiler_libcxx} "\n") - endif() - if(build_type) - string(APPEND profile "build_type=${build_type}\n") - endif() - - if(NOT DEFINED output_file) - set(file_name "${CMAKE_BINARY_DIR}/profile") - else() - set(file_name ${output_file}) - endif() - - string(APPEND profile "[conf]\n") - string(APPEND profile "tools.cmake.cmaketoolchain:generator=${CMAKE_GENERATOR}\n") - - # propagate compilers via profile - append_compiler_executables_configuration() - - if(os STREQUAL "Android") - string(APPEND profile "tools.android:ndk_path=${CMAKE_ANDROID_NDK}\n") - endif() - - message(STATUS "CMake-Conan: Creating profile ${file_name}") - file(WRITE ${file_name} ${profile}) - message(STATUS "CMake-Conan: Profile: \n${profile}") -endfunction() - - -function(conan_profile_detect_default) - message(STATUS "CMake-Conan: Checking if a default profile exists") - execute_process(COMMAND ${CONAN_COMMAND} profile path default - RESULT_VARIABLE return_code - OUTPUT_VARIABLE conan_stdout - ERROR_VARIABLE conan_stderr - ECHO_ERROR_VARIABLE # show the text output regardless - ECHO_OUTPUT_VARIABLE - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - if(NOT ${return_code} EQUAL "0") - message(STATUS "CMake-Conan: The default profile doesn't exist, detecting it.") - execute_process(COMMAND ${CONAN_COMMAND} profile detect - RESULT_VARIABLE return_code - OUTPUT_VARIABLE conan_stdout - ERROR_VARIABLE conan_stderr - ECHO_ERROR_VARIABLE # show the text output regardless - ECHO_OUTPUT_VARIABLE - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - endif() -endfunction() - - -function(conan_install) - set(conan_output_folder ${CMAKE_BINARY_DIR}/conan) - # Invoke "conan install" with the provided arguments - set(conan_args ${conan_args} -of=${conan_output_folder}) - message(STATUS "CMake-Conan: conan install ${CMAKE_SOURCE_DIR} ${conan_args} ${ARGN}") - - - # In case there was not a valid cmake executable in the PATH, we inject the - # same we used to invoke the provider to the PATH - if(DEFINED PATH_TO_CMAKE_BIN) - set(old_path $ENV{PATH}) - set(ENV{PATH} "$ENV{PATH}:${PATH_TO_CMAKE_BIN}") - endif() - - execute_process(COMMAND ${CONAN_COMMAND} install ${CMAKE_SOURCE_DIR} ${conan_args} ${ARGN} --format=json - RESULT_VARIABLE return_code - OUTPUT_VARIABLE conan_stdout - ERROR_VARIABLE conan_stderr - ECHO_ERROR_VARIABLE # show the text output regardless - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - - if(DEFINED PATH_TO_CMAKE_BIN) - set(ENV{PATH} "${old_path}") - endif() - - if(NOT "${return_code}" STREQUAL "0") - message(FATAL_ERROR "Conan install failed='${return_code}'") - endif() - - # the files are generated in a folder that depends on the layout used, if - # one is specified, but we don't know a priori where this is. - # TODO: this can be made more robust if Conan can provide this in the json output - string(JSON conan_generators_folder GET "${conan_stdout}" graph nodes 0 generators_folder) - cmake_path(CONVERT ${conan_generators_folder} TO_CMAKE_PATH_LIST conan_generators_folder) - - message(STATUS "CMake-Conan: CONAN_GENERATORS_FOLDER=${conan_generators_folder}") - set_property(GLOBAL PROPERTY CONAN_GENERATORS_FOLDER "${conan_generators_folder}") - # reconfigure on conanfile changes - string(JSON conanfile GET "${conan_stdout}" graph nodes 0 label) - message(STATUS "CMake-Conan: CONANFILE=${CMAKE_SOURCE_DIR}/${conanfile}") - set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/${conanfile}") - # success - set_property(GLOBAL PROPERTY CONAN_INSTALL_SUCCESS TRUE) - -endfunction() - - -function(conan_get_version conan_command conan_current_version) - execute_process( - COMMAND ${conan_command} --version - OUTPUT_VARIABLE conan_output - RESULT_VARIABLE conan_result - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(conan_result) - message(FATAL_ERROR "CMake-Conan: Error when trying to run Conan") - endif() - - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" conan_version ${conan_output}) - set(${conan_current_version} ${conan_version} PARENT_SCOPE) -endfunction() - - -function(conan_version_check) - set(options ) - set(one_value_args MINIMUM CURRENT) - set(multi_value_args ) - cmake_parse_arguments(conan_version_check - "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN}) - - if(NOT conan_version_check_MINIMUM) - message(FATAL_ERROR "CMake-Conan: Required parameter MINIMUM not set!") - endif() - if(NOT conan_version_check_CURRENT) - message(FATAL_ERROR "CMake-Conan: Required parameter CURRENT not set!") - endif() - - if(conan_version_check_CURRENT VERSION_LESS conan_version_check_MINIMUM) - message(FATAL_ERROR "CMake-Conan: Conan version must be ${conan_version_check_MINIMUM} or later") - endif() -endfunction() - - -macro(construct_profile_argument argument_variable profile_list) - set(${argument_variable} "") - if("${profile_list}" STREQUAL "CONAN_HOST_PROFILE") - set(_arg_flag "--profile:host=") - elseif("${profile_list}" STREQUAL "CONAN_BUILD_PROFILE") - set(_arg_flag "--profile:build=") - endif() - - set(_profile_list "${${profile_list}}") - list(TRANSFORM _profile_list REPLACE "auto-cmake" "${CMAKE_BINARY_DIR}/conan_host_profile") - list(TRANSFORM _profile_list PREPEND ${_arg_flag}) - set(${argument_variable} ${_profile_list}) - - unset(_arg_flag) - unset(_profile_list) -endmacro() - - -macro(conan_provide_dependency method package_name) - set_property(GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED TRUE) - get_property(_conan_install_success GLOBAL PROPERTY CONAN_INSTALL_SUCCESS) - if(NOT _conan_install_success) - if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") - set(CONAN_COMMAND "${CMAKE_SOURCE_DIR}/build/bin/conan.exe") - else () - set(CONAN_COMMAND "${CMAKE_SOURCE_DIR}/build/bin/conan") - endif () - if(NOT EXISTS ${CONAN_COMMAND}) - message(STATUS "CMake-Conan: Local conan not found, attempting to download it.") - execute_process(COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_SOURCE_DIR}/cmake/ConanGet.cmake" - RESULT_VARIABLE result - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}") - if(NOT result EQUAL 0) - message(FATAL_ERROR "Failed to download conan.") - endif() - endif() - if(NOT EXISTS ${CONAN_COMMAND}) - message(FATAL_ERROR "Conan executable not found at ${CONAN_COMMAND} after trying to download it. Also, make sure it has execution permissions.") - endif() - conan_get_version(${CONAN_COMMAND} CONAN_CURRENT_VERSION) - conan_version_check(MINIMUM ${CONAN_MINIMUM_VERSION} CURRENT ${CONAN_CURRENT_VERSION}) - message(STATUS "CMake-Conan: first find_package() found. Installing dependencies with Conan") - if("default" IN_LIST CONAN_HOST_PROFILE OR "default" IN_LIST CONAN_BUILD_PROFILE) - conan_profile_detect_default() - endif() - if("auto-cmake" IN_LIST CONAN_HOST_PROFILE) - detect_host_profile(${CMAKE_BINARY_DIR}/conan_host_profile) - endif() - construct_profile_argument(_host_profile_flags CONAN_HOST_PROFILE) - construct_profile_argument(_build_profile_flags CONAN_BUILD_PROFILE) - if(EXISTS "${CMAKE_SOURCE_DIR}/conanfile.py") - file(READ "${CMAKE_SOURCE_DIR}/conanfile.py" outfile) - if(NOT "${outfile}" MATCHES ".*CMakeDeps.*") - message(WARNING "Cmake-conan: CMakeDeps generator was not defined in the conanfile") - endif() - set(generator "") - elseif (EXISTS "${CMAKE_SOURCE_DIR}/conanfile.txt") - file(READ "${CMAKE_SOURCE_DIR}/conanfile.txt" outfile) - if(NOT "${outfile}" MATCHES ".*CMakeDeps.*") - message(WARNING "Cmake-conan: CMakeDeps generator was not defined in the conanfile. " - "Please define the generator as it will be mandatory in the future") - endif() - set(generator "-g;CMakeDeps") - endif() - get_property(_multiconfig_generator GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(NOT _multiconfig_generator) - message(STATUS "CMake-Conan: Installing single configuration ${CMAKE_BUILD_TYPE}") - conan_install(${_host_profile_flags} ${_build_profile_flags} ${CONAN_INSTALL_ARGS} ${generator}) - else() - message(STATUS "CMake-Conan: Installing both Debug and Release") - conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Release ${CONAN_INSTALL_ARGS} ${generator}) - conan_install(${_host_profile_flags} ${_build_profile_flags} -s build_type=Debug ${CONAN_INSTALL_ARGS} ${generator}) - endif() - unset(_host_profile_flags) - unset(_build_profile_flags) - unset(_multiconfig_generator) - unset(_conan_install_success) - else() - message(STATUS "CMake-Conan: find_package(${ARGV1}) found, 'conan install' already ran") - unset(_conan_install_success) - endif() - - get_property(_conan_generators_folder GLOBAL PROPERTY CONAN_GENERATORS_FOLDER) - - # Ensure that we consider Conan-provided packages ahead of any other, - # irrespective of other settings that modify the search order or search paths - # This follows the guidelines from the find_package documentation - # (https://cmake.org/cmake/help/latest/command/find_package.html): - # find_package ( PATHS paths... NO_DEFAULT_PATH) - # find_package () - - # Filter out `REQUIRED` from the argument list, as the first call may fail - set(_find_args_${package_name} "${ARGN}") - list(REMOVE_ITEM _find_args_${package_name} "REQUIRED") - if(NOT "MODULE" IN_LIST _find_args_${package_name}) - find_package(${package_name} ${_find_args_${package_name}} BYPASS_PROVIDER PATHS "${_conan_generators_folder}" NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - unset(_find_args_${package_name}) - endif() - - # Invoke find_package a second time - if the first call succeeded, - # this will simply reuse the result. If not, fall back to CMake default search - # behaviour, also allowing modules to be searched. - if(NOT ${package_name}_FOUND) - list(FIND CMAKE_MODULE_PATH "${_conan_generators_folder}" _index) - if(_index EQUAL -1) - list(PREPEND CMAKE_MODULE_PATH "${_conan_generators_folder}") - endif() - unset(_index) - find_package(${package_name} ${ARGN} BYPASS_PROVIDER) - list(REMOVE_ITEM CMAKE_MODULE_PATH "${_conan_generators_folder}") - endif() -endmacro() - - -cmake_language( - SET_DEPENDENCY_PROVIDER conan_provide_dependency - SUPPORTED_METHODS FIND_PACKAGE -) - - -macro(conan_provide_dependency_check) - set(_conan_provide_dependency_invoked FALSE) - get_property(_conan_provide_dependency_invoked GLOBAL PROPERTY CONAN_PROVIDE_DEPENDENCY_INVOKED) - if(NOT _conan_provide_dependency_invoked) - message(WARNING "Conan is correctly configured as dependency provider, " - "but Conan has not been invoked. Please add at least one " - "call to `find_package()`.") - if(DEFINED CONAN_COMMAND) - # supress warning in case `CONAN_COMMAND` was specified but unused. - set(_conan_command ${CONAN_COMMAND}) - unset(_conan_command) - endif() - endif() - unset(_conan_provide_dependency_invoked) -endmacro() - - -# Add a deferred call at the end of processing the top-level directory -# to check if the dependency provider was invoked at all. -cmake_language(DEFER DIRECTORY "${CMAKE_SOURCE_DIR}" CALL conan_provide_dependency_check) - -# Configurable variables for Conan profiles -set(CONAN_HOST_PROFILE "default;auto-cmake" CACHE STRING "Conan host profile") -set(CONAN_BUILD_PROFILE "default" CACHE STRING "Conan build profile") -set(CONAN_INSTALL_ARGS "--build=missing" CACHE STRING "Command line arguments for conan install") - -find_program(_cmake_program NAMES cmake NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH) -if(NOT _cmake_program) - get_filename_component(PATH_TO_CMAKE_BIN "${CMAKE_COMMAND}" DIRECTORY) - set(PATH_TO_CMAKE_BIN "${PATH_TO_CMAKE_BIN}" CACHE INTERNAL "Path where the CMake executable is") -endif() - -cmake_policy(POP) \ No newline at end of file diff --git a/cmake/DocBuilder.cmake b/cmake/DocBuilder.cmake deleted file mode 100644 index c02ad658..00000000 --- a/cmake/DocBuilder.cmake +++ /dev/null @@ -1,45 +0,0 @@ -set(MKDOCS_SRC "${CMAKE_SOURCE_DIR}/docs") -set(MKDOCS_OUT "${CMAKE_BINARY_DIR}/../docs") - -message("MKDocs src: ${MKDOCS_SRC} > ${MKDOCS_OUT}") - -file(MAKE_DIRECTORY "${MKDOCS_OUT}") - -add_custom_target(docs - COMMAND ${CMAKE_COMMAND} -E env PYTHONUNBUFFERED=1 - mkdocs build - --clean - --site-dir "${MKDOCS_OUT}" - --config-file "${MKDOCS_SRC}/mkdocs.yml" - WORKING_DIRECTORY "${MKDOCS_SRC}" - COMMENT "Generating documentation with MkDocs" - VERBATIM -) - -# Optional install step -install(DIRECTORY "${MKDOCS_OUT}/" - DESTINATION "share/doc/${PROJECT_NAME}") - -add_custom_target(install-docs - DEPENDS docs - COMMAND "${CMAKE_COMMAND}" --install . --component docs - COMMENT "Installing documentation") - -# Name of the target that launches the dev server -add_custom_target( - serve_docs # ← invoke with `make serve_docs` - COMMAND ${CMAKE_COMMAND} -E env PYTHONUNBUFFERED=1 - # On Windows we need to run the command through the shell - # so that the `&&` operator works correctly. - ${CMAKE_COMMAND} -E env - mkdocs serve - --dev-addr "127.0.0.1:8000" # optional – explicit bind address - --watch "${MKDOCS_SRC}" # watch source files for changes - --config-file "${MKDOCS_SRC}/mkdocs.yml" - WORKING_DIRECTORY "${MKDOCS_SRC}" - USES_TERMINAL # tells CMake to attach the child process to the console - COMMENT "Starting MkDocs live‑preview server (Ctrl‑C to stop)" - VERBATIM -) - -add_dependencies(serve_docs docs) # ensures the static site is up‑to‑date before serving \ No newline at end of file diff --git a/cmake/FindCcache.cmake b/cmake/FindCcache.cmake deleted file mode 100644 index 4b440f5a..00000000 --- a/cmake/FindCcache.cmake +++ /dev/null @@ -1,8 +0,0 @@ -find_program(CCACHE_FOUND ccache) -if (CCACHE_FOUND) - message(STATUS "Found usable ccache: ${CCACHE_FOUND}") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND} cache_dir=${CMAKE_SOURCE_DIR}/build/.ccache") - set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_FOUND} cache_dir=${CMAKE_SOURCE_DIR}/build/.ccache") -else() - message(STATUS "ccache NOT found! Please install it for faster rebuilds.") -endif() \ No newline at end of file diff --git a/cmake/profiles/apple-clang-armv8 b/cmake/profiles/apple-clang-armv8 deleted file mode 100644 index 0f36faa5..00000000 --- a/cmake/profiles/apple-clang-armv8 +++ /dev/null @@ -1,9 +0,0 @@ -[settings] -os=Macos -arch=armv8 -compiler=apple-clang -compiler.version=13 -compiler.libcxx=libc++ - -[conf] - diff --git a/cmake/profiles/apple-clang-x86_64 b/cmake/profiles/apple-clang-x86_64 deleted file mode 100644 index 9af72645..00000000 --- a/cmake/profiles/apple-clang-x86_64 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -os=Macos -arch=x86_64 -compiler=apple-clang -compiler.version=13 -compiler.libcxx=libc++ - -[conf] \ No newline at end of file diff --git a/cmake/profiles/gcc-linux-armv8 b/cmake/profiles/gcc-linux-armv8 deleted file mode 100644 index 48e1521c..00000000 --- a/cmake/profiles/gcc-linux-armv8 +++ /dev/null @@ -1,9 +0,0 @@ -[settings] -os=Linux -arch=armv8 -compiler=gcc -compiler.version=11 -compiler.libcxx=libstdc++11 - -[conf] -tools.cmake.cmaketoolchain:user_presets=False diff --git a/cmake/profiles/gcc-linux-x86_64 b/cmake/profiles/gcc-linux-x86_64 deleted file mode 100644 index 4a58979e..00000000 --- a/cmake/profiles/gcc-linux-x86_64 +++ /dev/null @@ -1,9 +0,0 @@ -[settings] -os=Linux -arch=x86_64 -compiler=gcc -compiler.version=11 -compiler.libcxx=libstdc++11 - -[conf] -tools.cmake.cmaketoolchain:user_presets=False diff --git a/cmake/profiles/msvc-193-x86_64 b/cmake/profiles/msvc-193-x86_64 deleted file mode 100644 index 19a699f5..00000000 --- a/cmake/profiles/msvc-193-x86_64 +++ /dev/null @@ -1,10 +0,0 @@ -[settings] -arch=x86_64 -compiler=msvc -compiler.cppstd=17 -compiler.runtime=static -compiler.version=193 -os=Windows - -[conf] -tools.cmake.cmaketoolchain:user_presets=False diff --git a/cmake/profiles/msvc-194-x86_64 b/cmake/profiles/msvc-194-x86_64 deleted file mode 100644 index 5d56b3b2..00000000 --- a/cmake/profiles/msvc-194-x86_64 +++ /dev/null @@ -1,8 +0,0 @@ -[settings] -arch=x86_64 -compiler=msvc -compiler.cppstd=17 -compiler.runtime=static -compiler.version=194 -os=Windows -build_type=Release \ No newline at end of file diff --git a/cmake/test-static-assert.c b/cmake/test-static-assert.c index fcac11ce..3e612bbc 100644 --- a/cmake/test-static-assert.c +++ b/cmake/test-static-assert.c @@ -3,4 +3,4 @@ static_assert(1, "FAIL"); int main(int argc, char *argv[]) { return 0; -} \ No newline at end of file +} diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index 8b1445cb..1f3d0b0b 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(db) add_subdirectory(ethereum) +add_subdirectory(randomx) if(USE_BITCOIN_SECP256K1_FOR_ECDSA) option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." OFF) diff --git a/contrib/randomx b/contrib/randomx new file mode 160000 index 00000000..cf15f402 --- /dev/null +++ b/contrib/randomx @@ -0,0 +1 @@ +Subproject commit cf15f4023ec8ddaa842f49111ba80ead1b5937f1 diff --git a/genesis-work/genesis_config.json b/genesis-work/genesis_config.json new file mode 100644 index 00000000..4feae998 --- /dev/null +++ b/genesis-work/genesis_config.json @@ -0,0 +1,30 @@ +{ + "payments": [ + { + "address_this": "iTHNdRWX6pKGXF1HqHgZyXie8EdaCwwdWUmsEnQhNojSUrkrR2eTemhFYkjWXbhdbyGcRBLgV2RYp3HhNAFCQ67w4bTHErZL1J", + "amount_this": 10000000.0, + "this_usd_price": "1.0", + "paid_prm": "", + "prm_usd_price": "", + "paid_xmr": "", + "xmr_usd_price": "", + "paid_qtum": "", + "qtum_usd_price": "", + "paid_bch": "", + "bch_usd_price": "", + "paid_rep": "", + "rep_usd_price": "", + "paid_dash": "", + "dash_usd_price": "", + "paid_ltc": "", + "ltc_usd_price": "", + "paid_eos": "", + "eos_usd_price": "", + "paid_eth": "", + "eth_usd_price": "", + "paid_btc": "", + "btc_usd_price": "" + } + ], + "proof_string": "Lethean genesis — the advantage of the nature of information being easy to spread but hard to stifle. - Satoshi Nakamoto" +} diff --git a/genesis-work/genesis_config.json.genesis.dictionary.txt b/genesis-work/genesis_config.json.genesis.dictionary.txt new file mode 100644 index 00000000..d49bb837 --- /dev/null +++ b/genesis-work/genesis_config.json.genesis.dictionary.txt @@ -0,0 +1,7 @@ +-------------genesis_acc.cpp------------- +const std::string ggenesis_tx_pub_key_str = "503ec7c167e3f2ead7d801bcbcebb3c58a84a2ba26a21ecb1f5c105fa159932b"; +const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string(ggenesis_tx_pub_key_str); +extern const genesis_tx_dictionary_entry ggenesis_dict[1]; +const genesis_tx_dictionary_entry ggenesis_dict[1] = { +{12778448838847345770ULL,0} +}; diff --git a/genesis-work/genesis_config.json.genesis.txt b/genesis-work/genesis_config.json.genesis.txt new file mode 100644 index 00000000..95ebbe63 --- /dev/null +++ b/genesis-work/genesis_config.json.genesis.txt @@ -0,0 +1 @@ +01010000018080a0cfc8e0c8e38a0103bd6b4dda729d39dc85cb22a0b3db9b4b04d6464be9f3c84640bdca8bc0afb148000516503ec7c167e3f2ead7d801bcbcebb3c58a84a2ba26a21ecb1f5c105fa159932b137a4c65746865616e2067656e6573697320e280942074686520616476616e74616765206f6620746865206e6174757265206f6620696e666f726d6174696f6e206265696e67206561737920746f2073707265616420627574206861726420746f20737469666c652e202d205361746f736869204e616b616d6f746f15000b029e4e0e0a0000 \ No newline at end of file diff --git a/genesis-work/genesis_config.json.genesis.uint64.array.txt b/genesis-work/genesis_config.json.genesis.uint64.array.txt new file mode 100644 index 00000000..94e32578 --- /dev/null +++ b/genesis-work/genesis_config.json.genesis.uint64.array.txt @@ -0,0 +1,14 @@ +--------- genesis.h--------- +#pragma pack(push, 1) +struct genesis_tx_raw_data +{ + uint64_t const v[27]; + uint8_t const r[1]; +}; +#pragma pack(pop) +extern const genesis_tx_raw_data ggenesis_tx_raw; + +--------- genesis.cpp--------- +const genesis_tx_raw_data ggenesis_tx_raw = {{ +0xa080800100000101,0x03018ae3c8e0c8cf,0xdc399d72da4d6bbd,0x4b9bdbb3a022cb85,0x46c8f3e94b46d604,0x48b1afc08bcabd40,0x67c1c73e50160500,0xbcbc01d8d7eaf2e3,0x26baa2848ac5b3eb,0xa15f105c1fcb1ea2,0x74654c7a132b9359,0x6e6567206e616568,0x9480e22073697365,0x7664612065687420,0x6f20656761746e61,0x616e206568742066,0x20666f2065727574,0x74616d726f666e69,0x6e696562206e6f69,0x7420797361652067,0x646165727073206f,0x7261682074756220,0x697473206f742064,0x53202d202e656c66,0x4e206968736f7461,0x156f746f6d616b61,0x000a0e4e9e020b00}, +{0x00}}; diff --git a/genesis-work/genesis_config.json.premine_stat.txt b/genesis-work/genesis_config.json.premine_stat.txt new file mode 100644 index 00000000..06d3f50c --- /dev/null +++ b/genesis-work/genesis_config.json.premine_stat.txt @@ -0,0 +1,14 @@ +NAME AMOUNT AMOUNT THIS USD EQ +bch 0.0000000000 0.000000000000 0.0000000000 +btc 0.0000000000 0.000000000000 0.0000000000 +dash 0.0000000000 0.000000000000 0.0000000000 +eos 0.0000000000 0.000000000000 0.0000000000 +eth 0.0000000000 0.000000000000 0.0000000000 +ltc 0.0000000000 0.000000000000 0.0000000000 +prm 0.0000000000 0.000000000000 0.0000000000 +qtum 0.0000000000 0.000000000000 0.0000000000 +rep 0.0000000000 0.000000000000 0.0000000000 + +TOTAL 0.000000000000 0.0000000000 + +PREMINE_AMOUNT 0 (0.000000000000THIS) diff --git a/genesis-work/premine_wallet b/genesis-work/premine_wallet new file mode 100644 index 00000000..69d00f3c Binary files /dev/null and b/genesis-work/premine_wallet differ diff --git a/genesis-work/premine_wallet.address b/genesis-work/premine_wallet.address new file mode 100644 index 00000000..3ca9e2d4 --- /dev/null +++ b/genesis-work/premine_wallet.address @@ -0,0 +1 @@ +iTHNdRWX6pKGXF1HqHgZyXie8EdaCwwdWUmsEnQhNojSUrkrR2eTemhFYkjWXbhdbyGcRBLgV2RYp3HhNAFCQ67w4bTHErZL1J \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d276457..d991d76e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -119,6 +119,7 @@ endif() add_library(currency_core ${CURRENCY_CORE}) add_dependencies(currency_core version config ${PCH_LIB_NAME}) target_link_libraries(currency_core config) +target_include_directories(currency_core PRIVATE ${RANDOMX_INCLUDE}) ENABLE_SHARED_PCH(currency_core CURRENCY_CORE) add_library(wallet ${WALLET}) @@ -164,19 +165,19 @@ target_link_libraries(currency_core config lmdb mdbx) add_executable(daemon ${DAEMON} ${P2P} ${CURRENCY_PROTOCOL}) add_dependencies(daemon version) -target_link_libraries(daemon rpc stratum currency_core crypto common miniupnpc::miniupnpc ZLIB::ZLIB ethash api::server ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(daemon rpc stratum currency_core crypto common miniupnpc::miniupnpc ZLIB::ZLIB ethash randomx api::server ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) ENABLE_SHARED_PCH(daemon DAEMON) ENABLE_SHARED_PCH_EXECUTABLE(daemon) add_executable(connectivity_tool ${CONN_TOOL}) add_dependencies(connectivity_tool version) -target_link_libraries(connectivity_tool currency_core crypto common ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(connectivity_tool currency_core crypto common ZLIB::ZLIB ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) ENABLE_SHARED_PCH(connectivity_tool CONN_TOOL) ENABLE_SHARED_PCH_EXECUTABLE(connectivity_tool) add_executable(simplewallet ${SIMPLEWALLET}) add_dependencies(simplewallet version) -target_link_libraries(simplewallet wallet rpc currency_core crypto common ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(simplewallet wallet rpc currency_core crypto common ZLIB::ZLIB ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET) ENABLE_SHARED_PCH_EXECUTABLE(simplewallet) diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt index e325f3a3..4304b9ac 100644 --- a/src/api/CMakeLists.txt +++ b/src/api/CMakeLists.txt @@ -59,6 +59,7 @@ target_link_libraries(api_server crypto common ethash + randomx ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} OpenSSL::SSL diff --git a/src/config/default.cmake b/src/config/default.cmake index 56929c50..b81a766f 100644 --- a/src/config/default.cmake +++ b/src/config/default.cmake @@ -21,7 +21,7 @@ set(base_reward_dust_threshold 1000000 CACHE STRING "BASE_REWARD_DUST_THRESHOLD" set(default_dust_threshold 0 CACHE STRING "DEFAULT_DUST_THRESHOLD" ) set(difficulty_pow_starter 1 CACHE STRING "DIFFICULTY_POW_STARTER" ) set(difficulty_pos_target 120 CACHE STRING "DIFFICULTY_POS_TARGET" ) -set(difficulty_pow_target 120 CACHE STRING "DIFFICULTY_POW_TARGET" ) +set(difficulty_pow_target 10 CACHE STRING "DIFFICULTY_POW_TARGET" ) set(difficulty_window 720 CACHE STRING "DIFFICULTY_WINDOW" ) set(difficulty_lag 15 CACHE STRING "DIFFICULTY_LAG" ) set(difficulty_cut 60 CACHE STRING "DIFFICULTY_CUT" ) diff --git a/src/currency_core/basic_pow_helpers.cpp b/src/currency_core/basic_pow_helpers.cpp index d0afcc7b..9ea80e12 100644 --- a/src/currency_core/basic_pow_helpers.cpp +++ b/src/currency_core/basic_pow_helpers.cpp @@ -27,39 +27,102 @@ using namespace epee; #include "crypto/crypto.h" #include "crypto/hash.h" #include "common/int-util.h" + +// RandomX PoW +#include "randomx.h" + +// Keep ethash headers for stratum/RPC compatibility (epoch seed helpers) #include "ethereum/libethash/ethash/ethash.hpp" -#include "ethereum/libethash/ethash/progpow.hpp" + +#include +#include +#include +#include +#include namespace currency { + //-------------------------------------------------------------- + // RandomX global state — full dataset mode for fast hashing + //-------------------------------------------------------------- + static randomx_cache* rx_cache = nullptr; + static randomx_dataset* rx_dataset = nullptr; + static randomx_flags rx_flags = RANDOMX_FLAG_DEFAULT; + static std::once_flag rx_init_flag; - //-------------------------------------------------------------- - int ethash_custom_log_get_level() + static void init_randomx() { - return epee::log_space::get_set_log_detalisation_level(); - } - //-------------------------------------------------------------- - void ethash_custom_log(const std::string& m, bool add_callstack) - { - std::string msg = epee::log_space::log_singletone::get_prefix_entry() + "[ETHASH]" + m; - if (add_callstack) - msg = msg + "callstask: " + epee::misc_utils::get_callstack(); + rx_flags = randomx_get_flags() | RANDOMX_FLAG_FULL_MEM; + LOG_PRINT_L0("[RandomX] Initializing with flags: " << static_cast(rx_flags)); - epee::log_space::log_singletone::do_log_message(msg, LOG_LEVEL_0, epee::log_space::console_color_default, true, LOG_DEFAULT_TARGET); - } - //-------------------------------------------------------------- - void init_ethash_log_if_necessary() - { - static bool inited = false; - if (inited) + rx_cache = randomx_alloc_cache(rx_flags); + if (!rx_cache) + { + LOG_ERROR("[RandomX] Failed to allocate cache"); + throw std::bad_alloc(); + } + + static const char rx_key[] = "LetheanRandomXv1"; + randomx_init_cache(rx_cache, rx_key, sizeof(rx_key) - 1); + LOG_PRINT_L0("[RandomX] Cache initialized with key \"LetheanRandomXv1\""); + + rx_dataset = randomx_alloc_dataset(rx_flags); + if (!rx_dataset) + { + LOG_ERROR("[RandomX] Failed to allocate dataset, falling back to light mode"); + rx_flags = rx_flags & ~RANDOMX_FLAG_FULL_MEM; return; + } - ethash::access_custom_log_level_function() = ðash_custom_log_get_level; - ethash::access_custom_log_function() = ðash_custom_log; + // Multi-threaded dataset init + unsigned long item_count = randomx_dataset_item_count(); + unsigned int num_threads = std::thread::hardware_concurrency(); + if (num_threads == 0) num_threads = 4; + if (num_threads > 16) num_threads = 16; - inited = true; + LOG_PRINT_L0("[RandomX] Initializing dataset (" << item_count << " items, " << num_threads << " threads)..."); + + std::vector threads; + unsigned long per_thread = item_count / num_threads; + unsigned long remainder = item_count % num_threads; + + for (unsigned int i = 0; i < num_threads; ++i) + { + unsigned long start = i * per_thread + std::min((unsigned long)i, remainder); + unsigned long count = per_thread + (i < remainder ? 1 : 0); + threads.emplace_back([start, count]() { + randomx_init_dataset(rx_dataset, rx_cache, start, count); + }); + } + for (auto& t : threads) t.join(); + + LOG_PRINT_L0("[RandomX] Dataset initialized OK"); } - //------------------------------------------------------------------ + + static randomx_vm* get_thread_vm() + { + std::call_once(rx_init_flag, init_randomx); + + static thread_local randomx_vm* vm = nullptr; + if (!vm) + { + if (rx_dataset) + vm = randomx_create_vm(rx_flags, nullptr, rx_dataset); + else + vm = randomx_create_vm(rx_flags & ~RANDOMX_FLAG_FULL_MEM, rx_cache, nullptr); + + if (!vm) + { + LOG_ERROR("[RandomX] Failed to create VM"); + throw std::bad_alloc(); + } + } + return vm; + } + + //-------------------------------------------------------------- + // Ethash helpers kept for stratum/RPC backward compat + //-------------------------------------------------------------- int ethash_height_to_epoch(uint64_t height) { return static_cast(height / ETHASH_EPOCH_LENGTH); @@ -75,17 +138,20 @@ namespace currency //-------------------------------------------------------------- crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_header_hash, uint64_t nonce) { - init_ethash_log_if_necessary(); - int epoch = ethash_height_to_epoch(height); - std::shared_ptr p_context = progpow::get_global_epoch_context_full(static_cast(epoch)); - if (!p_context) - { - LOG_ERROR("fatal error: get_global_epoch_context_full failed, throwing bad_alloc..."); - throw std::bad_alloc(); - } - auto res_eth = progpow::hash(*p_context, static_cast(height), *(ethash::hash256*)&block_header_hash, nonce); + // Combine header hash + nonce into a single input buffer + struct { + crypto::hash header; + uint64_t nonce; + } input; + input.header = block_header_hash; + input.nonce = nonce; + + char hash_out[RANDOMX_HASH_SIZE]; + randomx_vm* vm = get_thread_vm(); + randomx_calculate_hash(vm, &input, sizeof(input), hash_out); + crypto::hash result = currency::null_hash; - memcpy(&result.data, &res_eth.final_hash, sizeof(res_eth.final_hash)); + std::memcpy(&result.data, hash_out, sizeof(result.data)); return result; } //--------------------------------------------------------------- diff --git a/src/currency_core/blockchain_storage.cpp b/src/currency_core/blockchain_storage.cpp index 62a43393..f056193f 100644 --- a/src/currency_core/blockchain_storage.cpp +++ b/src/currency_core/blockchain_storage.cpp @@ -1428,14 +1428,7 @@ wide_difficulty_type blockchain_storage::calc_diff_at_h_from_timestamps(std::vec { wide_difficulty_type dif; TIME_MEASURE_START_PD(target_calculating_calc); - if (m_core_runtime_config.is_hardfork_active_for_height(1, h)) - { - dif = next_difficulty_2(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter); - } - else - { - dif = next_difficulty_1(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter); - } + dif = next_difficulty_lwma(timestamps, commulative_difficulties, pos ? global_difficulty_pos_target : global_difficulty_pow_target, pos ? global_difficulty_pos_starter : global_difficulty_pow_starter); TIME_MEASURE_FINISH_PD(target_calculating_calc); return dif; } diff --git a/src/currency_core/difficulty.cpp b/src/currency_core/difficulty.cpp index 592b3be7..843d7823 100644 --- a/src/currency_core/difficulty.cpp +++ b/src/currency_core/difficulty.cpp @@ -267,4 +267,75 @@ namespace currency { } return summ / devider; } + + //-------------------------------------------------------------- + // LWMA-1 difficulty algorithm (zawy12) + // Linear Weighted Moving Average — adjusts every block with a + // ~60-block window. Battle-tested in Monero against ASICs and + // botnets. Much faster convergence than the 720-block Zano algo. + //-------------------------------------------------------------- + wide_difficulty_type next_difficulty_lwma(vector& timestamps, vector& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter) + { + const int64_t T = static_cast(target_seconds); + const size_t N = 60; // LWMA window size (solve times) + + size_t length = timestamps.size(); + CHECK_AND_ASSERT_MES(length == cumulative_difficulties.size(), difficulty_starter, + "LWMA: timestamps/difficulties size mismatch"); + + if (length <= 1) + return difficulty_starter; + + // We need at most N+1 entries (giving N solve times) + if (length > N + 1) + { + timestamps.resize(N + 1); + cumulative_difficulties.resize(N + 1); + length = N + 1; + } + + // Input arrives newest-first; LWMA needs oldest-first + std::reverse(timestamps.begin(), timestamps.end()); + std::reverse(cumulative_difficulties.begin(), cumulative_difficulties.end()); + + // Now: [0]=oldest … [length-1]=newest + size_t n = length - 1; // number of solve-time intervals + + int64_t weighted_solvetimes = 0; + + for (size_t i = 1; i <= n; i++) + { + int64_t st = static_cast(timestamps[i]) + - static_cast(timestamps[i - 1]); + + // Clamp to [-6T, 6T] to limit timestamp-manipulation impact + if (st < -(6 * T)) st = -(6 * T); + if (st > (6 * T)) st = (6 * T); + + weighted_solvetimes += st * static_cast(i); + } + + // Guard against zero / negative (would be pathological timestamps) + if (weighted_solvetimes <= 0) + weighted_solvetimes = 1; + + wide_difficulty_type total_work = cumulative_difficulties[n] - cumulative_difficulties[0]; + + // LWMA-1 formula: + // next_D = total_work * T * (n+1) / (2 * weighted_solvetimes * n) + // + // The divisor (n+1)/(2*n) normalises the linear weights 1..n + // whose sum is n*(n+1)/2. + boost::multiprecision::uint256_t next_d = + (boost::multiprecision::uint256_t(total_work) * T * (n + 1)) + / (boost::multiprecision::uint256_t(2) * weighted_solvetimes * n); + + if (next_d < 1) + next_d = 1; + + if (next_d > max128bit) + return difficulty_starter; + + return next_d.convert_to(); + } } diff --git a/src/currency_core/difficulty.h b/src/currency_core/difficulty.h index 8ffb64df..f4187c05 100644 --- a/src/currency_core/difficulty.h +++ b/src/currency_core/difficulty.h @@ -32,6 +32,7 @@ namespace currency bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty); wide_difficulty_type next_difficulty_1(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter); wide_difficulty_type next_difficulty_2(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter); + wide_difficulty_type next_difficulty_lwma(std::vector& timestamps, std::vector& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter); uint64_t difficulty_to_boundary(wide_difficulty_type difficulty); void difficulty_to_boundary_long(wide_difficulty_type difficulty, crypto::hash& result); } diff --git a/src/genesis/_genesis.cpp.gen b/src/genesis/_genesis.cpp.gen index 24ca4e63..cfc5867b 100644 --- a/src/genesis/_genesis.cpp.gen +++ b/src/genesis/_genesis.cpp.gen @@ -1,3 +1,3 @@ const genesis_tx_raw_data ggenesis_tx_raw = {{ - 0xe980800100000101,0xfbfa3a0316deb183,0x0e4d0bf7103b2df2,0x682df55627fc33ed,0xcd945b3d70689611,0x16050066b218269a,0x34af8b24a9c955d2,0x3f514b3a2be34ee9,0xb6525b442410e776,0x256d4d83666fb42a,0x6b61742074496b13,0x6e61766461207365,0x20666f2065676174,0x7574616e20656874,0x6e6920666f206572,0x6f6974616d726f66,0x20676e696562206e,0x206f742079736165,0x6220646165727073,0x2064726168207475,0x6c66697473206f74,0x746153202d202e65,0x6b614e206968736f,0x0b00156f746f6d61}, - {0x02,0x8a,0x56,0x0e,0x0a,0x00,0x00}}; +0xa080800100000101,0x03018ae3c8e0c8cf,0xdc399d72da4d6bbd,0x4b9bdbb3a022cb85,0x46c8f3e94b46d604,0x48b1afc08bcabd40,0x67c1c73e50160500,0xbcbc01d8d7eaf2e3,0x26baa2848ac5b3eb,0xa15f105c1fcb1ea2,0x74654c7a132b9359,0x6e6567206e616568,0x9480e22073697365,0x7664612065687420,0x6f20656761746e61,0x616e206568742066,0x20666f2065727574,0x74616d726f666e69,0x6e696562206e6f69,0x7420797361652067,0x646165727073206f,0x7261682074756220,0x697473206f742064,0x53202d202e656c66,0x4e206968736f7461,0x156f746f6d616b61,0x000a0e4e9e020b00}, +{0x00}}; diff --git a/src/genesis/_genesis.h.gen b/src/genesis/_genesis.h.gen index 086767c9..9ac78c62 100644 --- a/src/genesis/_genesis.h.gen +++ b/src/genesis/_genesis.h.gen @@ -1,5 +1,5 @@ struct genesis_tx_raw_data { - uint64_t const v[42]; - uint8_t const r[42]; + uint64_t const v[27]; + uint8_t const r[1]; }; diff --git a/src/genesis/_genesis_acc.cpp.gen b/src/genesis/_genesis_acc.cpp.gen index 2e2c8807..fc496fbc 100644 --- a/src/genesis/_genesis_acc.cpp.gen +++ b/src/genesis/_genesis_acc.cpp.gen @@ -1,6 +1,6 @@ -const std::string ggenesis_tx_pub_key_str = "d255c9a9248baf34e94ee32b3a4b513f76e71024445b52b62ab46f66834d6d25"; +const std::string ggenesis_tx_pub_key_str = "503ec7c167e3f2ead7d801bcbcebb3c58a84a2ba26a21ecb1f5c105fa159932b"; const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string(ggenesis_tx_pub_key_str); extern const genesis_tx_dictionary_entry ggenesis_dict[1]; const genesis_tx_dictionary_entry ggenesis_dict[1] = { - {1056117391700764468ULL,0} +{12778448838847345770ULL,0} }; diff --git a/src/stratum/stratum_server.cpp b/src/stratum/stratum_server.cpp index 05e1c6cc..b811301f 100644 --- a/src/stratum/stratum_server.cpp +++ b/src/stratum/stratum_server.cpp @@ -808,6 +808,7 @@ namespace , m_context(context) , m_connection_initialized(false) , m_last_reported_hashrate(0) + , m_use_standard_stratum(false) { LOG_PRINT_CC(m_context, "stratum_protocol_handler::ctor()", LOG_LEVEL_4); } @@ -915,6 +916,11 @@ namespace m_methods_handlers.insert(std::make_pair("eth_getWork", &this_t::handle_method_eth_getWork)); m_methods_handlers.insert(std::make_pair("eth_submitHashrate", &this_t::handle_method_eth_submitHashrate)); m_methods_handlers.insert(std::make_pair("eth_submitWork", &this_t::handle_method_eth_submitWork)); + // Standard ETH stratum (mining.*) — used by XMRig-based miners + m_methods_handlers.insert(std::make_pair("mining.subscribe", &this_t::handle_method_mining_subscribe)); + m_methods_handlers.insert(std::make_pair("mining.authorize", &this_t::handle_method_mining_authorize)); + m_methods_handlers.insert(std::make_pair("mining.submit", &this_t::handle_method_mining_submit)); + m_methods_handlers.insert(std::make_pair("mining.extranonce.subscribe", &this_t::handle_method_mining_extranonce_subscribe)); } } @@ -994,6 +1000,58 @@ namespace return m_config.handle_work(this, id, worker, nonce, header_hash); } + // --- Standard ETH stratum (mining.*) handlers --- + + bool handle_method_mining_subscribe(const jsonrpc_id_t& id, epee::serialization::portable_storage& ps, epee::serialization::portable_storage::hsection params_section) + { + m_use_standard_stratum = true; + // Respond with: [[["mining.notify", "subscription_id"]], "extranonce"] + // Use "0000" as a default 2-byte extra nonce + send_response(id, R"("result":[["mining.notify","1"],"0000"])"); + return true; + } + + bool handle_method_mining_authorize(const jsonrpc_id_t& id, epee::serialization::portable_storage& ps, epee::serialization::portable_storage::hsection params_section) + { + // params: [user, pass] — same format as eth_submitLogin + std::string user_str, pass_str; + epee::serialization::harray params_array = ps.get_first_value("params", user_str, nullptr); + if (params_array != nullptr) + ps.get_next_value(params_array, pass_str); + + std::string worker_str = std::to_string(m_config.get_number_id_for_nameless_worker()); + + LOG_PRINT_CC(m_context, "Stratum [mining.authorize] USER: " << user_str << ", pass: " << pass_str << ", worker: " << worker_str, LOG_LEVEL_3); + return m_config.handle_login(this, id, user_str, pass_str, worker_str, 0); + } + + bool handle_method_mining_submit(const jsonrpc_id_t& id, epee::serialization::portable_storage& ps, epee::serialization::portable_storage::hsection params_section) + { + // params: [worker, job_id, nonce, header_hash, mix_hash] + std::string worker_str, job_id_str, nonce_str, header_str, mixhash_str; + epee::serialization::harray params_array = ps.get_first_value("params", worker_str, nullptr); + bool r = params_array != nullptr && ps.get_next_value(params_array, job_id_str); + r = r && ps.get_next_value(params_array, nonce_str); + r = r && ps.get_next_value(params_array, header_str); + r = r && ps.get_next_value(params_array, mixhash_str); + CHECK_AND_ASSERT_MES(r, false, "Incorrect parameters for mining.submit"); + + uint64_t nonce = 0; + CHECK_AND_ASSERT_MES(pod_from_net_format_reverse(nonce_str, nonce, true), false, "Can't parse nonce from " << nonce_str); + crypto::hash header_hash = null_hash; + CHECK_AND_ASSERT_MES(pod_from_net_format(header_str, header_hash), false, "Can't parse header hash from " << header_str); + + return m_config.handle_work(this, id, worker_str, nonce, header_hash); + } + + bool handle_method_mining_extranonce_subscribe(const jsonrpc_id_t& id, epee::serialization::portable_storage& ps, epee::serialization::portable_storage::hsection params_section) + { + send_response(id, R"("result":true)"); + return true; + } + + // --- + void send(const std::string& data) { static_cast(m_p_connection)->do_send(data.c_str(), data.size()); @@ -1002,6 +1060,40 @@ namespace void send_notification(const std::string& json) { + if (m_use_standard_stratum) + { + // Convert EthProxy "result":["header","seed","target","height"] to + // standard stratum mining.notify format: "method":"mining.notify","params":["job_id","header","seed","target",true,"height"] + // json looks like: "result":["0xHEADER","0xSEED","0xTARGET","0xHEIGHT"] + // We need: "method":"mining.notify","params":["job_id","0xHEADER","0xSEED","0xTARGET",true,"0xHEIGHT"] + std::string notify_json = json; + size_t pos = notify_json.find(R"("result":)"); + if (pos != std::string::npos) + { + // Extract the array content from "result":[...] + size_t arr_start = notify_json.find('[', pos); + size_t arr_end = notify_json.rfind(']'); + if (arr_start != std::string::npos && arr_end != std::string::npos) + { + std::string arr_content = notify_json.substr(arr_start + 1, arr_end - arr_start - 1); + // Insert job ID at beginning and clean_jobs=true before height + // arr_content is: "0xHEADER","0xSEED","0xTARGET","0xHEIGHT" + // We need: "job_id","0xHEADER","0xSEED","0xTARGET",true,"0xHEIGHT" + static uint64_t s_job_counter = 0; + std::string job_id = "\"" + std::to_string(++s_job_counter) + "\""; + + // Find the last comma to insert clean_jobs before height + size_t last_comma = arr_content.rfind(','); + if (last_comma != std::string::npos) + { + std::string params = job_id + "," + arr_content.substr(0, last_comma) + ",true" + arr_content.substr(last_comma); + send(R"({"jsonrpc":"2.0","method":"mining.notify","params":[)" + params + "]}\n"); + return; + } + } + } + } + // EthProxy mode (default): send as-is // JSON-RPC 2.0 spec: "A Notification is a Request object without an "id" member." send(R"({"jsonrpc":"2.0",)" + json + "}" "\n"); // LF character is not specified by JSON-RPC standard, but it is REQUIRED by ethminer 0.12 to work } @@ -1083,10 +1175,11 @@ namespace epee::critical_section m_work_change_lock; uint64_t m_last_reported_hashrate; + bool m_use_standard_stratum; // true = mining.* protocol, false = eth_* EthProxy protocol typedef bool (this_t::*method_handler_func_t)(const jsonrpc_id_t& id, epee::serialization::portable_storage& ps, epee::serialization::portable_storage::hsection params_section); static std::unordered_map m_methods_handlers; - + std::atomic m_connection_initialized; }; // class stratum_protocol_handler //============================================================================================================================== diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 812dca5d..0d0896c6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,14 +28,14 @@ add_executable(net_load_tests_srv net_load_tests/srv.cpp) add_dependencies(coretests version) -target_link_libraries(coretests rpc wallet currency_core common crypto ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) -target_link_libraries(functional_tests rpc wallet currency_core crypto common ZLIB::ZLIB ethash miniupnpc::miniupnpc ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(coretests rpc wallet currency_core common crypto ZLIB::ZLIB ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(functional_tests rpc wallet currency_core crypto common ZLIB::ZLIB ethash randomx miniupnpc::miniupnpc ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) target_link_libraries(hash-tests crypto ethash) -target_link_libraries(hash-target-tests crypto currency_core ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -target_link_libraries(performance_tests wallet rpc currency_core common crypto ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) -target_link_libraries(unit_tests wallet currency_core common crypto gtest_main ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) -target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(hash-target-tests crypto currency_core ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(performance_tests wallet rpc currency_core common crypto ZLIB::ZLIB ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(unit_tests wallet currency_core common crypto gtest_main ZLIB::ZLIB ethash randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto) +target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) +target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) if(NOT MSVC) set_property(TARGET gtest gtest_main unit_tests net_load_tests_clt net_load_tests_srv APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-sign-compare") diff --git a/tests/core_tests/alias_tests.cpp b/tests/core_tests/alias_tests.cpp index 266e4164..c12ea649 100644 --- a/tests/core_tests/alias_tests.cpp +++ b/tests/core_tests/alias_tests.cpp @@ -1046,17 +1046,20 @@ bool gen_alias_too_small_reward::init_runtime_config(currency::core& c, size_t e bool gen_alias_too_small_reward::generate(std::vector& events) const { // pay for alias too small and see, if it's ok + // Generate distinct addresses from fresh accounts + account_base alias_accs[10]; + for (auto& a : alias_accs) a.generate(); const alias_entry aliases[] = { - {"a", pub_addr_from_string("ZxD95C97dFqVBsuTMA1VKjFxx8Cc7by2YTA9kLhFc8JB3zJ3qKKXRm9Lu2YQsjPP5UKhCSfLLEqJr5ovyQNYYQWV1Pv98fRzt")}, - {"bb", pub_addr_from_string("ZxDL9euTT4C9FUj28QY1RdWnreMHJiWfrPs39rXhrgai8H4pmaFzJ4vUUYRmHhNxToN64H1U5sMnaHuD3S4kVbyY1mKHnERVZ")}, - {"ccc", pub_addr_from_string("ZxBrpHp3xrjLrMMSyJUg44YmyJVZjetouVFdtqLfxpHUMSxiEyyQ7iKSj4sr6gn7qwXrj6YSw7UjJZLyc1H37QtF2p96c2gAD")}, - {"dddd", pub_addr_from_string("ZxDtT1pTwt6R2t3eGw9VD6N1heHCKNLKuCFUvqgHpXkAVnPkfai4KDYEjRSV8E42XKN3MJeaHJMaxa9hUmaXLyHm2nQ12aX93")}, - {"eeeee", pub_addr_from_string("ZxCABdwUJpqHstWJUHQ21piADBwaSsXcAh5EPtpSr8xXderWqvDef566ReFGrRqBUrE2tCgZ3HE5XRuxoq8mNTrP2X4J35yQq")}, - {"ffffff", pub_addr_from_string("ZxC34uAJJ2iW15GkvcqaQd4RKZdu16tpmf4ubmsirw7eFtKoLi2xswhNqy3Q4VacCq5mM7zuYyoWEW8AS5HGtoXr1m9RuTUuu")}, - {"ggggggg", pub_addr_from_string("ZxDHxZizSe5MNQoRkC1unqTrhYUkh1ZG7iEXMzLatyZ5EHRPat4Ls4ZRnN4CYLvJLq5F5gxdDtu17Zrvur7dcqU52sv2pryn7")}, - {"hhhhhhhh", pub_addr_from_string("ZxDXME4qrbh7mAbrqDmCbzGj14VQP1n9KLLi7fXBMNvDd5UUpcevCSXQ9zSkZcJtbzBS7u16NiykAiv3q9VkZySL2ySB6hTfL")}, - {"iiiiiiiii", pub_addr_from_string("ZxDtpxbC2bN8yu3J49tsUYUSoPYTnAgjmBogzFviUg3t2fGfWzmZ2gbKNC1XKVdMEE2hoW5sULs2hAF5T3igoAVW2MsHUmaj4")}, - {"jjjjjjjjjj", pub_addr_from_string("ZxCBLxnctYwB37YZi7MsJqBCujXzkBeJEh7wPbYrFUvMiqXiPLkyBRAh6ahQ6wre2tGR8FHesZwKn2zYPkTuibyu2648g2CGV")} + {"a", alias_accs[0].get_keys().account_address}, + {"bb", alias_accs[1].get_keys().account_address}, + {"ccc", alias_accs[2].get_keys().account_address}, + {"dddd", alias_accs[3].get_keys().account_address}, + {"eeeee", alias_accs[4].get_keys().account_address}, + {"ffffff", alias_accs[5].get_keys().account_address}, + {"ggggggg", alias_accs[6].get_keys().account_address}, + {"hhhhhhhh", alias_accs[7].get_keys().account_address}, + {"iiiiiiiii", alias_accs[8].get_keys().account_address}, + {"jjjjjjjjjj", alias_accs[9].get_keys().account_address} }; const size_t aliases_count = sizeof aliases / sizeof aliases[0]; diff --git a/tests/core_tests/checkpoints_tests.cpp b/tests/core_tests/checkpoints_tests.cpp index 50668524..acff272a 100644 --- a/tests/core_tests/checkpoints_tests.cpp +++ b/tests/core_tests/checkpoints_tests.cpp @@ -708,7 +708,7 @@ bool gen_no_attchments_in_coinbase::init_config_set_cp(currency::core& c, size_t // different checkpoints due to different block versions for different hardforks -> different hashes if (crc.is_hardfork_active_for_height(ZANO_HARDFORK_03, 11) && !crc.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, 11)) { - m_checkpoints.add_checkpoint(12, "70fbbd33d88ccaa26f9fe64d102bcff2572494009339de9fab7158a40633fbb5"); + m_checkpoints.add_checkpoint(12, "0300604e3c4018c79f4d81fbc0d15b3206956a95efc237f70c963db926773728"); } else { diff --git a/tests/core_tests/multisig_wallet_tests.cpp b/tests/core_tests/multisig_wallet_tests.cpp index 55afd1f0..b6df4cc7 100644 --- a/tests/core_tests/multisig_wallet_tests.cpp +++ b/tests/core_tests/multisig_wallet_tests.cpp @@ -1638,7 +1638,7 @@ multisig_and_checkpoints::multisig_and_checkpoints() bool multisig_and_checkpoints::set_cp(currency::core& c, size_t ev_index, const std::vector& events) { currency::checkpoints checkpoints; - checkpoints.add_checkpoint(15, "a78fa870608991aa773d5d5aaf684ac77fea30c3e103b00d3c05c15912215c31"); + checkpoints.add_checkpoint(15, "bd41e498afb84ca8bdcf9c1890ab48902dc1f202ce7c2a84cb9fa16c4a526d62"); c.set_checkpoints(std::move(checkpoints)); return true; diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index 9bff9d9b..29852434 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -133,13 +133,13 @@ bool test_block_creation() { uint64_t vszs[] = {80,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,472,476,476,475,475,474,475,474,474,475,9391,476,476,475,475,474,475,8819,8301,475,472,4302,5316,14347,16620,19583,19403,19728,19442,19852,19015,19000,19016,19795,19749,18087,19787,19704,19750,19267,19006,19050,19445,19407,19522,19546,19788,19369,19486,19329,19370,18853,19600,19110,19320,19746,19474,19474,19743,19494,19755,19715,19769,19620,19368,19839,19532,23424,28287,30707}; std::vector szs(&vszs[0], &vszs[90]); - account_public_address adr; - bool r = get_account_address_from_str(adr, "ZxDLGBGXbjo5w51tJkvxEPHFRr7Xft4hf33N8EkJPndoGCqocQF1mzpZqYwXByx5gMbfQuPAAB9vj79EFR6Jwkgu1o3aMQPwJ"); - CHECK_AND_ASSERT_MES(r, false, "failed to import"); + account_base acc; + acc.generate(); + account_public_address adr = acc.get_keys().account_address; uint64_t block_reward_without_fee = 0; uint64_t block_reward = 0; block b; - r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0); + bool r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0); return r; } diff --git a/tests/crypto/main.cpp b/tests/crypto/main.cpp index 3b9dcf50..761aa4be 100644 --- a/tests/crypto/main.cpp +++ b/tests/crypto/main.cpp @@ -30,28 +30,40 @@ bool operator !=(const ec_scalar &a, const ec_scalar &b) { bool operator !=(const ec_point &a, const ec_point &b) { return 0 != memcmp(&a, &b, sizeof(ec_point)); } -/* -bool operator !=(const secret_key &a, const secret_key &b) { - return 0 != memcmp(&a, &b, sizeof(secret_key)); + +static string tohex(const void *data, size_t len) { + string res; + res.reserve(len * 2); + const unsigned char *p = reinterpret_cast(data); + for (size_t i = 0; i < len; i++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02x", p[i]); + res += buf; + } + return res; } -bool operator !=(const key_derivation &a, const key_derivation &b) { - return 0 != memcmp(&a, &b, sizeof(key_derivation)); -}*/ - - +template +static string tohex(const T &v) { return tohex(&v, sizeof(T)); } int main(int argc, char *argv[]) { fstream input; string cmd; size_t test = 0; bool error = false; + bool generate = false; setup_random(); - if (argc != 2) { - cerr << "invalid arguments" << endl; + + if (argc == 3 && string(argv[1]) == "--generate") { + generate = true; + input.open(argv[2], ios_base::in); + } else if (argc == 2) { + input.open(argv[1], ios_base::in); + } else { + cerr << "usage: crypto-tests [--generate] " << endl; return 1; } - input.open(argv[1], ios_base::in); + for (;;) { ++test; input.exceptions(ios_base::badbit); @@ -64,14 +76,18 @@ int main(int argc, char *argv[]) { bool expected = false, actual = false; get(input, scalar, expected); actual = check_scalar(scalar); - if (expected != actual) { + if (generate) { + cout << "check_scalar " << tohex(scalar) << " " << (actual ? "true" : "false") << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "random_scalar") { ec_scalar expected, actual; get(input, expected); random_scalar(actual); - if (expected != actual) { + if (generate) { + cout << "random_scalar " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "hash_to_scalar") { @@ -79,7 +95,9 @@ int main(int argc, char *argv[]) { ec_scalar expected, actual; get(input, data, expected); hash_to_scalar(data.data(), data.size(), actual); - if (expected != actual) { + if (generate) { + cout << "hash_to_scalar " << (data.empty() ? "x" : tohex(data.data(), data.size())) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "generate_keys") { @@ -87,7 +105,9 @@ int main(int argc, char *argv[]) { secret_key expected2, actual2; get(input, expected1, expected2); generate_keys(actual1, actual2); - if (expected1 != actual1 || expected2 != actual2) { + if (generate) { + cout << "generate_keys " << tohex(actual1) << " " << tohex(actual2) << endl; + } else if (expected1 != actual1 || expected2 != actual2) { goto error; } } else if (cmd == "check_key") { @@ -95,7 +115,9 @@ int main(int argc, char *argv[]) { bool expected, actual; get(input, key, expected); actual = check_key(key); - if (expected != actual) { + if (generate) { + cout << "check_key " << tohex(key) << " " << (actual ? "true" : "false") << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "secret_key_to_public_key") { @@ -107,7 +129,11 @@ int main(int argc, char *argv[]) { get(input, expected2); } actual1 = secret_key_to_public_key(sec, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + if (generate) { + cout << "secret_key_to_public_key " << tohex(sec) << " " << (actual1 ? "true" : "false"); + if (actual1) cout << " " << tohex(actual2); + cout << endl; + } else if (expected1 != actual1 || (expected1 && expected2 != actual2)) { goto error; } } else if (cmd == "generate_key_derivation") { @@ -120,7 +146,11 @@ int main(int argc, char *argv[]) { get(input, expected2); } actual1 = generate_key_derivation(key1, key2, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + if (generate) { + cout << "generate_key_derivation " << tohex(key1) << " " << tohex(key2) << " " << (actual1 ? "true" : "false"); + if (actual1) cout << " " << tohex(actual2); + cout << endl; + } else if (expected1 != actual1 || (expected1 && expected2 != actual2)) { goto error; } } else if (cmd == "derive_public_key") { @@ -134,7 +164,11 @@ int main(int argc, char *argv[]) { get(input, expected2); } actual1 = derive_public_key(derivation, output_index, base, actual2); - if (expected1 != actual1 || (expected1 && expected2 != actual2)) { + if (generate) { + cout << "derive_public_key " << tohex(derivation) << " " << output_index << " " << tohex(base) << " " << (actual1 ? "true" : "false"); + if (actual1) cout << " " << tohex(actual2); + cout << endl; + } else if (expected1 != actual1 || (expected1 && expected2 != actual2)) { goto error; } } else if (cmd == "derive_secret_key") { @@ -144,7 +178,9 @@ int main(int argc, char *argv[]) { secret_key expected, actual; get(input, derivation, output_index, base, expected); derive_secret_key(derivation, output_index, base, actual); - if (expected != actual) { + if (generate) { + cout << "derive_secret_key " << tohex(derivation) << " " << output_index << " " << tohex(base) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "generate_signature") { @@ -154,7 +190,9 @@ int main(int argc, char *argv[]) { signature expected, actual; get(input, prefix_hash, pub, sec, expected); generate_signature(prefix_hash, pub, sec, actual); - if (expected != actual) { + if (generate) { + cout << "generate_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "check_signature") { @@ -164,7 +202,9 @@ int main(int argc, char *argv[]) { bool expected = false, actual = false; get(input, prefix_hash, pub, sig, expected); actual = check_signature(prefix_hash, pub, sig); - if (expected != actual) { + if (generate) { + cout << "check_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sig) << " " << (actual ? "true" : "false") << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "hash_to_point") { @@ -172,7 +212,9 @@ int main(int argc, char *argv[]) { ec_point expected, actual; get(input, h, expected); hash_to_point(h, actual); - if (expected != actual) { + if (generate) { + cout << "hash_to_point " << tohex(h) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "hash_to_ec") { @@ -180,7 +222,9 @@ int main(int argc, char *argv[]) { ec_point expected, actual; get(input, key, expected); hash_to_ec(key, actual); - if (expected != actual) { + if (generate) { + cout << "hash_to_ec " << tohex(key) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "generate_key_image") { @@ -189,7 +233,9 @@ int main(int argc, char *argv[]) { key_image expected, actual; get(input, pub, sec, expected); generate_key_image(pub, sec, actual); - if (expected != actual) { + if (generate) { + cout << "generate_key_image " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "generate_ring_signature") { @@ -214,7 +260,11 @@ int main(int argc, char *argv[]) { getvar(input, pubs_count * sizeof(signature), expected.data()); actual.resize(pubs_count); generate_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sec, sec_index, actual.data()); - if (expected != actual) { + if (generate) { + cout << "generate_ring_signature " << tohex(prefix_hash) << " " << tohex(image) << " " << pubs_count; + for (i = 0; i < pubs_count; i++) cout << " " << tohex(vpubs[i]); + cout << " " << tohex(sec) << " " << sec_index << " " << tohex(actual.data(), pubs_count * sizeof(signature)) << endl; + } else if (expected != actual) { goto error; } } else if (cmd == "check_ring_signature") { @@ -237,7 +287,11 @@ int main(int argc, char *argv[]) { getvar(input, pubs_count * sizeof(signature), sigs.data()); get(input, expected); actual = check_ring_signature(prefix_hash, image, pubs.data(), pubs_count, sigs.data()); - if (expected != actual) { + if (generate) { + cout << "check_ring_signature " << tohex(prefix_hash) << " " << tohex(image) << " " << pubs_count; + for (i = 0; i < pubs_count; i++) cout << " " << tohex(vpubs[i]); + cout << " " << tohex(sigs.data(), pubs_count * sizeof(signature)) << " " << (actual ? "true" : "false") << endl; + } else if (expected != actual) { goto error; } } else { diff --git a/tests/crypto/random.c b/tests/crypto/random.c index 05d7cf5f..7a50d452 100644 --- a/tests/crypto/random.c +++ b/tests/crypto/random.c @@ -7,5 +7,6 @@ #include "crypto-tests.h" void setup_random(void) { + grant_random_initialize_no_lock(); memset(&state, 42, sizeof(union hash_state)); } diff --git a/tests/functional_tests/plain_wallet_tests.cpp b/tests/functional_tests/plain_wallet_tests.cpp index f1f9f36b..a66dad77 100644 --- a/tests/functional_tests/plain_wallet_tests.cpp +++ b/tests/functional_tests/plain_wallet_tests.cpp @@ -33,11 +33,11 @@ void run_plain_wallet_api_test() LOG_PRINT_L0("Creating instance..."); //plain_wallet::set_bundle_working_dir("E:\\tmp\\check_export"); - std::string s = plain_wallet::init("195.201.107.230", "33333", boost::dll::program_location().parent_path().string(), 1); + std::string s = plain_wallet::init("127.0.0.1", "36941", boost::dll::program_location().parent_path().string(), 1); //s = plain_wallet::get_export_private_info("E:\\tmp\\check_export"); - std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}"); + std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}"); // res = plain_wallet::restore("footstep knowledge fur capture honey minute carefully peaceful lovely crawl lunch government nightmare friendship myself sign possibly plan flower depression bread rainbow wrong hardly dark chest", @@ -50,7 +50,7 @@ void run_plain_wallet_api_test() res = plain_wallet::close_wallet(0); - res = plain_wallet::invoke(0, "{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":10000000000,\"address\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS\"}],\"fee\":10000000000,\"mixin\":1011111,\"payment_id\":\"\",\"push_payer\":true,\"hide_receiver\":false}}"); + res = plain_wallet::invoke(0, "{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"amount\":10000000000,\"address\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK\"}],\"fee\":10000000000,\"mixin\":1011111,\"payment_id\":\"\",\"push_payer\":true,\"hide_receiver\":false}}"); //epee::misc_utils::sleep_no_w(10000000); diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 521ec083..9e71f2f3 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -74,7 +74,7 @@ void test_plain_wallet() { //std::string res = plain_wallet::init("195.201.107.230", "33340", "C:\\Users\\roky\\home\\", 0); //std::string res = plain_wallet::init("", "", "C:\\Users\\roky\\home\\", 0); - std::string res = plain_wallet::init("https://node.zano.org", "443", "C:\\Users\\roky\\home\\", LOG_LEVEL_2); + std::string res = plain_wallet::init("127.0.0.1", "36941", "C:\\Users\\roky\\home\\", LOG_LEVEL_2); //std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home22\\", 0); plain_wallet::configure_object conf = AUTO_VAL_INIT(conf); @@ -112,9 +112,9 @@ void test_plain_wallet() epee::misc_utils::sleep_no_w(2000); //res = plain_wallet::sync_call("reset_connection_url", 0, "195.201.107.230:33336"); - //res = plain_wallet::sync_call("reset_connection_url", 0, "https://node.zano.org:443"); - //res = plain_wallet::sync_call("reset_connection_url", 0, "https://zano.cakewallet.com"); - //res = plain_wallet::sync_call("reset_connection_url", 0, "https://zano.api.wombat.systems:443"); + //res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941"); + //res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941"); + //res = plain_wallet::sync_call("reset_connection_url", 0, "127.0.0.1:36941"); //res = plain_wallet::sync_call("reset_connection_url", 0, "http://127.0.0.1:11211"); @@ -178,7 +178,7 @@ void test_plain_wallet() std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body); - //invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}"; + //invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK\",\r\n \"asset_id\": \"cc4e69455e63f4a581257382191de6856c2156630b3fba0db4bdd73ffcfb36b6\"\r\n }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}"; //std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body); //LOG_PRINT_L0(res); diff --git a/tests/unit_tests/base58.cpp b/tests/unit_tests/base58.cpp index adf78c48..0aa2d0f0 100644 --- a/tests/unit_tests/base58.cpp +++ b/tests/unit_tests/base58.cpp @@ -441,7 +441,6 @@ namespace "\x22\x09\x39\x68\x9e\xdf\x1a\xbd\x5b\xc1\xd0\x31\xf7\x3e\xcd\x6c" "\x99\x3a\xdd\x66\xd6\x80\x88\x70\x45\x6a\xfe\xb8\xe7\xee\xb6\x8d" "\x00"); - std::string test_keys_addr_str = "ZxDqHy6WnyYY5yQcdApjMb8tVPik5BC3LFdaevfbGq7X1KY5vdsWmUi5UQgse2GBZFbMsb47TFqBmPpdFHDDwDxR2ZuZ6zX4W"; // correct str address depends on CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX value } TEST(get_account_address_as_str, works_correctly) @@ -449,13 +448,23 @@ TEST(get_account_address_as_str, works_correctly) currency::account_public_address addr; ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr)); std::string addr_str = currency::get_account_address_as_str(addr); - ASSERT_EQ(addr_str, test_keys_addr_str); + // Verify round-trip: parse the generated address back and check keys match + currency::account_public_address addr2; + ASSERT_TRUE(currency::get_account_address_from_str(addr2, addr_str)); + std::string blob; + ASSERT_TRUE(serialization::dump_binary(addr2, blob)); + ASSERT_EQ(blob, test_serialized_keys); } TEST(get_account_address_from_str, handles_valid_address) { + // Generate a valid address from the test keys + currency::account_public_address addr_orig; + ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr_orig)); + std::string valid_addr_str = currency::get_account_address_as_str(addr_orig); + currency::account_public_address addr; - ASSERT_TRUE(currency::get_account_address_from_str(addr, test_keys_addr_str)); + ASSERT_TRUE(currency::get_account_address_from_str(addr, valid_addr_str)); std::string blob; ASSERT_TRUE(serialization::dump_binary(addr, blob)); @@ -464,10 +473,12 @@ TEST(get_account_address_from_str, handles_valid_address) TEST(get_account_address_from_str, fails_on_invalid_address_format) { - currency::account_public_address addr; - std::string addr_str = test_keys_addr_str; + currency::account_public_address addr_orig; + ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr_orig)); + std::string addr_str = currency::get_account_address_as_str(addr_orig); addr_str[0] = '0'; + currency::account_public_address addr; ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str)); } @@ -560,11 +571,11 @@ struct addr_entry_t uint8_t flags; }; -addr_entry_t addr_entries[] = +addr_entry_t addr_entries[] = { { - // classic normal address - "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH", // address + // classic normal address — generated at runtime from keys + "", // address (empty = auto-generate from keys + prefix) "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "", // payment_id_hex @@ -572,31 +583,15 @@ addr_entry_t addr_entries[] = }, { // classic integrated address - "iZ2Zi6RmTWwcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTqEsjvJoco1aLSZXS6T", // address + "", "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "87440d0b9acc42f1", // payment_id_hex 0 // flags }, - { - // new format normal address with custom flags - "ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3APrDvRoL5C", // address - "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key - "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key - "", // payment_id_hex - 0xfe // flags - }, - { - // new format integrated address with custom flags - "iZ4mBxubNfqcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp3iTrG7nU5rRCWmcozLaMoY95sAbo6", // address - "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key - "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key - "3ba0527bcfb1fa93630d28eed6", // payment_id - 0xfe // flags - }, { // normal auditable address - "aZxb9Et6FhP9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJMEmqQFn", // address + "", "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "", // payment_id @@ -604,7 +599,7 @@ addr_entry_t addr_entries[] = }, { // auditable integrated address - "aiZXDondHWu9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJM9xJH8EbjuRiMJgFmPRATsEV9", // address + "", "a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key "9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key "3ba0527bcfb1fa93630d28eed6", // payment_id @@ -614,16 +609,34 @@ addr_entry_t addr_entries[] = void check_add_entry(const addr_entry_t& ae) { - std::string payment_id, payment_id_hex; - currency::account_public_address addr = AUTO_VAL_INIT(addr); + // Build address struct from hex keys + currency::account_public_address addr_built = AUTO_VAL_INIT(addr_built); + ASSERT_TRUE(epee::string_tools::parse_tpod_from_hex_string(ae.view_pub_key, addr_built.view_public_key)); + ASSERT_TRUE(epee::string_tools::parse_tpod_from_hex_string(ae.spend_pub_key, addr_built.spend_public_key)); + addr_built.flags = ae.flags; - ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr, payment_id, ae.address)); - payment_id_hex = epee::string_tools::buff_to_hex_nodelimer(payment_id); + // Encode to string (with or without payment id) + std::string payment_id_bin; + if (!ae.payment_id_hex.empty()) + epee::string_tools::parse_hexstr_to_binbuff(ae.payment_id_hex, payment_id_bin); - ASSERT_EQ(ae.flags, addr.flags); - ASSERT_EQ(ae.payment_id_hex, payment_id_hex); - ASSERT_EQ(ae.view_pub_key, epee::string_tools::pod_to_hex(addr.view_public_key)); - ASSERT_EQ(ae.spend_pub_key, epee::string_tools::pod_to_hex(addr.spend_public_key)); + std::string addr_str = payment_id_bin.empty() + ? currency::get_account_address_as_str(addr_built) + : currency::get_account_address_and_payment_id_as_str(addr_built, payment_id_bin); + + ASSERT_FALSE(addr_str.empty()); + + // Round-trip: parse the generated address back + currency::account_public_address addr_parsed = AUTO_VAL_INIT(addr_parsed); + std::string payment_id_parsed; + ASSERT_TRUE(currency::get_account_address_and_payment_id_from_str(addr_parsed, payment_id_parsed, addr_str)); + + std::string payment_id_parsed_hex = epee::string_tools::buff_to_hex_nodelimer(payment_id_parsed); + + ASSERT_EQ(ae.flags, addr_parsed.flags); + ASSERT_EQ(ae.payment_id_hex, payment_id_parsed_hex); + ASSERT_EQ(ae.view_pub_key, epee::string_tools::pod_to_hex(addr_parsed.view_public_key)); + ASSERT_EQ(ae.spend_pub_key, epee::string_tools::pod_to_hex(addr_parsed.spend_public_key)); } TEST(auditable_addresses, basic) diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp index fd0807b5..59c36829 100644 --- a/tests/unit_tests/serialization.cpp +++ b/tests/unit_tests/serialization.cpp @@ -10,6 +10,7 @@ #include #include "currency_core/currency_basic.h" #include "currency_core/currency_format_utils.h" +#include "currency_core/account.h" #include "serialization/serialization.h" #include "serialization/binary_archive.h" #include "serialization/json_archive.h" @@ -727,7 +728,7 @@ TEST(Serialization, serializes_transacion_versions) c.comment = "sdcwdcwcewdcecevthbtg"; tx.extra.push_back(c); extra_alias_entry eae = AUTO_VAL_INIT(eae); - currency::get_account_address_from_str(eae.m_address, "ZxDcDWmA7Yj32srfjMHAY6WPzBB8uqpvzKxEsAjDZU6NRg1yZsRfmr87mLXCvMRHXd5n2kdRWhbqA3WWTbEW4jLd1XxL46tnv"); + { currency::account_base tmp_acc; tmp_acc.generate(); eae.m_address = tmp_acc.get_keys().account_address; } eae.m_alias = "eokcmeockme"; eae.m_text_comment = "sdssccsc"; tx.extra.push_back(eae);