1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-14 20:22:19 +00:00

Merge pull request #1427 from ton-blockchain/testnet

Merge developer branch
This commit is contained in:
EmelyanenkoK 2024-12-11 14:43:20 +03:00 committed by GitHub
commit ea0dc16163
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
199 changed files with 7261 additions and 2157 deletions

View file

@ -21,6 +21,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/android/build-android-tonlib.sh .
chmod +x build-android-tonlib.sh
./build-android-tonlib.sh -a

View file

@ -35,6 +35,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-ubuntu-shared.sh .
chmod +x build-ubuntu-shared.sh
./build-ubuntu-shared.sh -t -a

View file

@ -14,6 +14,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -t -a

View file

@ -14,6 +14,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -t -a

View file

@ -4,7 +4,7 @@ on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-12
runs-on: macos-13
steps:
- name: Check out repository
@ -14,6 +14,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -t -a
@ -21,5 +23,5 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-binaries-macos-12
name: ton-binaries-macos-13
path: artifacts

View file

@ -15,10 +15,12 @@ jobs:
- name: Install system libraries
run: |
sudo apt-get update
sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev
sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev libjemalloc-dev
- name: Build TON WASM artifacts
run: |
git submodule sync --recursive
git submodule update
cp assembly/wasm/fift-func-wasm-build-ubuntu.sh .
chmod +x fift-func-wasm-build-ubuntu.sh
./fift-func-wasm-build-ubuntu.sh -a

View file

@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v3
- name: Download Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-linux.yml
path: artifacts
@ -20,7 +20,7 @@ jobs:
skip_unpack: true
- name: Download and unzip Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-linux.yml
path: artifacts
@ -28,7 +28,7 @@ jobs:
skip_unpack: false
- name: Download Mac x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-macos.yml
path: artifacts
@ -36,7 +36,7 @@ jobs:
skip_unpack: true
- name: Download Mac arm64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-arm64-macos.yml
path: artifacts
@ -44,7 +44,7 @@ jobs:
skip_unpack: true
- name: Download and unzip Mac x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-macos.yml
path: artifacts
@ -52,7 +52,7 @@ jobs:
skip_unpack: false
- name: Download and unzip arm64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-arm64-macos.yml
path: artifacts
@ -60,7 +60,7 @@ jobs:
skip_unpack: false
- name: Download Windows artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-windows.yml
path: artifacts
@ -68,7 +68,7 @@ jobs:
skip_unpack: true
- name: Download and unzip Windows artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-windows.yml
path: artifacts
@ -76,7 +76,7 @@ jobs:
skip_unpack: false
- name: Download WASM artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-wasm-emscripten.yml
path: artifacts
@ -84,7 +84,7 @@ jobs:
skip_unpack: true
- name: Download Android Tonlib artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-android-tonlib.yml
path: artifacts
@ -183,6 +183,14 @@ jobs:
asset_name: lite-client.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/proxy-liteserver.exe
asset_name: proxy-liteserver.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
@ -281,6 +289,14 @@ jobs:
asset_name: lite-client-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/proxy-liteserver
asset_name: proxy-liteserver-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
@ -380,6 +396,14 @@ jobs:
asset_name: lite-client-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/proxy-liteserver
asset_name: proxy-liteserver-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
@ -478,6 +502,14 @@ jobs:
asset_name: lite-client-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/proxy-liteserver
asset_name: proxy-liteserver-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:

View file

@ -41,7 +41,7 @@ jobs:
id: docker_build
uses: docker/build-push-action@v6
with:
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
push: true
context: ./
tags: |

View file

@ -18,6 +18,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh -t

View file

@ -22,6 +22,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/nix/build-linux-x86-64-nix.sh .
chmod +x build-linux-x86-64-nix.sh
./build-linux-x86-64-nix.sh -t

View file

@ -4,7 +4,7 @@ on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-12
runs-on: macos-13
steps:
- uses: actions/checkout@v3
@ -18,6 +18,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh -t

View file

@ -23,6 +23,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
copy assembly\native\build-windows-github-2019.bat .
copy assembly\native\build-windows-2019.bat .
build-windows-github-2019.bat Enterprise

1
.gitignore vendored
View file

@ -19,7 +19,6 @@ zlib/
libsodium/
libmicrohttpd-0.9.77-w32-bin/
readline-5.0-1-lib/
secp256k1/
openssl-3.1.4/
libsodium-1.0.18-stable-msvc.zip
libmicrohttpd-0.9.77-w32-bin.zip

4
.gitmodules vendored
View file

@ -13,3 +13,7 @@
[submodule "third-party/blst"]
path = third-party/blst
url = https://github.com/supranational/blst.git
[submodule "third-party/secp256k1"]
path = third-party/secp256k1
url = https://github.com/bitcoin-core/secp256k1
branch = v0.3.2

View file

@ -0,0 +1,55 @@
if (NOT SECP256K1_LIBRARY)
set(SECP256K1_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1)
set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/third-party/secp256k1)
set(SECP256K1_INCLUDE_DIR ${SECP256K1_BINARY_DIR}/include)
file(MAKE_DIRECTORY ${SECP256K1_BINARY_DIR})
file(MAKE_DIRECTORY "${SECP256K1_BINARY_DIR}/include")
if (MSVC)
set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1)
set(SECP256K1_LIBRARY ${SECP256K1_SOURCE_DIR}/build/src/Release/libsecp256k1.lib)
set(SECP256K1_INCLUDE_DIR ${SECP256K1_BINARY_DIR}/include)
add_custom_command(
WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR}
COMMAND cmake -E env CFLAGS="/WX" cmake -A x64 -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_ENABLE_MODULE_EXTRAKEYS=ON -DSECP256K1_BUILD_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF
COMMAND cmake --build build --config Release
COMMENT "Build Secp256k1"
DEPENDS ${SECP256K1_SOURCE_DIR}
OUTPUT ${SECP256K1_LIBRARY}
)
elseif (EMSCRIPTEN)
set(SECP256K1_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third-party/secp256k1)
set(SECP256K1_LIBRARY ${SECP256K1_BINARY_DIR}/.libs/libsecp256k1.a)
set(SECP256K1_INCLUDE_DIR ${SECP256K1_SOURCE_DIR}/include)
add_custom_command(
WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR}
COMMAND ./autogen.sh
COMMAND emconfigure ./configure --enable-module-recovery --enable-module-extrakeys --disable-tests --disable-benchmark
COMMAND emmake make clean
COMMAND emmake make
COMMENT "Build Secp256k1 with emscripten"
DEPENDS ${SECP256K1_SOURCE_DIR}
OUTPUT ${SECP256K1_LIBRARY}
)
else()
if (NOT NIX)
set(SECP256K1_LIBRARY ${SECP256K1_BINARY_DIR}/lib/libsecp256k1.a)
add_custom_command(
WORKING_DIRECTORY ${SECP256K1_SOURCE_DIR}
COMMAND ./autogen.sh
COMMAND ./configure -q --disable-option-checking --enable-module-recovery --enable-module-extrakeys --prefix ${SECP256K1_BINARY_DIR} --with-pic --disable-shared --enable-static --disable-tests --disable-benchmark
COMMAND make -j16
COMMAND make install
COMMENT "Build secp256k1"
DEPENDS ${SECP256K1_SOURCE_DIR}
OUTPUT ${SECP256K1_LIBRARY}
)
endif()
endif()
else()
message(STATUS "Use Secp256k1: ${SECP256K1_LIBRARY}")
endif()
add_custom_target(secp256k1 DEPENDS ${SECP256K1_LIBRARY})

View file

@ -1,9 +1,8 @@
# - Try to find SECP256K1
# - Try to find Secp256k1
# Once done this will define
#
# SECP256K1_FOUND - system has SECP256K1
# SECP256K1_INCLUDE_DIR - the SECP256K1 include directory
# SECP256K1_LIBRARY - Link these to use SECP256K1
# SECP256K1_INCLUDE_DIR - the Secp256k1 include directory
# SECP256K1_LIBRARY - Link these to use Secp256k1
if (NOT SECP256K1_LIBRARY)
find_path(

View file

@ -183,6 +183,7 @@ message("Add ton")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
include(BuildBLST)
include(BuildSECP256K1)
# Configure CCache if available
find_program(CCACHE_FOUND ccache)
@ -237,6 +238,11 @@ if (TON_USE_JEMALLOC)
find_package(jemalloc REQUIRED)
endif()
if (NIX)
find_package(Secp256k1 REQUIRED)
endif()
set(MEMPROF "" CACHE STRING "Use one of \"ON\", \"FAST\" or \"SAFE\" to enable memory profiling. \
Works under macOS and Linux when compiled using glibc. \
In FAST mode stack is unwinded only using frame pointers, which may fail. \

View file

@ -1,3 +1,17 @@
## 2024.12 Update
1. FunC 0.4.6: Fix in try/catch handling, fixing pure flag for functions stored in variables
2. Merging parts of Accelerator: support of specific shard monitoring, archive/liteserver slice format, support for partial liteservers, proxy liteserver, on-demand neighbour queue loading
3. Fix of asynchronous cell loading
4. Various improvements: caching certificates checks, better block overloading detection, `_malloc` in emulator
5. Introduction of telemetry in overlays
6. Use non-null local-id for tonlib-LS interaction - mitigates MitM attack.
7. Adding `SECP256K1_XONLY_PUBKEY_TWEAK_ADD`, `SETCONTCTRMANY` instructions to TVM (activated by `Config8.version >= 9`)
8. Private keys export via validator-engine-console - required for better backups
9. Fix proof checking in tonlib, `hash` in `raw.Message` in tonlib_api
Besides the work of the core team, this update is based on the efforts of OtterSec and LayerZero (FunC), tg:@throwunless (FunC), Aviv Frenkel and Dima Kogan from Fordefi (LS MitM), @hacker-volodya (Tonlib), OKX team (async cell loading), @krigga (emulator)
## 2024.10 Update
1. Parallel write to celldb: substantial improvement of sync and GC speed, especially with slow disks.

View file

@ -1,6 +1,6 @@
FROM ubuntu:22.04 AS builder
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git ninja-build libsecp256k1-dev libsodium-dev libmicrohttpd-dev liblz4-dev pkg-config autoconf automake libtool libjemalloc-dev lsb-release software-properties-common gnupg
DEBIAN_FRONTEND=noninteractive apt-get install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git ninja-build libsodium-dev libmicrohttpd-dev liblz4-dev pkg-config autoconf automake libtool libjemalloc-dev lsb-release software-properties-common gnupg
RUN wget https://apt.llvm.org/llvm.sh && \
chmod +x llvm.sh && \
@ -20,14 +20,17 @@ COPY ./ ./
RUN mkdir build && \
cd build && \
cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= -DTON_USE_JEMALLOC=ON .. && \
ninja storage-daemon storage-daemon-cli tonlibjson fift func validator-engine validator-engine-console generate-random-id dht-server lite-client
ninja storage-daemon storage-daemon-cli tonlibjson fift func validator-engine validator-engine-console \
generate-random-id dht-server lite-client tolk rldp-http-proxy dht-server proxy-liteserver create-state \
blockchain-explorer emulator tonlibjson http-proxy adnl-proxy
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y wget curl libatomic1 openssl libsecp256k1-dev libsodium-dev libmicrohttpd-dev liblz4-dev libjemalloc-dev htop net-tools netcat iptraf-ng jq tcpdump pv plzip && \
apt-get install -y wget curl libatomic1 openssl libsodium-dev libmicrohttpd-dev liblz4-dev libjemalloc-dev htop \
net-tools netcat iptraf-ng jq tcpdump pv plzip && \
rm -rf /var/lib/apt/lists/*
RUN mkdir -p /var/ton-work/db /var/ton-work/scripts /usr/share/ton/smartcont/ /usr/lib/fift/
RUN mkdir -p /var/ton-work/db /var/ton-work/scripts /usr/share/ton/smartcont/auto /usr/lib/fift/
COPY --from=builder /ton/build/storage/storage-daemon/storage-daemon /usr/local/bin/
COPY --from=builder /ton/build/storage/storage-daemon/storage-daemon-cli /usr/local/bin/
@ -35,9 +38,20 @@ COPY --from=builder /ton/build/lite-client/lite-client /usr/local/bin/
COPY --from=builder /ton/build/validator-engine/validator-engine /usr/local/bin/
COPY --from=builder /ton/build/validator-engine-console/validator-engine-console /usr/local/bin/
COPY --from=builder /ton/build/utils/generate-random-id /usr/local/bin/
COPY --from=builder /ton/build/blockchain-explorer/blockchain-explorer /usr/local/bin/
COPY --from=builder /ton/build/crypto/create-state /usr/local/bin/
COPY --from=builder /ton/build/utils/proxy-liteserver /usr/local/bin/
COPY --from=builder /ton/build/dht-server/dht-server /usr/local/bin/
COPY --from=builder /ton/build/rldp-http-proxy/rldp-http-proxy /usr/local/bin/
COPY --from=builder /ton/build/http/http-proxy /usr/local/bin/
COPY --from=builder /ton/build/adnl/adnl-proxy /usr/local/bin/
COPY --from=builder /ton/build/tonlib/libtonlibjson.so /usr/local/bin/
COPY --from=builder /ton/build/emulator/libemulator.so /usr/local/bin/
COPY --from=builder /ton/build/tolk/tolk /usr/local/bin/
COPY --from=builder /ton/build/crypto/fift /usr/local/bin/
COPY --from=builder /ton/build/crypto/func /usr/local/bin/
COPY --from=builder /ton/crypto/smartcont/* /usr/share/ton/smartcont/
COPY --from=builder /ton/crypto/smartcont/auto/* /usr/share/ton/smartcont/auto/
COPY --from=builder /ton/crypto/fift/lib/* /usr/lib/fift/
WORKDIR /var/ton-work/db

View file

@ -43,7 +43,10 @@ class AdnlOutboundConnection : public AdnlExtConnection {
public:
AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr<AdnlExtConnection::Callback> callback, AdnlNodeIdFull dst,
td::actor::ActorId<AdnlExtClientImpl> ext_client)
: AdnlExtConnection(std::move(fd), std::move(callback), true), dst_(std::move(dst)), ext_client_(ext_client) {
: AdnlExtConnection(std::move(fd), std::move(callback), true)
, dst_(std::move(dst))
, local_id_(privkeys::Ed25519::random())
, ext_client_(ext_client) {
}
AdnlOutboundConnection(td::SocketFd fd, std::unique_ptr<AdnlExtConnection::Callback> callback, AdnlNodeIdFull dst,
PrivateKey local_id, td::actor::ActorId<AdnlExtClientImpl> ext_client)

View file

@ -8,14 +8,19 @@ while getopts 'a' flag; do
esac
done
export CC=$(which clang-16)
export CXX=$(which clang++-16)
export CCACHE_DISABLE=1
if [ ! -d android-ndk-r25b ]; then
rm android-ndk-r25b-linux.zip
echo "Downloading https://dl.google.com/android/repository/android-ndk-r25b-linux.zip"
wget -q https://dl.google.com/android/repository/android-ndk-r25b-linux.zip
unzip -q android-ndk-r25b-linux.zip
test $? -eq 0 || { echo "Can't unzip android-ndk-r25b-linux.zip"; exit 1; }
echo Android NDK extracted
echo "Android NDK extracted"
else
echo Using extracted Android NDK
echo "Using extracted Android NDK"
fi
export JAVA_AWT_LIBRARY=NotNeeded

View file

@ -52,21 +52,6 @@ else
echo "Using compiled lz4"
fi
if [ ! -d "secp256k1" ]; then
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
secp256k1Path=`pwd`
git checkout v0.3.2
./autogen.sh
./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark --with-pic
make -j12
test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; }
cd ..
else
secp256k1Path=$(pwd)/secp256k1
echo "Using compiled secp256k1"
fi
if [ ! -d "libsodium" ]; then
export LIBSODIUM_FULL_BUILD=1
git clone https://github.com/jedisct1/libsodium.git
@ -135,9 +120,6 @@ cmake -GNinja .. \
-DZLIB_FOUND=1 \
-DZLIB_INCLUDE_DIR=$zlibPath \
-DZLIB_LIBRARIES=$zlibPath/libz.a \
-DSECP256K1_FOUND=1 \
-DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \
-DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \
-DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \
@ -158,35 +140,16 @@ if [ "$with_tests" = true ]; then
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator \
test-ed25519 test-ed25519-crypto test-bigint test-vm test-fift test-cells test-smartcont \
test-net test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli blockchain-explorer \
tonlib tonlibjson tonlib-cli validator-engine func tolk fift \
lite-client pow-miner validator-engine-console generate-random-id json2tlo dht-server \
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -s storage/storage-daemon/storage-daemon
strip -s storage/storage-daemon/storage-daemon-cli
strip -s blockchain-explorer/blockchain-explorer
strip -s crypto/fift
strip -s crypto/func
strip -s tolk/tolk
strip -s crypto/create-state
strip -s crypto/tlbc
strip -s validator-engine-console/validator-engine-console
strip -s tonlib/tonlib-cli
strip -s http/http-proxy
strip -s rldp-http-proxy/rldp-http-proxy
strip -s dht-server/dht-server
strip -s lite-client/lite-client
strip -s validator-engine/validator-engine
strip -s utils/generate-random-id
strip -s utils/json2tlo
strip -s adnl/adnl-proxy
cd ..
if [ "$with_artifacts" = true ]; then
@ -211,6 +174,7 @@ if [ "$with_artifacts" = true ]; then
cp build/validator-engine/validator-engine artifacts/
cp build/utils/generate-random-id artifacts/
cp build/utils/json2tlo artifacts/
cp build/utils/proxy-liteserver artifacts/
cp build/adnl/adnl-proxy artifacts/
cp build/emulator/libemulator.dylib artifacts/
rsync -r crypto/smartcont artifacts/

View file

@ -36,21 +36,6 @@ else
fi
export CCACHE_DISABLE=1
if [ ! -d "secp256k1" ]; then
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
secp256k1Path=`pwd`
git checkout v0.3.2
./autogen.sh
./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark
make -j12
test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; }
cd ..
else
secp256k1Path=$(pwd)/secp256k1
echo "Using compiled secp256k1"
fi
if [ ! -d "lz4" ]; then
git clone https://github.com/lz4/lz4
cd lz4
@ -70,9 +55,6 @@ brew unlink openssl@3 && brew link --overwrite openssl@3
cmake -GNinja -DCMAKE_BUILD_TYPE=Release .. \
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
-DSECP256K1_FOUND=1 \
-DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \
-DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \
-DLZ4_FOUND=1 \
-DLZ4_LIBRARIES=$lz4Path/lib/liblz4.a \
-DLZ4_INCLUDE_DIRS=$lz4Path/lib
@ -86,36 +68,16 @@ if [ "$with_tests" = true ]; then
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator \
test-ed25519 test-ed25519-crypto test-bigint test-vm test-fift test-cells test-smartcont \
test-net test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli blockchain-explorer \
tonlib tonlibjson tonlib-cli validator-engine func tolk fift \
lite-client pow-miner validator-engine-console generate-random-id json2tlo dht-server \
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -s storage/storage-daemon/storage-daemon
strip -s storage/storage-daemon/storage-daemon-cli
strip -s blockchain-explorer/blockchain-explorer
strip -s crypto/fift
strip -s crypto/func
strip -s tolk/tolk
strip -s crypto/create-state
strip -s crypto/tlbc
strip -s validator-engine-console/validator-engine-console
strip -s tonlib/tonlib-cli
strip -s http/http-proxy
strip -s rldp-http-proxy/rldp-http-proxy
strip -s dht-server/dht-server
strip -s lite-client/lite-client
strip -s validator-engine/validator-engine
strip -s utils/generate-random-id
strip -s utils/json2tlo
strip -s adnl/adnl-proxy
cd ..
if [ "$with_artifacts" = true ]; then
@ -140,6 +102,7 @@ if [ "$with_artifacts" = true ]; then
cp build/validator-engine/validator-engine artifacts/
cp build/utils/generate-random-id artifacts/
cp build/utils/json2tlo artifacts/
cp build/utils/proxy-liteserver artifacts/
cp build/adnl/adnl-proxy artifacts/
cp build/emulator/libemulator.dylib artifacts/
cp -R crypto/smartcont artifacts/

View file

@ -43,23 +43,6 @@ else
echo "Using compiled lz4"
fi
if [ ! -d "secp256k1" ]; then
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
secp256k1Path=`pwd`
git checkout v0.3.2
./autogen.sh
./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark --with-pic
make -j12
test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; }
cd ..
# ./.libs/libsecp256k1.a
# ./include
else
secp256k1Path=$(pwd)/secp256k1
echo "Using compiled secp256k1"
fi
if [ ! -d "libsodium" ]; then
export LIBSODIUM_FULL_BUILD=1
git clone https://github.com/jedisct1/libsodium.git
@ -126,9 +109,6 @@ cmake -GNinja .. \
-DZLIB_FOUND=1 \
-DZLIB_INCLUDE_DIR=$zlibPath \
-DZLIB_LIBRARIES=$zlibPath/libz.a \
-DSECP256K1_FOUND=1 \
-DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \
-DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \
-DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \
@ -150,39 +130,16 @@ ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-
adnl-proxy create-state emulator test-ed25519 test-ed25519-crypto test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator
adnl-proxy create-state emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -s storage/storage-daemon/storage-daemon \
storage/storage-daemon/storage-daemon-cli \
blockchain-explorer/blockchain-explorer \
crypto/fift \
crypto/tlbc \
crypto/func \
tolk/tolk \
crypto/create-state \
validator-engine-console/validator-engine-console \
tonlib/tonlib-cli \
tonlib/libtonlibjson.so.0.5 \
http/http-proxy \
rldp-http-proxy/rldp-http-proxy \
dht-server/dht-server \
lite-client/lite-client \
validator-engine/validator-engine \
utils/generate-random-id \
utils/json2tlo \
adnl/adnl-proxy \
emulator/libemulator.*
test $? -eq 0 || { echo "Can't strip final binaries"; exit 1; }
# simple binaries' test
./storage/storage-daemon/storage-daemon -V || exit 1
./validator-engine/validator-engine -V || exit 1
@ -197,7 +154,7 @@ if [ "$with_artifacts" = true ]; then
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/tolk/tolk build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/utils/proxy-liteserver \
build/tonlib/libtonlibjson.so build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy \
build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine \
build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy build/emulator/libemulator.so \

View file

@ -58,39 +58,16 @@ ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-
adnl-proxy create-state emulator test-ed25519 test-ed25519-crypto test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator
adnl-proxy create-state emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -s storage/storage-daemon/storage-daemon \
storage/storage-daemon/storage-daemon-cli \
blockchain-explorer/blockchain-explorer \
crypto/fift \
crypto/tlbc \
crypto/func \
tolk/tolk \
crypto/create-state \
validator-engine-console/validator-engine-console \
tonlib/tonlib-cli \
tonlib/libtonlibjson.so.0.5 \
http/http-proxy \
rldp-http-proxy/rldp-http-proxy \
dht-server/dht-server \
lite-client/lite-client \
validator-engine/validator-engine \
utils/generate-random-id \
utils/json2tlo \
adnl/adnl-proxy \
emulator/libemulator.*
test $? -eq 0 || { echo "Can't strip final binaries"; exit 1; }
# simple binaries' test
./storage/storage-daemon/storage-daemon -V || exit 1
./validator-engine/validator-engine -V || exit 1
@ -107,7 +84,7 @@ if [ "$with_artifacts" = true ]; then
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/tolk/tolk build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/utils/proxy-liteserver \
build/tonlib/libtonlibjson.so build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy \
build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine \
build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy build/emulator/libemulator.so \

View file

@ -26,129 +26,109 @@ IF %errorlevel% NEQ 0 (
exit /b %errorlevel%
)
if not exist "zlib" (
git clone https://github.com/madler/zlib.git
cd zlib
git checkout v1.3.1
cd contrib\vstudio\vc14
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v142
echo Installing nasm...
choco install -y nasm
where nasm
SET PATH=%PATH%;C:\Program Files\NASM
IF %errorlevel% NEQ 0 (
echo Can't install zlib
echo Can't install nasm
exit /b %errorlevel%
)
cd ..\..\..\..
mkdir third_libs
cd third_libs
set third_libs=%cd%
echo %third_libs%
if not exist "zlib" (
git clone https://github.com/madler/zlib.git
cd zlib
git checkout v1.3.1
cd contrib\vstudio\vc14
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v142
cd ..\..\..\..
) else (
echo Using zlib...
echo Using zlib...
)
if not exist "lz4" (
git clone https://github.com/lz4/lz4.git
cd lz4
git checkout v1.9.4
cd build\VS2017\liblz4
msbuild liblz4.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v142
IF %errorlevel% NEQ 0 (
echo Can't install lz4
exit /b %errorlevel%
)
cd ..\..\..\..
git clone https://github.com/lz4/lz4.git
cd lz4
git checkout v1.9.4
cd build\VS2017\liblz4
msbuild liblz4.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v142
cd ..\..\..\..
) else (
echo Using lz4...
echo Using lz4...
)
if not exist "secp256k1" (
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
git checkout v0.3.2
cmake -G "Visual Studio 16 2019" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DBUILD_SHARED_LIBS=OFF
IF %errorlevel% NEQ 0 (
echo Can't configure secp256k1
exit /b %errorlevel%
if not exist "libsodium" (
git clone https://github.com/jedisct1/libsodium
cd libsodium
git checkout 1.0.18-RELEASE
msbuild libsodium.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v142
cd ..
) else (
echo Using libsodium...
)
cmake --build build --config Release
IF %errorlevel% NEQ 0 (
echo Can't install secp256k1
exit /b %errorlevel%
if not exist "openssl" (
git clone https://github.com/openssl/openssl.git
cd openssl
git checkout openssl-3.1.4
where perl
perl Configure VC-WIN64A
IF %errorlevel% NEQ 0 (
echo Can't configure openssl
exit /b %errorlevel%
)
nmake
cd ..
) else (
echo Using openssl...
)
if not exist "libmicrohttpd" (
git clone https://github.com/Karlson2k/libmicrohttpd.git
cd libmicrohttpd
git checkout v1.0.1
cd w32\VS2019
msbuild libmicrohttpd.vcxproj /p:Configuration=Release-static /p:platform=x64 -p:PlatformToolset=v142
IF %errorlevel% NEQ 0 (
echo Can't compile libmicrohttpd
exit /b %errorlevel%
)
cd ../../..
) else (
echo Using libmicrohttpd...
)
cd ..
) else (
echo Using secp256k1...
)
curl --retry 5 --retry-delay 10 -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip
IF %errorlevel% NEQ 0 (
echo Can't download libsodium
exit /b %errorlevel%
)
unzip libsodium-1.0.18-stable-msvc.zip
) else (
echo Using libsodium...
)
if not exist "openssl-3.1.4" (
curl -Lo openssl-3.1.4.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-3.1.4.zip
IF %errorlevel% NEQ 0 (
echo Can't download OpenSSL
exit /b %errorlevel%
)
unzip -q openssl-3.1.4.zip
) else (
echo Using openssl...
)
if not exist "libmicrohttpd-0.9.77-w32-bin" (
curl -Lo libmicrohttpd-0.9.77-w32-bin.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/libmicrohttpd-0.9.77-w32-bin.zip
IF %errorlevel% NEQ 0 (
echo Can't download libmicrohttpd
exit /b %errorlevel%
)
unzip -q libmicrohttpd-0.9.77-w32-bin.zip
) else (
echo Using libmicrohttpd...
)
if not exist "readline-5.0-1-lib" (
curl -Lo readline-5.0-1-lib.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/readline-5.0-1-lib.zip
IF %errorlevel% NEQ 0 (
echo Can't download readline
exit /b %errorlevel%
)
unzip -q -d readline-5.0-1-lib readline-5.0-1-lib.zip
) else (
echo Using readline...
)
set root=%cd%
echo %root%
set SODIUM_DIR=%root%\libsodium
echo Current dir %cd%
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^
-DPORTABLE=1 ^
-DSODIUM_USE_STATIC_LIBS=1 ^
-DSECP256K1_FOUND=1 ^
-DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^
-DSECP256K1_LIBRARY=%root%\secp256k1\build\src\Release\libsecp256k1.lib ^
-DSODIUM_LIBRARY_RELEASE=%third_libs%\libsodium\Build\Release\x64\libsodium.lib ^
-DSODIUM_LIBRARY_DEBUG=%third_libs%\libsodium\Build\Release\x64\libsodium.lib ^
-DSODIUM_INCLUDE_DIR=%third_libs%\libsodium\src\libsodium\include ^
-DLZ4_FOUND=1 ^
-DLZ4_INCLUDE_DIRS=%root%\lz4\lib ^
-DLZ4_LIBRARIES=%root%\lz4\build\VS2017\liblz4\bin\x64_Release\liblz4_static.lib ^
-DLZ4_INCLUDE_DIRS=%third_libs%\lz4\lib ^
-DLZ4_LIBRARIES=%third_libs%\lz4\build\VS2017\liblz4\bin\x64_Release\liblz4_static.lib ^
-DMHD_FOUND=1 ^
-DMHD_LIBRARY=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static\libmicrohttpd.lib ^
-DMHD_INCLUDE_DIR=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static ^
-DMHD_LIBRARY=%third_libs%\libmicrohttpd\w32\VS2019\Output\x64\libmicrohttpd.lib ^
-DMHD_INCLUDE_DIR=%third_libs%\libmicrohttpd\src\include ^
-DZLIB_FOUND=1 ^
-DZLIB_INCLUDE_DIR=%root%\zlib ^
-DZLIB_LIBRARIES=%root%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
-DZLIB_INCLUDE_DIR=%third_libs%\zlib ^
-DZLIB_LIBRARIES=%third_libs%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
-DOPENSSL_FOUND=1 ^
-DOPENSSL_INCLUDE_DIR=%root%\openssl-3.1.4\x64\include ^
-DOPENSSL_CRYPTO_LIBRARY=%root%\openssl-3.1.4\x64\lib\libcrypto_static.lib ^
-DREADLINE_INCLUDE_DIR=%root%\readline-5.0-1-lib\include ^
-DREADLINE_LIBRARY=%root%\readline-5.0-1-lib\lib\readline.lib ^
-DOPENSSL_INCLUDE_DIR=%third_libs%\openssl\include ^
-DOPENSSL_CRYPTO_LIBRARY=%third_libs%\openssl\libcrypto_static.lib ^
-DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj" ..
IF %errorlevel% NEQ 0 (
echo Can't configure TON
exit /b %errorlevel%
@ -160,7 +140,7 @@ tonlib-cli validator-engine lite-client pow-miner validator-engine-console gener
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator ^
test-ed25519 test-ed25519-crypto test-bigint test-vm test-fift test-cells test-smartcont test-net ^
test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
IF %errorlevel% NEQ 0 (
echo Can't compile TON
exit /b %errorlevel%
@ -168,7 +148,7 @@ IF %errorlevel% NEQ 0 (
) else (
ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tolk tonlib tonlibjson ^
tonlib-cli validator-engine lite-client pow-miner validator-engine-console generate-random-id ^
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator proxy-liteserver
IF %errorlevel% NEQ 0 (
echo Can't compile TON
exit /b %errorlevel%
@ -191,32 +171,38 @@ REM ctest -C Release --output-on-failure -E "test-catchain|test-actors|test-val
)
)
echo Creating artifacts...
echo Strip and copy artifacts
cd ..
echo where strip
where strip
mkdir artifacts
mkdir artifacts\smartcont
mkdir artifacts\lib
for %%I in (build\storage\storage-daemon\storage-daemon.exe ^
build\storage\storage-daemon\storage-daemon-cli.exe ^
build\blockchain-explorer\blockchain-explorer.exe ^
build\crypto\fift.exe ^
build\crypto\tlbc.exe ^
build\crypto\func.exe ^
build\tolk\tolk.exe ^
build\crypto\create-state.exe ^
build\validator-engine-console\validator-engine-console.exe ^
build\tonlib\tonlib-cli.exe ^
build\tonlib\tonlibjson.dll ^
build\http\http-proxy.exe ^
build\rldp-http-proxy\rldp-http-proxy.exe ^
build\dht-server\dht-server.exe ^
build\lite-client\lite-client.exe ^
build\validator-engine\validator-engine.exe ^
build\utils\generate-random-id.exe ^
build\utils\json2tlo.exe ^
build\adnl\adnl-proxy.exe ^
build\emulator\emulator.dll) do (strip -s %%I & copy %%I artifacts\)
build\storage\storage-daemon\storage-daemon-cli.exe ^
build\blockchain-explorer\blockchain-explorer.exe ^
build\crypto\fift.exe ^
build\crypto\tlbc.exe ^
build\crypto\func.exe ^
build\tolk\tolk.exe ^
build\crypto\create-state.exe ^
build\validator-engine-console\validator-engine-console.exe ^
build\tonlib\tonlib-cli.exe ^
build\tonlib\tonlibjson.dll ^
build\http\http-proxy.exe ^
build\rldp-http-proxy\rldp-http-proxy.exe ^
build\dht-server\dht-server.exe ^
build\lite-client\lite-client.exe ^
build\validator-engine\validator-engine.exe ^
build\utils\generate-random-id.exe ^
build\utils\json2tlo.exe ^
build\utils\proxy-liteserver.exe ^
build\adnl\adnl-proxy.exe ^
build\emulator\emulator.dll) do (
echo strip -s %%I & copy %%I artifacts\
strip -s %%I & copy %%I artifacts\
)
xcopy /e /k /h /i crypto\smartcont artifacts\smartcont
xcopy /e /k /h /i crypto\fift\lib artifacts\lib

View file

@ -26,130 +26,109 @@ IF %errorlevel% NEQ 0 (
exit /b %errorlevel%
)
if not exist "zlib" (
git clone https://github.com/madler/zlib.git
cd zlib
git checkout v1.3.1
cd contrib\vstudio\vc14
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v143
echo Installing nasm...
choco install -y nasm
where nasm
SET PATH=%PATH%;C:\Program Files\NASM
IF %errorlevel% NEQ 0 (
echo Can't install zlib
echo Can't install nasm
exit /b %errorlevel%
)
cd ..\..\..\..
mkdir third_libs
cd third_libs
set third_libs=%cd%
echo %third_libs%
if not exist "zlib" (
git clone https://github.com/madler/zlib.git
cd zlib
git checkout v1.3.1
cd contrib\vstudio\vc14
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v143
cd ..\..\..\..
) else (
echo Using zlib...
echo Using zlib...
)
if not exist "lz4" (
git clone https://github.com/lz4/lz4.git
cd lz4
git checkout v1.9.4
cd build\VS2017\liblz4
msbuild liblz4.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v143
dir /s
IF %errorlevel% NEQ 0 (
echo Can't install lz4
exit /b %errorlevel%
)
cd ..\..\..\..
git clone https://github.com/lz4/lz4.git
cd lz4
git checkout v1.9.4
cd build\VS2022\liblz4
msbuild liblz4.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v143
cd ..\..\..\..
) else (
echo Using lz4...
echo Using lz4...
)
if not exist "secp256k1" (
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
git checkout v0.3.2
cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DBUILD_SHARED_LIBS=OFF
IF %errorlevel% NEQ 0 (
echo Can't configure secp256k1
exit /b %errorlevel%
)
cmake --build build --config Release
IF %errorlevel% NEQ 0 (
echo Can't install secp256k1
exit /b %errorlevel%
)
cd ..
) else (
echo Using secp256k1...
)
if not exist "libsodium" (
curl -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip
IF %errorlevel% NEQ 0 (
echo Can't download libsodium
exit /b %errorlevel%
)
unzip libsodium-1.0.18-stable-msvc.zip
git clone https://github.com/jedisct1/libsodium
cd libsodium
git checkout 1.0.18-RELEASE
msbuild libsodium.vcxproj /p:Configuration=Release /p:platform=x64 -p:PlatformToolset=v143
cd ..
) else (
echo Using libsodium...
echo Using libsodium...
)
if not exist "openssl-3.1.4" (
curl -Lo openssl-3.1.4.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-3.1.4.zip
IF %errorlevel% NEQ 0 (
echo Can't download OpenSSL
exit /b %errorlevel%
)
unzip -q openssl-3.1.4.zip
if not exist "openssl" (
git clone https://github.com/openssl/openssl.git
cd openssl
git checkout openssl-3.1.4
where perl
perl Configure VC-WIN64A
IF %errorlevel% NEQ 0 (
echo Can't configure openssl
exit /b %errorlevel%
)
nmake
cd ..
) else (
echo Using openssl...
echo Using openssl...
)
if not exist "libmicrohttpd-0.9.77-w32-bin" (
curl -Lo libmicrohttpd-0.9.77-w32-bin.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/libmicrohttpd-0.9.77-w32-bin.zip
IF %errorlevel% NEQ 0 (
echo Can't download libmicrohttpd
exit /b %errorlevel%
)
unzip -q libmicrohttpd-0.9.77-w32-bin.zip
if not exist "libmicrohttpd" (
git clone https://github.com/Karlson2k/libmicrohttpd.git
cd libmicrohttpd
git checkout v1.0.1
cd w32\VS2022
msbuild libmicrohttpd.vcxproj /p:Configuration=Release-static /p:platform=x64 -p:PlatformToolset=v143
IF %errorlevel% NEQ 0 (
echo Can't compile libmicrohttpd
exit /b %errorlevel%
)
cd ../../..
) else (
echo Using libmicrohttpd...
echo Using libmicrohttpd...
)
if not exist "readline-5.0-1-lib" (
curl -Lo readline-5.0-1-lib.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/readline-5.0-1-lib.zip
IF %errorlevel% NEQ 0 (
echo Can't download readline
exit /b %errorlevel%
)
unzip -q -d readline-5.0-1-lib readline-5.0-1-lib.zip
) else (
echo Using readline...
)
set root=%cd%
echo %root%
set SODIUM_DIR=%root%\libsodium
cd ..
echo Current dir %cd%
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^
-DPORTABLE=1 ^
-DSODIUM_USE_STATIC_LIBS=1 ^
-DSECP256K1_FOUND=1 ^
-DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^
-DSECP256K1_LIBRARY=%root%\secp256k1\build\src\Release\libsecp256k1.lib ^
-DSODIUM_LIBRARY_RELEASE=%third_libs%\libsodium\Build\Release\x64\libsodium.lib ^
-DSODIUM_LIBRARY_DEBUG=%third_libs%\libsodium\Build\Release\x64\libsodium.lib ^
-DSODIUM_INCLUDE_DIR=%third_libs%\libsodium\src\libsodium\include ^
-DLZ4_FOUND=1 ^
-DLZ4_INCLUDE_DIRS=%root%\lz4\lib ^
-DLZ4_LIBRARIES=%root%\lz4\build\VS2017\liblz4\bin\x64_Release\liblz4_static.lib ^
-DLZ4_INCLUDE_DIRS=%third_libs%\lz4\lib ^
-DLZ4_LIBRARIES=%third_libs%\lz4\build\VS2022\liblz4\bin\x64_Release\liblz4_static.lib ^
-DMHD_FOUND=1 ^
-DMHD_LIBRARY=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static\libmicrohttpd.lib ^
-DMHD_INCLUDE_DIR=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static ^
-DMHD_LIBRARY=%third_libs%\libmicrohttpd\w32\VS2022\Output\x64\libmicrohttpd.lib ^
-DMHD_INCLUDE_DIR=%third_libs%\libmicrohttpd\src\include ^
-DZLIB_FOUND=1 ^
-DZLIB_INCLUDE_DIR=%root%\zlib ^
-DZLIB_LIBRARIES=%root%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
-DZLIB_INCLUDE_DIR=%third_libs%\zlib ^
-DZLIB_LIBRARIES=%third_libs%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
-DOPENSSL_FOUND=1 ^
-DOPENSSL_INCLUDE_DIR=%root%\openssl-3.1.4\x64\include ^
-DOPENSSL_CRYPTO_LIBRARY=%root%\openssl-3.1.4\x64\lib\libcrypto_static.lib ^
-DREADLINE_INCLUDE_DIR=%root%\readline-5.0-1-lib\include ^
-DREADLINE_LIBRARY=%root%\readline-5.0-1-lib\lib\readline.lib ^
-DOPENSSL_INCLUDE_DIR=%third_libs%\openssl\include ^
-DOPENSSL_CRYPTO_LIBRARY=%third_libs%\openssl\libcrypto_static.lib ^
-DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj" ..
IF %errorlevel% NEQ 0 (
echo Can't configure TON
exit /b %errorlevel%
@ -161,7 +140,7 @@ tonlib-cli validator-engine lite-client pow-miner validator-engine-console gener
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator ^
test-ed25519 test-ed25519-crypto test-bigint test-vm test-fift test-cells test-smartcont test-net ^
test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
IF %errorlevel% NEQ 0 (
echo Can't compile TON
exit /b %errorlevel%
@ -169,7 +148,7 @@ IF %errorlevel% NEQ 0 (
) else (
ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tolk tonlib tonlibjson ^
tonlib-cli validator-engine lite-client pow-miner validator-engine-console generate-random-id ^
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator proxy-liteserver
IF %errorlevel% NEQ 0 (
echo Can't compile TON
exit /b %errorlevel%
@ -192,32 +171,38 @@ REM ctest -C Release --output-on-failure -E "test-catchain|test-actors|test-val
)
)
echo Creating artifacts...
echo Strip and copy artifacts
cd ..
echo where strip
where strip
mkdir artifacts
mkdir artifacts\smartcont
mkdir artifacts\lib
for %%I in (build\storage\storage-daemon\storage-daemon.exe ^
build\storage\storage-daemon\storage-daemon-cli.exe ^
build\blockchain-explorer\blockchain-explorer.exe ^
build\crypto\fift.exe ^
build\crypto\tlbc.exe ^
build\crypto\func.exe ^
build\tolk\tolk.exe ^
build\crypto\create-state.exe ^
build\validator-engine-console\validator-engine-console.exe ^
build\tonlib\tonlib-cli.exe ^
build\tonlib\tonlibjson.dll ^
build\http\http-proxy.exe ^
build\rldp-http-proxy\rldp-http-proxy.exe ^
build\dht-server\dht-server.exe ^
build\lite-client\lite-client.exe ^
build\validator-engine\validator-engine.exe ^
build\utils\generate-random-id.exe ^
build\utils\json2tlo.exe ^
build\adnl\adnl-proxy.exe ^
build\emulator\emulator.dll) do (strip -s %%I & copy %%I artifacts\)
build\storage\storage-daemon\storage-daemon-cli.exe ^
build\blockchain-explorer\blockchain-explorer.exe ^
build\crypto\fift.exe ^
build\crypto\tlbc.exe ^
build\crypto\func.exe ^
build\tolk\tolk.exe ^
build\crypto\create-state.exe ^
build\validator-engine-console\validator-engine-console.exe ^
build\tonlib\tonlib-cli.exe ^
build\tonlib\tonlibjson.dll ^
build\http\http-proxy.exe ^
build\rldp-http-proxy\rldp-http-proxy.exe ^
build\dht-server\dht-server.exe ^
build\lite-client\lite-client.exe ^
build\validator-engine\validator-engine.exe ^
build\utils\generate-random-id.exe ^
build\utils\json2tlo.exe ^
build\utils\proxy-liteserver.exe ^
build\adnl\adnl-proxy.exe ^
build\emulator\emulator.dll) do (
echo strip -s %%I & copy %%I artifacts\
strip -s %%I & copy %%I artifacts\
)
xcopy /e /k /h /i crypto\smartcont artifacts\smartcont
xcopy /e /k /h /i crypto\fift\lib artifacts\lib

View file

@ -36,23 +36,3 @@ cp ./result/lib/libemulator.so artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts
cd artifacts
sudo strip -s storage-daemon \
storage-daemon-cli \
blockchain-explorer \
fift \
tlbc \
func \
tolk \
create-state \
validator-engine-console \
tonlib-cli \
http-proxy \
rldp-http-proxy \
dht-server \
lite-client \
validator-engine \
generate-random-id \
adnl-proxy \
libemulator.so \
libtonlibjson.so

View file

@ -36,23 +36,3 @@ cp ./result/lib/libemulator.so artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts
cd artifacts
sudo strip -s storage-daemon \
storage-daemon-cli \
blockchain-explorer \
fift \
tlbc \
func \
tolk \
create-state \
validator-engine-console \
tonlib-cli \
http-proxy \
rldp-http-proxy \
dht-server \
lite-client \
validator-engine \
generate-random-id \
adnl-proxy \
libemulator.so \
libtonlibjson.so

View file

@ -36,23 +36,3 @@ cp ./result/lib/libemulator.dylib artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts
cd artifacts
sudo strip -xSX storage-daemon \
storage-daemon-cli \
blockchain-explorer \
fift \
tlbc \
func \
tolk \
create-state \
validator-engine-console \
tonlib-cli \
http-proxy \
rldp-http-proxy \
dht-server \
lite-client \
validator-engine \
generate-random-id \
adnl-proxy \
libemulator.dylib \
libtonlibjson.dylib

View file

@ -2,7 +2,7 @@
# sudo apt update
# sudo apt install -y build-essential git make cmake ninja-build clang libgflags-dev zlib1g-dev libssl-dev \
# libreadline-dev libmicrohttpd-dev pkg-config libgsl-dev python3 python3-dev python3-pip \
# nodejs libsecp256k1-dev libsodium-dev automake libtool
# nodejs libsodium-dev automake libtool libjemalloc-dev
# wget https://apt.llvm.org/llvm.sh
# chmod +x llvm.sh
@ -26,13 +26,14 @@ export CCACHE_DISABLE=1
echo `pwd`
if [ "$scratch_new" = true ]; then
echo Compiling openssl zlib lz4 emsdk secp256k1 libsodium emsdk ton
rm -rf openssl zlib lz4 emsdk secp256k1 libsodium build
echo Compiling openssl zlib lz4 emsdk libsodium emsdk ton
rm -rf openssl zlib lz4 emsdk libsodium build openssl_em
fi
if [ ! -d "openssl" ]; then
git clone https://github.com/openssl/openssl.git
cp -r openssl openssl_em
cd openssl
git checkout openssl-3.1.4
./config
@ -47,21 +48,20 @@ fi
if [ ! -d "build" ]; then
mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_STANDARD=17 \
-DOPENSSL_FOUND=1 \
cmake -GNinja -DTON_USE_JEMALLOC=ON .. \
-DCMAKE_BUILD_TYPE=Release \
-DOPENSSL_ROOT_DIR=$OPENSSL_DIR \
-DOPENSSL_INCLUDE_DIR=$OPENSSL_DIR/include \
-DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.so \
-DTON_USE_ABSEIL=OFF ..
-DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.so
test $? -eq 0 || { echo "Can't configure TON build"; exit 1; }
ninja fift smc-envelope
test $? -eq 0 || { echo "Can't compile fift "; exit 1; }
rm -rf *
rm -rf * .ninja* CMakeCache.txt
cd ..
else
echo cleaning build...
rm -rf build/*
rm -rf build/* build/.ninja* build/CMakeCache.txt
fi
if [ ! -d "emsdk" ]; then
@ -71,8 +71,8 @@ echo
fi
cd emsdk
./emsdk install 3.1.19
./emsdk activate 3.1.19
./emsdk install 3.1.40
./emsdk activate 3.1.40
EMSDK_DIR=`pwd`
. $EMSDK_DIR/emsdk_env.sh
@ -82,9 +82,8 @@ export CCACHE_DISABLE=1
cd ..
if [ ! -f "openssl/openssl_em" ]; then
cd openssl
make clean
if [ ! -f "openssl_em/openssl_em" ]; then
cd openssl_em
emconfigure ./Configure linux-generic32 no-shared no-dso no-engine no-unit-test no-tests no-fuzz-afl no-fuzz-libfuzzer
sed -i 's/CROSS_COMPILE=.*/CROSS_COMPILE=/g' Makefile
sed -i 's/-ldl//g' Makefile
@ -92,10 +91,12 @@ if [ ! -f "openssl/openssl_em" ]; then
emmake make depend
emmake make -j16
test $? -eq 0 || { echo "Can't compile OpenSSL with emmake "; exit 1; }
OPENSSL_DIR=`pwd`
touch openssl_em
cd ..
else
echo Using compiled openssl with emscripten
OPENSSL_DIR=`pwd`/openssl_em
echo Using compiled with empscripten openssl at $OPENSSL_DIR
fi
if [ ! -d "zlib" ]; then
@ -125,21 +126,6 @@ else
echo Using compiled lz4 with emscripten at $LZ4_DIR
fi
if [ ! -d "secp256k1" ]; then
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
git checkout v0.3.2
./autogen.sh
SECP256K1_DIR=`pwd`
emconfigure ./configure --enable-module-recovery
emmake make -j16
test $? -eq 0 || { echo "Can't compile secp256k1 with emmake "; exit 1; }
cd ..
else
SECP256K1_DIR=`pwd`/secp256k1
echo Using compiled secp256k1 with emscripten at $SECP256K1_DIR
fi
if [ ! -d "libsodium" ]; then
git clone https://github.com/jedisct1/libsodium
cd libsodium
@ -168,9 +154,9 @@ emcmake cmake -DUSE_EMSCRIPTEN=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAK
-DOPENSSL_CRYPTO_LIBRARY=$OPENSSL_DIR/libcrypto.a \
-DCMAKE_TOOLCHAIN_FILE=$EMSDK_DIR/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake \
-DCMAKE_CXX_FLAGS="-sUSE_ZLIB=1" \
-DSECP256K1_INCLUDE_DIR=$SECP256K1_DIR/include \
-DSECP256K1_LIBRARY=$SECP256K1_DIR/.libs/libsecp256k1.a \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=$SODIUM_DIR/src/libsodium/include \
-DSODIUM_USE_STATIC_LIBS=1 \
-DSODIUM_LIBRARY_RELEASE=$SODIUM_DIR/src/libsodium/.libs/libsodium.a \
..
@ -194,5 +180,3 @@ if [ "$with_artifacts" = true ]; then
cp -R crypto/smartcont artifacts
cp -R crypto/fift/lib artifacts
fi

View file

@ -36,6 +36,7 @@ endif()
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer lite-client-common)
install(TARGETS blockchain-explorer RUNTIME DESTINATION bin)

View file

@ -1432,7 +1432,7 @@ void HttpQueryStatus::finish_query() {
for (td::uint32 i = 0; i < results_.ips.size(); i++) {
A << "<tr>";
if (results_.ips[i].is_valid()) {
A << "<td>" << results_.ips[i] << "</td>";
A << "<td>" << results_.ips[i].get_ip_str() << ":" << results_.ips[i].get_port() << "</td>";
} else {
A << "<td>hidden</td>";
}

View file

@ -57,6 +57,7 @@
#include "auto/tl/lite_api.h"
#include "ton/lite-tl.hpp"
#include "tl-utils/lite-utils.hpp"
#include "lite-client/ext-client.h"
#include <microhttpd.h>
@ -127,7 +128,7 @@ class CoreActor : public CoreActorInterface {
private:
std::string global_config_ = "ton-global.config";
std::vector<td::actor::ActorOwn<ton::adnl::AdnlExtClient>> clients_;
td::actor::ActorOwn<liteclient::ExtClient> client_;
td::uint32 http_port_ = 80;
MHD_Daemon* daemon_ = nullptr;
@ -137,35 +138,29 @@ class CoreActor : public CoreActorInterface {
bool hide_ips_ = false;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback(td::uint32 idx) {
class Callback : public ton::adnl::AdnlExtClient::Callback {
td::unique_ptr<liteclient::ExtClient::Callback> make_callback() {
class Callback : public liteclient::ExtClient::Callback {
public:
void on_ready() override {
td::actor::send_closure(id_, &CoreActor::conn_ready, idx_);
}
void on_stop_ready() override {
td::actor::send_closure(id_, &CoreActor::conn_closed, idx_);
}
Callback(td::actor::ActorId<CoreActor> id, td::uint32 idx) : id_(std::move(id)), idx_(idx) {
Callback(td::actor::ActorId<CoreActor> id) : id_(std::move(id)) {
}
private:
td::actor::ActorId<CoreActor> id_;
td::uint32 idx_;
};
return std::make_unique<Callback>(actor_id(this), idx);
return td::make_unique<Callback>(actor_id(this));
}
std::shared_ptr<RemoteNodeStatus> new_result_;
td::int32 attempt_ = 0;
td::int32 waiting_ = 0;
std::vector<bool> ready_;
size_t n_servers_ = 0;
void run_queries();
void got_result(td::uint32 idx, td::int32 attempt, td::Result<td::BufferSlice> data);
void send_query(td::uint32 idx);
void got_servers_ready(td::int32 attempt, std::vector<bool> ready);
void send_ping(td::uint32 idx);
void got_ping_result(td::uint32 idx, td::int32 attempt, td::Result<td::BufferSlice> data);
void add_result() {
if (new_result_) {
@ -196,12 +191,6 @@ class CoreActor : public CoreActorInterface {
static CoreActor* instance_;
td::actor::ActorId<CoreActor> self_id_;
void conn_ready(td::uint32 idx) {
ready_.at(idx) = true;
}
void conn_closed(td::uint32 idx) {
ready_.at(idx) = false;
}
void set_global_config(std::string str) {
global_config_ = str;
}
@ -226,10 +215,7 @@ class CoreActor : public CoreActorInterface {
hide_ips_ = value;
}
void send_lite_query(td::uint32 idx, td::BufferSlice query, td::Promise<td::BufferSlice> promise);
void send_lite_query(td::BufferSlice data, td::Promise<td::BufferSlice> promise) override {
return send_lite_query(0, std::move(data), std::move(promise));
}
void send_lite_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) override;
void get_last_result(td::Promise<std::shared_ptr<RemoteNodeStatus>> promise) override {
}
void get_results(td::uint32 max, td::Promise<RemoteNodeStatusList> promise) override {
@ -449,33 +435,27 @@ class CoreActor : public CoreActorInterface {
}
void run() {
std::vector<liteclient::LiteServerConfig> servers;
if (remote_public_key_.empty()) {
auto G = td::read_file(global_config_).move_as_ok();
auto gc_j = td::json_decode(G.as_slice()).move_as_ok();
ton::ton_api::liteclient_config_global gc;
ton::ton_api::from_json(gc, gc_j.get_object()).ensure();
CHECK(gc.liteservers_.size() > 0);
td::uint32 size = static_cast<td::uint32>(gc.liteservers_.size());
ready_.resize(size, false);
for (td::uint32 i = 0; i < size; i++) {
auto& cli = gc.liteservers_[i];
td::IPAddress addr;
addr.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure();
addrs_.push_back(addr);
clients_.emplace_back(ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull::create(cli->id_).move_as_ok(),
addr, make_callback(i)));
auto r_servers = liteclient::LiteServerConfig::parse_global_config(gc);
r_servers.ensure();
servers = r_servers.move_as_ok();
for (const auto& serv : servers) {
addrs_.push_back(serv.addr);
}
} else {
if (!remote_addr_.is_valid()) {
LOG(FATAL) << "remote addr not set";
}
ready_.resize(1, false);
addrs_.push_back(remote_addr_);
clients_.emplace_back(ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_},
remote_addr_, make_callback(0)));
servers.push_back(liteclient::LiteServerConfig{ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_});
}
n_servers_ = servers.size();
client_ = liteclient::ExtClient::create(std::move(servers), make_callback(), true);
daemon_ = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, static_cast<td::uint16>(http_port_), nullptr, nullptr,
&process_http_request, nullptr, MHD_OPTION_NOTIFY_COMPLETED, request_completed, nullptr,
MHD_OPTION_THREAD_POOL_SIZE, 16, MHD_OPTION_END);
@ -483,7 +463,46 @@ class CoreActor : public CoreActorInterface {
}
};
void CoreActor::got_result(td::uint32 idx, td::int32 attempt, td::Result<td::BufferSlice> R) {
void CoreActor::run_queries() {
waiting_ = 0;
new_result_ = std::make_shared<RemoteNodeStatus>(n_servers_, td::Timestamp::at_unix(attempt_ * 60));
td::actor::send_closure(client_, &liteclient::ExtClient::get_servers_status,
[SelfId = actor_id(this), attempt = attempt_](td::Result<std::vector<bool>> R) {
R.ensure();
td::actor::send_closure(SelfId, &CoreActor::got_servers_ready, attempt, R.move_as_ok());
});
}
void CoreActor::got_servers_ready(td::int32 attempt, std::vector<bool> ready) {
if (attempt != attempt_) {
return;
}
CHECK(ready.size() == n_servers_);
for (td::uint32 i = 0; i < n_servers_; i++) {
if (ready[i]) {
send_ping(i);
}
}
CHECK(waiting_ >= 0);
if (waiting_ == 0) {
add_result();
}
}
void CoreActor::send_ping(td::uint32 idx) {
waiting_++;
auto query = ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfo>();
auto q = ton::create_tl_object<ton::lite_api::liteServer_query>(serialize_tl_object(query, true));
auto P =
td::PromiseCreator::lambda([SelfId = actor_id(this), idx, attempt = attempt_](td::Result<td::BufferSlice> R) {
td::actor::send_closure(SelfId, &CoreActor::got_ping_result, idx, attempt, std::move(R));
});
td::actor::send_closure(client_, &liteclient::ExtClient::send_query_to_server, "query", serialize_tl_object(q, true),
idx, td::Timestamp::in(10.0), std::move(P));
}
void CoreActor::got_ping_result(td::uint32 idx, td::int32 attempt, td::Result<td::BufferSlice> R) {
if (attempt != attempt_) {
return;
}
@ -524,39 +543,7 @@ void CoreActor::got_result(td::uint32 idx, td::int32 attempt, td::Result<td::Buf
}
}
void CoreActor::send_query(td::uint32 idx) {
if (!ready_[idx]) {
return;
}
waiting_++;
auto query = ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfo>();
auto q = ton::create_tl_object<ton::lite_api::liteServer_query>(serialize_tl_object(query, true));
auto P =
td::PromiseCreator::lambda([SelfId = actor_id(this), idx, attempt = attempt_](td::Result<td::BufferSlice> R) {
td::actor::send_closure(SelfId, &CoreActor::got_result, idx, attempt, std::move(R));
});
td::actor::send_closure(clients_[idx], &ton::adnl::AdnlExtClient::send_query, "query", serialize_tl_object(q, true),
td::Timestamp::in(10.0), std::move(P));
}
void CoreActor::run_queries() {
waiting_ = 0;
new_result_ = std::make_shared<RemoteNodeStatus>(ready_.size(), td::Timestamp::at_unix(attempt_ * 60));
for (td::uint32 i = 0; i < ready_.size(); i++) {
send_query(i);
}
CHECK(waiting_ >= 0);
if (waiting_ == 0) {
add_result();
}
}
void CoreActor::send_lite_query(td::uint32 idx, td::BufferSlice query, td::Promise<td::BufferSlice> promise) {
if (!ready_[idx]) {
promise.set_error(td::Status::Error(ton::ErrorCode::notready, "ext conn not ready"));
return;
}
void CoreActor::send_lite_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise) {
auto P = td::PromiseCreator::lambda([promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
if (R.is_error()) {
promise.set_error(R.move_as_error());
@ -574,7 +561,7 @@ void CoreActor::send_lite_query(td::uint32 idx, td::BufferSlice query, td::Promi
promise.set_value(std::move(B));
});
auto q = ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(query));
td::actor::send_closure(clients_[idx], &ton::adnl::AdnlExtClient::send_query, "query", serialize_tl_object(q, true),
td::actor::send_closure(client_, &liteclient::ExtClient::send_query, "query", serialize_tl_object(q, true),
td::Timestamp::in(10.0), std::move(P));
}

View file

@ -236,9 +236,8 @@ class HardforkCreator : public td::actor::Actor {
td::actor::send_closure(id_, &ton::validator::ValidatorManager::sync_complete,
td::PromiseCreator::lambda([](td::Unit) {}));
}
void add_shard(ton::ShardIdFull) override {
}
void del_shard(ton::ShardIdFull) override {
void on_new_masterchain_block(td::Ref<ton::validator::MasterchainState> state,
std::set<ton::ShardIdFull> shards_to_monitor) override {
}
void send_ihr_message(ton::AccountIdPrefixFull dst, td::BufferSlice data) override {
}
@ -270,13 +269,19 @@ class HardforkCreator : public td::actor::Actor {
void get_next_key_blocks(ton::BlockIdExt block_id, td::Timestamp timeout,
td::Promise<std::vector<ton::BlockIdExt>> promise) override {
}
void download_archive(ton::BlockSeqno masterchain_seqno, std::string tmp_dir, td::Timestamp timeout,
td::Promise<std::string> promise) override {
void download_archive(ton::BlockSeqno masterchain_seqno, ton::ShardIdFull shard_prefix, std::string tmp_dir,
td::Timestamp timeout, td::Promise<std::string> promise) override {
}
void download_out_msg_queue_proof(
ton::ShardIdFull dst_shard, std::vector<ton::BlockIdExt> blocks, block::ImportedMsgQueueLimits limits,
td::Timestamp timeout, td::Promise<std::vector<td::Ref<ton::validator::OutMsgQueueProof>>> promise) override {
}
void new_key_block(ton::validator::BlockHandle handle) override {
}
void send_validator_telemetry(ton::PublicKeyHash key,
ton::tl_object_ptr<ton::ton_api::validator_telemetry> telemetry) override {
}
};
td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManagerInterface::install_callback,

View file

@ -318,20 +318,20 @@ endif()
target_include_directories(ton_crypto SYSTEM PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
add_dependencies(ton_crypto blst)
add_dependencies(ton_crypto_core secp256k1)
target_include_directories(ton_crypto PRIVATE ${BLST_INCLUDE_DIR})
target_link_libraries(ton_crypto PRIVATE ${BLST_LIB})
if (NOT USE_EMSCRIPTEN)
find_package(Secp256k1 REQUIRED)
endif()
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
if (MSVC)
find_package(Sodium REQUIRED)
target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY})
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY})
elseif (ANDROID OR EMSCRIPTEN)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
elseif (EMSCRIPTEN)
target_link_libraries(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_LIBRARY}>)
target_link_libraries(ton_crypto PUBLIC $<BUILD_INTERFACE:${SECP256K1_LIBRARY}>)
else()
if (NOT SODIUM_FOUND)
@ -340,11 +340,10 @@ else()
message(STATUS "Using Sodium ${SODIUM_LIBRARY_RELEASE}")
endif()
target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY})
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY})
endif()
target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY})
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SODIUM_INCLUDE_DIR}>)
target_link_libraries(ton_crypto PUBLIC ${SODIUM_LIBRARY_RELEASE})

View file

@ -660,6 +660,12 @@ bool EnqueuedMsgDescr::check_key(td::ConstBitPtr key) const {
hash_ == key + 96;
}
bool ImportedMsgQueueLimits::deserialize(vm::CellSlice& cs) {
return cs.fetch_ulong(8) == 0xd3 // imported_msg_queue_limits#d3
&& cs.fetch_uint_to(32, max_bytes) // max_bytes:#
&& cs.fetch_uint_to(32, max_msgs); // max_msgs:#
}
bool ParamLimits::deserialize(vm::CellSlice& cs) {
return cs.fetch_ulong(8) == 0xc3 // param_limits#c3
&& cs.fetch_uint_to(32, limits_[0]) // underload:uint32

View file

@ -216,6 +216,16 @@ static inline std::ostream& operator<<(std::ostream& os, const MsgProcessedUptoC
return proc_coll.print(os);
}
struct ImportedMsgQueueLimits {
// Default values
td::uint32 max_bytes = 1 << 16;
td::uint32 max_msgs = 30;
bool deserialize(vm::CellSlice& cs);
ImportedMsgQueueLimits operator*(td::uint32 x) const {
return {max_bytes * x, max_msgs * x};
}
};
struct ParamLimits {
enum { limits_cnt = 4 };
enum { cl_underload = 0, cl_normal = 1, cl_soft = 2, cl_medium = 3, cl_hard = 4 };

View file

@ -818,7 +818,7 @@ _ OracleBridgeParams = ConfigParam 72; // Binance Smart Chain bridge
_ OracleBridgeParams = ConfigParam 73; // Polygon bridge
// Note that chains in which bridge, minter and jetton-wallet operate are fixated
jetton_bridge_prices#_ bridge_burn_fee:Coins bridge_mint_fee:Coins
jetton_bridge_prices#_ bridge_burn_fee:Coins bridge_mint_fee:Coins
wallet_min_tons_for_storage:Coins
wallet_gas_consumption:Coins
minter_min_tons_for_storage:Coins

View file

@ -554,11 +554,7 @@ class BitArray {
set_same(0);
}
void set_zero_s() {
volatile uint8* p = data();
auto x = m;
while (x--) {
*p++ = 0;
}
as_slice().fill_zero_secure();
}
void set_ones() {
set_same(1);

View file

@ -17,13 +17,22 @@
#include "secp256k1.h"
#include "td/utils/check.h"
#include "td/utils/logging.h"
#include <secp256k1_recovery.h>
#include <secp256k1_extrakeys.h>
#include <cstring>
namespace td {
namespace td::secp256k1 {
static const secp256k1_context* get_context() {
static secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
LOG_CHECK(ctx) << "Failed to create secp256k1_context";
return ctx;
}
bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key) {
static secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
const secp256k1_context* ctx = get_context();
secp256k1_ecdsa_recoverable_signature ecdsa_signature;
if (signature[64] > 3 ||
!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &ecdsa_signature, signature, signature[64])) {
@ -39,4 +48,22 @@ bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsign
return true;
}
bool xonly_pubkey_tweak_add(const unsigned char* xonly_pubkey_bytes, const unsigned char* tweak,
unsigned char* output_pubkey_bytes) {
const secp256k1_context* ctx = get_context();
secp256k1_xonly_pubkey xonly_pubkey;
secp256k1_pubkey output_pubkey;
if (!secp256k1_xonly_pubkey_parse(ctx, &xonly_pubkey, xonly_pubkey_bytes)) {
return false;
}
if (!secp256k1_xonly_pubkey_tweak_add(ctx, &output_pubkey, &xonly_pubkey, tweak)) {
return false;
}
size_t len = 65;
secp256k1_ec_pubkey_serialize(ctx, output_pubkey_bytes, &len, &output_pubkey, SECP256K1_EC_UNCOMPRESSED);
CHECK(len == 65);
return true;
}
} // namespace td::secp256k1

View file

@ -16,8 +16,10 @@
*/
#pragma once
namespace td {
namespace td::secp256k1 {
bool ecrecover(const unsigned char* hash, const unsigned char* signature, unsigned char* public_key);
bool xonly_pubkey_tweak_add(const unsigned char* xonly_pubkey_bytes, const unsigned char* tweak,
unsigned char* output_pubkey_bytes);
}
} // namespace td::secp256k1

View file

@ -1015,6 +1015,10 @@ x{EDC} dup @Defop(c) SAVEBOTH @Defop(c) SAVEBOTHCTR
x{EDE0} @Defop PUSHCTRX
x{EDE1} @Defop POPCTRX
x{EDE2} @Defop SETCONTCTRX
x{EDE3} @Defop(8u) SETCONTCTRMANY
x{EDE3} @Defop(8u) SETCONTMANY
x{EDE4} @Defop SETCONTCTRMANYX
x{EDE4} @Defop SETCONTMANYX
x{EDF0} dup @Defop BOOLAND @Defop COMPOS
x{EDF1} dup @Defop BOOLOR @Defop COMPOSALT
x{EDF2} @Defop COMPOSBOTH
@ -1354,6 +1358,7 @@ x{F90704} @Defop HASHEXTAR_KECCAK512
x{F910} @Defop CHKSIGNU
x{F911} @Defop CHKSIGNS
x{F912} @Defop ECRECOVER
x{F913} @Defop SECP256K1_XONLY_PUBKEY_TWEAK_ADD
x{F914} @Defop P256_CHKSIGNU
x{F915} @Defop P256_CHKSIGNS

View file

@ -1,4 +1,4 @@
int foo(int x) method_id(11) {
int foo(int x) {
try {
if (x == 7) {
throw(44);
@ -9,7 +9,7 @@ int foo(int x) method_id(11) {
}
}
int foo_inline(int x) inline method_id(12) {
int foo_inline(int x) inline {
try {
if (x == 7) {
throw(44);
@ -20,7 +20,7 @@ int foo_inline(int x) inline method_id(12) {
}
}
int foo_inlineref(int x) inline_ref method_id(13) {
int foo_inlineref(int x) inline_ref {
try {
if (x == 7) {
throw(44);
@ -31,17 +31,17 @@ int foo_inlineref(int x) inline_ref method_id(13) {
}
}
int test(int x, int y, int z) method_id(1) {
int test(int x, int y, int z) method_id(101) {
y = foo(y);
return x * 100 + y * 10 + z;
}
int test_inline(int x, int y, int z) method_id(2) {
int test_inline(int x, int y, int z) method_id(102) {
y = foo_inline(y);
return x * 100 + y * 10 + z;
}
int test_inlineref(int x, int y, int z) method_id(3) {
int test_inlineref(int x, int y, int z) method_id(103) {
y = foo_inlineref(y);
return x * 100 + y * 10 + z;
}
@ -49,7 +49,7 @@ int test_inlineref(int x, int y, int z) method_id(3) {
int foo_inline_big(
int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9, int x10,
int x11, int x12, int x13, int x14, int x15, int x16, int x17, int x18, int x19, int x20
) inline method_id(14) {
) inline {
try {
if (x1 == 7) {
throw(44);
@ -60,7 +60,7 @@ int foo_inline_big(
}
}
int test_inline_big(int x, int y, int z) method_id(4) {
int test_inline_big(int x, int y, int z) method_id(104) {
y = foo_inline_big(
y, y + 1, y + 2, y + 3, y + 4, y + 5, y + 6, y + 7, y + 8, y + 9,
y + 10, y + 11, y + 12, y + 13, y + 14, y + 15, y + 16, y + 17, y + 18, y + 19);
@ -70,7 +70,7 @@ int test_inline_big(int x, int y, int z) method_id(4) {
int foo_big(
int x1, int x2, int x3, int x4, int x5, int x6, int x7, int x8, int x9, int x10,
int x11, int x12, int x13, int x14, int x15, int x16, int x17, int x18, int x19, int x20
) method_id(15) {
) {
try {
if (x1 == 7) {
throw(44);
@ -81,29 +81,69 @@ int foo_big(
}
}
int test_big(int x, int y, int z) method_id(5) {
int test_big(int x, int y, int z) method_id(105) {
y = foo_big(
y, y + 1, y + 2, y + 3, y + 4, y + 5, y + 6, y + 7, y + 8, y + 9,
y + 10, y + 11, y + 12, y + 13, y + 14, y + 15, y + 16, y + 17, y + 18, y + 19);
return x * 1000000 + y * 1000 + z;
}
() some_throwing(int op) impure {
if (op == 1) {
return ();
} elseif (op == 2) {
return ();
} else {
throw(1);
}
}
int test106() method_id(106) {
try {
some_throwing(1337);
return 1337;
} catch(_, code) {
return code;
}
return -1;
}
global int g_reg;
(int, int) test107() method_id(107) {
int l_reg = 10;
g_reg = 10;
try {
;; note, that regardless of assignment, an exception RESTORES them to previous (to 10)
;; it's very unexpected, but is considered to be a TVM feature, not a bug
g_reg = 999;
l_reg = 999;
some_throwing(999);
} catch(_, _) {
}
;; returns (10,10) because of an exception, see a comment above
return (g_reg, l_reg);
}
() main() {
}
{-
method_id | in | out
TESTCASE | 1 | 1 2 3 | 123
TESTCASE | 1 | 3 8 9 | 389
TESTCASE | 1 | 3 7 9 | 329
TESTCASE | 2 | 1 2 3 | 123
TESTCASE | 2 | 3 8 9 | 389
TESTCASE | 2 | 3 7 9 | 329
TESTCASE | 3 | 1 2 3 | 123
TESTCASE | 3 | 3 8 9 | 389
TESTCASE | 3 | 3 7 9 | 329
TESTCASE | 4 | 4 8 9 | 4350009
TESTCASE | 4 | 4 7 9 | 4001009
TESTCASE | 5 | 4 8 9 | 4350009
TESTCASE | 5 | 4 7 9 | 4001009
method_id | in | out
TESTCASE | 101 | 1 2 3 | 123
TESTCASE | 101 | 3 8 9 | 389
TESTCASE | 101 | 3 7 9 | 329
TESTCASE | 102 | 1 2 3 | 123
TESTCASE | 102 | 3 8 9 | 389
TESTCASE | 102 | 3 7 9 | 329
TESTCASE | 103 | 1 2 3 | 123
TESTCASE | 103 | 3 8 9 | 389
TESTCASE | 103 | 3 7 9 | 329
TESTCASE | 104 | 4 8 9 | 4350009
TESTCASE | 104 | 4 7 9 | 4001009
TESTCASE | 105 | 4 8 9 | 4350009
TESTCASE | 105 | 4 7 9 | 4001009
TESTCASE | 106 | | 1
TESTCASE | 107 | | 10 10
-}

View file

@ -0,0 +1,132 @@
tuple empty_tuple() asm "NIL";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
builder begin_cell() asm "NEWC";
cell end_cell(builder b) asm "ENDC";
slice begin_parse(cell c) asm "CTOS";
_ getBeginCell() {
return begin_cell;
}
_ getBeginParse() {
return begin_parse;
}
(int, int) test101() method_id(101) {
var (_, f_end_cell) = (0, end_cell);
builder b = (getBeginCell())().store_int(1, 32);
b~store_int(2, 32);
var s = (getBeginParse())(f_end_cell(b));
return (s~load_int(32), s~load_int(32));
}
() my_throw_always() inline {
throw(1000);
}
_ get_raiser() inline {
return my_throw_always;
}
int test102() method_id(102) {
try {
var raiser = get_raiser();
raiser(); ;; `some_var()` is always impure, the compiler has no considerations about its runtime value
return 0;
} catch (_, code) {
return code;
}
}
int sum(int a, int b) impure inline {
throw_unless(1000, a + b < 24);
return a + b;
}
int mul(int a, int b) impure inline {
throw_unless(1001, a * b < 24);
return a * b;
}
int sum_pure(int a, int b) inline {
throw_unless(1000, a + b < 24);
return a + b;
}
int mul_pure(int a, int b) inline {
throw_unless(1001, a * b < 24);
return a * b;
}
int demo_handler(int op, int query_id, int a, int b) {
if (op == 0xF2) {
var func = query_id % 2 == 0 ? sum : mul;
int result = func(a, b);
return 0; ;; result not used, we test that func is nevertheless called
}
if (op == 0xF3) {
var func = query_id % 2 == 0 ? sum_pure : mul_pure;
int result = func(a, b);
return 0; ;; the same for sum_pure, since `some_var()` is always impure
}
if (op == 0xF4) {
var func = query_id % 2 == 0 ? sum : mul;
int result = func(a, b);
return result;
}
return -1;
}
tuple test103() method_id(103) {
tuple t = empty_tuple();
try {
t~tpush(demo_handler(0xF2, 122, 100, 200));
} catch(_, code) {
t~tpush(code);
}
try {
t~tpush(demo_handler(0xF4, 122, 100, 200));
} catch(_, code) {
t~tpush(code);
}
try {
t~tpush(demo_handler(0xF3, 122, 10, 10));
} catch(_, code) {
t~tpush(code);
}
try {
t~tpush(demo_handler(0xF3, 123, 10, 10));
} catch(_, code) {
t~tpush(code);
}
return t;
}
() always_throw2(int x) impure {
throw (239 + x);
}
global int -> () global_f;
int test104() method_id(104) {
try {
global_f = always_throw2;
global_f(1);
return 0;
} catch (_, code) {
return code;
}
}
() main() {
}
{-
method_id | in | out
TESTCASE | 101 | | 1 2
TESTCASE | 102 | | 1000
TESTCASE | 103 | | [ 1000 1000 0 1001 ]
TESTCASE | 104 | | 240
-}

View file

@ -830,6 +830,8 @@ bool Op::generate_code_step(Stack& stack) {
catch_stack.push_new_var(left[1]);
stack.rearrange_top(catch_vars, catch_last);
stack.opt_show();
stack.o << "c1 PUSH";
stack.o << "c3 PUSH";
stack.o << "c4 PUSH";
stack.o << "c5 PUSH";
stack.o << "c7 PUSH";
@ -846,6 +848,8 @@ bool Op::generate_code_step(Stack& stack) {
stack.o << "c7 SETCONT";
stack.o << "c5 SETCONT";
stack.o << "c4 SETCONT";
stack.o << "c3 SETCONT";
stack.o << "c1 SETCONT";
for (size_t begin = catch_vars.size(), end = begin; end > 0; end = begin) {
begin = end >= block_size ? end - block_size : 0;
stack.o << std::to_string(end - begin) + " PUSHINT";

View file

@ -45,7 +45,7 @@ extern std::string generated_from;
constexpr int optimize_depth = 20;
const std::string func_version{"0.4.5"};
const std::string func_version{"0.4.6"};
enum Keyword {
_Eof = -1,

View file

@ -380,7 +380,10 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
}
res.push_back(tfunc[0]);
auto rvect = new_tmp_vect(code);
code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
auto& op = code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
if (flags & _IsImpure) {
op.flags |= Op::_Impure;
}
return rvect;
}
case _Const: {

View file

@ -427,7 +427,7 @@ Expr* make_func_apply(Expr* fun, Expr* x) {
res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
} else {
res = new Expr{Expr::_VarApply, {fun, x}};
res->flags = Expr::_IsRvalue;
res->flags = Expr::_IsRvalue | Expr::_IsImpure; // for `some_var()`, don't make any considerations about runtime value, it's impure
}
return res;
}

View file

@ -167,3 +167,7 @@ TEST(Fift, test_bls_ops) {
TEST(Fift, test_levels) {
run_fift("levels.fif");
}
TEST(Fift, test_secp256k1) {
run_fift("secp256k1.fif");
}

View file

@ -0,0 +1,82 @@
"Asm.fif" include
"FiftExt.fif" include
{
=: expected_result
=: tweak
=: pubkey
B{e80fe1639c9ca050e3af1b39c143c63e429cbceb15d940fbb5c5a1f4af57c5e9e80fe1639c9ca050e3af1b39c143c63e429cbceb15d940fbb5c5a1f4af57c5e9}
@' pubkey 256 u>B @' tweak 256 u>B B+ B+ Bhashu =: tweak2
@' pubkey @' tweak2
[[ <{ SECP256K1_XONLY_PUBKEY_TWEAK_ADD }>s ]] 0 runvmx
abort"exitcode != 0" -1 <> abort"xonly_pubkey_tweak_add failed"
drop
=: result
."Pubkey = " @' pubkey x. cr
."Tweak = " @' tweak x. cr
."Tweak2 = " @' tweak2 x. cr
@' expected_result @' result <> { ."Expected = " @' expected_result x. cr ."Found = " @' result x. cr -1 abort"result mismatch" } if
."Result = " @' result x. cr
4 <> abort"first byte is expected to be 4"
cr
} : run-test
0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2
0x7eeda5cc8b219363ffc29a77d170f923dbb939ea5164b71db862d4a192f2680f
0x5a001d32f9fc59c2965ef36d9ff154469a3ba87f00b95879f3b5198bb557494d
run-test
0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5
0x3f339347d8b1dde7edade3dc59fc63d18cb21fc2326ffbd30f0711a02d25075a
0xc621ca417b8915474020c0c9471a13918b6a02fd20d48a0e526c896923457fcd
run-test
0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02
0x3197d6b03d78ebbe694d2b89945a21a5a671ca78393481d44739b7351767adef
0xcbf0da3bbb498fd575506060d04db426164cb9d1477f07481fc6e3a2f84b01ea
run-test
0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19
0xcf9bfedc7251c2f8e233ae1e2c8b7a6cbe25d96a46a38b79e45d5684d026b64c
0x19b1aa4551bf08363b2533c146c02fa61e26941336aaa16cdd4393a5440392ea
run-test
0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2
0x1762cbfa935318fb1395b50c64f961baab3ecaed4afad3068ba2f7f3a9d15cec
0x38be4b9791c0cb4952b9fb944eb0fe9256ce0d48be7b92129caafdf2f521248a
run-test
0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5
0x099ec2e6ee1c40f533a61abca2860733727204c2f31d078297194d5e93e148f7
0x8e9d15851e9aeb652216378f6bc0b88fb66b491697c9b9588f37c11d0b0fbced
run-test
0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02
0x63494cee8217ca2a10076e2031534fdda39f132dbdf91606aa65021709cb3116
0x5dd1aa62a438469f4934e1ab9ada9ba3945651a2641316ec91d0780ca71891f8
run-test
0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19
0x36e26133dc62474040eae511ce89610dae6bb0359aa80738baf812ecfa03d2a1
0xf9ab8bbbee0ad1e90492c952b362d43d56412debdd1224e9729dc79aff931943
run-test
0x4be5f2020ebe2f37b65fb1bcd8aecf2ab0a333427208a5e6dd3dc691f1fb6ae2
0x94f8fb43dd6001bb8acd2c53d094f9c919766dad596498d3d582cebdb39c63da
0xf7b4c76d79925f62e7969cb0e4af0673808f646add78563f711dc33a2687dc1b
run-test
0x3ad84c3844e66aa255a121ed46d0e69e7b98f31233941c5197917c97c7aeaec5
0xa2f55c34c4eee5881584714bd5c7a63c397ef38ff1afedd04ada10fdeb541cef
0x73f9a15b76612ca4254e6c2758508589c0112eb724f42dbb4c65ff8b025d2103
run-test
0x57bb69f0d446ee2cf9f77a2bdca7a3a462a61d85997a1154f2321a2717951b02
0x05130a68853e5e4aff579fa21ff10010410a3be47b94d908e203f69ec9dc7d00
0x4ce6b5b1bd77b1666d33a0c9fd37b98952078bcc451d6de2d0bff65e8f2b46ed
run-test
0x4af537be1a1ae11770eef23e6087f83ce1019fbee7a5876837107f84929a1d19
0x9765369cb4467bebc8a468d44aa60f0154f04ee32fbcf1c8bdf646d4840163d1
0x118953c642b8f25fea3519bcaab3ae6cea25402088e11a8efdc2e0bd222958ad
run-test

View file

@ -923,6 +923,41 @@ int exec_setcont_ctr_var(VmState* st) {
return 0;
}
int exec_setcont_ctr_many(VmState* st, unsigned args) {
unsigned mask = args & 255;
VM_LOG(st) << "execute SETCONTCTRMANY " << mask;
if (mask & (1 << 6)) {
throw VmError{Excno::range_chk, "no control register c6"};
}
Stack& stack = st->get_stack();
auto cont = stack.pop_cont();
for (int i = 0; i < 8; ++i) {
if (mask & (1 << i)) {
throw_typechk(force_cregs(cont)->define(i, st->get(i)));
}
}
st->get_stack().push_cont(std::move(cont));
return 0;
}
int exec_setcont_ctr_many_var(VmState* st) {
VM_LOG(st) << "execute SETCONTCTRMANYX";
Stack& stack = st->get_stack();
stack.check_underflow(2);
int mask = stack.pop_smallint_range(255);
if (mask & (1 << 6)) {
throw VmError{Excno::range_chk, "no control register c6"};
}
auto cont = stack.pop_cont();
for (int i = 0; i < 8; ++i) {
if (mask & (1 << i)) {
throw_typechk(force_cregs(cont)->define(i, st->get(i)));
}
}
st->get_stack().push_cont(std::move(cont));
return 0;
}
int exec_compos(VmState* st, unsigned mask, const char* name) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute " << name;
@ -1037,6 +1072,8 @@ void register_continuation_change_ops(OpcodeTable& cp0) {
cp0.insert(OpcodeInstr::mksimple(0xede0, 16, "PUSHCTRX", exec_push_ctr_var))
.insert(OpcodeInstr::mksimple(0xede1, 16, "POPCTRX", exec_pop_ctr_var))
.insert(OpcodeInstr::mksimple(0xede2, 16, "SETCONTCTRX", exec_setcont_ctr_var))
.insert(OpcodeInstr::mkfixed(0xede3, 16, 8, instr::dump_1c_l_add(1, "SETCONTCTRMANY "), exec_setcont_ctr_many)->require_version(9))
.insert(OpcodeInstr::mksimple(0xede4, 16, "SETCONTCTRMANYX", exec_setcont_ctr_many_var)->require_version(9))
.insert(OpcodeInstr::mksimple(0xedf0, 16, "BOOLAND", std::bind(exec_compos, _1, 1, "BOOLAND")))
.insert(OpcodeInstr::mksimple(0xedf1, 16, "BOOLOR", std::bind(exec_compos, _1, 2, "BOOLOR")))
.insert(OpcodeInstr::mksimple(0xedf2, 16, "COMPOSBOTH", std::bind(exec_compos, _1, 3, "COMPOSBOTH")))

View file

@ -111,14 +111,16 @@ class DynamicBagOfCellsDbImpl : public DynamicBagOfCellsDb, private ExtCellCreat
}
void load_cell_async(td::Slice hash, std::shared_ptr<AsyncExecutor> executor,
td::Promise<Ref<DataCell>> promise) override {
auto promise_ptr = std::make_shared<td::Promise<Ref<DataCell>>>(std::move(promise));
auto info = hash_table_.get_if_exists(hash);
if (info && info->sync_with_db) {
TRY_RESULT_PROMISE(promise, loaded_cell, info->cell->load_cell());
promise.set_result(loaded_cell.data_cell);
executor->execute_async([promise = std::move(promise_ptr), cell = info->cell]() mutable {
TRY_RESULT_PROMISE((*promise), loaded_cell, cell->load_cell());
promise->set_result(loaded_cell.data_cell);
});
return;
}
SimpleExtCellCreator ext_cell_creator(cell_db_reader_);
auto promise_ptr = std::make_shared<td::Promise<Ref<DataCell>>>(std::move(promise));
executor->execute_async(
[executor, loader = *loader_, hash = CellHash::from_slice(hash), db = this,
ext_cell_creator = std::move(ext_cell_creator), promise = std::move(promise_ptr)]() mutable {

View file

@ -661,7 +661,38 @@ int exec_ecrecover(VmState* st) {
}
st->consume_gas(VmState::ecrecover_gas_price);
unsigned char public_key[65];
if (td::ecrecover(hash_bytes, signature, public_key)) {
if (td::secp256k1::ecrecover(hash_bytes, signature, public_key)) {
td::uint8 h = public_key[0];
td::RefInt256 x1{true}, x2{true};
CHECK(x1.write().import_bytes(public_key + 1, 32, false));
CHECK(x2.write().import_bytes(public_key + 33, 32, false));
stack.push_smallint(h);
stack.push_int(std::move(x1));
stack.push_int(std::move(x2));
stack.push_bool(true);
} else {
stack.push_bool(false);
}
return 0;
}
int exec_secp256k1_xonly_pubkey_tweak_add(VmState* st) {
VM_LOG(st) << "execute SECP256K1_XONLY_PUBKEY_TWEAK_ADD";
Stack& stack = st->get_stack();
stack.check_underflow(2);
auto tweak_int = stack.pop_int();
auto key_int = stack.pop_int();
unsigned char key[32], tweak[32];
if (!key_int->export_bytes(key, 32, false)) {
throw VmError{Excno::range_chk, "key must fit in an unsigned 256-bit integer"};
}
if (!tweak_int->export_bytes(tweak, 32, false)) {
throw VmError{Excno::range_chk, "tweak must fit in an unsigned 256-bit integer"};
}
st->consume_gas(VmState::secp256k1_xonly_pubkey_tweak_add_gas_price);
unsigned char public_key[65];
if (td::secp256k1::xonly_pubkey_tweak_add(key, tweak, public_key)) {
td::uint8 h = public_key[0];
td::RefInt256 x1{true}, x2{true};
CHECK(x1.write().import_bytes(public_key + 1, 32, false));
@ -1214,6 +1245,7 @@ void register_ton_crypto_ops(OpcodeTable& cp0) {
.insert(OpcodeInstr::mksimple(0xf910, 16, "CHKSIGNU", std::bind(exec_ed25519_check_signature, _1, false)))
.insert(OpcodeInstr::mksimple(0xf911, 16, "CHKSIGNS", std::bind(exec_ed25519_check_signature, _1, true)))
.insert(OpcodeInstr::mksimple(0xf912, 16, "ECRECOVER", exec_ecrecover)->require_version(4))
.insert(OpcodeInstr::mksimple(0xf913, 16, "SECP256K1_XONLY_PUBKEY_TWEAK_ADD", exec_secp256k1_xonly_pubkey_tweak_add)->require_version(9))
.insert(OpcodeInstr::mksimple(0xf914, 16, "P256_CHKSIGNU", std::bind(exec_p256_chksign, _1, false))->require_version(4))
.insert(OpcodeInstr::mksimple(0xf915, 16, "P256_CHKSIGNS", std::bind(exec_p256_chksign, _1, true))->require_version(4))

View file

@ -127,6 +127,7 @@ class VmState final : public VmStateInterface {
rist255_validate_gas_price = 200,
ecrecover_gas_price = 1500,
secp256k1_xonly_pubkey_tweak_add_gas_price = 1250,
chksgn_free_count = 10,
chksgn_gas_price = 4000,
p256_chksgn_gas_price = 3500,

View file

@ -54,7 +54,7 @@ Config::Config() {
out_port = 3278;
}
Config::Config(ton::ton_api::engine_validator_config &config) {
Config::Config(const ton::ton_api::engine_validator_config &config) {
out_port = static_cast<td::uint16>(config.out_port_);
if (!out_port) {
out_port = 3278;
@ -162,6 +162,7 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
control_vec.push_back(ton::create_tl_object<ton::ton_api::engine_controlInterface>(x.second.key.tl(), x.first,
std::move(control_proc_vec)));
}
std::vector<ton::tl_object_ptr<ton::ton_api::tonNode_shardId>> shard_vec;
auto gc_vec = ton::create_tl_object<ton::ton_api::engine_gc>(std::vector<td::Bits256>{});
for (auto &id : gc) {
@ -170,7 +171,7 @@ ton::tl_object_ptr<ton::ton_api::engine_validator_config> Config::tl() const {
return ton::create_tl_object<ton::ton_api::engine_validator_config>(
out_port, std::move(addrs_vec), std::move(adnl_vec), std::move(dht_vec), std::move(val_vec),
ton::PublicKeyHash::zero().tl(), std::move(full_node_slaves_vec), std::move(full_node_masters_vec),
nullptr, nullptr, std::move(liteserver_vec), std::move(control_vec), std::move(gc_vec));
nullptr, nullptr, std::move(liteserver_vec), std::move(control_vec), std::move(shard_vec), std::move(gc_vec));
}
td::Result<bool> Config::config_add_network_addr(td::IPAddress in_ip, td::IPAddress out_ip,

View file

@ -94,7 +94,7 @@ struct Config {
ton::tl_object_ptr<ton::ton_api::engine_validator_config> tl() const;
Config();
Config(ton::ton_api::engine_validator_config &config);
Config(const ton::ton_api::engine_validator_config &config);
};
class DhtServer : public td::actor::Actor {

View file

@ -113,6 +113,13 @@ Operations for working with Merkle proofs, where cells can have non-zero level a
## Version 9
### New TVM instructions
- `SECP256K1_XONLY_PUBKEY_TWEAK_ADD` (`key tweak - 0 or f x y -1`) - performs [`secp256k1_xonly_pubkey_tweak_add`](https://github.com/bitcoin-core/secp256k1/blob/master/include/secp256k1_extrakeys.h#L120).
`key` and `tweak` are 256-bit unsigned integers. 65-byte public key is returned as `uint8 f`, `uint256 x, y` (as in `ECRECOVER`). Gas cost: `1276`.
- `mask SETCONTCTRMANY` (`cont - cont'`) - takes continuation, performs the equivalent of `c[i] PUSHCTR SWAP c[i] SETCONTCNR` for each `i` that is set in `mask` (mask is in `0..255`).
- `SETCONTCTRMANYX` (`cont mask - cont'`) - same as `SETCONTCTRMANY`, but takes `mask` from stack.
### Other changes
- Fix `RAWRESERVE` action with flag `4` (use original balance of the account) by explicitly setting `original_balance` to `balance - msg_balance_remaining`.
- Previously it did not work if storage fee was greater than the original balance.
- Jumps to nested continuations of depth more than 8 consume 1 gas for eact subsequent continuation (this does not affect most of TVM code).

View file

@ -47,8 +47,8 @@ endif()
if (USE_EMSCRIPTEN)
add_executable(emulator-emscripten ${EMULATOR_EMSCRIPTEN_SOURCE})
target_link_libraries(emulator-emscripten PUBLIC emulator)
target_link_options(emulator-emscripten PRIVATE -sEXPORTED_RUNTIME_METHODS=_malloc,free,UTF8ToString,stringToUTF8,allocate,ALLOC_NORMAL,lengthBytesUTF8)
target_link_options(emulator-emscripten PRIVATE -sEXPORTED_FUNCTIONS=_emulate,_free,_run_get_method,_create_emulator,_destroy_emulator,_emulate_with_emulator,_version)
target_link_options(emulator-emscripten PRIVATE -sEXPORTED_RUNTIME_METHODS=UTF8ToString,stringToUTF8,allocate,ALLOC_NORMAL,lengthBytesUTF8)
target_link_options(emulator-emscripten PRIVATE -sEXPORTED_FUNCTIONS=_emulate,_free,_malloc,_run_get_method,_create_emulator,_destroy_emulator,_emulate_with_emulator,_version)
target_link_options(emulator-emscripten PRIVATE -sEXPORT_NAME=EmulatorModule)
target_link_options(emulator-emscripten PRIVATE -sERROR_ON_UNDEFINED_SYMBOLS=0)
target_link_options(emulator-emscripten PRIVATE -Oz)

View file

@ -3,7 +3,9 @@
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1 FATAL_ERROR)
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(TON_ANDROID VERSION 0.5 LANGUAGES C CXX)
option(TONLIB_ENABLE_JNI "Enable JNI-compatible TonLib API" ON)

View file

@ -48,7 +48,6 @@ mkdir -p build-$ARCH
cd build-$ARCH
cmake .. -GNinja \
-DPORTABLE=1 \
-DTON_ONLY_TONLIB=ON \
-DTON_ARCH="" \
-DANDROID_ABI=x86 \
@ -58,12 +57,12 @@ cmake .. -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=${ABI} \
-DOPENSSL_ROOT_DIR=${OPENSSL_DIR}/${ORIG_ARCH} \
-DSECP256K1_FOUND=1 \
-DSECP256K1_INCLUDE_DIR=${SECP256K1_INCLUDE_DIR} \
-DSECP256K1_LIBRARY=${SECP256K1_LIBRARY} \
-DLZ4_FOUND=1 \
-DLZ4_INCLUDE_DIRS=${LZ4_INCLUDE_DIR} \
-DLZ4_LIBRARIES=${LZ4_LIBRARY} \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=${SODIUM_INCLUDE_DIR} \
-DSODIUM_LIBRARY_RELEASE=${SODIUM_LIBRARY_RELEASE} \
-DSODIUM_USE_STATIC_LIBS=1 \

30
example/android/third_party/secp256k1/build.sh vendored Normal file → Executable file
View file

@ -5,28 +5,32 @@ export CC=
export CXX=
rm -rf secp256k1
git clone https://github.com/libbitcoin/secp256k1.git
git clone https://github.com/bitcoin-core/secp256k1
cd secp256k1
git checkout v0.3.2
./autogen.sh
mkdir build
cd build
./configure --enable-module-recovery --enable-experimental --with-asm=arm --host=arm-linux-androideabi CC=armv7a-linux-androideabi21-clang CFLAGS="-mthumb -march=armv7-a" CCASFLAGS="-Wa,-mthumb -Wa,-march=armv7-a"
cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=armeabi-v7a -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=arm-linux-androideabi
make
cp .libs/libsecp256k1.a ../armv7/
cp .libs/libsecp256k1.so ../armv7/
cp lib/libsecp256k1.a ../../armv7/
rm -rf *
./configure --enable-module-recovery --host=aarch64-linux-android CC=aarch64-linux-android21-clang CFLAGS="-mthumb -march=armv8-a" CCASFLAGS="-Wa,-mthumb -Wa,-march=armv8-a"
cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=aarch64-linux-android
make
cp .libs/libsecp256k1.a ../armv8/
cp .libs/libsecp256k1.so ../armv8/
cp lib/libsecp256k1.a ../../armv8/
rm -rf *
./configure --enable-module-recovery --host=x86_64-linux-android CC=x86_64-linux-android21-clang
cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=x86_64 -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=x86_64
make
cp .libs/libsecp256k1.a ../x86-64/
cp .libs/libsecp256k1.so ../x86-64/
cp lib/libsecp256k1.a ../../x86-64/
rm -rf *
./configure --enable-module-recovery --host=i686-linux-android CC=i686-linux-android21-clang
cmake .. -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI= -DANDROID_PLATFORM=21 -DBUILD_SHARED_LIBS=OFF -DANDROID_TOOLCHAIN_NAME=x86-
make
cp .libs/libsecp256k1.a ../i686/
cp .libs/libsecp256k1.so ../i686/
cp lib/libsecp256k1.a ../../i686/
rm -rf *
rm -rf ../secp256k1

File diff suppressed because it is too large Load diff

View file

@ -7,43 +7,51 @@
extern "C" {
#endif
/** A pointer to a function that applies hash function to a point
/** A pointer to a function that hashes an EC point to obtain an ECDH secret
*
* Returns: 1 if a point was successfully hashed. 0 will cause ecdh to fail
* Out: output: pointer to an array to be filled by the function
* In: x: pointer to a 32-byte x coordinate
* y: pointer to a 32-byte y coordinate
* data: Arbitrary data pointer that is passed through
* Returns: 1 if the point was successfully hashed.
* 0 will cause secp256k1_ecdh to fail and return 0.
* Other return values are not allowed, and the behaviour of
* secp256k1_ecdh is undefined for other return values.
* Out: output: pointer to an array to be filled by the function
* In: x32: pointer to a 32-byte x coordinate
* y32: pointer to a 32-byte y coordinate
* data: arbitrary data pointer that is passed through
*/
typedef int (*secp256k1_ecdh_hash_function)(
unsigned char *output,
const unsigned char *x,
const unsigned char *y,
const unsigned char *x32,
const unsigned char *y32,
void *data
);
/** An implementation of SHA256 hash function that applies to compressed public key. */
SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
/** An implementation of SHA256 hash function that applies to compressed public key.
* Populates the output parameter with 32 bytes. */
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_sha256;
/** A default ecdh hash function (currently equal to secp256k1_ecdh_hash_function_sha256). */
SECP256K1_API extern const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
/** A default ECDH hash function (currently equal to secp256k1_ecdh_hash_function_sha256).
* Populates the output parameter with 32 bytes. */
SECP256K1_API const secp256k1_ecdh_hash_function secp256k1_ecdh_hash_function_default;
/** Compute an EC Diffie-Hellman secret in constant time
*
* Returns: 1: exponentiation was successful
* 0: scalar was invalid (zero or overflow)
* Args: ctx: pointer to a context object (cannot be NULL)
* Out: output: pointer to an array to be filled by the function
* In: pubkey: a pointer to a secp256k1_pubkey containing an
* initialized public key
* privkey: a 32-byte scalar with which to multiply the point
* hashfp: pointer to a hash function. If NULL, secp256k1_ecdh_hash_function_sha256 is used
* data: Arbitrary data pointer that is passed through
* 0: scalar was invalid (zero or overflow) or hashfp returned 0
* Args: ctx: pointer to a context object.
* Out: output: pointer to an array to be filled by hashfp.
* In: pubkey: pointer to a secp256k1_pubkey containing an initialized public key.
* seckey: a 32-byte scalar with which to multiply the point.
* hashfp: pointer to a hash function. If NULL,
* secp256k1_ecdh_hash_function_sha256 is used
* (in which case, 32 bytes will be written to output).
* data: arbitrary data pointer that is passed through to hashfp
* (can be NULL for secp256k1_ecdh_hash_function_sha256).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh(
const secp256k1_context* ctx,
const secp256k1_context *ctx,
unsigned char *output,
const secp256k1_pubkey *pubkey,
const unsigned char *privkey,
const unsigned char *seckey,
secp256k1_ecdh_hash_function hashfp,
void *data
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);

View file

@ -0,0 +1,200 @@
#ifndef SECP256K1_ELLSWIFT_H
#define SECP256K1_ELLSWIFT_H
#include "secp256k1.h"
#ifdef __cplusplus
extern "C" {
#endif
/* This module provides an implementation of ElligatorSwift as well as a
* version of x-only ECDH using it (including compatibility with BIP324).
*
* ElligatorSwift is described in https://eprint.iacr.org/2022/759 by
* Chavez-Saab, Rodriguez-Henriquez, and Tibouchi. It permits encoding
* uniformly chosen public keys as 64-byte arrays which are indistinguishable
* from uniformly random arrays.
*
* Let f be the function from pairs of field elements to point X coordinates,
* defined as follows (all operations modulo p = 2^256 - 2^32 - 977)
* f(u,t):
* - Let C = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852,
* a square root of -3.
* - If u=0, set u=1 instead.
* - If t=0, set t=1 instead.
* - If u^3 + t^2 + 7 = 0, multiply t by 2.
* - Let X = (u^3 + 7 - t^2) / (2 * t)
* - Let Y = (X + t) / (C * u)
* - Return the first in [u + 4 * Y^2, (-X/Y - u) / 2, (X/Y - u) / 2] that is an
* X coordinate on the curve (at least one of them is, for any u and t).
*
* Then an ElligatorSwift encoding of x consists of the 32-byte big-endian
* encodings of field elements u and t concatenated, where f(u,t) = x.
* The encoding algorithm is described in the paper, and effectively picks a
* uniformly random pair (u,t) among those which encode x.
*
* If the Y coordinate is relevant, it is given the same parity as t.
*
* Changes w.r.t. the paper:
* - The u=0, t=0, and u^3+t^2+7=0 conditions result in decoding to the point
* at infinity in the paper. Here they are remapped to finite points.
* - The paper uses an additional encoding bit for the parity of y. Here the
* parity of t is used (negating t does not affect the decoded x coordinate,
* so this is possible).
*
* For mathematical background about the scheme, see the doc/ellswift.md file.
*/
/** A pointer to a function used by secp256k1_ellswift_xdh to hash the shared X
* coordinate along with the encoded public keys to a uniform shared secret.
*
* Returns: 1 if a shared secret was successfully computed.
* 0 will cause secp256k1_ellswift_xdh to fail and return 0.
* Other return values are not allowed, and the behaviour of
* secp256k1_ellswift_xdh is undefined for other return values.
* Out: output: pointer to an array to be filled by the function
* In: x32: pointer to the 32-byte serialized X coordinate
* of the resulting shared point (will not be NULL)
* ell_a64: pointer to the 64-byte encoded public key of party A
* (will not be NULL)
* ell_b64: pointer to the 64-byte encoded public key of party B
* (will not be NULL)
* data: arbitrary data pointer that is passed through
*/
typedef int (*secp256k1_ellswift_xdh_hash_function)(
unsigned char *output,
const unsigned char *x32,
const unsigned char *ell_a64,
const unsigned char *ell_b64,
void *data
);
/** An implementation of an secp256k1_ellswift_xdh_hash_function which uses
* SHA256(prefix64 || ell_a64 || ell_b64 || x32), where prefix64 is the 64-byte
* array pointed to by data. */
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix;
/** An implementation of an secp256k1_ellswift_xdh_hash_function compatible with
* BIP324. It returns H_tag(ell_a64 || ell_b64 || x32), where H_tag is the
* BIP340 tagged hash function with tag "bip324_ellswift_xonly_ecdh". Equivalent
* to secp256k1_ellswift_xdh_hash_function_prefix with prefix64 set to
* SHA256("bip324_ellswift_xonly_ecdh")||SHA256("bip324_ellswift_xonly_ecdh").
* The data argument is ignored. */
SECP256K1_API const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324;
/** Construct a 64-byte ElligatorSwift encoding of a given pubkey.
*
* Returns: 1 always.
* Args: ctx: pointer to a context object
* Out: ell64: pointer to a 64-byte array to be filled
* In: pubkey: pointer to a secp256k1_pubkey containing an
* initialized public key
* rnd32: pointer to 32 bytes of randomness
*
* It is recommended that rnd32 consists of 32 uniformly random bytes, not
* known to any adversary trying to detect whether public keys are being
* encoded, though 16 bytes of randomness (padded to an array of 32 bytes,
* e.g., with zeros) suffice to make the result indistinguishable from
* uniform. The randomness in rnd32 must not be a deterministic function of
* the pubkey (it can be derived from the private key, though).
*
* It is not guaranteed that the computed encoding is stable across versions
* of the library, even if all arguments to this function (including rnd32)
* are the same.
*
* This function runs in variable time.
*/
SECP256K1_API int secp256k1_ellswift_encode(
const secp256k1_context *ctx,
unsigned char *ell64,
const secp256k1_pubkey *pubkey,
const unsigned char *rnd32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Decode a 64-bytes ElligatorSwift encoded public key.
*
* Returns: always 1
* Args: ctx: pointer to a context object
* Out: pubkey: pointer to a secp256k1_pubkey that will be filled
* In: ell64: pointer to a 64-byte array to decode
*
* This function runs in variable time.
*/
SECP256K1_API int secp256k1_ellswift_decode(
const secp256k1_context *ctx,
secp256k1_pubkey *pubkey,
const unsigned char *ell64
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Compute an ElligatorSwift public key for a secret key.
*
* Returns: 1: secret was valid, public key was stored.
* 0: secret was invalid, try again.
* Args: ctx: pointer to a context object
* Out: ell64: pointer to a 64-byte array to receive the ElligatorSwift
* public key
* In: seckey32: pointer to a 32-byte secret key
* auxrnd32: (optional) pointer to 32 bytes of randomness
*
* Constant time in seckey and auxrnd32, but not in the resulting public key.
*
* It is recommended that auxrnd32 contains 32 uniformly random bytes, though
* it is optional (and does result in encodings that are indistinguishable from
* uniform even without any auxrnd32). It differs from the (mandatory) rnd32
* argument to secp256k1_ellswift_encode in this regard.
*
* This function can be used instead of calling secp256k1_ec_pubkey_create
* followed by secp256k1_ellswift_encode. It is safer, as it uses the secret
* key as entropy for the encoding (supplemented with auxrnd32, if provided).
*
* Like secp256k1_ellswift_encode, this function does not guarantee that the
* computed encoding is stable across versions of the library, even if all
* arguments (including auxrnd32) are the same.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_create(
const secp256k1_context *ctx,
unsigned char *ell64,
const unsigned char *seckey32,
const unsigned char *auxrnd32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Given a private key, and ElligatorSwift public keys sent in both directions,
* compute a shared secret using x-only Elliptic Curve Diffie-Hellman (ECDH).
*
* Returns: 1: shared secret was successfully computed
* 0: secret was invalid or hashfp returned 0
* Args: ctx: pointer to a context object.
* Out: output: pointer to an array to be filled by hashfp.
* In: ell_a64: pointer to the 64-byte encoded public key of party A
* (will not be NULL)
* ell_b64: pointer to the 64-byte encoded public key of party B
* (will not be NULL)
* seckey32: pointer to our 32-byte secret key
* party: boolean indicating which party we are: zero if we are
* party A, non-zero if we are party B. seckey32 must be
* the private key corresponding to that party's ell_?64.
* This correspondence is not checked.
* hashfp: pointer to a hash function.
* data: arbitrary data pointer passed through to hashfp.
*
* Constant time in seckey32.
*
* This function is more efficient than decoding the public keys, and performing
* ECDH on them.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ellswift_xdh(
const secp256k1_context *ctx,
unsigned char *output,
const unsigned char *ell_a64,
const unsigned char *ell_b64,
const unsigned char *seckey32,
int party,
secp256k1_ellswift_xdh_hash_function hashfp,
void *data
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(7);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_ELLSWIFT_H */

View file

@ -0,0 +1,250 @@
#ifndef SECP256K1_EXTRAKEYS_H
#define SECP256K1_EXTRAKEYS_H
#include "secp256k1.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Opaque data structure that holds a parsed and valid "x-only" public key.
* An x-only pubkey encodes a point whose Y coordinate is even. It is
* serialized using only its X coordinate (32 bytes). See BIP-340 for more
* information about x-only pubkeys.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 64 bytes in size, and can be safely copied/moved.
* If you need to convert to a format suitable for storage, transmission, use
* use secp256k1_xonly_pubkey_serialize and secp256k1_xonly_pubkey_parse. To
* compare keys, use secp256k1_xonly_pubkey_cmp.
*/
typedef struct secp256k1_xonly_pubkey {
unsigned char data[64];
} secp256k1_xonly_pubkey;
/** Opaque data structure that holds a keypair consisting of a secret and a
* public key.
*
* The exact representation of data inside is implementation defined and not
* guaranteed to be portable between different platforms or versions. It is
* however guaranteed to be 96 bytes in size, and can be safely copied/moved.
*/
typedef struct secp256k1_keypair {
unsigned char data[96];
} secp256k1_keypair;
/** Parse a 32-byte sequence into a xonly_pubkey object.
*
* Returns: 1 if the public key was fully valid.
* 0 if the public key could not be parsed or is invalid.
*
* Args: ctx: pointer to a context object.
* Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a
* parsed version of input. If not, it's set to an invalid value.
* In: input32: pointer to a serialized xonly_pubkey.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_parse(
const secp256k1_context *ctx,
secp256k1_xonly_pubkey *pubkey,
const unsigned char *input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an xonly_pubkey object into a 32-byte sequence.
*
* Returns: 1 always.
*
* Args: ctx: pointer to a context object.
* Out: output32: pointer to a 32-byte array to place the serialized key in.
* In: pubkey: pointer to a secp256k1_xonly_pubkey containing an initialized public key.
*/
SECP256K1_API int secp256k1_xonly_pubkey_serialize(
const secp256k1_context *ctx,
unsigned char *output32,
const secp256k1_xonly_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Compare two x-only public keys using lexicographic order
*
* Returns: <0 if the first public key is less than the second
* >0 if the first public key is greater than the second
* 0 if the two public keys are equal
* Args: ctx: pointer to a context object.
* In: pubkey1: first public key to compare
* pubkey2: second public key to compare
*/
SECP256K1_API int secp256k1_xonly_pubkey_cmp(
const secp256k1_context *ctx,
const secp256k1_xonly_pubkey *pk1,
const secp256k1_xonly_pubkey *pk2
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Converts a secp256k1_pubkey into a secp256k1_xonly_pubkey.
*
* Returns: 1 always.
*
* Args: ctx: pointer to a context object.
* Out: xonly_pubkey: pointer to an x-only public key object for placing the converted public key.
* pk_parity: Ignored if NULL. Otherwise, pointer to an integer that
* will be set to 1 if the point encoded by xonly_pubkey is
* the negation of the pubkey and set to 0 otherwise.
* In: pubkey: pointer to a public key that is converted.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_from_pubkey(
const secp256k1_context *ctx,
secp256k1_xonly_pubkey *xonly_pubkey,
int *pk_parity,
const secp256k1_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
/** Tweak an x-only public key by adding the generator multiplied with tweak32
* to it.
*
* Note that the resulting point can not in general be represented by an x-only
* pubkey because it may have an odd Y coordinate. Instead, the output_pubkey
* is a normal secp256k1_pubkey.
*
* Returns: 0 if the arguments are invalid or the resulting public key would be
* invalid (only when the tweak is the negation of the corresponding
* secret key). 1 otherwise.
*
* Args: ctx: pointer to a context object.
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0.
* In: internal_pubkey: pointer to an x-only pubkey to apply the tweak to.
* tweak32: pointer to a 32-byte tweak, which must be valid
* according to secp256k1_ec_seckey_verify or 32 zero
* bytes. For uniformly random 32-byte tweaks, the chance of
* being invalid is negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add(
const secp256k1_context *ctx,
secp256k1_pubkey *output_pubkey,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Checks that a tweaked pubkey is the result of calling
* secp256k1_xonly_pubkey_tweak_add with internal_pubkey and tweak32.
*
* The tweaked pubkey is represented by its 32-byte x-only serialization and
* its pk_parity, which can both be obtained by converting the result of
* tweak_add to a secp256k1_xonly_pubkey.
*
* Note that this alone does _not_ verify that the tweaked pubkey is a
* commitment. If the tweak is not chosen in a specific way, the tweaked pubkey
* can easily be the result of a different internal_pubkey and tweak.
*
* Returns: 0 if the arguments are invalid or the tweaked pubkey is not the
* result of tweaking the internal_pubkey with tweak32. 1 otherwise.
* Args: ctx: pointer to a context object.
* In: tweaked_pubkey32: pointer to a serialized xonly_pubkey.
* tweaked_pk_parity: the parity of the tweaked pubkey (whose serialization
* is passed in as tweaked_pubkey32). This must match the
* pk_parity value that is returned when calling
* secp256k1_xonly_pubkey with the tweaked pubkey, or
* this function will fail.
* internal_pubkey: pointer to an x-only public key object to apply the tweak to.
* tweak32: pointer to a 32-byte tweak.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_xonly_pubkey_tweak_add_check(
const secp256k1_context *ctx,
const unsigned char *tweaked_pubkey32,
int tweaked_pk_parity,
const secp256k1_xonly_pubkey *internal_pubkey,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Compute the keypair for a valid secret key.
*
* See the documentation of `secp256k1_ec_seckey_verify` for more information
* about the validity of secret keys.
*
* Returns: 1: secret key is valid
* 0: secret key is invalid
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: keypair: pointer to the created keypair.
* In: seckey: pointer to a 32-byte secret key.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_create(
const secp256k1_context *ctx,
secp256k1_keypair *keypair,
const unsigned char *seckey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Get the secret key from a keypair.
*
* Returns: 1 always.
* Args: ctx: pointer to a context object.
* Out: seckey: pointer to a 32-byte buffer for the secret key.
* In: keypair: pointer to a keypair.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_sec(
const secp256k1_context *ctx,
unsigned char *seckey,
const secp256k1_keypair *keypair
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Get the public key from a keypair.
*
* Returns: 1 always.
* Args: ctx: pointer to a context object.
* Out: pubkey: pointer to a pubkey object, set to the keypair public key.
* In: keypair: pointer to a keypair.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_pub(
const secp256k1_context *ctx,
secp256k1_pubkey *pubkey,
const secp256k1_keypair *keypair
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Get the x-only public key from a keypair.
*
* This is the same as calling secp256k1_keypair_pub and then
* secp256k1_xonly_pubkey_from_pubkey.
*
* Returns: 1 always.
* Args: ctx: pointer to a context object.
* Out: pubkey: pointer to an xonly_pubkey object, set to the keypair
* public key after converting it to an xonly_pubkey.
* pk_parity: Ignored if NULL. Otherwise, pointer to an integer that will be set to the
* pk_parity argument of secp256k1_xonly_pubkey_from_pubkey.
* In: keypair: pointer to a keypair.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_pub(
const secp256k1_context *ctx,
secp256k1_xonly_pubkey *pubkey,
int *pk_parity,
const secp256k1_keypair *keypair
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(4);
/** Tweak a keypair by adding tweak32 to the secret key and updating the public
* key accordingly.
*
* Calling this function and then secp256k1_keypair_pub results in the same
* public key as calling secp256k1_keypair_xonly_pub and then
* secp256k1_xonly_pubkey_tweak_add.
*
* Returns: 0 if the arguments are invalid or the resulting keypair would be
* invalid (only when the tweak is the negation of the keypair's
* secret key). 1 otherwise.
*
* Args: ctx: pointer to a context object.
* In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to
* an invalid value if this function returns 0.
* In: tweak32: pointer to a 32-byte tweak, which must be valid according to
* secp256k1_ec_seckey_verify or 32 zero bytes. For uniformly
* random 32-byte tweaks, the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_keypair_xonly_tweak_add(
const secp256k1_context *ctx,
secp256k1_keypair *keypair,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_EXTRAKEYS_H */

View file

@ -0,0 +1,588 @@
#ifndef SECP256K1_MUSIG_H
#define SECP256K1_MUSIG_H
#include "secp256k1_extrakeys.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/** This module implements BIP 327 "MuSig2 for BIP340-compatible
* Multi-Signatures"
* (https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
* v1.0.0. You can find an example demonstrating the musig module in
* examples/musig.c.
*
* The module also supports BIP 341 ("Taproot") public key tweaking.
*
* It is recommended to read the documentation in this include file carefully.
* Further notes on API usage can be found in doc/musig.md
*
* Since the first version of MuSig is essentially replaced by MuSig2, we use
* MuSig, musig and MuSig2 synonymously unless noted otherwise.
*/
/** Opaque data structures
*
* The exact representation of data inside the opaque data structures is
* implementation defined and not guaranteed to be portable between different
* platforms or versions. With the exception of `secp256k1_musig_secnonce`, the
* data structures can be safely copied/moved. If you need to convert to a
* format suitable for storage, transmission, or comparison, use the
* corresponding serialization and parsing functions.
*/
/** Opaque data structure that caches information about public key aggregation.
*
* Guaranteed to be 197 bytes in size. No serialization and parsing functions
* (yet).
*/
typedef struct secp256k1_musig_keyagg_cache {
unsigned char data[197];
} secp256k1_musig_keyagg_cache;
/** Opaque data structure that holds a signer's _secret_ nonce.
*
* Guaranteed to be 132 bytes in size.
*
* WARNING: This structure MUST NOT be copied or read or written to directly. A
* signer who is online throughout the whole process and can keep this
* structure in memory can use the provided API functions for a safe standard
* workflow.
*
* Copying this data structure can result in nonce reuse which will leak the
* secret signing key.
*/
typedef struct secp256k1_musig_secnonce {
unsigned char data[132];
} secp256k1_musig_secnonce;
/** Opaque data structure that holds a signer's public nonce.
*
* Guaranteed to be 132 bytes in size. Serialized and parsed with
* `musig_pubnonce_serialize` and `musig_pubnonce_parse`.
*/
typedef struct secp256k1_musig_pubnonce {
unsigned char data[132];
} secp256k1_musig_pubnonce;
/** Opaque data structure that holds an aggregate public nonce.
*
* Guaranteed to be 132 bytes in size. Serialized and parsed with
* `musig_aggnonce_serialize` and `musig_aggnonce_parse`.
*/
typedef struct secp256k1_musig_aggnonce {
unsigned char data[132];
} secp256k1_musig_aggnonce;
/** Opaque data structure that holds a MuSig session.
*
* This structure is not required to be kept secret for the signing protocol to
* be secure. Guaranteed to be 133 bytes in size. No serialization and parsing
* functions (yet).
*/
typedef struct secp256k1_musig_session {
unsigned char data[133];
} secp256k1_musig_session;
/** Opaque data structure that holds a partial MuSig signature.
*
* Guaranteed to be 36 bytes in size. Serialized and parsed with
* `musig_partial_sig_serialize` and `musig_partial_sig_parse`.
*/
typedef struct secp256k1_musig_partial_sig {
unsigned char data[36];
} secp256k1_musig_partial_sig;
/** Parse a signer's public nonce.
*
* Returns: 1 when the nonce could be parsed, 0 otherwise.
* Args: ctx: pointer to a context object
* Out: nonce: pointer to a nonce object
* In: in66: pointer to the 66-byte nonce to be parsed
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubnonce_parse(
const secp256k1_context *ctx,
secp256k1_musig_pubnonce *nonce,
const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a signer's public nonce
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* Out: out66: pointer to a 66-byte array to store the serialized nonce
* In: nonce: pointer to the nonce
*/
SECP256K1_API int secp256k1_musig_pubnonce_serialize(
const secp256k1_context *ctx,
unsigned char *out66,
const secp256k1_musig_pubnonce *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse an aggregate public nonce.
*
* Returns: 1 when the nonce could be parsed, 0 otherwise.
* Args: ctx: pointer to a context object
* Out: nonce: pointer to a nonce object
* In: in66: pointer to the 66-byte nonce to be parsed
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_aggnonce_parse(
const secp256k1_context *ctx,
secp256k1_musig_aggnonce *nonce,
const unsigned char *in66
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an aggregate public nonce
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* Out: out66: pointer to a 66-byte array to store the serialized nonce
* In: nonce: pointer to the nonce
*/
SECP256K1_API int secp256k1_musig_aggnonce_serialize(
const secp256k1_context *ctx,
unsigned char *out66,
const secp256k1_musig_aggnonce *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Parse a MuSig partial signature.
*
* Returns: 1 when the signature could be parsed, 0 otherwise.
* Args: ctx: pointer to a context object
* Out: sig: pointer to a signature object
* In: in32: pointer to the 32-byte signature to be parsed
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_parse(
const secp256k1_context *ctx,
secp256k1_musig_partial_sig *sig,
const unsigned char *in32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize a MuSig partial signature
*
* Returns: 1 always
* Args: ctx: pointer to a context object
* Out: out32: pointer to a 32-byte array to store the serialized signature
* In: sig: pointer to the signature
*/
SECP256K1_API int secp256k1_musig_partial_sig_serialize(
const secp256k1_context *ctx,
unsigned char *out32,
const secp256k1_musig_partial_sig *sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Computes an aggregate public key and uses it to initialize a keyagg_cache
*
* Different orders of `pubkeys` result in different `agg_pk`s.
*
* Before aggregating, the pubkeys can be sorted with `secp256k1_ec_pubkey_sort`
* which ensures the same `agg_pk` result for the same multiset of pubkeys.
* This is useful to do before `pubkey_agg`, such that the order of pubkeys
* does not affect the aggregate public key.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: agg_pk: the MuSig-aggregated x-only public key. If you do not need it,
* this arg can be NULL.
* keyagg_cache: if non-NULL, pointer to a musig_keyagg_cache struct that
* is required for signing (or observing the signing session
* and verifying partial signatures).
* In: pubkeys: input array of pointers to public keys to aggregate. The order
* is important; a different order will result in a different
* aggregate public key.
* n_pubkeys: length of pubkeys array. Must be greater than 0.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_agg(
const secp256k1_context *ctx,
secp256k1_xonly_pubkey *agg_pk,
secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_pubkey * const *pubkeys,
size_t n_pubkeys
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(4);
/** Obtain the aggregate public key from a keyagg_cache.
*
* This is only useful if you need the non-xonly public key, in particular for
* plain (non-xonly) tweaking or batch-verifying multiple key aggregations
* (not implemented).
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: agg_pk: the MuSig-aggregated public key.
* In: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
* `musig_pubkey_agg`
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_get(
const secp256k1_context *ctx,
secp256k1_pubkey *agg_pk,
const secp256k1_musig_keyagg_cache *keyagg_cache
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Apply plain "EC" tweaking to a public key in a given keyagg_cache by adding
* the generator multiplied with `tweak32` to it. This is useful for deriving
* child keys from an aggregate public key via BIP 32 where `tweak32` is set to
* a hash as defined in BIP 32.
*
* Callers are responsible for deriving `tweak32` in a way that does not reduce
* the security of MuSig (for example, by following BIP 32).
*
* The tweaking method is the same as `secp256k1_ec_pubkey_tweak_add`. So after
* the following pseudocode buf and buf2 have identical contents (absent
* earlier failures).
*
* secp256k1_musig_pubkey_agg(..., keyagg_cache, pubkeys, ...)
* secp256k1_musig_pubkey_get(..., agg_pk, keyagg_cache)
* secp256k1_musig_pubkey_ec_tweak_add(..., output_pk, tweak32, keyagg_cache)
* secp256k1_ec_pubkey_serialize(..., buf, ..., output_pk, ...)
* secp256k1_ec_pubkey_tweak_add(..., agg_pk, tweak32)
* secp256k1_ec_pubkey_serialize(..., buf2, ..., agg_pk, ...)
*
* This function is required if you want to _sign_ for a tweaked aggregate key.
* If you are only computing a public key but not intending to create a
* signature for it, use `secp256k1_ec_pubkey_tweak_add` instead.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0. If you
* do not need it, this arg can be NULL.
* In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
* `musig_pubkey_agg`
* In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes
* `secp256k1_ec_seckey_verify` and is not equal to the
* secret key corresponding to the public key represented
* by keyagg_cache or its negation. For uniformly random
* 32-byte arrays the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_ec_tweak_add(
const secp256k1_context *ctx,
secp256k1_pubkey *output_pubkey,
secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Apply x-only tweaking to a public key in a given keyagg_cache by adding the
* generator multiplied with `tweak32` to it. This is useful for creating
* Taproot outputs where `tweak32` is set to a TapTweak hash as defined in BIP
* 341.
*
* Callers are responsible for deriving `tweak32` in a way that does not reduce
* the security of MuSig (for example, by following Taproot BIP 341).
*
* The tweaking method is the same as `secp256k1_xonly_pubkey_tweak_add`. So in
* the following pseudocode xonly_pubkey_tweak_add_check (absent earlier
* failures) returns 1.
*
* secp256k1_musig_pubkey_agg(..., agg_pk, keyagg_cache, pubkeys, ...)
* secp256k1_musig_pubkey_xonly_tweak_add(..., output_pk, keyagg_cache, tweak32)
* secp256k1_xonly_pubkey_serialize(..., buf, output_pk)
* secp256k1_xonly_pubkey_tweak_add_check(..., buf, ..., agg_pk, tweak32)
*
* This function is required if you want to _sign_ for a tweaked aggregate key.
* If you are only computing a public key but not intending to create a
* signature for it, use `secp256k1_xonly_pubkey_tweak_add` instead.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: output_pubkey: pointer to a public key to store the result. Will be set
* to an invalid value if this function returns 0. If you
* do not need it, this arg can be NULL.
* In/Out: keyagg_cache: pointer to a `musig_keyagg_cache` struct initialized by
* `musig_pubkey_agg`
* In: tweak32: pointer to a 32-byte tweak. The tweak is valid if it passes
* `secp256k1_ec_seckey_verify` and is not equal to the
* secret key corresponding to the public key represented
* by keyagg_cache or its negation. For uniformly random
* 32-byte arrays the chance of being invalid is
* negligible (around 1 in 2^128).
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_pubkey_xonly_tweak_add(
const secp256k1_context *ctx,
secp256k1_pubkey *output_pubkey,
secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *tweak32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Starts a signing session by generating a nonce
*
* This function outputs a secret nonce that will be required for signing and a
* corresponding public nonce that is intended to be sent to other signers.
*
* MuSig differs from regular Schnorr signing in that implementers _must_ take
* special care to not reuse a nonce. This can be ensured by following these rules:
*
* 1. Each call to this function must have a UNIQUE session_secrand32 that must
* NOT BE REUSED in subsequent calls to this function and must be KEPT
* SECRET (even from other signers).
* 2. If you already know the seckey, message or aggregate public key
* cache, they can be optionally provided to derive the nonce and increase
* misuse-resistance. The extra_input32 argument can be used to provide
* additional data that does not repeat in normal scenarios, such as the
* current time.
* 3. Avoid copying (or serializing) the secnonce. This reduces the possibility
* that it is used more than once for signing.
*
* If you don't have access to good randomness for session_secrand32, but you
* have access to a non-repeating counter, then see
* secp256k1_musig_nonce_gen_counter.
*
* Remember that nonce reuse will leak the secret key!
* Note that using the same seckey for multiple MuSig sessions is fine.
*
* Returns: 0 if the arguments are invalid and 1 otherwise
* Args: ctx: pointer to a context object (not secp256k1_context_static)
* Out: secnonce: pointer to a structure to store the secret nonce
* pubnonce: pointer to a structure to store the public nonce
* In/Out:
* session_secrand32: a 32-byte session_secrand32 as explained above. Must be unique to this
* call to secp256k1_musig_nonce_gen and must be uniformly
* random. If the function call is successful, the
* session_secrand32 buffer is invalidated to prevent reuse.
* In:
* seckey: the 32-byte secret key that will later be used for signing, if
* already known (can be NULL)
* pubkey: public key of the signer creating the nonce. The secnonce
* output of this function cannot be used to sign for any
* other public key. While the public key should correspond
* to the provided seckey, a mismatch will not cause the
* function to return 0.
* msg32: the 32-byte message that will later be signed, if already known
* (can be NULL)
* keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate
* (and potentially tweaked) public key if already known
* (can be NULL)
* extra_input32: an optional 32-byte array that is input to the nonce
* derivation function (can be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen(
const secp256k1_context *ctx,
secp256k1_musig_secnonce *secnonce,
secp256k1_musig_pubnonce *pubnonce,
unsigned char *session_secrand32,
const unsigned char *seckey,
const secp256k1_pubkey *pubkey,
const unsigned char *msg32,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *extra_input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(6);
/** Alternative way to generate a nonce and start a signing session
*
* This function outputs a secret nonce that will be required for signing and a
* corresponding public nonce that is intended to be sent to other signers.
*
* This function differs from `secp256k1_musig_nonce_gen` by accepting a
* non-repeating counter value instead of a secret random value. This requires
* that a secret key is provided to `secp256k1_musig_nonce_gen_counter`
* (through the keypair argument), as opposed to `secp256k1_musig_nonce_gen`
* where the seckey argument is optional.
*
* MuSig differs from regular Schnorr signing in that implementers _must_ take
* special care to not reuse a nonce. This can be ensured by following these rules:
*
* 1. The nonrepeating_cnt argument must be a counter value that never repeats,
* i.e., you must never call `secp256k1_musig_nonce_gen_counter` twice with
* the same keypair and nonrepeating_cnt value. For example, this implies
* that if the same keypair is used with `secp256k1_musig_nonce_gen_counter`
* on multiple devices, none of the devices should have the same counter
* value as any other device.
* 2. If the seckey, message or aggregate public key cache is already available
* at this stage, any of these can be optionally provided, in which case
* they will be used in the derivation of the nonce and increase
* misuse-resistance. The extra_input32 argument can be used to provide
* additional data that does not repeat in normal scenarios, such as the
* current time.
* 3. Avoid copying (or serializing) the secnonce. This reduces the possibility
* that it is used more than once for signing.
*
* Remember that nonce reuse will leak the secret key!
* Note that using the same keypair for multiple MuSig sessions is fine.
*
* Returns: 0 if the arguments are invalid and 1 otherwise
* Args: ctx: pointer to a context object (not secp256k1_context_static)
* Out: secnonce: pointer to a structure to store the secret nonce
* pubnonce: pointer to a structure to store the public nonce
* In:
* nonrepeating_cnt: the value of a counter as explained above. Must be
* unique to this call to secp256k1_musig_nonce_gen.
* keypair: keypair of the signer creating the nonce. The secnonce
* output of this function cannot be used to sign for any
* other keypair.
* msg32: the 32-byte message that will later be signed, if already known
* (can be NULL)
* keyagg_cache: pointer to the keyagg_cache that was used to create the aggregate
* (and potentially tweaked) public key if already known
* (can be NULL)
* extra_input32: an optional 32-byte array that is input to the nonce
* derivation function (can be NULL)
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_gen_counter(
const secp256k1_context *ctx,
secp256k1_musig_secnonce *secnonce,
secp256k1_musig_pubnonce *pubnonce,
uint64_t nonrepeating_cnt,
const secp256k1_keypair *keypair,
const unsigned char *msg32,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const unsigned char *extra_input32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);
/** Aggregates the nonces of all signers into a single nonce
*
* This can be done by an untrusted party to reduce the communication
* between signers. Instead of everyone sending nonces to everyone else, there
* can be one party receiving all nonces, aggregating the nonces with this
* function and then sending only the aggregate nonce back to the signers.
*
* If the aggregator does not compute the aggregate nonce correctly, the final
* signature will be invalid.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: aggnonce: pointer to an aggregate public nonce object for
* musig_nonce_process
* In: pubnonces: array of pointers to public nonces sent by the
* signers
* n_pubnonces: number of elements in the pubnonces array. Must be
* greater than 0.
*/
SECP256K1_API int secp256k1_musig_nonce_agg(
const secp256k1_context *ctx,
secp256k1_musig_aggnonce *aggnonce,
const secp256k1_musig_pubnonce * const *pubnonces,
size_t n_pubnonces
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Takes the aggregate nonce and creates a session that is required for signing
* and verification of partial signatures.
*
* Returns: 0 if the arguments are invalid, 1 otherwise
* Args: ctx: pointer to a context object
* Out: session: pointer to a struct to store the session
* In: aggnonce: pointer to an aggregate public nonce object that is the
* output of musig_nonce_agg
* msg32: the 32-byte message to sign
* keyagg_cache: pointer to the keyagg_cache that was used to create the
* aggregate (and potentially tweaked) pubkey
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_nonce_process(
const secp256k1_context *ctx,
secp256k1_musig_session *session,
const secp256k1_musig_aggnonce *aggnonce,
const unsigned char *msg32,
const secp256k1_musig_keyagg_cache *keyagg_cache
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);
/** Produces a partial signature
*
* This function overwrites the given secnonce with zeros and will abort if given a
* secnonce that is all zeros. This is a best effort attempt to protect against nonce
* reuse. However, this is of course easily defeated if the secnonce has been
* copied (or serialized). Remember that nonce reuse will leak the secret key!
*
* For signing to succeed, the secnonce provided to this function must have
* been generated for the provided keypair. This means that when signing for a
* keypair consisting of a seckey and pubkey, the secnonce must have been
* created by calling musig_nonce_gen with that pubkey. Otherwise, the
* illegal_callback is called.
*
* This function does not verify the output partial signature, deviating from
* the BIP 327 specification. It is recommended to verify the output partial
* signature with `secp256k1_musig_partial_sig_verify` to prevent random or
* adversarially provoked computation errors.
*
* Returns: 0 if the arguments are invalid or the provided secnonce has already
* been used for signing, 1 otherwise
* Args: ctx: pointer to a context object
* Out: partial_sig: pointer to struct to store the partial signature
* In/Out: secnonce: pointer to the secnonce struct created in
* musig_nonce_gen that has been never used in a
* partial_sign call before and has been created for the
* keypair
* In: keypair: pointer to keypair to sign the message with
* keyagg_cache: pointer to the keyagg_cache that was output when the
* aggregate public key for this session
* session: pointer to the session that was created with
* musig_nonce_process
*/
SECP256K1_API int secp256k1_musig_partial_sign(
const secp256k1_context *ctx,
secp256k1_musig_partial_sig *partial_sig,
secp256k1_musig_secnonce *secnonce,
const secp256k1_keypair *keypair,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_musig_session *session
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
/** Verifies an individual signer's partial signature
*
* The signature is verified for a specific signing session. In order to avoid
* accidentally verifying a signature from a different or non-existing signing
* session, you must ensure the following:
* 1. The `keyagg_cache` argument is identical to the one used to create the
* `session` with `musig_nonce_process`.
* 2. The `pubkey` argument must be identical to the one sent by the signer
* before aggregating it with `musig_pubkey_agg` to create the
* `keyagg_cache`.
* 3. The `pubnonce` argument must be identical to the one sent by the signer
* before aggregating it with `musig_nonce_agg` and using the result to
* create the `session` with `musig_nonce_process`.
*
* It is not required to call this function in regular MuSig sessions, because
* if any partial signature does not verify, the final signature will not
* verify either, so the problem will be caught. However, this function
* provides the ability to identify which specific partial signature fails
* verification.
*
* Returns: 0 if the arguments are invalid or the partial signature does not
* verify, 1 otherwise
* Args ctx: pointer to a context object
* In: partial_sig: pointer to partial signature to verify, sent by
* the signer associated with `pubnonce` and `pubkey`
* pubnonce: public nonce of the signer in the signing session
* pubkey: public key of the signer in the signing session
* keyagg_cache: pointer to the keyagg_cache that was output when the
* aggregate public key for this signing session
* session: pointer to the session that was created with
* `musig_nonce_process`
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_musig_partial_sig_verify(
const secp256k1_context *ctx,
const secp256k1_musig_partial_sig *partial_sig,
const secp256k1_musig_pubnonce *pubnonce,
const secp256k1_pubkey *pubkey,
const secp256k1_musig_keyagg_cache *keyagg_cache,
const secp256k1_musig_session *session
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);
/** Aggregates partial signatures
*
* Returns: 0 if the arguments are invalid, 1 otherwise (which does NOT mean
* the resulting signature verifies).
* Args: ctx: pointer to a context object
* Out: sig64: complete (but possibly invalid) Schnorr signature
* In: session: pointer to the session that was created with
* musig_nonce_process
* partial_sigs: array of pointers to partial signatures to aggregate
* n_sigs: number of elements in the partial_sigs array. Must be
* greater than 0.
*/
SECP256K1_API int secp256k1_musig_partial_sig_agg(
const secp256k1_context *ctx,
unsigned char *sig64,
const secp256k1_musig_session *session,
const secp256k1_musig_partial_sig * const *partial_sigs,
size_t n_sigs
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -52,17 +52,19 @@ SECP256K1_API size_t secp256k1_context_preallocated_size(
* in the memory. In simpler words, the prealloc pointer (or any pointer derived
* from it) should not be used during the lifetime of the context object.
*
* Returns: a newly created context object.
* In: prealloc: a pointer to a rewritable contiguous block of memory of
* Returns: pointer to newly created context object.
* In: prealloc: pointer to a rewritable contiguous block of memory of
* size at least secp256k1_context_preallocated_size(flags)
* bytes, as detailed above (cannot be NULL)
* bytes, as detailed above.
* flags: which parts of the context to initialize.
*
* See secp256k1_context_create (in secp256k1.h) for further details.
*
* See also secp256k1_context_randomize (in secp256k1.h)
* and secp256k1_context_preallocated_destroy.
*/
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create(
void* prealloc,
SECP256K1_API secp256k1_context *secp256k1_context_preallocated_create(
void *prealloc,
unsigned int flags
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
@ -70,10 +72,10 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_create(
* caller-provided memory.
*
* Returns: the required size of the caller-provided memory block.
* In: ctx: an existing context to copy (cannot be NULL)
* In: ctx: pointer to a context to copy.
*/
SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
const secp256k1_context* ctx
const secp256k1_context *ctx
) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT;
/** Copy a secp256k1 context object into caller-provided memory.
@ -86,15 +88,18 @@ SECP256K1_API size_t secp256k1_context_preallocated_clone_size(
* the lifetime of this context object, see the description of
* secp256k1_context_preallocated_create for details.
*
* Returns: a newly created context object.
* Args: ctx: an existing context to copy (cannot be NULL)
* In: prealloc: a pointer to a rewritable contiguous block of memory of
* Cloning secp256k1_context_static is not possible, and should not be emulated by
* the caller (e.g., using memcpy). Create a new context instead.
*
* Returns: pointer to a newly created context object.
* Args: ctx: pointer to a context to copy (not secp256k1_context_static).
* In: prealloc: pointer to a rewritable contiguous block of memory of
* size at least secp256k1_context_preallocated_size(flags)
* bytes, as detailed above (cannot be NULL)
* bytes, as detailed above.
*/
SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
const secp256k1_context* ctx,
void* prealloc
SECP256K1_API secp256k1_context *secp256k1_context_preallocated_clone(
const secp256k1_context *ctx,
void *prealloc
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_WARN_UNUSED_RESULT;
/** Destroy a secp256k1 context object that has been created in
@ -113,13 +118,14 @@ SECP256K1_API secp256k1_context* secp256k1_context_preallocated_clone(
* preallocated pointer given to secp256k1_context_preallocated_create or
* secp256k1_context_preallocated_clone.
*
* Args: ctx: an existing context to destroy, constructed using
* Args: ctx: pointer to a context to destroy, constructed using
* secp256k1_context_preallocated_create or
* secp256k1_context_preallocated_clone (cannot be NULL)
* secp256k1_context_preallocated_clone
* (i.e., not secp256k1_context_static).
*/
SECP256K1_API void secp256k1_context_preallocated_destroy(
secp256k1_context* ctx
);
secp256k1_context *ctx
) SECP256K1_ARG_NONNULL(1);
#ifdef __cplusplus
}

View file

@ -7,7 +7,7 @@
extern "C" {
#endif
/** Opaque data structured that holds a parsed ECDSA signature,
/** Opaque data structure that holds a parsed ECDSA signature,
* supporting pubkey recovery.
*
* The exact representation of data inside is implementation defined and not
@ -21,21 +21,21 @@ extern "C" {
* recoverability) will have identical representation, so they can be
* memcmp'ed.
*/
typedef struct {
typedef struct secp256k1_ecdsa_recoverable_signature {
unsigned char data[65];
} secp256k1_ecdsa_recoverable_signature;
/** Parse a compact ECDSA signature (64 bytes + recovery id).
*
* Returns: 1 when the signature could be parsed, 0 otherwise
* Args: ctx: a secp256k1 context object
* Out: sig: a pointer to a signature object
* In: input64: a pointer to a 64-byte compact signature
* Args: ctx: pointer to a context object
* Out: sig: pointer to a signature object
* In: input64: pointer to a 64-byte compact signature
* recid: the recovery id (0, 1, 2 or 3)
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
const secp256k1_context* ctx,
secp256k1_ecdsa_recoverable_signature* sig,
const secp256k1_context *ctx,
secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *input64,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
@ -43,45 +43,48 @@ SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact(
/** Convert a recoverable signature into a normal signature.
*
* Returns: 1
* Out: sig: a pointer to a normal signature (cannot be NULL).
* In: sigin: a pointer to a recoverable signature (cannot be NULL).
* Args: ctx: pointer to a context object.
* Out: sig: pointer to a normal signature.
* In: sigin: pointer to a recoverable signature.
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert(
const secp256k1_context* ctx,
secp256k1_ecdsa_signature* sig,
const secp256k1_ecdsa_recoverable_signature* sigin
const secp256k1_context *ctx,
secp256k1_ecdsa_signature *sig,
const secp256k1_ecdsa_recoverable_signature *sigin
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);
/** Serialize an ECDSA signature in compact format (64 bytes + recovery id).
*
* Returns: 1
* Args: ctx: a secp256k1 context object
* Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)
* recid: a pointer to an integer to hold the recovery id (can be NULL).
* In: sig: a pointer to an initialized signature object (cannot be NULL)
* Args: ctx: pointer to a context object.
* Out: output64: pointer to a 64-byte array of the compact signature.
* recid: pointer to an integer to hold the recovery id.
* In: sig: pointer to an initialized signature object.
*/
SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact(
const secp256k1_context* ctx,
const secp256k1_context *ctx,
unsigned char *output64,
int *recid,
const secp256k1_ecdsa_recoverable_signature* sig
const secp256k1_ecdsa_recoverable_signature *sig
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Create a recoverable ECDSA signature.
*
* Returns: 1: signature created
* 0: the nonce generation function failed, or the private key was invalid.
* Args: ctx: pointer to a context object, initialized for signing (cannot be NULL)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In: msg32: the 32-byte message hash being signed (cannot be NULL)
* seckey: pointer to a 32-byte secret key (cannot be NULL)
* noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used
* ndata: pointer to arbitrary data used by the nonce generation function (can be NULL)
* 0: the nonce generation function failed, or the secret key was invalid.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig: pointer to an array where the signature will be placed.
* In: msghash32: the 32-byte message hash being signed.
* seckey: pointer to a 32-byte secret key.
* noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_default is used.
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL for secp256k1_nonce_function_default).
*/
SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
const secp256k1_context* ctx,
const secp256k1_context *ctx,
secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32,
const unsigned char *msghash32,
const unsigned char *seckey,
secp256k1_nonce_function noncefp,
const void *ndata
@ -91,16 +94,16 @@ SECP256K1_API int secp256k1_ecdsa_sign_recoverable(
*
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* Args: ctx: pointer to a context object, initialized for verification (cannot be NULL)
* Out: pubkey: pointer to the recovered public key (cannot be NULL)
* In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL)
* msg32: the 32-byte message hash assumed to be signed (cannot be NULL)
* Args: ctx: pointer to a context object.
* Out: pubkey: pointer to the recovered public key.
* In: sig: pointer to initialized signature that supports pubkey recovery.
* msghash32: the 32-byte message hash assumed to be signed.
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover(
const secp256k1_context* ctx,
const secp256k1_context *ctx,
secp256k1_pubkey *pubkey,
const secp256k1_ecdsa_recoverable_signature *sig,
const unsigned char *msg32
const unsigned char *msghash32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
#ifdef __cplusplus

View file

@ -0,0 +1,190 @@
#ifndef SECP256K1_SCHNORRSIG_H
#define SECP256K1_SCHNORRSIG_H
#include "secp256k1.h"
#include "secp256k1_extrakeys.h"
#ifdef __cplusplus
extern "C" {
#endif
/** This module implements a variant of Schnorr signatures compliant with
* Bitcoin Improvement Proposal 340 "Schnorr Signatures for secp256k1"
* (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
*/
/** A pointer to a function to deterministically generate a nonce.
*
* Same as secp256k1_nonce function with the exception of accepting an
* additional pubkey argument and not requiring an attempt argument. The pubkey
* argument can protect signature schemes with key-prefixed challenge hash
* inputs against reusing the nonce when signing with the wrong precomputed
* pubkey.
*
* Returns: 1 if a nonce was successfully generated. 0 will cause signing to
* return an error.
* Out: nonce32: pointer to a 32-byte array to be filled by the function
* In: msg: the message being verified. Is NULL if and only if msglen
* is 0.
* msglen: the length of the message
* key32: pointer to a 32-byte secret key (will not be NULL)
* xonly_pk32: the 32-byte serialized xonly pubkey corresponding to key32
* (will not be NULL)
* algo: pointer to an array describing the signature
* algorithm (will not be NULL)
* algolen: the length of the algo array
* data: arbitrary data pointer that is passed through
*
* Except for test cases, this function should compute some cryptographic hash of
* the message, the key, the pubkey, the algorithm description, and data.
*/
typedef int (*secp256k1_nonce_function_hardened)(
unsigned char *nonce32,
const unsigned char *msg,
size_t msglen,
const unsigned char *key32,
const unsigned char *xonly_pk32,
const unsigned char *algo,
size_t algolen,
void *data
);
/** An implementation of the nonce generation function as defined in Bitcoin
* Improvement Proposal 340 "Schnorr Signatures for secp256k1"
* (https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
*
* If a data pointer is passed, it is assumed to be a pointer to 32 bytes of
* auxiliary random data as defined in BIP-340. If the data pointer is NULL,
* the nonce derivation procedure follows BIP-340 by setting the auxiliary
* random data to zero. The algo argument must be non-NULL, otherwise the
* function will fail and return 0. The hash will be tagged with algo.
* Therefore, to create BIP-340 compliant signatures, algo must be set to
* "BIP0340/nonce" and algolen to 13.
*/
SECP256K1_API const secp256k1_nonce_function_hardened secp256k1_nonce_function_bip340;
/** Data structure that contains additional arguments for schnorrsig_sign_custom.
*
* A schnorrsig_extraparams structure object can be initialized correctly by
* setting it to SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT.
*
* Members:
* magic: set to SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC at initialization
* and has no other function than making sure the object is
* initialized.
* noncefp: pointer to a nonce generation function. If NULL,
* secp256k1_nonce_function_bip340 is used
* ndata: pointer to arbitrary data used by the nonce generation function
* (can be NULL). If it is non-NULL and
* secp256k1_nonce_function_bip340 is used, then ndata must be a
* pointer to 32-byte auxiliary randomness as per BIP-340.
*/
typedef struct secp256k1_schnorrsig_extraparams {
unsigned char magic[4];
secp256k1_nonce_function_hardened noncefp;
void *ndata;
} secp256k1_schnorrsig_extraparams;
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC { 0xda, 0x6f, 0xb3, 0x8c }
#define SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT {\
SECP256K1_SCHNORRSIG_EXTRAPARAMS_MAGIC,\
NULL,\
NULL\
}
/** Create a Schnorr signature.
*
* Does _not_ strictly follow BIP-340 because it does not verify the resulting
* signature. Instead, you can manually use secp256k1_schnorrsig_verify and
* abort if it fails.
*
* This function only signs 32-byte messages. If you have messages of a
* different size (or the same size but without a context-specific tag
* prefix), it is recommended to create a 32-byte message hash with
* secp256k1_tagged_sha256 and then sign the hash. Tagged hashing allows
* providing an context-specific tag for domain separation. This prevents
* signatures from being valid in multiple contexts by accident.
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg32: the 32-byte message being signed.
* keypair: pointer to an initialized keypair.
* aux_rand32: 32 bytes of fresh randomness. While recommended to provide
* this, it is only supplemental to security and can be NULL. A
* NULL argument is treated the same as an all-zero one. See
* BIP-340 "Default Signing" for a full explanation of this
* argument and for guidance if randomness is expensive.
*/
SECP256K1_API int secp256k1_schnorrsig_sign32(
const secp256k1_context *ctx,
unsigned char *sig64,
const unsigned char *msg32,
const secp256k1_keypair *keypair,
const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
/** Same as secp256k1_schnorrsig_sign32, but DEPRECATED. Will be removed in
* future versions. */
SECP256K1_API int secp256k1_schnorrsig_sign(
const secp256k1_context *ctx,
unsigned char *sig64,
const unsigned char *msg32,
const secp256k1_keypair *keypair,
const unsigned char *aux_rand32
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4)
SECP256K1_DEPRECATED("Use secp256k1_schnorrsig_sign32 instead");
/** Create a Schnorr signature with a more flexible API.
*
* Same arguments as secp256k1_schnorrsig_sign except that it allows signing
* variable length messages and accepts a pointer to an extraparams object that
* allows customizing signing by passing additional arguments.
*
* Equivalent to secp256k1_schnorrsig_sign32(..., aux_rand32) if msglen is 32
* and extraparams is initialized as follows:
* ```
* secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
* extraparams.ndata = (unsigned char*)aux_rand32;
* ```
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg: the message being signed. Can only be NULL if msglen is 0.
* msglen: length of the message.
* keypair: pointer to an initialized keypair.
* extraparams: pointer to an extraparams object (can be NULL).
*/
SECP256K1_API int secp256k1_schnorrsig_sign_custom(
const secp256k1_context *ctx,
unsigned char *sig64,
const unsigned char *msg,
size_t msglen,
const secp256k1_keypair *keypair,
secp256k1_schnorrsig_extraparams *extraparams
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5);
/** Verify a Schnorr signature.
*
* Returns: 1: correct signature
* 0: incorrect signature
* Args: ctx: pointer to a context object.
* In: sig64: pointer to the 64-byte signature to verify.
* msg: the message being verified. Can only be NULL if msglen is 0.
* msglen: length of the message
* pubkey: pointer to an x-only public key to verify with
*/
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify(
const secp256k1_context *ctx,
const unsigned char *sig64,
const unsigned char *msg,
size_t msglen,
const secp256k1_xonly_pubkey *pubkey
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(5);
#ifdef __cplusplus
}
#endif
#endif /* SECP256K1_SCHNORRSIG_H */

View file

@ -28,7 +28,7 @@ namespace ton {
namespace keyring {
KeyringImpl::PrivateKeyDescr::PrivateKeyDescr(PrivateKey private_key, bool is_temp)
: public_key(private_key.compute_public_key()), is_temp(is_temp) {
: public_key(private_key.compute_public_key()), private_key(private_key), is_temp(is_temp) {
auto D = private_key.create_decryptor_async();
D.ensure();
decryptor_sign = D.move_as_ok();
@ -190,6 +190,16 @@ void KeyringImpl::decrypt_message(PublicKeyHash key_hash, td::BufferSlice data,
}
}
void KeyringImpl::export_all_private_keys(td::Promise<std::vector<PrivateKey>> promise) {
std::vector<PrivateKey> keys;
for (auto& [_, descr] : map_) {
if (!descr->is_temp && descr->private_key.exportable()) {
keys.push_back(descr->private_key);
}
}
promise.set_value(std::move(keys));
}
td::actor::ActorOwn<Keyring> Keyring::create(std::string db_root) {
return td::actor::create_actor<KeyringImpl>("keyring", db_root);
}

View file

@ -44,6 +44,8 @@ class Keyring : public td::actor::Actor {
virtual void decrypt_message(PublicKeyHash key_hash, td::BufferSlice data, td::Promise<td::BufferSlice> promise) = 0;
virtual void export_all_private_keys(td::Promise<std::vector<PrivateKey>> promise) = 0;
static td::actor::ActorOwn<Keyring> create(std::string db_root);
};

View file

@ -33,6 +33,7 @@ class KeyringImpl : public Keyring {
td::actor::ActorOwn<DecryptorAsync> decryptor_sign;
td::actor::ActorOwn<DecryptorAsync> decryptor_decrypt;
PublicKey public_key;
PrivateKey private_key;
bool is_temp;
PrivateKeyDescr(PrivateKey private_key, bool is_temp);
};
@ -56,6 +57,8 @@ class KeyringImpl : public Keyring {
void decrypt_message(PublicKeyHash key_hash, td::BufferSlice data, td::Promise<td::BufferSlice> promise) override;
void export_all_private_keys(td::Promise<std::vector<PrivateKey>> promise) override;
KeyringImpl(std::string db_root) : db_root_(db_root) {
}

View file

@ -1,9 +1,10 @@
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
add_library(lite-client-common STATIC lite-client-common.cpp lite-client-common.h)
add_library(lite-client-common STATIC lite-client-common.cpp lite-client-common.h ext-client.cpp ext-client.h
query-utils.hpp query-utils.cpp)
target_link_libraries(lite-client-common PUBLIC tdactor adnllite tl_api tl_lite_api tl-lite-utils ton_crypto)
add_executable(lite-client lite-client.cpp lite-client.h)
add_executable(lite-client lite-client.cpp lite-client.h ext-client.h ext-client.cpp)
target_link_libraries(lite-client tdutils tdactor adnllite tl_api tl_lite_api tl-lite-utils terminal lite-client-common git)
install(TARGETS lite-client RUNTIME DESTINATION bin)

228
lite-client/ext-client.cpp Normal file
View file

@ -0,0 +1,228 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ext-client.h"
#include "td/utils/Random.h"
#include "ton/ton-shard.h"
namespace liteclient {
class ExtClientImpl : public ExtClient {
public:
ExtClientImpl(std::vector<LiteServerConfig> liteservers, td::unique_ptr<Callback> callback, bool connect_to_all)
: callback_(std::move(callback)), connect_to_all_(connect_to_all) {
CHECK(!liteservers.empty());
servers_.resize(liteservers.size());
for (size_t i = 0; i < servers_.size(); ++i) {
servers_[i].config = std::move(liteservers[i]);
servers_[i].idx = i;
}
}
void start_up() override {
LOG(INFO) << "Started ext client, " << servers_.size() << " liteservers";
td::Random::Fast rnd;
td::random_shuffle(td::as_mutable_span(servers_), rnd);
server_indices_.resize(servers_.size());
for (size_t i = 0; i < servers_.size(); ++i) {
server_indices_[servers_[i].idx] = i;
}
if (connect_to_all_) {
for (size_t i = 0; i < servers_.size(); ++i) {
prepare_server(i, nullptr);
}
}
}
void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
td::Promise<td::BufferSlice> promise) override {
QueryInfo query_info = get_query_info(data);
TRY_RESULT_PROMISE(promise, server_idx, select_server(query_info));
send_query_internal(std::move(name), std::move(data), std::move(query_info), server_idx, timeout,
std::move(promise));
}
void send_query_to_server(std::string name, td::BufferSlice data, size_t server_idx, td::Timestamp timeout,
td::Promise<td::BufferSlice> promise) override {
if (server_idx >= servers_.size()) {
promise.set_error(td::Status::Error(PSTRING() << "server idx " << server_idx << " is too big"));
return;
}
server_idx = server_indices_[server_idx];
QueryInfo query_info = get_query_info(data);
prepare_server(server_idx, &query_info);
send_query_internal(std::move(name), std::move(data), std::move(query_info), server_idx, timeout,
std::move(promise));
}
void get_servers_status(td::Promise<std::vector<bool>> promise) override {
std::vector<bool> status(servers_.size());
for (const Server& s : servers_) {
status[s.idx] = s.alive;
}
promise.set_result(std::move(status));
}
void reset_servers() override {
LOG(INFO) << "Force resetting all liteservers";
for (Server& server : servers_) {
server.alive = false;
server.timeout = {};
server.ignore_until = {};
server.client.reset();
}
}
private:
void send_query_internal(std::string name, td::BufferSlice data, QueryInfo query_info, size_t server_idx,
td::Timestamp timeout, td::Promise<td::BufferSlice> promise) {
auto& server = servers_[server_idx];
CHECK(!server.client.empty());
if (!connect_to_all_) {
alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT));
}
td::Promise<td::BufferSlice> P = [SelfId = actor_id(this), server_idx,
promise = std::move(promise)](td::Result<td::BufferSlice> R) mutable {
if (R.is_error() &&
(R.error().code() == ton::ErrorCode::timeout || R.error().code() == ton::ErrorCode::cancelled)) {
td::actor::send_closure(SelfId, &ExtClientImpl::on_server_error, server_idx);
}
promise.set_result(std::move(R));
};
LOG(DEBUG) << "Sending query " << query_info.to_str() << " to server #" << server.idx << " ("
<< server.config.addr.get_ip_str() << ":" << server.config.addr.get_port() << ")";
send_closure(server.client, &ton::adnl::AdnlExtClient::send_query, std::move(name), std::move(data), timeout,
std::move(P));
}
td::Result<size_t> select_server(const QueryInfo& query_info) {
for (size_t i = 0; i < servers_.size(); ++i) {
if (servers_[i].alive && servers_[i].config.accepts_query(query_info)) {
return i;
}
}
size_t server_idx = servers_.size();
int cnt = 0;
int best_priority = -1;
for (size_t i = 0; i < servers_.size(); ++i) {
Server& server = servers_[i];
if (!server.config.accepts_query(query_info)) {
continue;
}
int priority = 0;
priority += (server.ignore_until && !server.ignore_until.is_in_past() ? 0 : 10);
if (priority < best_priority) {
continue;
}
if (priority > best_priority) {
best_priority = priority;
cnt = 0;
}
if (td::Random::fast(0, cnt) == 0) {
server_idx = i;
}
++cnt;
}
if (server_idx == servers_.size()) {
return td::Status::Error(PSTRING() << "no liteserver for query " << query_info.to_str());
}
prepare_server(server_idx, &query_info);
return server_idx;
}
void prepare_server(size_t server_idx, const QueryInfo* query_info) {
Server& server = servers_[server_idx];
if (server.alive) {
return;
}
server.alive = true;
server.ignore_until = {};
if (!connect_to_all_) {
alarm_timestamp().relax(server.timeout = td::Timestamp::in(MAX_NO_QUERIES_TIMEOUT));
}
if (!server.client.empty()) {
return;
}
class Callback : public ton::adnl::AdnlExtClient::Callback {
public:
explicit Callback(td::actor::ActorId<ExtClientImpl> parent, size_t idx) : parent_(std::move(parent)), idx_(idx) {
}
void on_ready() override {
}
void on_stop_ready() override {
td::actor::send_closure(parent_, &ExtClientImpl::on_server_error, idx_);
}
private:
td::actor::ActorId<ExtClientImpl> parent_;
size_t idx_;
};
LOG(INFO) << "Connecting to liteserver #" << server.idx << " (" << server.config.addr.get_ip_str() << ":"
<< server.config.addr.get_port() << ") for query " << (query_info ? query_info->to_str() : "[none]");
server.client = ton::adnl::AdnlExtClient::create(server.config.adnl_id, server.config.addr,
std::make_unique<Callback>(actor_id(this), server_idx));
}
struct Server {
LiteServerConfig config;
size_t idx = 0;
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client;
bool alive = false;
td::Timestamp timeout = td::Timestamp::never();
td::Timestamp ignore_until = td::Timestamp::never();
};
std::vector<Server> servers_;
std::vector<size_t> server_indices_;
td::unique_ptr<Callback> callback_;
bool connect_to_all_ = false;
static constexpr double MAX_NO_QUERIES_TIMEOUT = 100.0;
static constexpr double BAD_SERVER_TIMEOUT = 30.0;
void alarm() override {
if (connect_to_all_) {
return;
}
for (Server& server : servers_) {
if (server.timeout && server.timeout.is_in_past()) {
LOG(INFO) << "Closing connection to liteserver #" << server.idx << " (" << server.config.addr.get_ip_str()
<< ":" << server.config.addr.get_port() << ")";
server.client.reset();
server.alive = false;
server.ignore_until = {};
}
}
}
void on_server_error(size_t idx) {
servers_[idx].alive = false;
servers_[idx].ignore_until = td::Timestamp::in(BAD_SERVER_TIMEOUT);
}
};
td::actor::ActorOwn<ExtClient> ExtClient::create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback) {
return create({LiteServerConfig{dst, dst_addr}}, std::move(callback));
}
td::actor::ActorOwn<ExtClient> ExtClient::create(std::vector<LiteServerConfig> liteservers,
td::unique_ptr<Callback> callback, bool connect_to_all) {
return td::actor::create_actor<ExtClientImpl>("ExtClient", std::move(liteservers), std::move(callback),
connect_to_all);
}
} // namespace liteclient

48
lite-client/ext-client.h Normal file
View file

@ -0,0 +1,48 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "td/actor/actor.h"
#include "ton/ton-types.h"
#include "adnl/adnl-ext-client.h"
#include "query-utils.hpp"
namespace liteclient {
class ExtClient : public td::actor::Actor {
public:
class Callback {
public:
virtual ~Callback() = default;
};
virtual void send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
td::Promise<td::BufferSlice> promise) = 0;
virtual void send_query_to_server(std::string name, td::BufferSlice data, size_t server_idx, td::Timestamp timeout,
td::Promise<td::BufferSlice> promise) {
promise.set_error(td::Status::Error("not supported"));
}
virtual void get_servers_status(td::Promise<std::vector<bool>> promise) {
promise.set_error(td::Status::Error("not supported"));
}
virtual void reset_servers() {
}
static td::actor::ActorOwn<ExtClient> create(ton::adnl::AdnlNodeIdFull dst, td::IPAddress dst_addr,
td::unique_ptr<Callback> callback);
static td::actor::ActorOwn<ExtClient> create(std::vector<LiteServerConfig> liteservers,
td::unique_ptr<Callback> callback, bool connect_to_all = false);
};
} // namespace liteclient

View file

@ -29,22 +29,16 @@
#include "lite-client-common.h"
#include "adnl/adnl-ext-client.h"
#include "tl-utils/lite-utils.hpp"
#include "auto/tl/ton_api_json.h"
#include "auto/tl/lite_api.hpp"
#include "td/utils/OptionParser.h"
#include "td/utils/Time.h"
#include "td/utils/filesystem.h"
#include "td/utils/format.h"
#include "td/utils/Random.h"
#include "td/utils/crypto.h"
#include "td/utils/overloaded.h"
#include "td/utils/port/signals.h"
#include "td/utils/port/stacktrace.h"
#include "td/utils/port/StdStreams.h"
#include "td/utils/port/FileFd.h"
#include "terminal/terminal.h"
#include "ton/lite-tl.hpp"
#include "block/block-db.h"
#include "block/block.h"
@ -58,18 +52,14 @@
#include "vm/vm.h"
#include "vm/cp0.h"
#include "vm/memo.h"
#include "ton/ton-shard.h"
#include "openssl/rand.hpp"
#include "crypto/vm/utils.h"
#include "crypto/common/util.h"
#include "common/checksum.h"
#if TD_DARWIN || TD_LINUX
#include <unistd.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <sstream>
#include "git.h"
using namespace std::literals::string_literals;
@ -77,24 +67,6 @@ using td::Ref;
int verbosity;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> TestNode::make_callback() {
class Callback : public ton::adnl::AdnlExtClient::Callback {
public:
void on_ready() override {
td::actor::send_closure(id_, &TestNode::conn_ready);
}
void on_stop_ready() override {
td::actor::send_closure(id_, &TestNode::conn_closed);
}
Callback(td::actor::ActorId<TestNode> id) : id_(std::move(id)) {
}
private:
td::actor::ActorId<TestNode> id_;
};
return std::make_unique<Callback>(actor_id(this));
}
void TestNode::run() {
class Cb : public td::TerminalIO::Callback {
public:
@ -110,19 +82,20 @@ void TestNode::run() {
io_ = td::TerminalIO::create("> ", readline_enabled_, ex_mode_, std::make_unique<Cb>(actor_id(this)));
td::actor::send_closure(io_, &td::TerminalIO::set_log_interface);
if (remote_public_key_.empty()) {
std::vector<liteclient::LiteServerConfig> servers;
if (!single_remote_public_key_.empty()) { // Use single provided liteserver
servers.push_back(
liteclient::LiteServerConfig{ton::adnl::AdnlNodeIdFull{single_remote_public_key_}, single_remote_addr_});
td::TerminalIO::out() << "using liteserver " << single_remote_addr_ << "\n";
} else {
auto G = td::read_file(global_config_).move_as_ok();
auto gc_j = td::json_decode(G.as_slice()).move_as_ok();
ton::ton_api::liteclient_config_global gc;
ton::ton_api::from_json(gc, gc_j.get_object()).ensure();
CHECK(gc.liteservers_.size() > 0);
auto idx = liteserver_idx_ >= 0 ? liteserver_idx_
: td::Random::fast(0, static_cast<td::uint32>(gc.liteservers_.size() - 1));
CHECK(idx >= 0 && static_cast<td::uint32>(idx) <= gc.liteservers_.size());
auto& cli = gc.liteservers_[idx];
remote_addr_.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure();
remote_public_key_ = ton::PublicKey{cli->id_};
td::TerminalIO::out() << "using liteserver " << idx << " with addr " << remote_addr_ << "\n";
auto r_servers = liteclient::LiteServerConfig::parse_global_config(gc);
r_servers.ensure();
servers = r_servers.move_as_ok();
if (gc.validator_ && gc.validator_->zero_state_) {
zstate_id_.workchain = gc.validator_->zero_state_->workchain_;
if (zstate_id_.workchain != ton::workchainInvalid) {
@ -131,10 +104,19 @@ void TestNode::run() {
td::TerminalIO::out() << "zerostate set to " << zstate_id_.to_str() << "\n";
}
}
}
client_ =
ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull{remote_public_key_}, remote_addr_, make_callback());
if (single_liteserver_idx_ != -1) { // Use single liteserver from config
CHECK(single_liteserver_idx_ >= 0 && (size_t)single_liteserver_idx_ < servers.size());
td::TerminalIO::out() << "using liteserver #" << single_liteserver_idx_ << " with addr "
<< servers[single_liteserver_idx_].addr << "\n";
servers = {servers[single_liteserver_idx_]};
}
}
CHECK(!servers.empty());
client_ = liteclient::ExtClient::create(std::move(servers), nullptr);
ready_ = true;
run_init_queries();
}
void TestNode::got_result(td::Result<td::BufferSlice> R, td::Promise<td::BufferSlice> promise) {
@ -191,8 +173,8 @@ bool TestNode::envelope_send_query(td::BufferSlice query, td::Promise<td::Buffer
});
td::BufferSlice b =
ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_query>(std::move(query)), true);
td::actor::send_closure(client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b),
td::Timestamp::in(10.0), std::move(P));
td::actor::send_closure(client_, &liteclient::ExtClient::send_query, "query", std::move(b), td::Timestamp::in(10.0),
std::move(P));
return true;
}
@ -319,9 +301,10 @@ bool TestNode::get_server_time() {
if (F.is_error()) {
LOG(ERROR) << "cannot parse answer to liteServer.getTime";
} else {
server_time_ = F.move_as_ok()->now_;
server_time_got_at_ = now();
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")";
mc_server_time_ = F.move_as_ok()->now_;
mc_server_time_got_at_ = now();
LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_
<< ")";
}
}
});
@ -335,7 +318,7 @@ bool TestNode::get_server_version(int mode) {
};
void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
server_ok_ = false;
mc_server_ok_ = false;
if (res.is_error()) {
LOG(ERROR) << "cannot get server version and time (server too old?)";
} else {
@ -344,11 +327,11 @@ void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
LOG(ERROR) << "cannot parse answer to liteServer.getVersion";
} else {
auto a = F.move_as_ok();
set_server_version(a->version_, a->capabilities_);
set_server_time(a->now_);
set_mc_server_version(a->version_, a->capabilities_);
set_mc_server_time(a->now_);
}
}
if (!server_ok_) {
if (!mc_server_ok_) {
LOG(ERROR) << "server version is too old (at least " << (min_ls_version >> 8) << "." << (min_ls_version & 0xff)
<< " with capabilities " << min_ls_capabilities << " required), some queries are unavailable";
}
@ -357,24 +340,24 @@ void TestNode::got_server_version(td::Result<td::BufferSlice> res, int mode) {
}
}
void TestNode::set_server_version(td::int32 version, td::int64 capabilities) {
if (server_version_ != version || server_capabilities_ != capabilities) {
server_version_ = version;
server_capabilities_ = capabilities;
LOG(WARNING) << "server version is " << (server_version_ >> 8) << "." << (server_version_ & 0xff)
<< ", capabilities " << server_capabilities_;
void TestNode::set_mc_server_version(td::int32 version, td::int64 capabilities) {
if (mc_server_version_ != version || mc_server_capabilities_ != capabilities) {
mc_server_version_ = version;
mc_server_capabilities_ = capabilities;
LOG(WARNING) << "server version is " << (mc_server_version_ >> 8) << "." << (mc_server_version_ & 0xff)
<< ", capabilities " << mc_server_capabilities_;
}
server_ok_ = (server_version_ >= min_ls_version) && !(~server_capabilities_ & min_ls_capabilities);
mc_server_ok_ = (mc_server_version_ >= min_ls_version) && !(~mc_server_capabilities_ & min_ls_capabilities);
}
void TestNode::set_server_time(int server_utime) {
server_time_ = server_utime;
server_time_got_at_ = now();
LOG(INFO) << "server time is " << server_time_ << " (delta " << server_time_ - server_time_got_at_ << ")";
void TestNode::set_mc_server_time(int server_utime) {
mc_server_time_ = server_utime;
mc_server_time_got_at_ = now();
LOG(INFO) << "server time is " << mc_server_time_ << " (delta " << mc_server_time_ - mc_server_time_got_at_ << ")";
}
bool TestNode::get_server_mc_block_id() {
int mode = (server_capabilities_ & 2) ? 0 : -1;
int mode = (mc_server_capabilities_ & 2) ? 0 : -1;
if (mode < 0) {
auto b = ton::serialize_tl_object(ton::create_tl_object<ton::lite_api::liteServer_getMasterchainInfo>(), true);
return envelope_send_query(std::move(b), [Self = actor_id(this)](td::Result<td::BufferSlice> res) -> void {
@ -448,8 +431,8 @@ void TestNode::got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt
void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version,
long long capabilities, int last_utime, int server_now) {
set_server_version(version, capabilities);
set_server_time(server_now);
set_mc_server_version(version, capabilities);
set_mc_server_time(server_now);
if (last_utime > server_now) {
LOG(WARNING) << "server claims to have a masterchain block " << blkid.to_str() << " created at " << last_utime
<< " (" << last_utime - server_now << " seconds in the future)";
@ -457,10 +440,10 @@ void TestNode::got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateI
LOG(WARNING) << "server appears to be out of sync: its newest masterchain block is " << blkid.to_str()
<< " created at " << last_utime << " (" << server_now - last_utime
<< " seconds ago according to the server's clock)";
} else if (last_utime < server_time_got_at_ - 60) {
} else if (last_utime < mc_server_time_got_at_ - 60) {
LOG(WARNING) << "either the server is out of sync, or the local clock is set incorrectly: the newest masterchain "
"block known to server is "
<< blkid.to_str() << " created at " << last_utime << " (" << server_now - server_time_got_at_
<< blkid.to_str() << " created at " << last_utime << " (" << server_now - mc_server_time_got_at_
<< " seconds ago according to the local clock)";
}
got_server_mc_block_id(blkid, zstateid, last_utime);

View file

@ -26,6 +26,7 @@
Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "ext-client.h"
#include "adnl/adnl-ext-client.h"
#include "tl-utils/tl-utils.hpp"
#include "ton/ton-types.h"
@ -46,22 +47,24 @@ class TestNode : public td::actor::Actor {
min_ls_version = 0x101,
min_ls_capabilities = 1
}; // server version >= 1.1, capabilities at least +1 = build proof chains
td::actor::ActorOwn<ton::adnl::AdnlExtClient> client_;
td::actor::ActorOwn<liteclient::ExtClient> client_;
td::actor::ActorOwn<td::TerminalIO> io_;
bool ready_ = false;
td::int32 single_liteserver_idx_ = -1;
td::IPAddress single_remote_addr_;
ton::PublicKey single_remote_public_key_;
bool readline_enabled_ = true;
bool server_ok_ = false;
td::int32 liteserver_idx_ = -1;
int print_limit_ = 1024;
bool ready_ = false;
bool inited_ = false;
std::string db_root_;
int server_time_ = 0;
int server_time_got_at_ = 0;
int server_version_ = 0;
long long server_capabilities_ = 0;
int mc_server_time_ = 0;
int mc_server_time_got_at_ = 0;
int mc_server_version_ = 0;
long long mc_server_capabilities_ = 0;
bool mc_server_ok_ = false;
ton::ZeroStateIdExt zstate_id_;
ton::BlockIdExt mc_last_id_;
@ -76,9 +79,6 @@ class TestNode : public td::actor::Actor {
const char *parse_ptr_, *parse_end_;
td::Status error_;
td::IPAddress remote_addr_;
ton::PublicKey remote_public_key_;
std::vector<ton::BlockIdExt> known_blk_ids_;
std::size_t shown_blk_ids_ = 0;
@ -89,8 +89,6 @@ class TestNode : public td::actor::Actor {
std::map<td::Bits256, Ref<vm::Cell>> cell_cache_;
std::unique_ptr<ton::adnl::AdnlExtClient::Callback> make_callback();
using creator_stats_func_t =
std::function<bool(const td::Bits256&, const block::DiscountedCounter&, const block::DiscountedCounter&)>;
@ -183,8 +181,8 @@ class TestNode : public td::actor::Actor {
void got_server_mc_block_id(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int created_at);
void got_server_mc_block_id_ext(ton::BlockIdExt blkid, ton::ZeroStateIdExt zstateid, int mode, int version,
long long capabilities, int last_utime, int server_now);
void set_server_version(td::int32 version, td::int64 capabilities);
void set_server_time(int server_utime);
void set_mc_server_version(td::int32 version, td::int64 capabilities);
void set_mc_server_time(int server_utime);
bool request_block(ton::BlockIdExt blkid);
bool request_state(ton::BlockIdExt blkid);
void got_mc_block(ton::BlockIdExt blkid, td::BufferSlice data);
@ -370,9 +368,6 @@ class TestNode : public td::actor::Actor {
bool parse_shard_id(ton::ShardIdFull& shard);
bool parse_block_id_ext(ton::BlockIdExt& blkid, bool allow_incomplete = false);
bool parse_block_id_ext(std::string blk_id_string, ton::BlockIdExt& blkid, bool allow_incomplete = false) const;
bool parse_stack_value(td::Slice str, vm::StackEntry& value);
bool parse_stack_value(vm::StackEntry& value);
bool parse_stack_values(std::vector<vm::StackEntry>& values);
bool register_blkid(const ton::BlockIdExt& blkid);
bool show_new_blkids(bool all = false);
bool complete_blkid(ton::BlockId partial_blkid, ton::BlockIdExt& complete_blkid) const;
@ -391,16 +386,6 @@ class TestNode : public td::actor::Actor {
static const tlb::TypenameLookup& get_tlb_dict();
public:
void conn_ready() {
LOG(ERROR) << "conn ready";
ready_ = true;
if (!inited_) {
run_init_queries();
}
}
void conn_closed() {
ready_ = false;
}
void set_global_config(std::string str) {
global_config_ = str;
}
@ -411,10 +396,10 @@ class TestNode : public td::actor::Actor {
readline_enabled_ = value;
}
void set_liteserver_idx(td::int32 idx) {
liteserver_idx_ = idx;
single_liteserver_idx_ = idx;
}
void set_remote_addr(td::IPAddress addr) {
remote_addr_ = addr;
single_remote_addr_ = addr;
}
void set_public_key(td::BufferSlice file_name) {
auto R = [&]() -> td::Result<ton::PublicKey> {
@ -425,7 +410,7 @@ class TestNode : public td::actor::Actor {
if (R.is_error()) {
LOG(FATAL) << "bad server public key: " << R.move_as_error();
}
remote_public_key_ = R.move_as_ok();
single_remote_public_key_ = R.move_as_ok();
}
void decode_public_key(td::BufferSlice b64_key) {
auto R = [&]() -> td::Result<ton::PublicKey> {
@ -437,7 +422,7 @@ class TestNode : public td::actor::Actor {
if (R.is_error()) {
LOG(FATAL) << "bad b64 server public key: " << R.move_as_error();
}
remote_public_key_ = R.move_as_ok();
single_remote_public_key_ = R.move_as_ok();
}
void set_fail_timeout(td::Timestamp ts) {
fail_timeout_ = ts;
@ -475,8 +460,7 @@ class TestNode : public td::actor::Actor {
bool envelope_send_query(td::BufferSlice query, td::Promise<td::BufferSlice> promise);
void parse_line(td::BufferSlice data);
TestNode() {
}
TestNode() = default;
void run();
};

400
lite-client/query-utils.cpp Normal file
View file

@ -0,0 +1,400 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "query-utils.hpp"
#include "block-parse.h"
#include "td/utils/overloaded.h"
#include "tl-utils/common-utils.hpp"
#include "block/block-auto.h"
#include "auto/tl/lite_api.hpp"
#include "overlay/overlay-broadcast.hpp"
#include "tl-utils/lite-utils.hpp"
#include "ton/lite-tl.hpp"
#include "ton/ton-shard.h"
#include <ton/ton-tl.hpp>
namespace liteclient {
using namespace ton;
std::string QueryInfo::to_str() const {
td::StringBuilder sb;
sb << "[ " << lite_query_name_by_id(query_id) << " " << shard_id.to_str();
switch (type) {
case t_simple:
break;
case t_seqno:
sb << " seqno=" << value;
break;
case t_utime:
sb << " utime=" << value;
break;
case t_lt:
sb << " lt=" << value;
break;
case t_mc_seqno:
sb << " mc_seqno=" << value;
break;
}
sb << " ]";
return sb.as_cslice().str();
}
QueryInfo get_query_info(td::Slice data) {
auto F = fetch_tl_object<lite_api::liteServer_query>(data, true);
if (F.is_ok()) {
data = F.ok()->data_;
} else {
fetch_tl_prefix<lite_api::liteServer_queryPrefix>(data, true).ignore();
}
fetch_tl_prefix<lite_api::liteServer_waitMasterchainSeqno>(data, true).ignore();
auto Q = fetch_tl_object<lite_api::Function>(data, true);
if (Q.is_error()) {
return {};
}
return get_query_info(*Q.ok());
}
QueryInfo get_query_info(const lite_api::Function& f) {
QueryInfo info;
info.query_id = f.get_id();
auto from_block_id = [&](const tl_object_ptr<lite_api::tonNode_blockIdExt>& id) {
BlockIdExt block_id = create_block_id(id);
info.shard_id = block_id.shard_full();
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno();
};
downcast_call(
const_cast<lite_api::Function&>(f),
td::overloaded([&](const lite_api::liteServer_getTime& q) { /* t_simple */ },
[&](const lite_api::liteServer_getVersion& q) { /* t_simple */ },
[&](const lite_api::liteServer_getMasterchainInfo& q) { /* t_simple */ },
[&](const lite_api::liteServer_getMasterchainInfoExt& q) { /* t_simple */ },
[&](const lite_api::liteServer_getBlock& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getBlockHeader& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getState& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getAccountState& q) {
BlockIdExt block_id = create_block_id(q.id_);
AccountIdPrefixFull acc_id_prefix = extract_addr_prefix(q.account_->workchain_, q.account_->id_);
info.shard_id = acc_id_prefix.as_leaf_shard();
// See LiteQuery::perform_getAccountState
if (block_id.id.workchain != masterchainId) {
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno();
} else if (block_id.id.seqno != ~0U) {
info.type = QueryInfo::t_mc_seqno;
info.value = block_id.seqno();
} else {
info.type = QueryInfo::t_simple;
}
},
[&](const lite_api::liteServer_getAccountStatePrunned& q) {
BlockIdExt block_id = create_block_id(q.id_);
AccountIdPrefixFull acc_id_prefix = extract_addr_prefix(q.account_->workchain_, q.account_->id_);
info.shard_id = acc_id_prefix.as_leaf_shard();
// See LiteQuery::perform_getAccountState
if (block_id.id.workchain != masterchainId) {
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno();
} else if (block_id.id.seqno != ~0U) {
info.type = QueryInfo::t_mc_seqno;
info.value = block_id.seqno();
} else {
info.type = QueryInfo::t_simple;
}
},
[&](const lite_api::liteServer_getOneTransaction& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getTransactions& q) {
AccountIdPrefixFull acc_id_prefix = extract_addr_prefix(q.account_->workchain_, q.account_->id_);
info.shard_id = acc_id_prefix.as_leaf_shard();
info.type = QueryInfo::t_lt;
info.value = q.lt_;
},
[&](const lite_api::liteServer_sendMessage& q) {
info.type = QueryInfo::t_simple;
auto r_root = vm::std_boc_deserialize(q.body_);
if (r_root.is_error()) {
return;
}
block::gen::CommonMsgInfo::Record_ext_in_msg_info msg_info;
if (!tlb::unpack_cell_inexact(r_root.ok(), msg_info)) {
return;
}
auto dest_prefix = block::tlb::MsgAddressInt::get_prefix(msg_info.dest);
if (!dest_prefix.is_valid()) {
return;
}
info.shard_id = dest_prefix.as_leaf_shard();
},
[&](const lite_api::liteServer_getShardInfo& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getAllShardsInfo& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_lookupBlock& q) {
BlockId block_id = create_block_id_simple(q.id_);
info.shard_id = block_id.shard_full();
// See LiteQuery::perform_lookupBlock
if (q.mode_ & 1) {
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno;
} else if (q.mode_ == 2) {
info.type = QueryInfo::t_lt;
info.value = q.lt_;
} else if (q.mode_ == 4) {
info.type = QueryInfo::t_utime;
info.value = q.utime_;
}
},
[&](const lite_api::liteServer_lookupBlockWithProof& q) {
BlockId block_id = create_block_id_simple(q.id_);
info.shard_id = block_id.shard_full();
// See LiteQuery::perform_lookupBlockWithProof
if (q.mode_ & 1) {
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno;
} else if (q.mode_ == 2) {
info.type = QueryInfo::t_lt;
info.value = q.lt_;
} else if (q.mode_ == 4) {
info.type = QueryInfo::t_utime;
info.value = q.utime_;
}
},
[&](const lite_api::liteServer_listBlockTransactions& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_listBlockTransactionsExt& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getConfigParams& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getConfigAll& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getBlockProof& q) {
info.shard_id = ShardIdFull{masterchainId};
BlockIdExt from = create_block_id(q.known_block_);
// See LiteQuery::perform_getBlockProof
if ((q.mode_ & 1) && (q.mode_ & 0x1000)) {
BlockIdExt to = create_block_id(q.target_block_); // target_block is non-null if (mode & 1)
info.type = QueryInfo::t_seqno;
info.value = std::max(from.seqno(), to.seqno());
} else {
info.type = QueryInfo::t_simple;
}
},
[&](const lite_api::liteServer_getValidatorStats& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_runSmcMethod& q) {
BlockIdExt block_id = create_block_id(q.id_);
AccountIdPrefixFull acc_id_prefix = extract_addr_prefix(q.account_->workchain_, q.account_->id_);
info.shard_id = acc_id_prefix.as_leaf_shard();
// See LiteQuery::perform_getAccountState
if (block_id.id.workchain != masterchainId) {
info.type = QueryInfo::t_seqno;
info.value = block_id.seqno();
} else if (block_id.id.seqno != ~0U) {
info.type = QueryInfo::t_mc_seqno;
info.value = block_id.seqno();
} else {
info.type = QueryInfo::t_simple;
}
},
[&](const lite_api::liteServer_getLibraries& q) { /* t_simple */ },
[&](const lite_api::liteServer_getLibrariesWithProof& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getShardBlockProof& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_nonfinal_getCandidate& q) { /* t_simple */ },
[&](const lite_api::liteServer_nonfinal_getValidatorGroups& q) { /* t_simple */ },
[&](const lite_api::liteServer_getOutMsgQueueSizes& q) {
// This query is expected to be removed, as it is not fully compatible with separated liteservers
/* t_simple */
},
[&](const lite_api::liteServer_getBlockOutMsgQueueSize& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getDispatchQueueInfo& q) { from_block_id(q.id_); },
[&](const lite_api::liteServer_getDispatchQueueMessages& q) { from_block_id(q.id_); },
[&](const auto&) { /* t_simple */ }));
if (info.shard_id.workchain == masterchainId) {
info.shard_id.shard = shardIdAll;
}
if (!info.shard_id.is_valid_ext()) {
info.shard_id = ShardIdFull{masterchainId};
info.type = QueryInfo::t_simple;
info.value = 0;
}
return info;
}
bool LiteServerConfig::accepts_query(const QueryInfo& query_info) const {
if (is_full) {
return true;
}
for (const Slice& s : slices) {
if (s.accepts_query(query_info)) {
return true;
}
}
return false;
}
bool LiteServerConfig::Slice::accepts_query(const QueryInfo& query_info) const {
if (unlimited) {
for (const ShardInfo& shard : shards_from) {
if (shard_intersects(shard.shard_id, query_info.shard_id)) {
return true;
}
}
return false;
}
if (!shards_from.empty()) {
bool from_ok = false;
DCHECK(shards_from[0].shard_id.is_masterchain());
for (const ShardInfo& shard : shards_from) {
if (shard_intersects(shard.shard_id, query_info.shard_id)) {
switch (query_info.type) {
case QueryInfo::t_simple:
from_ok = true;
break;
case QueryInfo::t_seqno:
from_ok = shard.seqno <= query_info.value;
break;
case QueryInfo::t_utime:
from_ok = shard.utime <= query_info.value;
break;
case QueryInfo::t_lt:
from_ok = shard.lt <= query_info.value;
break;
case QueryInfo::t_mc_seqno:
from_ok = shards_from[0].seqno <= query_info.value;
break;
}
if (from_ok) {
break;
}
}
}
if (!from_ok) {
return false;
}
}
if (!shards_to.empty()) {
bool to_ok = false;
DCHECK(shards_to[0].shard_id.is_masterchain());
for (const ShardInfo& shard : shards_to) {
if (shard_intersects(shard.shard_id, query_info.shard_id)) {
switch (query_info.type) {
case QueryInfo::t_simple:
break;
case QueryInfo::t_seqno:
to_ok = shard.seqno >= query_info.value;
break;
case QueryInfo::t_utime:
to_ok = shard.utime >= query_info.value;
break;
case QueryInfo::t_lt:
to_ok = shard.lt >= query_info.value;
break;
case QueryInfo::t_mc_seqno:
to_ok = shards_from[0].seqno >= query_info.value;
break;
}
if (to_ok) {
break;
}
}
}
if (!to_ok) {
return false;
}
}
return true;
}
td::Result<std::vector<LiteServerConfig>> LiteServerConfig::parse_global_config(
const ton_api::liteclient_config_global& config) {
std::vector<LiteServerConfig> servers;
for (const auto& f : config.liteservers_) {
LiteServerConfig server;
TRY_STATUS(server.addr.init_host_port(td::IPAddress::ipv4_to_str(f->ip_), f->port_));
server.adnl_id = adnl::AdnlNodeIdFull{PublicKey{f->id_}};
server.is_full = true;
servers.push_back(std::move(server));
}
for (const auto& f : config.liteservers_v2_) {
LiteServerConfig server;
TRY_STATUS(server.addr.init_host_port(td::IPAddress::ipv4_to_str(f->ip_), f->port_));
server.adnl_id = adnl::AdnlNodeIdFull{PublicKey{f->id_}};
server.is_full = false;
for (const auto& slice_obj : f->slices_) {
Slice slice;
td::Status S = td::Status::OK();
downcast_call(*slice_obj,
td::overloaded(
[&](const ton_api::liteserver_descV2_sliceSimple& s) {
slice.unlimited = true;
slice.shards_from.push_back({ShardIdFull{masterchainId}, 0, 0, 0});
for (const auto& shard_obj : s.shards_) {
ShardIdFull shard_id = create_shard_id(shard_obj);
if (!shard_id.is_valid_ext()) {
S = td::Status::Error(PSTRING() << "invalid shard id " << shard_id.to_str());
break;
}
if (!shard_id.is_masterchain()) {
slice.shards_from.push_back({shard_id, 0, 0, 0});
}
}
},
[&](const ton_api::liteserver_descV2_sliceTimed& s) {
auto parse_shards =
[](const std::vector<tl_object_ptr<ton_api::liteserver_descV2_shardInfo>>& shard_objs,
std::vector<ShardInfo>& shards) -> td::Status {
if (shard_objs.empty()) {
return td::Status::OK();
}
size_t i = 0;
int mc_idx = -1;
for (const auto& shard_obj : shard_objs) {
ShardIdFull shard_id = create_shard_id(shard_obj->shard_id_);
if (!shard_id.is_valid_ext()) {
return td::Status::Error(PSTRING() << "invalid shard id " << shard_id.to_str());
}
if (shard_id.is_masterchain()) {
shard_id = ShardIdFull{masterchainId};
if (mc_idx != -1) {
return td::Status::Error("duplicate masterchain shard in sliceTimed");
}
mc_idx = (int)i;
}
shards.push_back({shard_id, (BlockSeqno)shard_obj->seqno_, (UnixTime)shard_obj->utime_,
(LogicalTime)shard_obj->lt_});
++i;
}
if (mc_idx == -1) {
return td::Status::Error("no masterchain shard in sliceTimed");
}
std::swap(shards[0], shards[mc_idx]);
return td::Status::OK();
};
S = parse_shards(s.shards_from_, slice.shards_from);
if (S.is_ok()) {
S = parse_shards(s.shards_to_, slice.shards_to);
}
if (S.is_ok() && slice.shards_from.empty() && slice.shards_to.empty()) {
S = td::Status::Error("shards_from and shards_to are both empty");
}
}));
TRY_STATUS(std::move(S));
server.slices.push_back(slice);
}
servers.push_back(std::move(server));
}
return servers;
}
} // namespace liteclient

View file

@ -0,0 +1,89 @@
/*
This file is part of TON Blockchain Library.
TON Blockchain Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
TON Blockchain Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "ton/ton-types.h"
#include "auto/tl/lite_api.h"
#include "td/utils/port/IPAddress.h"
#include "adnl/adnl-node-id.hpp"
namespace liteclient {
struct QueryInfo {
enum Type { t_simple, t_seqno, t_utime, t_lt, t_mc_seqno };
int query_id = 0;
ton::ShardIdFull shard_id{ton::masterchainId};
Type type = t_simple;
td::uint64 value = 0;
/* Query types and examples:
* t_simple - query to the recent blocks in a shard, or general info. value = 0.
* getTime, getMasterchainInfo (shard_id = masterchain)
* sendMessage
* getAccountState, runSmcMethod - when no block is given
* t_seqno - query to block with seqno in a shard. value = seqno.
* lookupBlock by seqno
* getBlock, getBlockHeader
* getAccountState, runSmcMethod - when shard block is given
* t_utime - query to a block with given unixtime in a shard. value = utime.
* lookupBlock by utime
* t_lt - query to a block with given lt in a shard. value = lt.
* lookupBlock by lt
* getTransactions
* t_mc_seqno - query to a block in a shard, masterchain seqno is given. value = mc_seqno.
* getAccountState, runSmcMethod - when mc block is given
*/
std::string to_str() const;
};
QueryInfo get_query_info(td::Slice data);
QueryInfo get_query_info(const ton::lite_api::Function& f);
struct LiteServerConfig {
private:
struct ShardInfo {
ton::ShardIdFull shard_id;
ton::BlockSeqno seqno;
ton::UnixTime utime;
ton::LogicalTime lt;
};
struct Slice {
std::vector<ShardInfo> shards_from, shards_to;
bool unlimited = false;
bool accepts_query(const QueryInfo& query_info) const;
};
bool is_full = false;
std::vector<Slice> slices;
public:
ton::adnl::AdnlNodeIdFull adnl_id;
td::IPAddress addr;
LiteServerConfig() = default;
LiteServerConfig(ton::adnl::AdnlNodeIdFull adnl_id, td::IPAddress addr)
: is_full(true), adnl_id(adnl_id), addr(addr) {
}
bool accepts_query(const QueryInfo& query_info) const;
static td::Result<std::vector<LiteServerConfig>> parse_global_config(
const ton::ton_api::liteclient_config_global& config);
};
} // namespace liteclient

View file

@ -68,6 +68,9 @@ void OverlayManager::register_overlay(adnl::AdnlNodeIdShort local_id, OverlayIdS
}
overlays_[local_id][overlay_id] = OverlayDescription{std::move(overlay), std::move(cert)};
if (!with_db_) {
return;
}
auto P =
td::PromiseCreator::lambda([id = overlays_[local_id][overlay_id].overlay.get()](td::Result<DbType::GetResult> R) {
R.ensure();
@ -417,13 +420,19 @@ OverlayManager::OverlayManager(std::string db_root, td::actor::ActorId<keyring::
}
void OverlayManager::start_up() {
std::shared_ptr<td::KeyValue> kv =
std::make_shared<td::RocksDb>(td::RocksDb::open(PSTRING() << db_root_ << "/overlays").move_as_ok());
db_ = DbType{std::move(kv)};
if (!db_root_.empty()) {
with_db_ = true;
std::shared_ptr<td::KeyValue> kv =
std::make_shared<td::RocksDb>(td::RocksDb::open(PSTRING() << db_root_ << "/overlays").move_as_ok());
db_ = DbType{std::move(kv)};
}
}
void OverlayManager::save_to_db(adnl::AdnlNodeIdShort local_id, OverlayIdShort overlay_id,
std::vector<OverlayNode> nodes) {
if (!with_db_) {
return;
}
std::vector<tl_object_ptr<ton_api::overlay_node>> nodes_vec;
for (auto &n : nodes) {
nodes_vec.push_back(n.tl());
@ -564,7 +573,7 @@ td::Result<std::shared_ptr<Certificate>> Certificate::create(tl_object_ptr<ton_a
}
BroadcastCheckResult Certificate::check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time,
td::uint32 size, bool is_fec) const {
td::uint32 size, bool is_fec, bool skip_check_signature) const {
if (size > max_size_) {
return BroadcastCheckResult::Forbidden;
}
@ -575,16 +584,16 @@ BroadcastCheckResult Certificate::check(PublicKeyHash node, OverlayIdShort overl
return BroadcastCheckResult::Forbidden;
}
auto R1 = issued_by_.get<PublicKey>().create_encryptor();
if (R1.is_error()) {
return BroadcastCheckResult::Forbidden;
}
auto E = R1.move_as_ok();
auto B = to_sign(overlay_id, node);
if (E->check_signature(B.as_slice(), signature_.as_slice()).is_error()) {
return BroadcastCheckResult::Forbidden;
if (!skip_check_signature) {
auto R1 = issued_by_.get<PublicKey>().create_encryptor();
if (R1.is_error()) {
return BroadcastCheckResult::Forbidden;
}
auto E = R1.move_as_ok();
auto B = to_sign(overlay_id, node);
if (E->check_signature(B.as_slice(), signature_.as_slice()).is_error()) {
return BroadcastCheckResult::Forbidden;
}
}
return (flags_ & CertificateFlags::Trusted) ? BroadcastCheckResult::Allowed : BroadcastCheckResult::NeedCheck;

View file

@ -131,6 +131,7 @@ class OverlayManager : public Overlays {
td::actor::ActorId<dht::Dht> dht_node_;
using DbType = td::KeyValueAsync<td::Bits256, td::BufferSlice>;
bool with_db_ = false;
DbType db_;
class AdnlCallback : public adnl::Adnl::Callback {

View file

@ -213,7 +213,7 @@ void OverlayImpl::add_peer(OverlayNode node) {
peer_list_.peers_.insert(id, OverlayPeer(std::move(node)));
del_some_peers();
auto X = peer_list_.peers_.get(id);
if (X != nullptr && peer_list_.neighbours_.size() < max_neighbours() &&
if (X != nullptr && !X->is_neighbour() && peer_list_.neighbours_.size() < max_neighbours() &&
!(X->get_node()->flags() & OverlayMemberFlags::DoNotReceiveBroadcasts) && X->get_id() != local_id_) {
peer_list_.neighbours_.push_back(X->get_id());
X->set_neighbour(true);
@ -440,7 +440,7 @@ void OverlayImpl::update_neighbours(td::uint32 nodes_to_change) {
VLOG(OVERLAY_INFO) << this << ": adding new neighbour " << X->get_id();
peer_list_.neighbours_.push_back(X->get_id());
X->set_neighbour(true);
} else {
} else if (X->is_alive()) {
CHECK(nodes_to_change > 0);
auto i = td::Random::fast(0, static_cast<td::uint32>(peer_list_.neighbours_.size()) - 1);
auto Y = peer_list_.peers_.get(peer_list_.neighbours_[i]);

View file

@ -347,7 +347,12 @@ void OverlayImpl::alarm() {
update_db_at_ = td::Timestamp::in(60.0);
}
update_neighbours(0);
if (update_neighbours_at_.is_in_past()) {
update_neighbours(2);
update_neighbours_at_ = td::Timestamp::in(td::Random::fast(30.0, 120.0));
} else {
update_neighbours(0);
}
alarm_timestamp() = td::Timestamp::in(1.0);
} else {
update_neighbours(0);
@ -503,37 +508,44 @@ td::Status OverlayImpl::check_date(td::uint32 date) {
return td::Status::OK();
}
BroadcastCheckResult OverlayImpl::check_source_eligible(const PublicKeyHash &source, const Certificate *cert,
BroadcastCheckResult OverlayImpl::check_source_eligible(const PublicKeyHash& source, const Certificate* cert,
td::uint32 size, bool is_fec) {
if (size == 0) {
return BroadcastCheckResult::Forbidden;
}
auto r = rules_.check_rules(source, size, is_fec);
if (!cert || r == BroadcastCheckResult::Allowed) {
return r;
}
td::Bits256 cert_hash = get_tl_object_sha_bits256(cert->tl());
auto cached_cert = checked_certificates_cache_.find(source);
bool cached = cached_cert != checked_certificates_cache_.end() && cached_cert->second->cert_hash == cert_hash;
auto r2 = cert->check(source, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec);
auto r2 = cert->check(source, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec,
/* skip_check_signature = */ cached);
if (r2 != BroadcastCheckResult::Forbidden) {
if (cached_cert == checked_certificates_cache_.end()) {
cached_cert = checked_certificates_cache_.emplace(
source, std::make_unique<CachedCertificate>(source, cert_hash)).first;
} else {
cached_cert->second->cert_hash = cert_hash;
cached_cert->second->remove();
}
checked_certificates_cache_lru_.put(cached_cert->second.get());
while (checked_certificates_cache_.size() > max_checked_certificates_cache_size_) {
auto to_remove = (CachedCertificate*)checked_certificates_cache_lru_.get();
CHECK(to_remove);
to_remove->remove();
checked_certificates_cache_.erase(to_remove->source);
}
}
r2 = broadcast_check_result_min(r2, rules_.check_rules(cert->issuer_hash(), size, is_fec));
return broadcast_check_result_max(r, r2);
}
BroadcastCheckResult OverlayImpl::check_source_eligible(PublicKey source, const Certificate *cert, td::uint32 size,
BroadcastCheckResult OverlayImpl::check_source_eligible(PublicKey source, const Certificate* cert, td::uint32 size,
bool is_fec) {
if (size == 0) {
return BroadcastCheckResult::Forbidden;
}
auto short_id = source.compute_short_id();
auto r = rules_.check_rules(short_id, size, is_fec);
if (!cert || r == BroadcastCheckResult::Allowed) {
return r;
}
auto r2 = cert->check(short_id, overlay_id_, static_cast<td::int32>(td::Clocks::system()), size, is_fec);
r2 = broadcast_check_result_min(r2, rules_.check_rules(cert->issuer_hash(), size, is_fec));
return broadcast_check_result_max(r, r2);
return check_source_eligible(source.compute_short_id(), cert, size, is_fec);
}
td::Status OverlayImpl::check_delivered(BroadcastHash hash) {

View file

@ -391,6 +391,7 @@ class OverlayImpl : public Overlay {
td::Timestamp next_dht_store_query_ = td::Timestamp::in(1.0);
td::Timestamp update_db_at_;
td::Timestamp update_throughput_at_;
td::Timestamp update_neighbours_at_;
td::Timestamp last_throughput_update_;
std::unique_ptr<Overlays::Callback> callback_;
@ -466,6 +467,19 @@ class OverlayImpl : public Overlay {
TrafficStats total_traffic_responses, total_traffic_responses_ctr;
OverlayOptions opts_;
struct CachedCertificate : td::ListNode {
CachedCertificate(PublicKeyHash source, td::Bits256 cert_hash)
: source(source)
, cert_hash(cert_hash) {
}
PublicKeyHash source;
td::Bits256 cert_hash;
};
std::map<PublicKeyHash, std::unique_ptr<CachedCertificate>> checked_certificates_cache_;
td::ListNode checked_certificates_cache_lru_;
size_t max_checked_certificates_cache_size_ = 1000;
};
} // namespace overlay

View file

@ -149,7 +149,7 @@ class Certificate {
td::BufferSlice to_sign(OverlayIdShort overlay_id, PublicKeyHash issued_to) const;
BroadcastCheckResult check(PublicKeyHash node, OverlayIdShort overlay_id, td::int32 unix_time, td::uint32 size,
bool is_fec) const;
bool is_fec, bool skip_check_signature = false) const;
tl_object_ptr<ton_api::overlay_Certificate> tl() const;
const PublicKey &issuer() const;
const PublicKeyHash issuer_hash() const;

View file

@ -1,17 +1,13 @@
## 2024.10 Update
1. Parallel write to celldb: substantial improvement of sync and GC speed, especially with slow disks.
2. Decreased network traffic: only first block candidate is sent optimistically.
3. Improved channel creation and dht lookups, introduction of semi-private overlays
4. New LS dispatch queue related methods and improvement security
5. Fixing recursion in TVM continuations
6. Improved stats for actors, validator sessions, perf counters, overlays, adnl, rocksdb
7. Migration to C++20
8. Improved block size estimates: account for depth in various structures
9. Fix bug with `<<` optimization in FunC
10. Minor changes of TVM which will be activated by `Config8.version >= 9`
11. Multiple minor improvements
Besides the work of the core team, this update is based on the efforts of @krigga (emulator), Arayz @ TonBit (LS security, TVM recursion), @ret2happy (UB in BLST).
## 2024.12 Update
1. FunC 0.4.6: Fix in try/catch handling, fixing pure flag for functions stored in variables
2. Merging parts of Accelerator: support of specific shard monitoring, archive/liteserver slice format, support for partial liteservers, proxy liteserver, on-demand neighbour queue loading
3. Fix of asynchronous cell loading
4. Various improvements: caching certificates checks, better block overloading detection, `_malloc` in emulator
5. Introduction of telemetry in overlays
6. Use non-null local-id for tonlib-LS interaction - mitigates MitM attack.
7. Adding `SECP256K1_XONLY_PUBKEY_TWEAK_ADD`, `SETCONTCTRMANY` instructions to TVM (activated by `Config8.version >= 9`)
8. Private keys export via validator-engine-console - required for better backups
9. Fix proof checking in tonlib, `hash` in `raw.Message` in tonlib_api
Besides the work of the core team, this update is based on the efforts of OtterSec and LayerZero (FunC), tg:@throwunless (FunC), Aviv Frenkel and Dima Kogan from Fordefi (LS MitM), @hacker-volodya (Tonlib), OKX team (async cell loading), @krigga (emulator)

View file

@ -149,4 +149,19 @@ std::enable_if_t<std::is_arithmetic<T>::value, string> to_string(const T &x) {
return sb.as_cslice().str();
}
template <class SB>
struct LambdaPrintHelper {
SB& sb;
};
template <class SB, class F>
SB& operator<<(const LambdaPrintHelper<SB>& helper, F&& f) {
f(helper.sb);
return helper.sb;
}
struct LambdaPrint {};
inline LambdaPrintHelper<td::StringBuilder> operator<<(td::StringBuilder& sb, const LambdaPrint&) {
return LambdaPrintHelper<td::StringBuilder>{sb};
}
} // namespace td

View file

@ -74,6 +74,7 @@
#define LOG(level) LOG_IMPL(level, level, true, ::td::Slice())
#define LOG_IF(level, condition) LOG_IMPL(level, level, condition, #condition)
#define FLOG(level) LOG_IMPL(level, level, true, ::td::Slice()) << td::LambdaPrint{} << [&](auto &sb)
#define VLOG(level) LOG_IMPL(DEBUG, level, true, TD_DEFINE_STR(level))
#define VLOG_IF(level, condition) LOG_IMPL(DEBUG, level, condition, TD_DEFINE_STR(level) " " #condition)
@ -95,13 +96,13 @@ inline bool no_return_func() {
#define DUMMY_LOG_CHECK(condition) LOG_IF(NEVER, !(condition))
#ifdef TD_DEBUG
#if TD_MSVC
#if TD_MSVC
#define LOG_CHECK(condition) \
__analysis_assume(!!(condition)); \
LOG_IMPL(FATAL, FATAL, !(condition), #condition)
#else
#else
#define LOG_CHECK(condition) LOG_IMPL(FATAL, FATAL, !(condition) && no_return_func(), #condition)
#endif
#endif
#else
#define LOG_CHECK DUMMY_LOG_CHECK
#endif
@ -263,6 +264,9 @@ class Logger {
sb_ << other;
return *this;
}
LambdaPrintHelper<td::Logger> operator<<(const LambdaPrint &) {
return LambdaPrintHelper<td::Logger>{*this};
}
MutableCSlice as_cslice() {
return sb_.as_cslice();

View file

@ -472,4 +472,45 @@ Result<TotalMemStat> get_total_mem_stat() {
#endif
}
Result<uint32> get_cpu_cores() {
#if TD_LINUX
uint32 result = 0;
TRY_RESULT(fd, FileFd::open("/proc/cpuinfo", FileFd::Read));
SCOPE_EXIT {
fd.close();
};
std::string data;
char buf[10000];
while (true) {
TRY_RESULT(size, fd.read(MutableSlice{buf, sizeof(buf) - 1}));
if (size == 0) {
break;
}
buf[size] = '\0';
data += buf;
}
size_t i = 0;
while (i < data.size()) {
const char *line_begin = data.data() + i;
while (i < data.size() && data[i] != '\n') {
++i;
}
auto line_end = data.data() + i;
++i;
Slice line{line_begin, line_end};
size_t j = 0;
while (j < line.size() && line[j] != ' ' && line[j] != '\t' && line[j] != ':') {
++j;
}
Slice name = line.substr(0, j);
if (name == "processor") {
++result;
}
}
return result;
#else
return Status::Error("Not supported");
#endif
}
} // namespace td

Some files were not shown because too many files have changed in this diff Show more