Compare commits
No commits in common. "dev" and "main" have entirely different histories.
53 changed files with 1287 additions and 873 deletions
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 9c9346d5494688a78ea573f3bc0547ad12b9be2a
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
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"
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
|
|
@ -10,9 +10,3 @@
|
|||
[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
|
||||
|
|
|
|||
|
|
@ -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}/.core/build/cmake")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
if(POLICY CMP0043)
|
||||
cmake_policy(SET CMP0043 NEW)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"cacheVariables": {
|
||||
"TESTNET": "ON",
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES":".core/build/cmake/ConanProvider.cmake"
|
||||
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES":"cmake/ConanProvider.cmake"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
"cacheVariables": {
|
||||
"TESTNET": "OFF",
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES":".core/build/cmake/ConanProvider.cmake"
|
||||
"CMAKE_PROJECT_TOP_LEVEL_INCLUDES":"cmake/ConanProvider.cmake"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
"conan": {}
|
||||
},
|
||||
"include": [
|
||||
"build/release/generators/CMakePresets.json"
|
||||
"build/release/conan/build/debug/generators/CMakePresets.json"
|
||||
]
|
||||
}
|
||||
61
Makefile
61
Makefile
|
|
@ -4,15 +4,12 @@
|
|||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
# ============================================================
|
||||
# Build system from host-uk/build submodule
|
||||
# ============================================================
|
||||
BUILD_SYS := .core/build
|
||||
CMAKE_DIR := $(BUILD_SYS)/cmake
|
||||
# ------------------------------------------------------------
|
||||
# Detect the number of logical CPU cores – works on Linux,
|
||||
# macOS, BSD, and Windows (both cmd.exe and PowerShell).
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# ============================================================
|
||||
# Project Configuration
|
||||
# ============================================================
|
||||
# Default to “unknown” – will be overwritten below.
|
||||
CPU_CORES := 1
|
||||
TESTNET:= 0
|
||||
STATIC:= 0
|
||||
|
|
@ -22,22 +19,21 @@ 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
|
||||
|
||||
|
|
@ -45,27 +41,29 @@ 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
|
||||
# -----------------------------------------------------------------
|
||||
# Safety net – ensure we always have a positive integer.
|
||||
# -----------------------------------------------------------------
|
||||
CPU_CORES := $(or $(CPU_CORES),1)
|
||||
CPU_CORES := $(shell expr $(CPU_CORES) + 0 2>/dev/null || echo 1)
|
||||
CONAN_CPU_COUNT=$(CPU_CORES)
|
||||
|
||||
# ============================================================
|
||||
# Paths — profiles and cmake modules from .build submodule
|
||||
# ============================================================
|
||||
PROFILES :=$(patsubst $(CMAKE_DIR)/profiles/%,%,$(wildcard $(CMAKE_DIR)/profiles/*))
|
||||
PROFILES :=$(patsubst cmake/profiles/%,%,$(wildcard cmake/profiles/*))
|
||||
SORTED_PROFILES :=$(sort $(PROFILES))
|
||||
CONAN_CACHE :=$(CURDIR)/build/sdk
|
||||
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_URL :=https://artifacts.host.uk.com/artifactory/api/conan/conan-build
|
||||
CONAN_USER :=public
|
||||
CONAN_PASSWORD :=Lethean1234
|
||||
CONAN_EXECUTABLE :=$(CURDIR)/build/bin/conan
|
||||
CC_DOCKER_FILE ?=utils/docker/images/lthn-chain/Dockerfile
|
||||
SDK_PACKAGES_JSON :=$(wildcard utils/sdk/packages/*.json)
|
||||
|
|
@ -113,10 +111,10 @@ docs: configure
|
|||
sdk:
|
||||
$(MAKE) -C utils/sdk $(filter-out $@,$(MAKECMDGOALS)) PACKAGE_VERSION=$(BUILD_VERSION)
|
||||
|
||||
# Rule for each profile — uses .build/cmake/profiles/
|
||||
# Rule for each profile
|
||||
$(PROFILES): conan-profile-detect
|
||||
@echo "Building profile: $@"
|
||||
CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) install . -pr:h=$(CMAKE_DIR)/profiles/$@ --build=missing -s build_type=$(BUILD_TYPE)
|
||||
CONAN_HOME=$(CONAN_CACHE) $(CONAN_EXECUTABLE) install . -pr:h=cmake/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)
|
||||
|
|
@ -130,10 +128,10 @@ help:
|
|||
@echo ""
|
||||
@echo "Available targets:"
|
||||
@printf " %-42s %s\n" "make clean" "Clean all build directories"
|
||||
@printf " %-42s %s\n" "make conan-get" "Download and install conan locally"
|
||||
@printf " %-42s %s\n" "make get-conan" "Download and install conan locally"
|
||||
@printf " %-42s %s\n" "make release" "Build release"
|
||||
@printf " %-42s %s\n" "make testnet" "Build testnet"
|
||||
@printf " %-42s %s\n" "make mainnet" "Build mainnet"
|
||||
@printf " %-42s %s\n" "make static" "Build static release"
|
||||
@printf " %-42s %s\n" "make debug" "Build debug"
|
||||
@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"
|
||||
|
|
@ -163,19 +161,17 @@ test-debug:
|
|||
cmake --build build/test-debug --config=Debug --parallel=$(CPU_CORES)
|
||||
$(MAKE) test
|
||||
|
||||
# Conan management — cmake modules from .build submodule
|
||||
# allowing this target to error quietly saves cross brwoser file detection
|
||||
conan-get:
|
||||
cmake -P $(CMAKE_DIR)/ConanGet.cmake
|
||||
ifneq ($(CONAN_USER),)
|
||||
cmake -P cmake/ConanGet.cmake
|
||||
(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_DIR)/ConanProfileSetup.cmake
|
||||
cmake -P cmake/ConanProfileSetup.cmake
|
||||
|
||||
docs-dev: configure
|
||||
@echo "Building Documentation"
|
||||
|
|
@ -185,7 +181,7 @@ $(SDK_TARGETS):
|
|||
@# This is a proxy target. Handled by the 'sdk' rule.
|
||||
|
||||
clean:
|
||||
@cmake -P $(CMAKE_DIR)/CleanBuild.cmake
|
||||
@cmake -P cmake/CleanBuild.cmake
|
||||
|
||||
clean-build: clean
|
||||
rm -rf build
|
||||
|
|
@ -193,4 +189,5 @@ 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 conan-get $(PROFILES) sdk $(SDK_TARGETS)
|
||||
.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
|
||||
88
cmake/CPackConfig.cmake
Normal file
88
cmake/CPackConfig.cmake
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
|
||||
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()
|
||||
76
cmake/CleanBuild.cmake
Normal file
76
cmake/CleanBuild.cmake
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# 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()
|
||||
102
cmake/ConanGet.cmake
Normal file
102
cmake/ConanGet.cmake
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# 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()
|
||||
38
cmake/ConanProfileSetup.cmake
Normal file
38
cmake/ConanProfileSetup.cmake
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
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.")
|
||||
698
cmake/ConanProvider.cmake
Normal file
698
cmake/ConanProvider.cmake
Normal file
|
|
@ -0,0 +1,698 @@
|
|||
# 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 <cstddef>
|
||||
#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 <string>
|
||||
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 <cstddef>
|
||||
#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$<$<CONFIG:Debug>: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$<$<CONFIG:Debug>:Debug> MultiThreaded$<$<CONFIG:Debug>: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 "<CONFIG:Debug>: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 (<PackageName> PATHS paths... NO_DEFAULT_PATH)
|
||||
# find_package (<PackageName>)
|
||||
|
||||
# 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)
|
||||
45
cmake/DocBuilder.cmake
Normal file
45
cmake/DocBuilder.cmake
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
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
|
||||
8
cmake/FindCcache.cmake
Normal file
8
cmake/FindCcache.cmake
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
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()
|
||||
9
cmake/profiles/apple-clang-armv8
Normal file
9
cmake/profiles/apple-clang-armv8
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[settings]
|
||||
os=Macos
|
||||
arch=armv8
|
||||
compiler=apple-clang
|
||||
compiler.version=13
|
||||
compiler.libcxx=libc++
|
||||
|
||||
[conf]
|
||||
|
||||
8
cmake/profiles/apple-clang-x86_64
Normal file
8
cmake/profiles/apple-clang-x86_64
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[settings]
|
||||
os=Macos
|
||||
arch=x86_64
|
||||
compiler=apple-clang
|
||||
compiler.version=13
|
||||
compiler.libcxx=libc++
|
||||
|
||||
[conf]
|
||||
9
cmake/profiles/gcc-linux-armv8
Normal file
9
cmake/profiles/gcc-linux-armv8
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[settings]
|
||||
os=Linux
|
||||
arch=armv8
|
||||
compiler=gcc
|
||||
compiler.version=11
|
||||
compiler.libcxx=libstdc++11
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_presets=False
|
||||
9
cmake/profiles/gcc-linux-x86_64
Normal file
9
cmake/profiles/gcc-linux-x86_64
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=gcc
|
||||
compiler.version=11
|
||||
compiler.libcxx=libstdc++11
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_presets=False
|
||||
10
cmake/profiles/msvc-193-x86_64
Normal file
10
cmake/profiles/msvc-193-x86_64
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[settings]
|
||||
arch=x86_64
|
||||
compiler=msvc
|
||||
compiler.cppstd=17
|
||||
compiler.runtime=static
|
||||
compiler.version=193
|
||||
os=Windows
|
||||
|
||||
[conf]
|
||||
tools.cmake.cmaketoolchain:user_presets=False
|
||||
8
cmake/profiles/msvc-194-x86_64
Normal file
8
cmake/profiles/msvc-194-x86_64
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[settings]
|
||||
arch=x86_64
|
||||
compiler=msvc
|
||||
compiler.cppstd=17
|
||||
compiler.runtime=static
|
||||
compiler.version=194
|
||||
os=Windows
|
||||
build_type=Release
|
||||
|
|
@ -3,4 +3,4 @@
|
|||
static_assert(1, "FAIL");
|
||||
int main(int argc, char *argv[]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
add_subdirectory(db)
|
||||
add_subdirectory(ethereum)
|
||||
add_subdirectory(randomx)
|
||||
|
||||
if(USE_BITCOIN_SECP256K1_FOR_ECDSA)
|
||||
option(SECP256K1_BUILD_BENCHMARK "Build benchmarks." OFF)
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit cf15f4023ec8ddaa842f49111ba80ead1b5937f1
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
-------------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<crypto::public_key>(ggenesis_tx_pub_key_str);
|
||||
extern const genesis_tx_dictionary_entry ggenesis_dict[1];
|
||||
const genesis_tx_dictionary_entry ggenesis_dict[1] = {
|
||||
{12778448838847345770ULL,0}
|
||||
};
|
||||
|
|
@ -1 +0,0 @@
|
|||
01010000018080a0cfc8e0c8e38a0103bd6b4dda729d39dc85cb22a0b3db9b4b04d6464be9f3c84640bdca8bc0afb148000516503ec7c167e3f2ead7d801bcbcebb3c58a84a2ba26a21ecb1f5c105fa159932b137a4c65746865616e2067656e6573697320e280942074686520616476616e74616765206f6620746865206e6174757265206f6620696e666f726d6174696f6e206265696e67206561737920746f2073707265616420627574206861726420746f20737469666c652e202d205361746f736869204e616b616d6f746f15000b029e4e0e0a0000
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
--------- 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}};
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
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)
|
||||
Binary file not shown.
|
|
@ -1 +0,0 @@
|
|||
iTHNdRWX6pKGXF1HqHgZyXie8EdaCwwdWUmsEnQhNojSUrkrR2eTemhFYkjWXbhdbyGcRBLgV2RYp3HhNAFCQ67w4bTHErZL1J
|
||||
|
|
@ -119,7 +119,6 @@ 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})
|
||||
|
|
@ -165,19 +164,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 randomx 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 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 randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(connectivity_tool currency_core crypto common ZLIB::ZLIB ethash ${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 randomx ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(simplewallet wallet rpc currency_core crypto common ZLIB::ZLIB ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
|
||||
ENABLE_SHARED_PCH(simplewallet SIMPLEWALLET)
|
||||
ENABLE_SHARED_PCH_EXECUTABLE(simplewallet)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ target_link_libraries(api_server
|
|||
crypto
|
||||
common
|
||||
ethash
|
||||
randomx
|
||||
${Boost_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
OpenSSL::SSL
|
||||
|
|
|
|||
|
|
@ -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 10 CACHE STRING "DIFFICULTY_POW_TARGET" )
|
||||
set(difficulty_pow_target 120 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" )
|
||||
|
|
|
|||
|
|
@ -27,102 +27,39 @@ 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 <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "ethereum/libethash/ethash/progpow.hpp"
|
||||
|
||||
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;
|
||||
|
||||
static void init_randomx()
|
||||
//--------------------------------------------------------------
|
||||
int ethash_custom_log_get_level()
|
||||
{
|
||||
rx_flags = randomx_get_flags() | RANDOMX_FLAG_FULL_MEM;
|
||||
LOG_PRINT_L0("[RandomX] Initializing with flags: " << static_cast<int>(rx_flags));
|
||||
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_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;
|
||||
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)
|
||||
return;
|
||||
}
|
||||
|
||||
// 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;
|
||||
ethash::access_custom_log_level_function() = ðash_custom_log_get_level;
|
||||
ethash::access_custom_log_function() = ðash_custom_log;
|
||||
|
||||
LOG_PRINT_L0("[RandomX] Initializing dataset (" << item_count << " items, " << num_threads << " threads)...");
|
||||
|
||||
std::vector<std::thread> 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");
|
||||
inited = true;
|
||||
}
|
||||
|
||||
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<int>(height / ETHASH_EPOCH_LENGTH);
|
||||
|
|
@ -138,20 +75,17 @@ namespace currency
|
|||
//--------------------------------------------------------------
|
||||
crypto::hash get_block_longhash(uint64_t height, const crypto::hash& block_header_hash, uint64_t 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);
|
||||
|
||||
init_ethash_log_if_necessary();
|
||||
int epoch = ethash_height_to_epoch(height);
|
||||
std::shared_ptr<ethash::epoch_context_full> p_context = progpow::get_global_epoch_context_full(static_cast<int>(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<int>(height), *(ethash::hash256*)&block_header_hash, nonce);
|
||||
crypto::hash result = currency::null_hash;
|
||||
std::memcpy(&result.data, hash_out, sizeof(result.data));
|
||||
memcpy(&result.data, &res_eth.final_hash, sizeof(res_eth.final_hash));
|
||||
return result;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1428,7 +1428,14 @@ wide_difficulty_type blockchain_storage::calc_diff_at_h_from_timestamps(std::vec
|
|||
{
|
||||
wide_difficulty_type dif;
|
||||
TIME_MEASURE_START_PD(target_calculating_calc);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(target_calculating_calc);
|
||||
return dif;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,75 +267,4 @@ 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<uint64_t>& timestamps, vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter)
|
||||
{
|
||||
const int64_t T = static_cast<int64_t>(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<int64_t>(timestamps[i])
|
||||
- static_cast<int64_t>(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<int64_t>(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<wide_difficulty_type>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ namespace currency
|
|||
bool check_hash(const crypto::hash &hash, wide_difficulty_type difficulty);
|
||||
wide_difficulty_type next_difficulty_1(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter);
|
||||
wide_difficulty_type next_difficulty_2(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& cumulative_difficulties, size_t target_seconds, const wide_difficulty_type& difficulty_starter);
|
||||
wide_difficulty_type next_difficulty_lwma(std::vector<std::uint64_t>& timestamps, std::vector<wide_difficulty_type>& 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
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}};
|
||||
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}};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
struct genesis_tx_raw_data
|
||||
{
|
||||
uint64_t const v[27];
|
||||
uint8_t const r[1];
|
||||
uint64_t const v[42];
|
||||
uint8_t const r[42];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const std::string ggenesis_tx_pub_key_str = "503ec7c167e3f2ead7d801bcbcebb3c58a84a2ba26a21ecb1f5c105fa159932b";
|
||||
const std::string ggenesis_tx_pub_key_str = "d255c9a9248baf34e94ee32b3a4b513f76e71024445b52b62ab46f66834d6d25";
|
||||
const crypto::public_key ggenesis_tx_pub_key = epee::string_tools::parse_tpod_from_hex_string<crypto::public_key>(ggenesis_tx_pub_key_str);
|
||||
extern const genesis_tx_dictionary_entry ggenesis_dict[1];
|
||||
const genesis_tx_dictionary_entry ggenesis_dict[1] = {
|
||||
{12778448838847345770ULL,0}
|
||||
{1056117391700764468ULL,0}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -808,7 +808,6 @@ 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);
|
||||
}
|
||||
|
|
@ -916,11 +915,6 @@ 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1000,58 +994,6 @@ 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<epee::net_utils::i_service_endpoint*>(m_p_connection)->do_send(data.c_str(), data.size());
|
||||
|
|
@ -1060,40 +1002,6 @@ 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
|
||||
}
|
||||
|
|
@ -1175,11 +1083,10 @@ 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<std::string, method_handler_func_t> m_methods_handlers;
|
||||
|
||||
|
||||
std::atomic<bool> m_connection_initialized;
|
||||
}; // class stratum_protocol_handler
|
||||
//==============================================================================================================================
|
||||
|
|
|
|||
|
|
@ -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 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(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(hash-tests crypto ethash)
|
||||
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})
|
||||
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})
|
||||
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -1046,20 +1046,17 @@ bool gen_alias_too_small_reward::init_runtime_config(currency::core& c, size_t e
|
|||
bool gen_alias_too_small_reward::generate(std::vector<test_event_entry>& 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", 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}
|
||||
{"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")}
|
||||
};
|
||||
|
||||
const size_t aliases_count = sizeof aliases / sizeof aliases[0];
|
||||
|
|
|
|||
|
|
@ -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, "0300604e3c4018c79f4d81fbc0d15b3206956a95efc237f70c963db926773728");
|
||||
m_checkpoints.add_checkpoint(12, "70fbbd33d88ccaa26f9fe64d102bcff2572494009339de9fab7158a40633fbb5");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<test_event_entry>& events)
|
||||
{
|
||||
currency::checkpoints checkpoints;
|
||||
checkpoints.add_checkpoint(15, "bd41e498afb84ca8bdcf9c1890ab48902dc1f202ce7c2a84cb9fa16c4a526d62");
|
||||
checkpoints.add_checkpoint(15, "a78fa870608991aa773d5d5aaf684ac77fea30c3e103b00d3c05c15912215c31");
|
||||
c.set_checkpoints(std::move(checkpoints));
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -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<uint64_t> szs(&vszs[0], &vszs[90]);
|
||||
account_base acc;
|
||||
acc.generate();
|
||||
account_public_address adr = acc.get_keys().account_address;
|
||||
account_public_address adr;
|
||||
bool r = get_account_address_from_str(adr, "ZxDLGBGXbjo5w51tJkvxEPHFRr7Xft4hf33N8EkJPndoGCqocQF1mzpZqYwXByx5gMbfQuPAAB9vj79EFR6Jwkgu1o3aMQPwJ");
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to import");
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
uint64_t block_reward = 0;
|
||||
block b;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,40 +30,28 @@ 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));
|
||||
}
|
||||
|
||||
static string tohex(const void *data, size_t len) {
|
||||
string res;
|
||||
res.reserve(len * 2);
|
||||
const unsigned char *p = reinterpret_cast<const unsigned char *>(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 secret_key &a, const secret_key &b) {
|
||||
return 0 != memcmp(&a, &b, sizeof(secret_key));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static string tohex(const T &v) { return tohex(&v, sizeof(T)); }
|
||||
bool operator !=(const key_derivation &a, const key_derivation &b) {
|
||||
return 0 != memcmp(&a, &b, sizeof(key_derivation));
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
fstream input;
|
||||
string cmd;
|
||||
size_t test = 0;
|
||||
bool error = false;
|
||||
bool generate = false;
|
||||
setup_random();
|
||||
|
||||
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] <tests.txt>" << endl;
|
||||
if (argc != 2) {
|
||||
cerr << "invalid arguments" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
input.open(argv[1], ios_base::in);
|
||||
for (;;) {
|
||||
++test;
|
||||
input.exceptions(ios_base::badbit);
|
||||
|
|
@ -76,18 +64,14 @@ int main(int argc, char *argv[]) {
|
|||
bool expected = false, actual = false;
|
||||
get(input, scalar, expected);
|
||||
actual = check_scalar(scalar);
|
||||
if (generate) {
|
||||
cout << "check_scalar " << tohex(scalar) << " " << (actual ? "true" : "false") << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "random_scalar") {
|
||||
ec_scalar expected, actual;
|
||||
get(input, expected);
|
||||
random_scalar(actual);
|
||||
if (generate) {
|
||||
cout << "random_scalar " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "hash_to_scalar") {
|
||||
|
|
@ -95,9 +79,7 @@ int main(int argc, char *argv[]) {
|
|||
ec_scalar expected, actual;
|
||||
get(input, data, expected);
|
||||
hash_to_scalar(data.data(), data.size(), actual);
|
||||
if (generate) {
|
||||
cout << "hash_to_scalar " << (data.empty() ? "x" : tohex(data.data(), data.size())) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "generate_keys") {
|
||||
|
|
@ -105,9 +87,7 @@ int main(int argc, char *argv[]) {
|
|||
secret_key expected2, actual2;
|
||||
get(input, expected1, expected2);
|
||||
generate_keys(actual1, actual2);
|
||||
if (generate) {
|
||||
cout << "generate_keys " << tohex(actual1) << " " << tohex(actual2) << endl;
|
||||
} else if (expected1 != actual1 || expected2 != actual2) {
|
||||
if (expected1 != actual1 || expected2 != actual2) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "check_key") {
|
||||
|
|
@ -115,9 +95,7 @@ int main(int argc, char *argv[]) {
|
|||
bool expected, actual;
|
||||
get(input, key, expected);
|
||||
actual = check_key(key);
|
||||
if (generate) {
|
||||
cout << "check_key " << tohex(key) << " " << (actual ? "true" : "false") << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "secret_key_to_public_key") {
|
||||
|
|
@ -129,11 +107,7 @@ int main(int argc, char *argv[]) {
|
|||
get(input, expected2);
|
||||
}
|
||||
actual1 = secret_key_to_public_key(sec, 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)) {
|
||||
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "generate_key_derivation") {
|
||||
|
|
@ -146,11 +120,7 @@ int main(int argc, char *argv[]) {
|
|||
get(input, expected2);
|
||||
}
|
||||
actual1 = generate_key_derivation(key1, key2, 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)) {
|
||||
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "derive_public_key") {
|
||||
|
|
@ -164,11 +134,7 @@ int main(int argc, char *argv[]) {
|
|||
get(input, expected2);
|
||||
}
|
||||
actual1 = derive_public_key(derivation, output_index, base, 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)) {
|
||||
if (expected1 != actual1 || (expected1 && expected2 != actual2)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "derive_secret_key") {
|
||||
|
|
@ -178,9 +144,7 @@ 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 (generate) {
|
||||
cout << "derive_secret_key " << tohex(derivation) << " " << output_index << " " << tohex(base) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "generate_signature") {
|
||||
|
|
@ -190,9 +154,7 @@ int main(int argc, char *argv[]) {
|
|||
signature expected, actual;
|
||||
get(input, prefix_hash, pub, sec, expected);
|
||||
generate_signature(prefix_hash, pub, sec, actual);
|
||||
if (generate) {
|
||||
cout << "generate_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "check_signature") {
|
||||
|
|
@ -202,9 +164,7 @@ 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 (generate) {
|
||||
cout << "check_signature " << tohex(prefix_hash) << " " << tohex(pub) << " " << tohex(sig) << " " << (actual ? "true" : "false") << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "hash_to_point") {
|
||||
|
|
@ -212,9 +172,7 @@ int main(int argc, char *argv[]) {
|
|||
ec_point expected, actual;
|
||||
get(input, h, expected);
|
||||
hash_to_point(h, actual);
|
||||
if (generate) {
|
||||
cout << "hash_to_point " << tohex(h) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "hash_to_ec") {
|
||||
|
|
@ -222,9 +180,7 @@ int main(int argc, char *argv[]) {
|
|||
ec_point expected, actual;
|
||||
get(input, key, expected);
|
||||
hash_to_ec(key, actual);
|
||||
if (generate) {
|
||||
cout << "hash_to_ec " << tohex(key) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "generate_key_image") {
|
||||
|
|
@ -233,9 +189,7 @@ int main(int argc, char *argv[]) {
|
|||
key_image expected, actual;
|
||||
get(input, pub, sec, expected);
|
||||
generate_key_image(pub, sec, actual);
|
||||
if (generate) {
|
||||
cout << "generate_key_image " << tohex(pub) << " " << tohex(sec) << " " << tohex(actual) << endl;
|
||||
} else if (expected != actual) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "generate_ring_signature") {
|
||||
|
|
@ -260,11 +214,7 @@ 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 (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) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else if (cmd == "check_ring_signature") {
|
||||
|
|
@ -287,11 +237,7 @@ 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 (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) {
|
||||
if (expected != actual) {
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,5 @@
|
|||
#include "crypto-tests.h"
|
||||
|
||||
void setup_random(void) {
|
||||
grant_random_initialize_no_lock();
|
||||
memset(&state, 42, sizeof(union hash_state));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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("127.0.0.1", "36941", boost::dll::program_location().parent_path().string(), 1);
|
||||
std::string s = plain_wallet::init("195.201.107.230", "33333", 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\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK:1780c4d5dd7e97cc4a75ea8baa7977d12ef948b9a6dddc2a9a37e5e22ac7180e:1599495055\"}");
|
||||
std::string res = plain_wallet::sync_call("get_seed_phrase_info", 0, "{\"seed_phrase\":\"aZxat4HAWriVQ3enkGcVsrZRdMseAJswG3CSEwTqZS246VsFQ53w26eZstYsu1jWE74Atz9ajLxFnBsVTafncWNH5SMv4zHFaTS: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\":\"iTHNHvUTA2gR7gSb854s58SpAyqtR5aCNcfzBzVHjhvPcw2gQ2PHDiwT48U4ZyLVjtLxev8fAQ7NaGLZe6ihTSgp7gL45MJTCK\"}],\"fee\":10000000000,\"mixin\":1011111,\"payment_id\":\"\",\"push_payer\":true,\"hide_receiver\":false}}");
|
||||
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}}");
|
||||
|
||||
//epee::misc_utils::sleep_no_w(10000000);
|
||||
|
||||
|
|
|
|||
|
|
@ -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("127.0.0.1", "36941", "C:\\Users\\roky\\home\\", LOG_LEVEL_2);
|
||||
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", "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, "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, "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, "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\": \"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}";
|
||||
//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}";
|
||||
//std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
//LOG_PRINT_L0(res);
|
||||
|
|
|
|||
|
|
@ -441,6 +441,7 @@ 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)
|
||||
|
|
@ -448,23 +449,13 @@ 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);
|
||||
// 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);
|
||||
ASSERT_EQ(addr_str, test_keys_addr_str);
|
||||
}
|
||||
|
||||
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, valid_addr_str));
|
||||
ASSERT_TRUE(currency::get_account_address_from_str(addr, test_keys_addr_str));
|
||||
|
||||
std::string blob;
|
||||
ASSERT_TRUE(serialization::dump_binary(addr, blob));
|
||||
|
|
@ -473,12 +464,10 @@ 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_orig;
|
||||
ASSERT_TRUE(serialization::parse_binary(test_serialized_keys, addr_orig));
|
||||
std::string addr_str = currency::get_account_address_as_str(addr_orig);
|
||||
currency::account_public_address addr;
|
||||
std::string addr_str = test_keys_addr_str;
|
||||
addr_str[0] = '0';
|
||||
|
||||
currency::account_public_address addr;
|
||||
ASSERT_FALSE(currency::get_account_address_from_str(addr, addr_str));
|
||||
}
|
||||
|
||||
|
|
@ -571,11 +560,11 @@ struct addr_entry_t
|
|||
uint8_t flags;
|
||||
};
|
||||
|
||||
addr_entry_t addr_entries[] =
|
||||
addr_entry_t addr_entries[] =
|
||||
{
|
||||
{
|
||||
// classic normal address — generated at runtime from keys
|
||||
"", // address (empty = auto-generate from keys + prefix)
|
||||
// classic normal address
|
||||
"ZxD5aoLDPTdcaRx4uCpyW4XiLfEXejepAVz8cSY2fwHNEiJNu6NmpBBDLGTJzCsUvn3acCVDVDPMV8yQXdPooAp338Se7AxeH", // address
|
||||
"a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key
|
||||
"9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key
|
||||
"", // payment_id_hex
|
||||
|
|
@ -583,15 +572,31 @@ 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
|
||||
|
|
@ -599,7 +604,7 @@ addr_entry_t addr_entries[] =
|
|||
},
|
||||
{
|
||||
// auditable integrated address
|
||||
"",
|
||||
"aiZXDondHWu9AinRwcPqSqBKjckre7PgoZjK3q5YG2fUKHYWFZMWjB6YAEAdw4yDDUGEQ7CGEgbqhGRKeadGV1jLYcEJM9xJH8EbjuRiMJgFmPRATsEV9", // address
|
||||
"a3f208c8f9ba49bab28eed62b35b0f6be0a297bcd85c2faa1eb1820527bcf7e3", // view_pub_key
|
||||
"9f5e1fa93630d4b281b18bb67a3db79e9622fc703cc3ad4a453a82e0a36d51fa", // spend_pub_key
|
||||
"3ba0527bcfb1fa93630d28eed6", // payment_id
|
||||
|
|
@ -609,34 +614,16 @@ addr_entry_t addr_entries[] =
|
|||
|
||||
void check_add_entry(const addr_entry_t& ae)
|
||||
{
|
||||
// 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;
|
||||
std::string payment_id, payment_id_hex;
|
||||
currency::account_public_address addr = AUTO_VAL_INIT(addr);
|
||||
|
||||
// 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_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);
|
||||
|
||||
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));
|
||||
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));
|
||||
}
|
||||
|
||||
TEST(auditable_addresses, basic)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#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"
|
||||
|
|
@ -728,7 +727,7 @@ TEST(Serialization, serializes_transacion_versions)
|
|||
c.comment = "sdcwdcwcewdcecevthbtg";
|
||||
tx.extra.push_back(c);
|
||||
extra_alias_entry eae = AUTO_VAL_INIT(eae);
|
||||
{ currency::account_base tmp_acc; tmp_acc.generate(); eae.m_address = tmp_acc.get_keys().account_address; }
|
||||
currency::get_account_address_from_str(eae.m_address, "ZxDcDWmA7Yj32srfjMHAY6WPzBB8uqpvzKxEsAjDZU6NRg1yZsRfmr87mLXCvMRHXd5n2kdRWhbqA3WWTbEW4jLd1XxL46tnv");
|
||||
eae.m_alias = "eokcmeockme";
|
||||
eae.m_text_comment = "sdssccsc";
|
||||
tx.extra.push_back(eae);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue