From 152f6429227d6d3a350c85d224af7c8102ad6e7b Mon Sep 17 00:00:00 2001 From: SpyCheese Date: Fri, 3 Nov 2023 14:14:47 +0300 Subject: [PATCH] Various changes in TVM, github builds and tests * Bugfixes in TVM and node * Upgrade to C++17 * Improve GitHub builds * Fix existing tests and partially integrate them into builds --------- Co-authored-by: neodiX42 Co-authored-by: EmelyanenkoK --- .clang_complete | 2 +- .github/script/fift-func-wasm-build-ubuntu.sh | 2 +- .github/workflows/macos-11.7-compile.yml | 32 +- .github/workflows/macos-12.6-compile.yml | 29 +- .github/workflows/ton-x86-64-linux.yml | 2 +- .github/workflows/ton-x86-64-macos.yml | 2 +- .github/workflows/ubuntu-22.04-compile.yml | 20 +- .github/workflows/ubuntu-compile.yml | 21 +- .github/workflows/win-2019-compile.yml | 15 +- CMakeLists.txt | 67 +- README.md | 5 + adnl/CMakeLists.txt | 2 +- blockchain-explorer/CMakeLists.txt | 2 +- blockchain-explorer/blockchain-explorer.cpp | 4 +- catchain/CMakeLists.txt | 2 +- common/CMakeLists.txt | 2 +- create-hardfork/CMakeLists.txt | 2 +- create-hardfork/create-hardfork.cpp | 4 +- crypto/CMakeLists.txt | 2 +- crypto/block/transaction.cpp | 663 +++++- crypto/block/transaction.h | 4 +- crypto/common/bitstring.cpp | 4 +- crypto/fift/lib/Asm.fif | 94 +- crypto/fift/words.cpp | 2 +- crypto/func/auto-tests/legacy_tester.py | 130 +- crypto/func/auto-tests/run_tests.py | 36 +- crypto/openssl/bignum.cpp | 12 +- crypto/openssl/bignum.h | 2 +- crypto/parser/lexer.cpp | 1 - crypto/smc-envelope/ManualDns.h | 4 +- crypto/smc-envelope/SmartContract.cpp | 2 +- crypto/test/fift.cpp | 2 +- crypto/test/fift/rist255.fif | 3 + crypto/test/modbigint.cpp | 6 +- crypto/test/test-bigint.cpp | 6 +- crypto/test/test-db.cpp | 8 +- crypto/test/test-smartcont.cpp | 13 +- crypto/test/vm.cpp | 2 +- crypto/tl/tlbc-gen-cpp.cpp | 1 - crypto/tl/tlbc.cpp | 2 - crypto/vm/arithops.cpp | 44 +- crypto/vm/tonops.cpp | 33 +- crypto/vm/vm.cpp | 13 + crypto/vm/vm.h | 2 + dht-server/CMakeLists.txt | 2 +- dht/CMakeLists.txt | 2 +- emulator/CMakeLists.txt | 2 +- emulator/emulator-extern.cpp | 4 +- emulator/transaction-emulator.cpp | 4 +- fec/CMakeLists.txt | 2 +- fec/fec.cpp | 2 +- flake.lock | 6 +- flake.nix | 8 +- http/CMakeLists.txt | 2 +- keyring/CMakeLists.txt | 2 +- keys/CMakeLists.txt | 2 +- lite-client/CMakeLists.txt | 2 +- lite-client/lite-client.cpp | 2 +- memprof/CMakeLists.txt | 2 +- overlay/CMakeLists.txt | 2 +- rldp-http-proxy/CMakeLists.txt | 2 +- rldp/CMakeLists.txt | 2 +- rldp2/CMakeLists.txt | 2 +- storage/CMakeLists.txt | 2 +- storage/storage-daemon/CMakeLists.txt | 2 +- storage/test/storage.cpp | 3 - tdactor/CMakeLists.txt | 2 +- tdactor/benchmark/CMakeLists.txt | 2 +- tdactor/test/actors_core.cpp | 4 +- tdactor/test/actors_promise.cpp | 2 +- tddb/CMakeLists.txt | 2 +- tddb/td/db/utils/BlobView.cpp | 1 + tdfec/CMakeLists.txt | 2 +- tdfec/benchmark/CMakeLists.txt | 2 +- tdfec/td/fec/raptorq/Rfc.h | 2 +- tdnet/CMakeLists.txt | 2 +- tdtl/CMakeLists.txt | 2 +- tdutils/CMakeLists.txt | 4 +- tdutils/generate/CMakeLists.txt | 2 +- tdutils/td/utils/BigNum.cpp | 4 + tdutils/td/utils/BufferedUdp.h | 1 + tdutils/td/utils/crypto.cpp | 46 +- tdutils/td/utils/crypto.h | 2 +- tdutils/td/utils/port/stacktrace.cpp | 45 +- tdutils/test/MpmcWaiter.cpp | 6 +- terminal/CMakeLists.txt | 2 +- test/ed25519_crypto.cpp | 2053 ----------------- test/regression-tests.ans | 68 +- test/test-adnl.cpp | 2 +- test/test-catchain.cpp | 8 +- test/test-dht.cpp | 2 +- test/test-ext-client.cpp | 220 -- test/test-ext-server.cpp | 221 -- test/test-node.cpp | 376 --- test/test-rldp.cpp | 2 +- test/test-rldp2.cpp | 2 +- test/test-ton-collator.cpp | 4 +- test/test-validator-session-state.cpp | 1 + test/test-validator-session.cpp | 356 --- test/test-validator.cpp | 356 --- third-party/blst | 2 +- third-party/rocksdb | 2 +- tl-utils/CMakeLists.txt | 2 +- tl/CMakeLists.txt | 2 +- tl/generate/CMakeLists.txt | 2 +- tl/tl/tl_json.h | 3 +- tonlib/CMakeLists.txt | 2 +- tonlib/test/offline.cpp | 25 +- tonlib/tonlib/TonlibClient.cpp | 2 +- utils/CMakeLists.txt | 2 +- utils/opcode-timing.cpp | 3 +- validator-engine-console/CMakeLists.txt | 2 +- validator-engine/CMakeLists.txt | 2 +- validator-engine/validator-engine.cpp | 4 +- validator-session/CMakeLists.txt | 2 +- validator/CMakeLists.txt | 2 +- validator/impl/CMakeLists.txt | 2 +- validator/impl/collator-impl.h | 8 +- validator/impl/collator.cpp | 962 +++++++- validator/impl/external-message.cpp | 2 +- validator/impl/validate-query.cpp | 786 ++++++- validator/impl/validate-query.hpp | 3 +- 122 files changed, 2891 insertions(+), 4102 deletions(-) delete mode 100644 test/ed25519_crypto.cpp delete mode 100644 test/test-ext-client.cpp delete mode 100644 test/test-ext-server.cpp delete mode 100644 test/test-node.cpp delete mode 100644 test/test-validator-session.cpp delete mode 100644 test/test-validator.cpp diff --git a/.clang_complete b/.clang_complete index d7cda0ff1..e88dbc7bf 100644 --- a/.clang_complete +++ b/.clang_complete @@ -1,5 +1,5 @@ -xc++ --std=c++14 +-std=c++17 -iquote . -iquote tdtl/ -iquote tl/ diff --git a/.github/script/fift-func-wasm-build-ubuntu.sh b/.github/script/fift-func-wasm-build-ubuntu.sh index 259377ccb..feac19e31 100755 --- a/.github/script/fift-func-wasm-build-ubuntu.sh +++ b/.github/script/fift-func-wasm-build-ubuntu.sh @@ -13,7 +13,7 @@ echo `pwd` git clone https://github.com/openssl/openssl.git cd openssl -git checkout OpenSSL_1_1_1j +git checkout checkout openssl-3.1.4 ./config make -j16 OPENSSL_DIR=`pwd` diff --git a/.github/workflows/macos-11.7-compile.yml b/.github/workflows/macos-11.7-compile.yml index 100d51c8f..eb12db1b5 100644 --- a/.github/workflows/macos-11.7-compile.yml +++ b/.github/workflows/macos-11.7-compile.yml @@ -12,24 +12,33 @@ jobs: uses: actions/checkout@v3 with: submodules: 'recursive' - - name: Compile OpenSSL + + - name: Compile Secp256k1 run: | export NONINTERACTIVE=1 brew install ninja secp256k1 libsodium libmicrohttpd pkg-config automake libtool - git clone https://github.com/openssl/openssl openssl_1_1_1 - cd openssl_1_1_1 - git checkout OpenSSL_1_1_1-stable - ./Configure darwin64-x86_64-cc -static -mmacosx-version-min=11.7 - make build_libs -j4 + git clone https://github.com/libbitcoin/secp256k1.git + cd secp256k1 + ./autogen.sh + ./configure --enable-module-recovery + make + make install - name: Build all run: | - brew unlink openssl@3 + brew unlink openssl@1.1 + brew install openssl@3 + brew unlink openssl@3 && brew link --overwrite openssl@3 rootPath=`pwd` mkdir build cd build - cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$rootPath/openssl_1_1_1/include -DOPENSSL_CRYPTO_LIBRARY=$rootPath/openssl_1_1_1/libcrypto.a -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=11.7 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release .. - ninja storage-daemon storage-daemon-cli blockchain-explorer fift func 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 tlbc emulator + cmake -GNinja -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=11.7 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release .. + + ninja storage-daemon storage-daemon-cli blockchain-explorer fift func 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 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 - name: Strip binaries run: | @@ -51,6 +60,11 @@ jobs: strip build/utils/json2tlo strip build/adnl/adnl-proxy + - name: Run tests + run: | + cd build + ctest --output-on-failure -E "test-catchain|test-actors" + - name: Find & copy binaries run: | mkdir artifacts diff --git a/.github/workflows/macos-12.6-compile.yml b/.github/workflows/macos-12.6-compile.yml index 8660a10b8..f41efc669 100644 --- a/.github/workflows/macos-12.6-compile.yml +++ b/.github/workflows/macos-12.6-compile.yml @@ -12,18 +12,11 @@ jobs: uses: actions/checkout@v3 with: submodules: 'recursive' - - name: Compile OpenSSL - run: | - export NONINTERACTIVE=1 - brew install ninja secp256k1 libsodium libmicrohttpd pkg-config automake libtool - git clone https://github.com/openssl/openssl openssl_1_1_1 - cd openssl_1_1_1 - git checkout OpenSSL_1_1_1-stable - ./Configure darwin64-x86_64-cc -static -mmacosx-version-min=12.6 - make build_libs -j4 - name: Compile Secp256k1 run: | + export NONINTERACTIVE=1 + brew install ninja secp256k1 libsodium libmicrohttpd pkg-config automake libtool git clone https://github.com/libbitcoin/secp256k1.git cd secp256k1 ./autogen.sh @@ -33,12 +26,19 @@ jobs: - name: Build all run: | - brew unlink openssl@3 + brew unlink openssl@1.1 + brew install openssl@3 + brew unlink openssl@3 && brew link --overwrite openssl@3 rootPath=`pwd` mkdir build cd build - cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$rootPath/openssl_1_1_1/include -DOPENSSL_CRYPTO_LIBRARY=$rootPath/openssl_1_1_1/libcrypto.a -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=12.6 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release .. - ninja storage-daemon storage-daemon-cli blockchain-explorer fift func 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 tlbc emulator + cmake -GNinja -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=12.6 -DCMAKE_CXX_FLAGS="-stdlib=libc++" -DCMAKE_BUILD_TYPE=Release .. + + ninja storage-daemon storage-daemon-cli blockchain-explorer fift func 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 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 - name: Strip binaries run: | @@ -60,6 +60,11 @@ jobs: strip build/utils/json2tlo strip build/adnl/adnl-proxy + - name: Run tests + run: | + cd build + ctest --output-on-failure -E "test-catchain|test-actors" + - name: Find & copy binaries run: | mkdir artifacts diff --git a/.github/workflows/ton-x86-64-linux.yml b/.github/workflows/ton-x86-64-linux.yml index e939f22f8..a4760dc41 100644 --- a/.github/workflows/ton-x86-64-linux.yml +++ b/.github/workflows/ton-x86-64-linux.yml @@ -15,7 +15,7 @@ jobs: with: submodules: 'recursive' - - uses: cachix/install-nix-action@v18 + - uses: cachix/install-nix-action@v23 with: extra_nix_config: | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ton-x86-64-macos.yml b/.github/workflows/ton-x86-64-macos.yml index b9e9cf9b9..cea2937a3 100644 --- a/.github/workflows/ton-x86-64-macos.yml +++ b/.github/workflows/ton-x86-64-macos.yml @@ -11,7 +11,7 @@ jobs: with: submodules: 'recursive' - - uses: cachix/install-nix-action@v22 + - uses: cachix/install-nix-action@v23 with: extra_nix_config: | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ubuntu-22.04-compile.yml b/.github/workflows/ubuntu-22.04-compile.yml index b5d4d5711..af8943a1c 100644 --- a/.github/workflows/ubuntu-22.04-compile.yml +++ b/.github/workflows/ubuntu-22.04-compile.yml @@ -28,9 +28,9 @@ jobs: export CXX=$(which clang++) export CCACHE_DISABLE=1 - git clone https://github.com/openssl/openssl openssl_1_1_1 - cd openssl_1_1_1 - git checkout OpenSSL_1_1_1-stable + git clone https://github.com/openssl/openssl openssl_3 + cd openssl_3 + git checkout openssl-3.1.4 ./config make build_libs -j4 @@ -39,13 +39,23 @@ jobs: mkdir build cd build - cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$rootPath/openssl_1_1_1/include -DOPENSSL_CRYPTO_LIBRARY=$rootPath/openssl_1_1_1/libcrypto.a -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= .. - ninja storage-daemon storage-daemon-cli fift func 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 emulator + cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$rootPath/openssl_3/include -DOPENSSL_CRYPTO_LIBRARY=$rootPath/openssl_3/libcrypto.a -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= .. + + ninja storage-daemon storage-daemon-cli fift func 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 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 - name: Strip binaries run: | strip -g build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli build/crypto/fift build/crypto/tlbc build/crypto/func build/crypto/create-state build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/tonlib/libtonlibjson.so.0.5 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.* + - name: Run tests + run: | + cd build + ctest --output-on-failure -E "test-catchain|test-actors" + - name: Find & copy binaries run: | mkdir artifacts diff --git a/.github/workflows/ubuntu-compile.yml b/.github/workflows/ubuntu-compile.yml index be3878f5e..3c1e7bad1 100644 --- a/.github/workflows/ubuntu-compile.yml +++ b/.github/workflows/ubuntu-compile.yml @@ -34,22 +34,31 @@ jobs: mkdir build-${{ matrix.os }} cd build-${{ matrix.os }} - git clone https://github.com/openssl/openssl openssl_1_1_1 - cd openssl_1_1_1 - git checkout OpenSSL_1_1_1-stable + git clone https://github.com/openssl/openssl openssl_3 + cd openssl_3 + git checkout openssl-3.1.4 ./config make build_libs -j4 cd .. - buildPath=`pwd` + rootPath=`pwd` - cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$buildPath/openssl_1_1_1/include -DOPENSSL_CRYPTO_LIBRARY=$buildPath/openssl_1_1_1/libcrypto.a -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= .. - ninja storage-daemon storage-daemon-cli fift func 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 + cmake -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$rootPath/openssl_3/include -DOPENSSL_CRYPTO_LIBRARY=$rootPath/openssl_3/libcrypto.a -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= .. + ninja storage-daemon storage-daemon-cli fift func 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 \ + 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 - name: Strip binaries run: | strip -g build-${{ matrix.os }}/storage/storage-daemon/storage-daemon build-${{ matrix.os }}/storage/storage-daemon/storage-daemon-cli build-${{ matrix.os }}/crypto/fift build-${{ matrix.os }}/crypto/tlbc build-${{ matrix.os }}/crypto/func build-${{ matrix.os }}/crypto/create-state build-${{ matrix.os }}/validator-engine-console/validator-engine-console build-${{ matrix.os }}/tonlib/tonlib-cli build-${{ matrix.os }}/tonlib/libtonlibjson.so.0.5 build-${{ matrix.os }}/http/http-proxy build-${{ matrix.os }}/rldp-http-proxy/rldp-http-proxy build-${{ matrix.os }}/dht-server/dht-server build-${{ matrix.os }}/lite-client/lite-client build-${{ matrix.os }}/validator-engine/validator-engine build-${{ matrix.os }}/utils/generate-random-id build-${{ matrix.os }}/utils/json2tlo build-${{ matrix.os }}/adnl/adnl-proxy build-${{ matrix.os }}/emulator/libemulator.* + - name: Run tests + run: | + cd build-${{ matrix.os }} + ctest --output-on-failure -E "test-catchain|test-actors" + - name: Find & copy binaries run: | mkdir artifacts-${{ matrix.os }} diff --git a/.github/workflows/win-2019-compile.yml b/.github/workflows/win-2019-compile.yml index 9b4d3bef2..e94655f7d 100644 --- a/.github/workflows/win-2019-compile.yml +++ b/.github/workflows/win-2019-compile.yml @@ -49,10 +49,10 @@ jobs: curl -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip unzip libsodium-1.0.18-stable-msvc.zip - - name: Install pre-compiled OpenSSL Win64 + - name: Install pre-compiled OpenSSL 3 Win64 run: | - curl -Lo openssl-1.1.1j.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-1.1.1j.zip - jar xf openssl-1.1.1j.zip + curl -Lo openssl-3.1.4.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-3.1.4.zip + unzip openssl-3.1.4.zip - name: Install pre-compiled libmicrohttpd Win64 run: | @@ -72,8 +72,13 @@ jobs: echo %SODIUM_DIR% mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release -DSODIUM_USE_STATIC_LIBS=1 -DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include -DSECP256K1_LIBRARY=%root%\secp256k1\bin\x64\Release\v142\static\secp256k1.lib -DREADLINE_INCLUDE_DIR=%root%\readline-5.0-1-lib\include\readline -DREADLINE_LIBRARY=%root%\readline-5.0-1-lib\lib\readline.lib -DPORTABLE=1 -DZLIB_FOUND=1 -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 -DZLIB_INCLUDE_DIR=%root%\zlib -DZLIB_LIBRARY=%root%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=%root%/openssl-1.1.1j/include -DOPENSSL_CRYPTO_LIBRARY=%root%/openssl-1.1.1j/lib/libcrypto_static.lib -DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj /W0" .. - cmake --build . --target storage-daemon storage-daemon-cli blockchain-explorer fift func 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 --config Release + cmake -DSODIUM_USE_STATIC_LIBS=1 -DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include -DSECP256K1_LIBRARY=%root%\secp256k1\bin\x64\Release\v142\static\secp256k1.lib -DREADLINE_INCLUDE_DIR=%root%\readline-5.0-1-lib\include\readline -DREADLINE_LIBRARY=%root%\readline-5.0-1-lib\lib\readline.lib -DPORTABLE=1 -DZLIB_FOUND=1 -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 -DZLIB_INCLUDE_DIR=%root%\zlib -DZLIB_LIBRARY=%root%\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 -DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj /W0" .. + cmake --build . --config Release --target storage-daemon storage-daemon-cli blockchain-explorer fift func 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 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 + + - name: Run tests + run: | + cd build + ctest -C Release --output-on-failure -E "test-catchain|test-actors|test-validator-session-state" - name: Show executables run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b6f0dc9f..c6d7ed87a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(TON VERSION 0.5 LANGUAGES C CXX) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -79,7 +79,7 @@ else() set(HAVE_SSE42 FALSE) endif() -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_EXTENSIONS FALSE) @@ -255,6 +255,9 @@ if (MSVC) add_definitions(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /wd4127 /wd4324 /wd4456 /wd4457 /wd4458 /wd4505 /wd4702") elseif (CLANG OR GCC) + if (GCC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstrong-eval-order=some") + endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer") if (APPLE) #use "-Wl,-exported_symbols_list,${CMAKE_CURRENT_SOURCE_DIR}/export_list" for exported symbols @@ -447,6 +450,10 @@ target_link_libraries(test-smartcont PRIVATE smc-envelope fift-lib ton_db) add_executable(test-bigint ${BIGINT_TEST_SOURCE}) target_link_libraries(test-bigint PRIVATE ton_crypto) +if (WINGETOPT_FOUND) + target_link_libraries_system(test-bigint wingetopt) +endif() + add_executable(test-cells test/test-td-main.cpp ${CELLS_TEST_SOURCE}) target_link_libraries(test-cells PRIVATE ton_crypto) @@ -513,26 +520,12 @@ target_link_libraries(test-rldp2 adnl adnltest dht rldp2 tl_api) add_executable(test-validator-session-state test/test-validator-session-state.cpp) target_link_libraries(test-validator-session-state adnl dht rldp validatorsession tl_api) -#add_executable(test-node test/test-node.cpp) -#target_link_libraries(test-node overlay tdutils tdactor adnl tl_api dht -# catchain validatorsession) - add_executable(test-catchain test/test-catchain.cpp) target_link_libraries(test-catchain overlay tdutils tdactor adnl adnltest rldp tl_api dht catchain ) -#add_executable(test-validator-session test/test-validator-session.cpp) -#target_link_libraries(test-validator-session overlay tdutils tdactor adnl tl_api dht -# catchain validatorsession) add_executable(test-ton-collator test/test-ton-collator.cpp) target_link_libraries(test-ton-collator overlay tdutils tdactor adnl tl_api dht catchain validatorsession validator-disk ton_validator validator-disk ) -#add_executable(test-validator test/test-validator.cpp) -#target_link_libraries(test-validator overlay tdutils tdactor adnl tl_api dht -# rldp catchain validatorsession ton-node validator ton_validator validator memprof ${JEMALLOC_LIBRARIES}) -#add_executable(test-ext-server test/test-ext-server.cpp) -#target_link_libraries(test-ext-server tdutils tdactor adnl tl_api dht ) -#add_executable(test-ext-client test/test-ext-client.cpp) -#target_link_libraries(test-ext-client tdutils tdactor adnl tl_api tl-lite-utils) add_executable(test-http test/test-http.cpp) target_link_libraries(test-http PRIVATE tonhttp) @@ -574,13 +567,53 @@ add_test(test-tdutils test-tdutils) add_test(test-tonlib-offline test-tonlib-offline) #END tonlib +# FunC tests +if (NOT NIX) + if (MSVC) + set(PYTHON_VER "python") + else() + set(PYTHON_VER "python3") + endif() + add_test( + NAME test-func + COMMAND ${PYTHON_VER} run_tests.py tests/ + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/crypto/func/auto-tests) + if (WIN32) + set_property(TEST test-func PROPERTY ENVIRONMENT + "FUNC_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/Release/func.exe" + "FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/Release/fift.exe" + "FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/") + else() + set_property(TEST test-func PROPERTY ENVIRONMENT + "FUNC_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/func" + "FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/fift" + "FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/") + endif() + + add_test( + NAME test-func-legacy + COMMAND ${PYTHON_VER} legacy_tester.py + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/crypto/func/auto-tests) + if (WIN32) + set_property(TEST test-func-legacy PROPERTY ENVIRONMENT + "FUNC_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/Release/func.exe" + "FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/Release/fift.exe" + "FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/") + else() + set_property(TEST test-func-legacy PROPERTY ENVIRONMENT + "FUNC_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/func" + "FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/fift" + "FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/") + endif() +endif() + #BEGIN internal if (NOT TON_ONLY_TONLIB) add_test(test-adnl test-adnl) add_test(test-dht test-dht) add_test(test-rldp test-rldp) add_test(test-rldp2 test-rldp2) -#add_test(test-validator-session-state test-validator-session-state) +add_test(test-validator-session-state test-validator-session-state) add_test(test-catchain test-catchain) add_test(test-fec test-fec) diff --git a/README.md b/README.md index 6bc3b1f50..12d051905 100644 --- a/README.md +++ b/README.md @@ -66,3 +66,8 @@ If a CI workflow fails not because of your changes but workflow issues, try to f * **C/C++ CI (ccpp-linux.yml)**: TBD * **C/C++ CI Win64 Compile (ccpp-win64.yml)**: TBD + + +## Running tests + +Tests are executed by running `ctest` in the build directory. \ No newline at end of file diff --git a/adnl/CMakeLists.txt b/adnl/CMakeLists.txt index b287cba06..217a96247 100644 --- a/adnl/CMakeLists.txt +++ b/adnl/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) #BEGIN internal if (NOT TON_ONLY_TONLIB) diff --git a/blockchain-explorer/CMakeLists.txt b/blockchain-explorer/CMakeLists.txt index 11328a7a3..fc94e7093 100644 --- a/blockchain-explorer/CMakeLists.txt +++ b/blockchain-explorer/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) option(NIX "Use \"ON\" for a static build." OFF) diff --git a/blockchain-explorer/blockchain-explorer.cpp b/blockchain-explorer/blockchain-explorer.cpp index 035b84ea7..bf41b31f8 100644 --- a/blockchain-explorer/blockchain-explorer.cpp +++ b/blockchain-explorer/blockchain-explorer.cpp @@ -52,7 +52,7 @@ #include "vm/boc.h" #include "vm/cellops.h" #include "vm/cells/MerkleProof.h" -#include "vm/cp0.h" +#include "vm/vm.h" #include "auto/tl/lite_api.h" #include "ton/lite-tl.hpp" @@ -654,7 +654,7 @@ int main(int argc, char* argv[]) { }); #endif - vm::init_op_cp0(); + vm::init_vm().ensure(); td::actor::Scheduler scheduler({2}); scheduler_ptr = &scheduler; diff --git a/catchain/CMakeLists.txt b/catchain/CMakeLists.txt index a57d37882..8ab9525da 100644 --- a/catchain/CMakeLists.txt +++ b/catchain/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 96d92371a..88a3671b3 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(COMMON_SOURCE checksum.h diff --git a/create-hardfork/CMakeLists.txt b/create-hardfork/CMakeLists.txt index 3d78c118b..41b94b523 100644 --- a/create-hardfork/CMakeLists.txt +++ b/create-hardfork/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/create-hardfork/create-hardfork.cpp b/create-hardfork/create-hardfork.cpp index 15533768d..5f0b93bed 100644 --- a/create-hardfork/create-hardfork.cpp +++ b/create-hardfork/create-hardfork.cpp @@ -49,7 +49,7 @@ #include "validator/fabric.h" #include "validator/impl/collator.h" -#include "crypto/vm/cp0.h" +#include "crypto/vm/vm.h" #include "crypto/block/block-db.h" #include "common/errorlog.h" @@ -307,7 +307,7 @@ int main(int argc, char *argv[]) { SET_VERBOSITY_LEVEL(verbosity_INFO); td::set_default_failure_signal_handler().ensure(); - CHECK(vm::init_op_cp0()); + vm::init_vm().ensure(); td::actor::ActorOwn x; diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index 9f7a0a5a7..62b0d2161 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/crypto/block/transaction.cpp b/crypto/block/transaction.cpp index 0c77317fa..9df5be132 100644 --- a/crypto/block/transaction.cpp +++ b/crypto/block/transaction.cpp @@ -28,9 +28,20 @@ #include "td/utils/Timer.h" namespace { +/** + * Logger that stores the tail of log messages. + * + * @param max_size The size of the buffer. Default is 256. + */ class StringLoggerTail : public td::LogInterface { public: explicit StringLoggerTail(size_t max_size = 256) : buf(max_size, '\0') {} + + /** + * Appends a slice of data to the buffer. + * + * @param slice The slice of data to be appended. + */ void append(td::CSlice slice) override { if (slice.size() > buf.size()) { slice.remove_prefix(slice.size() - buf.size()); @@ -46,6 +57,12 @@ class StringLoggerTail : public td::LogInterface { slice.remove_prefix(s); } } + + /** + * Retrieves the tail of the log. + * + * @returns The log as std::string. + */ std::string get_log() const { if (truncated) { std::string res = buf; @@ -55,6 +72,7 @@ class StringLoggerTail : public td::LogInterface { return buf.substr(0, pos); } } + private: std::string buf; size_t pos = 0; @@ -65,6 +83,13 @@ class StringLoggerTail : public td::LogInterface { namespace block { using td::Ref; +/** + * Looks up a library among public libraries. + * + * @param key A constant bit pointer representing the key of the library to lookup. + * + * @returns A reference to the library cell if found, null otherwise. + */ Ref ComputePhaseConfig::lookup_library(td::ConstBitPtr key) const { return libraries ? vm::lookup_library_in(key, libraries->get_root_cell()) : Ref{}; } @@ -75,12 +100,27 @@ Ref ComputePhaseConfig::lookup_library(td::ConstBitPtr key) const { * */ +/** + * Sets the address of the account. + * + * @param wc The workchain ID of the account. + * @param new_addr The new address of the account. + * + * @returns True if the address was successfully set, false otherwise. + */ bool Account::set_address(ton::WorkchainId wc, td::ConstBitPtr new_addr) { workchain = wc; addr = new_addr; return true; } +/** + * Sets the split depth of the account. + * + * @param new_split_depth The new split depth value to be set. + * + * @returns True if the split depth was successfully set, False otherwise. + */ bool Account::set_split_depth(int new_split_depth) { if (new_split_depth < 0 || new_split_depth > 30) { return false; // invalid value for split_depth @@ -94,11 +134,26 @@ bool Account::set_split_depth(int new_split_depth) { } } +/** + * Checks if the given split depth is valid for the Account. + * + * @param split_depth The split depth to be checked. + * + * @returns True if the split depth is valid, False otherwise. + */ bool Account::check_split_depth(int split_depth) const { return split_depth_set_ ? (split_depth == split_depth_) : (split_depth >= 0 && split_depth <= 30); } -// initializes split_depth and addr_rewrite +/** + * Parses anycast data of the account address. + * + * Initializes split_depth and addr_rewrite. + * + * @param cs The cell slice containing partially-parsed account addressa. + * + * @returns True if parsing was successful, false otherwise. + */ bool Account::parse_maybe_anycast(vm::CellSlice& cs) { int t = (int)cs.fetch_ulong(1); if (t < 0) { @@ -113,6 +168,13 @@ bool Account::parse_maybe_anycast(vm::CellSlice& cs) { && set_split_depth(depth); } +/** + * Stores the anycast information to a serialized account address. + * + * @param cb The vm::CellBuilder object to store the information in. + * + * @returns True if the anycast information was successfully stored, false otherwise. + */ bool Account::store_maybe_anycast(vm::CellBuilder& cb) const { if (!split_depth_set_ || !split_depth_) { return cb.store_bool_bool(false); @@ -122,6 +184,13 @@ bool Account::store_maybe_anycast(vm::CellBuilder& cb) const { && cb.store_bits_bool(addr_rewrite.cbits(), split_depth_); // rewrite_pfx:(bits depth) } +/** + * Unpacks the address from a given CellSlice. + * + * @param addr_cs The CellSlice containing the address. + * + * @returns True if the address was successfully unpacked, False otherwise. + */ bool Account::unpack_address(vm::CellSlice& addr_cs) { int addr_tag = block::gen::t_MsgAddressInt.get_tag(addr_cs); int new_wc = ton::workchainInvalid; @@ -172,6 +241,15 @@ bool Account::unpack_address(vm::CellSlice& addr_cs) { return true; } +/** + * Unpacks storage information from a CellSlice. + * + * Storage information is serialized using StorageInfo TLB-scheme. + * + * @param cs The CellSlice containing the storage information. + * + * @returns True if the unpacking is successful, false otherwise. + */ bool Account::unpack_storage_info(vm::CellSlice& cs) { block::gen::StorageInfo::Record info; block::gen::StorageUsed::Record used; @@ -198,7 +276,16 @@ bool Account::unpack_storage_info(vm::CellSlice& cs) { return (u != std::numeric_limits::max()); } -// initializes split_depth (from account state - StateInit) +/** + * Unpacks the state of an Account from a CellSlice. + * + * State is serialized using StateInit TLB-scheme. + * Initializes split_depth (from account state - StateInit) + * + * @param cs The CellSlice containing the serialized state. + * + * @returns True if the state was successfully unpacked, False otherwise. + */ bool Account::unpack_state(vm::CellSlice& cs) { block::gen::StateInit::Record state; if (!tlb::unpack_exact(cs, state)) { @@ -226,6 +313,13 @@ bool Account::unpack_state(vm::CellSlice& cs) { return true; } +/** + * Computes the address of the account. + * + * @param force If set to true, the address will be recomputed even if it already exists. + * + * @returns True if the address was successfully computed, false otherwise. + */ bool Account::compute_my_addr(bool force) { if (!force && my_addr.not_null() && my_addr_exact.not_null()) { return true; @@ -266,6 +360,15 @@ bool Account::compute_my_addr(bool force) { return true; } +/** + * Computes the address of the Account. + * + * @param tmp_addr A reference to the CellSlice for the result. + * @param split_depth The split depth for the address. + * @param orig_addr_rewrite Address prefox of length split_depth. + * + * @returns True if the address was successfully computed, false otherwise. + */ bool Account::recompute_tmp_addr(Ref& tmp_addr, int split_depth, td::ConstBitPtr orig_addr_rewrite) const { if (!split_depth && my_addr_exact.not_null()) { @@ -307,6 +410,14 @@ bool Account::recompute_tmp_addr(Ref& tmp_addr, int split_depth, (tmp_addr = vm::load_cell_slice_ref(std::move(cell))).not_null(); } +/** + * Sets address rewriting info for a newly-activated account. + * + * @param split_depth The split depth for the account address. + * @param orig_addr_rewrite Address frepix of length split_depth. + * + * @returns True if the rewriting info was successfully set, false otherwise. + */ bool Account::init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewrite) { if (split_depth_set_ || !set_split_depth(split_depth)) { return false; @@ -317,8 +428,18 @@ bool Account::init_rewrite_addr(int split_depth, td::ConstBitPtr orig_addr_rewri return compute_my_addr(true); } -// used to unpack previously existing accounts -bool Account::unpack(Ref shard_account, Ref extra, ton::UnixTime now, bool special) { +/** + * Unpacks the account information from the provided CellSlice. + * + * Used to unpack previously existing accounts. + * + * @param shard_account The ShardAccount to unpack. + * @param now The current Unix time. + * @param special Flag indicating if the account is special. + * + * @returns True if the unpacking is successful, false otherwise. + */ +bool Account::unpack(Ref shard_account, ton::UnixTime now, bool special) { LOG(DEBUG) << "unpacking " << (special ? "special " : "") << "account " << addr.to_hex(); if (shard_account.is_null()) { LOG(ERROR) << "account " << addr.to_hex() << " does not have a valid ShardAccount to unpack"; @@ -386,7 +507,13 @@ bool Account::unpack(Ref shard_account, Ref extra, return true; } -// used to initialize new accounts +/** + * Initializes a new Account object. + * + * @param now The current Unix time. + * + * @returns True if the initialization is successful, false otherwise. + */ bool Account::init_new(ton::UnixTime now) { // only workchain and addr are initialized at this point if (workchain == ton::workchainInvalid) { @@ -429,6 +556,11 @@ bool Account::init_new(ton::UnixTime now) { return true; } +/** + * Resets the split depth of the account. + * + * @returns True if the split depth was successfully reset, false otherwise. + */ bool Account::forget_split_depth() { split_depth_set_ = false; split_depth_ = 0; @@ -438,6 +570,11 @@ bool Account::forget_split_depth() { return true; } +/** + * Deactivates the account. + * + * @returns True if the account was successfully deactivated, false otherwise. + */ bool Account::deactivate() { if (status == acc_active) { return false; @@ -461,10 +598,26 @@ bool Account::deactivate() { return true; } +/** + * Checks if the account belongs to a specific shard. + * + * @param shard The shard to check against. + * + * @returns True if the account belongs to the shard, False otherwise. + */ bool Account::belongs_to_shard(ton::ShardIdFull shard) const { return workchain == shard.workchain && ton::shard_is_ancestor(shard.shard, addr); } +/** + * Adds the partial storage payment to the total sum. + * + * @param payment The total sum to be updated. + * @param delta The time delta for which the payment is calculated. + * @param prices The storage prices. + * @param storage Account storage statistics. + * @param is_mc A flag indicating whether the account is in the masterchain. + */ void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, const block::StoragePrices& prices, const vm::CellStorageStat& storage, bool is_mc) { td::BigInt256 c{(long long)storage.cells}, b{(long long)storage.bits}; @@ -483,6 +636,18 @@ void add_partial_storage_payment(td::BigInt256& payment, ton::UnixTime delta, co payment += b; } +/** + * Computes the storage fees based on the given parameters. + * + * @param now The current Unix time. + * @param pricing The vector of storage prices. + * @param storage_stat Account storage statistics. + * @param last_paid The Unix time when the last payment was made. + * @param is_special A flag indicating if the account is special. + * @param is_masterchain A flag indicating if the account is in the masterchain. + * + * @returns The computed storage fees as RefInt256. + */ td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std::vector& pricing, const vm::CellStorageStat& storage_stat, ton::UnixTime last_paid, bool is_special, bool is_masterchain) { @@ -509,11 +674,30 @@ td::RefInt256 StoragePrices::compute_storage_fees(ton::UnixTime now, const std:: return td::rshift(total, 16, 1); // divide by 2^16 with ceil rounding to obtain nanograms } +/** + * Computes the storage fees for the account. + * + * @param now The current Unix time. + * @param pricing The vector of storage prices. + * + * @returns The computed storage fees as RefInt256. + */ td::RefInt256 Account::compute_storage_fees(ton::UnixTime now, const std::vector& pricing) const { return StoragePrices::compute_storage_fees(now, pricing, storage_stat, last_paid, is_special, is_masterchain()); } namespace transaction { +/** + * Constructs a new Transaction object. + * + * @param _account The Account object. + * @param ttype The type of the transaction (see transaction.cpp#309). + * @param req_start_lt The minimal logical time of the transaction. + * @param _now The current Unix time. + * @param _inmsg The input message that caused the transaction. + * + * @returns None + */ Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime req_start_lt, ton::UnixTime _now, Ref _inmsg) : trans_type(ttype) @@ -540,6 +724,14 @@ Transaction::Transaction(const Account& _account, int ttype, ton::LogicalTime re } } +/** + * Unpacks the input message of a transaction. + * + * @param ihr_delivered A boolean indicating whether the message was delivered using IHR (Instant Hypercube Routing). + * @param cfg Action phase configuration. + * + * @returns A boolean indicating whether the unpacking was successful. + */ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* cfg) { if (in_msg.is_null() || in_msg_type) { return false; @@ -680,6 +872,15 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig* return true; } +/** + * Prepares the storage phase of a transaction. + * + * @param cfg The configuration for the storage phase. + * @param force_collect Flag indicating whether to collect fees for frozen accounts. + * @param adjust_msg_value Flag indicating whether to adjust the message value if the account balance becomes less than the message balance. + * + * @returns True if the storage phase was successfully prepared, false otherwise. + */ bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool force_collect, bool adjust_msg_value) { if (now < account.last_paid) { return false; @@ -743,12 +944,21 @@ bool Transaction::prepare_storage_phase(const StoragePhaseConfig& cfg, bool forc return true; } +/** + * Prepares the credit phase of a transaction. + * + * This function creates a CreditPhase object and performs the necessary calculations + * to determine the amount to be credited in the credit phase. It updates the due payment, + * credit, balance, and total fees accordingly. + * + * @returns True if the credit phase is prepared successfully, false otherwise. + */ bool Transaction::prepare_credit_phase() { credit_phase = std::make_unique(); - auto collected = std::min(msg_balance_remaining.grams, due_payment); - credit_phase->due_fees_collected = collected; - due_payment -= collected; - credit_phase->credit = msg_balance_remaining -= collected; + // auto collected = std::min(msg_balance_remaining.grams, due_payment); + // credit_phase->due_fees_collected = collected; + // due_payment -= collected; + // credit_phase->credit = msg_balance_remaining -= collected; if (!msg_balance_remaining.is_valid()) { LOG(ERROR) << "cannot compute the amount to be credited in the credit phase of transaction"; return false; @@ -759,17 +969,35 @@ bool Transaction::prepare_credit_phase() { LOG(ERROR) << "cannot credit currency collection to account"; return false; } - total_fees += std::move(collected); + // total_fees += std::move(collected); return true; } } // namespace transaction +/** + * Parses the gas limits and prices from a given cell. + * + * @param cell The cell containing the gas limits and prices serialized using GasLimitsPricing TLB-scheme. + * @param freeze_due_limit Reference to store the freeze due limit. + * @param delete_due_limit Reference to store the delete due limit. + * + * @returns True if the parsing is successful, false otherwise. + */ bool ComputePhaseConfig::parse_GasLimitsPrices(Ref cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit) { return cell.not_null() && parse_GasLimitsPrices(vm::load_cell_slice_ref(std::move(cell)), freeze_due_limit, delete_due_limit); } +/** + * Parses the gas limits and prices from a given cell slice. + * + * @param cs The cell slice containing the gas limits and prices serialized using GasLimitsPricing TLB-scheme. + * @param freeze_due_limit Reference to store the freeze due limit. + * @param delete_due_limit Reference to store the delete due limit. + * + * @returns True if the parsing is successful, false otherwise. + */ bool ComputePhaseConfig::parse_GasLimitsPrices(Ref cs, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit) { if (cs.is_null()) { @@ -784,6 +1012,17 @@ bool ComputePhaseConfig::parse_GasLimitsPrices(Ref cs, td::RefInt } } +/** + * Parses the gas limits and prices from a gas limits and prices record. + * + * @param cs The cell slice containing the gas limits and prices serialized using GasLimitsPricing TLB-scheme. + * @param freeze_due_limit A reference to store the freeze due limit. + * @param delete_due_limit A reference to store the delete due limit. + * @param _flat_gas_limit The flat gas limit. + * @param _flat_gas_price The flat gas price. + * + * @returns True if the parsing is successful, false otherwise. + */ bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref cs, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit, td::uint64 _flat_gas_limit, td::uint64 _flat_gas_price) { @@ -812,6 +1051,14 @@ bool ComputePhaseConfig::parse_GasLimitsPrices_internal(Ref cs, t return true; } +/** + * Checks if an address is suspended according to the ConfigParam(44). + * + * @param wc The workchain ID. + * @param addr The account address address. + * + * @returns True if the address is suspended, False otherwise. + */ bool ComputePhaseConfig::is_address_suspended(ton::WorkchainId wc, td::Bits256 addr) const { if (!suspended_addresses) { return false; @@ -826,6 +1073,11 @@ bool ComputePhaseConfig::is_address_suspended(ton::WorkchainId wc, td::Bits256 a } } +/** + * Computes the maximum for gas fee based on the gas prices and limits. + * + * Updates max_gas_threshold. + */ void ComputePhaseConfig::compute_threshold() { gas_price256 = td::make_refint(gas_price); if (gas_limit > flat_gas_limit) { @@ -836,6 +1088,13 @@ void ComputePhaseConfig::compute_threshold() { } } +/** + * Computes the amount of gas that can be bought for a given amount of nanograms. + * + * @param nanograms The amount of nanograms to compute gas for. + * + * @returns The amount of gas. + */ td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const { if (nanograms.is_null() || sgn(nanograms) < 0) { return 0; @@ -850,12 +1109,27 @@ td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const { return res->to_long() + flat_gas_limit; } +/** + * Computes the gas price. + * + * @param gas_used The amount of gas used. + * + * @returns The computed gas price. + */ td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const { return gas_used <= flat_gas_limit ? td::make_refint(flat_gas_price) : td::rshift(gas_price256 * (gas_used - flat_gas_limit), 16, 1) + flat_gas_price; } namespace transaction { +/** + * Computes the gas limits for a transaction. + * + * @param cp The ComputePhase object to store the computed gas limits. + * @param cfg The compute phase configuration. + * + * @returns True if the gas limits were successfully computed, false otherwise. + */ bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& cfg) { // Compute gas limits if (account.is_special) { @@ -880,6 +1154,14 @@ bool Transaction::compute_gas_limits(ComputePhase& cp, const ComputePhaseConfig& return true; } +/** + * Prepares a TVM stack for a transaction. + * + * @param cp The compute phase object. + * + * @returns A reference to the prepared virtual machine stack. + * Returns an empty reference if the transaction type is invalid. + */ Ref Transaction::prepare_vm_stack(ComputePhase& cp) { Ref stack_ref{true}; td::RefInt256 acc_addr{true}; @@ -906,6 +1188,14 @@ Ref Transaction::prepare_vm_stack(ComputePhase& cp) { } } +/** + * Prepares a random seed for a transaction. + * + * @param rand_seed The output random seed. + * @param cfg The configuration for the compute phase. + * + * @returns True if the random seed was successfully prepared, false otherwise. + */ bool Transaction::prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputePhaseConfig& cfg) const { // we might use SHA256(block_rand_seed . addr . trans_lt) // instead, we use SHA256(block_rand_seed . addr) @@ -918,6 +1208,15 @@ bool Transaction::prepare_rand_seed(td::BitArray<256>& rand_seed, const ComputeP return true; } +/** + * Prepares the c7 tuple (virtual machine context) for a compute phase of a transaction. + * + * @param cfg The configuration for the compute phase. + * + * @returns A reference to a Tuple object. + * + * @throws CollatorError if the rand_seed cannot be computed for the transaction. + */ Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const { td::BitArray<256> rand_seed; td::RefInt256 rand_seed_int{true}; @@ -947,10 +1246,15 @@ Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const { } tuple.push_back(storage_phase->fees_collected); // storage_fees:Integer - // See crypto/block/mc-config.cpp#2115 (get_prev_blocks_info) + // See crypto/block/mc-config.cpp#2223 (get_prev_blocks_info) // [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId; // [ last_mc_blocks:[BlockId...] // prev_key_block:BlockId ] : PrevBlocksInfo + // The only context where PrevBlocksInfo (13 parameter of c7) is null is inside emulator + // where it need to be set via transaction_emulator_set_prev_blocks_info (see emulator/emulator-extern.cpp) + // Inside validator, collator and liteserver checking external message contexts + // prev_blocks_info is always not null, since get_prev_blocks_info() + // may only return tuple or raise Error (See crypto/block/mc-config.cpp#2223) tuple.push_back(cfg.prev_blocks_info.not_null() ? vm::StackEntry(cfg.prev_blocks_info) : vm::StackEntry()); } auto tuple_ref = td::make_cnt_ref>(std::move(tuple)); @@ -958,6 +1262,13 @@ Ref Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const { return vm::make_tuple_ref(std::move(tuple_ref)); } +/** + * Computes the number of output actions in a list. + * + * @param list c5 cell. + * + * @returns The number of output actions. + */ int output_actions_count(Ref list) { int i = -1; do { @@ -972,6 +1283,13 @@ int output_actions_count(Ref list) { return i; } +/** + * Unpacks the message StateInit. + * + * @param lib_only If true, only unpack libraries from the state. + * + * @returns True if the unpacking is successful, false otherwise. + */ bool Transaction::unpack_msg_state(bool lib_only) { block::gen::StateInit::Record state; if (in_msg_state.is_null() || !tlb::unpack_cell(in_msg_state, state)) { @@ -1002,6 +1320,13 @@ bool Transaction::unpack_msg_state(bool lib_only) { return true; } +/** + * Computes the set of libraries to be used during TVM execution. + * + * @param cfg The configuration for the compute phase. + * + * @returns A vector of hashmaps with libraries. + */ std::vector> Transaction::compute_vm_libraries(const ComputePhaseConfig& cfg) { std::vector> lib_set; if (in_msg_library.not_null()) { @@ -1017,6 +1342,11 @@ std::vector> Transaction::compute_vm_libraries(const ComputePhaseC return lib_set; } +/** + * Checks if the input message StateInit hash corresponds to the account address. + * + * @returns True if the input message state hash is valid, False otherwise. + */ bool Transaction::check_in_msg_state_hash() { CHECK(in_msg_state.not_null()); CHECK(new_split_depth >= 0 && new_split_depth < 32); @@ -1030,6 +1360,13 @@ bool Transaction::check_in_msg_state_hash() { return account.recompute_tmp_addr(my_addr, d, orig_addr_rewrite.bits()); } +/** + * Prepares the compute phase of a transaction, which includes running TVM. + * + * @param cfg The configuration for the compute phase. + * + * @returns True if the compute phase was successfully prepared and executed, false otherwise. + */ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { // TODO: add more skip verifications + sometimes use state from in_msg to re-activate // ... @@ -1188,6 +1525,13 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) { return true; } +/** + * Prepares the action phase of a transaction. + * + * @param cfg The configuration for the action phase. + * + * @returns True if the action phase was prepared successfully, false otherwise. + */ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) { if (!compute_phase || !compute_phase->success) { return false; @@ -1358,6 +1702,15 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) { return true; } +/** + * Tries to set the code for an account. + * + * @param cs The CellSlice containing the action data serialized as action_set_code TLB-scheme. + * @param ap The action phase object. + * @param cfg The action phase configuration. + * + * @returns 0 if the code was successfully set, -1 otherwise. + */ int Transaction::try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { block::gen::OutAction::Record_action_set_code rec; if (!tlb::unpack_exact(cs, rec)) { @@ -1369,6 +1722,19 @@ int Transaction::try_action_set_code(vm::CellSlice& cs, ActionPhase& ap, const A return 0; } +/** + * Tries to change the library in the transaction. + * + * @param cs The cell slice containing the action data serialized as action_change_library TLB-scheme. + * @param ap The action phase object. + * @param cfg The action phase configuration. + * + * @returns 0 if the action was successfully performed, + * -1 if there was an error unpacking the data or the mode is invalid, + * 41 if the library reference is required but is null, + * 43 if the number of cells in the library exceeds the limit, + * 42 if there was a VM error during the operation. + */ int Transaction::try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { block::gen::OutAction::Record_action_change_library rec; if (!tlb::unpack_exact(cs, rec)) { @@ -1435,9 +1801,18 @@ int Transaction::try_action_change_library(vm::CellSlice& cs, ActionPhase& ap, c } } // namespace transaction -// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms -// ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms -// bits in the root cell of a message are not included in msg.bits (lump_price pays for them) +/** + * Computes the forward fees for a message based on the number of cells and bits. + * + * msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms + * ihr_fwd_fees = ceil((msg_fwd_fees * ihr_price_factor)/2^16) nanograms + * bits in the root cell of a message are not included in msg.bits (lump_price pays for them) + * + * @param cells The number of cells in the message. + * @param bits The number of bits in the message. + * + * @returns The computed forward fees for the message. + */ td::uint64 MsgPrices::compute_fwd_fees(td::uint64 cells, td::uint64 bits) const { return lump_price + td::uint128(bit_price) .mult(bits) @@ -1447,6 +1822,15 @@ td::uint64 MsgPrices::compute_fwd_fees(td::uint64 cells, td::uint64 bits) const .lo(); } +/** + * Computes the forward fees and IHR fees for a message with the given number of cells and bits. + * + * @param cells The number of cells. + * @param bits The number of bits. + * @param ihr_disabled Flag indicating whether IHR is disabled. + * + * @returns A pair of values representing the forward fees and IHR fees. + */ std::pair MsgPrices::compute_fwd_ihr_fees(td::uint64 cells, td::uint64 bits, bool ihr_disabled) const { td::uint64 fwd = compute_fwd_fees(cells, bits); @@ -1456,19 +1840,47 @@ std::pair MsgPrices::compute_fwd_ihr_fees(td::uint64 cel return std::pair(fwd, td::uint128(fwd).mult(ihr_factor).shr(16).lo()); } +/** + * Computes the part of the fees that go to the total fees of the current block. + * + * @param total The amount of fees. + * + * @returns The the part of the fees that go to the total fees of the current block. + */ td::RefInt256 MsgPrices::get_first_part(td::RefInt256 total) const { return (std::move(total) * first_frac) >> 16; } +/** + * Computes the part of the fees that go to the total fees of the current block. + * + * @param total The amount of fees. + * + * @returns The the part of the fees that go to the total fees of the current block. + */ td::uint64 MsgPrices::get_first_part(td::uint64 total) const { return td::uint128(total).mult(first_frac).shr(16).lo(); } +/** + * Computes the part of the fees that go to the total fees of the transit block. + * + * @param total The amount of fees. + * + * @returns The the part of the fees that go to the total fees of the transit block. + */ td::RefInt256 MsgPrices::get_next_part(td::RefInt256 total) const { return (std::move(total) * next_frac) >> 16; } namespace transaction { +/** + * Checks if the source address is addr_none and replaces is with the account address. + * + * @param src_addr A reference to the source address of the message. + * + * @returns True if the source address is addr_none or is equal to the account address. + */ bool Transaction::check_replace_src_addr(Ref& src_addr) const { int t = (int)src_addr->prefetch_ulong(2); if (!t && src_addr->size_ext() == 2) { @@ -1489,6 +1901,15 @@ bool Transaction::check_replace_src_addr(Ref& src_addr) const { return false; } +/** + * Checks the destination address of a message, rewrites it if it is an anycast address. + * + * @param dest_addr A reference to the destination address of the transaction. + * @param cfg The configuration for the action phase. + * @param is_mc A pointer to a boolean where it will be stored whether the destination is in the masterchain. + * + * @returns True if the destination address is valid, false otherwise. + */ bool Transaction::check_rewrite_dest_addr(Ref& dest_addr, const ActionPhaseConfig& cfg, bool* is_mc) const { if (!dest_addr->prefetch_ulong(1)) { @@ -1595,6 +2016,17 @@ bool Transaction::check_rewrite_dest_addr(Ref& dest_addr, const A return true; } +/** + * Tries to send a message. + * + * @param cs0 The cell slice containing the action data serialized as action_send_msg TLB-scheme. + * @param ap The action phase. + * @param cfg The action phase configuration. + * @param redoing The index of the attempt, starting from 0. On later attempts tries to move message body and StateInit to separate cells. + * + * @returns 0 if the message is successfully sent or if the error may be ignored, error code otherwise. + * Returns -2 if the action should be attempted again. + */ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, const ActionPhaseConfig& cfg, int redoing) { block::gen::OutAction::Record_action_send_msg act_rec; @@ -1990,6 +2422,15 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap, return 0; } +/** + * Tries to reserve a currency an action phase. + * + * @param cs The cell slice containing the action data serialized as action_reserve_currency TLB-scheme. + * @param ap The action phase. + * @param cfg The action phase configuration. + * + * @returns 0 if the currency is successfully reserved, error code otherwise. + */ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, const ActionPhaseConfig& cfg) { block::gen::OutAction::Record_action_reserve_currency rec; if (!tlb::unpack_exact(cs, rec)) { @@ -2060,6 +2501,15 @@ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap, return 0; } +/** + * Checks that the new account state fits in the limits. + * + * @param cfg The configuration for the action phase. + * + * @returns A `td::Status` indicating the result of the check. + * - If the state limits are within the allowed range, returns OK. + * - If the state limits exceed the maximum allowed range, returns an error. + */ td::Status Transaction::check_state_limits(const ActionPhaseConfig& cfg) { auto cell_equal = [](const td::Ref& a, const td::Ref& b) -> bool { if (a.is_null()) { @@ -2104,6 +2554,13 @@ td::Status Transaction::check_state_limits(const ActionPhaseConfig& cfg) { : td::Status::Error("state too big"); } +/** + * Prepares the bounce phase of a transaction. + * + * @param cfg The configuration for the action phase. + * + * @returns True if the bounce phase was successfully prepared, false otherwise. + */ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) { if (in_msg.is_null() || !bounce_enabled) { return false; @@ -2209,6 +2666,14 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) { * */ +/** + * Stores the account status in a CellBuilder object. + * + * @param cb The CellBuilder object to store the account status in. + * @param acc_status The account status to store. + * + * @returns True if the account status was successfully stored, false otherwise. + */ bool Account::store_acc_status(vm::CellBuilder& cb, int acc_status) const { int v; switch (acc_status) { @@ -2231,6 +2696,17 @@ bool Account::store_acc_status(vm::CellBuilder& cb, int acc_status) const { return cb.store_long_bool(v, 2); } +/** + * Tries to update the storage statistics based on the old storage statistics and old account state without fully recomputing it. + * + * It succeeds if only root cell of AccountStorage is changed. + * + * @param old_stat The old storage statistics. + * @param old_cs The old AccountStorage. + * @param new_cell The new AccountStorage. + * + * @returns An optional value of type vm::CellStorageStat. If the update is successful, it returns the new storage statistics. Otherwise, it returns an empty optional. + */ static td::optional try_update_storage_stat(const vm::CellStorageStat& old_stat, td::Ref old_cs, td::Ref new_cell) { @@ -2258,6 +2734,11 @@ static td::optional try_update_storage_stat(const vm::CellS } namespace transaction { +/** + * Computes the new state of the account. + * + * @returns True if the state computation is successful, false otherwise. + */ bool Transaction::compute_state() { if (new_total_state.not_null()) { return true; @@ -2360,6 +2841,13 @@ bool Transaction::compute_state() { return true; } +/** + * Serializes the transaction object using Transaction TLB-scheme. + * + * Updates root. + * + * @returns True if the serialization is successful, False otherwise. + */ bool Transaction::serialize() { if (root.not_null()) { return true; @@ -2462,6 +2950,13 @@ bool Transaction::serialize() { return true; } +/** + * Serializes the storage phase of a transaction. + * + * @param cb The CellBuilder to store the serialized data. + * + * @returns True if the serialization is successful, false otherwise. + */ bool Transaction::serialize_storage_phase(vm::CellBuilder& cb) { if (!storage_phase) { return false; @@ -2485,6 +2980,13 @@ bool Transaction::serialize_storage_phase(vm::CellBuilder& cb) { return ok; } +/** + * Serializes the credit phase of a transaction. + * + * @param cb The CellBuilder to store the serialized data. + * + * @returns True if the credit phase was successfully serialized, false otherwise. + */ bool Transaction::serialize_credit_phase(vm::CellBuilder& cb) { if (!credit_phase) { return false; @@ -2494,6 +2996,13 @@ bool Transaction::serialize_credit_phase(vm::CellBuilder& cb) { return block::store_Maybe_Grams_nz(cb, cp.due_fees_collected) && cp.credit.store(cb); } +/** + * Serializes the compute phase of a transaction. + * + * @param cb The CellBuilder to store the serialized data. + * + * @returns True if the serialization was successful, false otherwise. + */ bool Transaction::serialize_compute_phase(vm::CellBuilder& cb) { if (!compute_phase) { return false; @@ -2536,6 +3045,13 @@ bool Transaction::serialize_compute_phase(vm::CellBuilder& cb) { return ok; } +/** + * Serializes the action phase of a transaction. + * + * @param cb The CellBuilder to store the serialized data. + * + * @returns True if the serialization is successful, false otherwise. + */ bool Transaction::serialize_action_phase(vm::CellBuilder& cb) { if (!action_phase) { return false; @@ -2560,6 +3076,13 @@ bool Transaction::serialize_action_phase(vm::CellBuilder& cb) { return ok; } +/** + * Serializes the bounce phase of a transaction. + * + * @param cb The CellBuilder to store the serialized data. + * + * @returns True if the bounce phase was successfully serialized, false otherwise. + */ bool Transaction::serialize_bounce_phase(vm::CellBuilder& cb) { if (!bounce_phase) { return false; @@ -2580,6 +3103,15 @@ bool Transaction::serialize_bounce_phase(vm::CellBuilder& cb) { } } +/** + * Estimates the block storage profile increment if the transaction is added to the block. + * + * @param store_stat The current storage statistics of the block. + * @param usage_tree The usage tree of the block. + * + * @returns The estimated block storage profile increment. + * Returns Error if the transaction is not serialized or if its new state is not computed. + */ td::Result Transaction::estimate_block_storage_profile_incr( const vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const { if (root.is_null()) { @@ -2591,26 +3123,14 @@ td::Result Transaction::estimate_block_storage_pro return store_stat.tentative_add_proof(new_total_state, usage_tree) + store_stat.tentative_add_cell(root); } -bool Transaction::update_block_storage_profile(vm::NewCellStorageStat& store_stat, - const vm::CellUsageTree* usage_tree) const { - if (root.is_null() || new_total_state.is_null()) { - return false; - } - store_stat.add_proof(new_total_state, usage_tree); - store_stat.add_cell(root); - return true; -} - -bool Transaction::would_fit(unsigned cls, const block::BlockLimitStatus& blimst) const { - auto res = estimate_block_storage_profile_incr(blimst.st_stat, blimst.limits.usage_tree); - if (res.is_error()) { - LOG(ERROR) << res.move_as_error(); - return false; - } - auto extra = res.move_as_ok(); - return blimst.would_fit(cls, end_lt, gas_used(), &extra); -} - +/** + * Updates the limits status of a block. + * + * @param blimst The block limit status object to update. + * @param with_size Flag indicating whether to update the size limits. + * + * @returns True if the limits were successfully updated, False otherwise. + */ bool Transaction::update_limits(block::BlockLimitStatus& blimst, bool with_size) const { if (!(blimst.update_lt(end_lt) && blimst.update_gas(gas_used()))) { return false; @@ -2628,6 +3148,13 @@ bool Transaction::update_limits(block::BlockLimitStatus& blimst, bool with_size) * */ +/** + * Commits a transaction for a given account. + * + * @param acc The account to commit the transaction for. + * + * @returns A reference to the root cell of the serialized transaction. + */ Ref Transaction::commit(Account& acc) { CHECK(account.last_trans_end_lt_ <= start_lt && start_lt < end_lt); CHECK(root.not_null()); @@ -2672,14 +3199,33 @@ Ref Transaction::commit(Account& acc) { return root; } +/** + * Extracts the output message at the specified index from the transaction. + * + * @param i The index of the output message to extract. + * + * @returns A pair of the logical time and the extracted output message. + */ LtCellRef Transaction::extract_out_msg(unsigned i) { return {start_lt + i + 1, std::move(out_msgs.at(i))}; } +/** + * Extracts the output message at index i from the transaction. + * + * @param i The index of the output message to extract. + * + * @returns A triple of the logical time, the extracted output message and the transaction root. + */ NewOutMsg Transaction::extract_out_msg_ext(unsigned i) { return {start_lt + i + 1, std::move(out_msgs.at(i)), root}; } +/** + * Extracts the outgoing messages from the transaction and adds them to the given list. + * + * @param list The list to which the outgoing messages will be added. + */ void Transaction::extract_out_msgs(std::vector& list) { for (unsigned i = 0; i < out_msgs.size(); i++) { list.emplace_back(start_lt + i + 1, std::move(out_msgs[i])); @@ -2687,10 +3233,23 @@ void Transaction::extract_out_msgs(std::vector& list) { } } // namespace transaction +/** + * Adds a transaction to the account's transaction list. + * + * @param trans_root The root of the transaction cell. + * @param trans_lt The logical time of the transaction. + */ void Account::push_transaction(Ref trans_root, ton::LogicalTime trans_lt) { transactions.emplace_back(trans_lt, std::move(trans_root)); } +/** + * Serializes an account block for the account using AccountBlock TLB-scheme. + * + * @param cb The CellBuilder used to store the serialized data. + * + * @returns True if the account block was successfully created, false otherwise. + */ bool Account::create_account_block(vm::CellBuilder& cb) { if (transactions.empty()) { return false; @@ -2719,6 +3278,11 @@ bool Account::create_account_block(vm::CellBuilder& cb) { && cb.store_ref_bool(cb2.finalize()); // state_update:^(HASH_UPDATE Account) } +/** + * Checks if the libraries stored in the account object have changed. + * + * @returns True if the libraries have changed, False otherwise. + */ bool Account::libraries_changed() const { bool s = orig_library.not_null(); bool t = library.not_null(); @@ -2729,6 +3293,21 @@ bool Account::libraries_changed() const { } } +/** + * Fetches and initializes various configuration parameters from masterchain config for transaction processing. + * + * @param config The masterchain configuration. + * @param old_mparams Pointer to store a dictionary of mandatory parameters (ConfigParam 9). + * @param storage_prices Pointer to store the storage prices. + * @param storage_phase_cfg Pointer to store the storage phase configuration. + * @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`. + * @param compute_phase_cfg Pointer to store the compute phase configuration. + * @param action_phase_cfg Pointer to store the action phase configuration. + * @param masterchain_create_fee Pointer to store the masterchain create fee. + * @param basechain_create_fee Pointer to store the basechain create fee. + * @param wc The workchain ID. + * @param now The current Unix time. + */ td::Status FetchConfigParams::fetch_config_params( const block::ConfigInfo& config, Ref* old_mparams, std::vector* storage_prices, StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg, @@ -2744,6 +3323,22 @@ td::Status FetchConfigParams::fetch_config_params( basechain_create_fee, wc, now); } +/** + * Fetches and initializes various configuration parameters from masterchain config for transaction processing. + * + * @param config The masterchain configuration. + * @param prev_blocks_info The tuple with information about previous blocks. + * @param old_mparams Pointer to store a dictionary of mandatory parameters (ConfigParam 9). + * @param storage_prices Pointer to store the storage prices. + * @param storage_phase_cfg Pointer to store the storage phase configuration. + * @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`. + * @param compute_phase_cfg Pointer to store the compute phase configuration. + * @param action_phase_cfg Pointer to store the action phase configuration. + * @param masterchain_create_fee Pointer to store the masterchain create fee. + * @param basechain_create_fee Pointer to store the basechain create fee. + * @param wc The workchain ID. + * @param now The current Unix time. + */ td::Status FetchConfigParams::fetch_config_params( const block::Config& config, td::Ref prev_blocks_info, Ref* old_mparams, std::vector* storage_prices, StoragePhaseConfig* storage_phase_cfg, diff --git a/crypto/block/transaction.h b/crypto/block/transaction.h index 3ae8cdf88..6bb47fd99 100644 --- a/crypto/block/transaction.h +++ b/crypto/block/transaction.h @@ -270,7 +270,7 @@ struct Account { return balance; } bool set_address(ton::WorkchainId wc, td::ConstBitPtr new_addr); - bool unpack(Ref account, Ref extra, ton::UnixTime now, bool special = false); + bool unpack(Ref account, ton::UnixTime now, bool special); bool init_new(ton::UnixTime now); bool deactivate(); bool recompute_tmp_addr(Ref& tmp_addr, int split_depth, td::ConstBitPtr orig_addr_rewrite) const; @@ -382,8 +382,6 @@ struct Transaction { td::Result estimate_block_storage_profile_incr( const vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const; - bool update_block_storage_profile(vm::NewCellStorageStat& store_stat, const vm::CellUsageTree* usage_tree) const; - bool would_fit(unsigned cls, const block::BlockLimitStatus& blk_lim_st) const; bool update_limits(block::BlockLimitStatus& blk_lim_st, bool with_size = true) const; Ref commit(Account& _account); // _account should point to the same account diff --git a/crypto/common/bitstring.cpp b/crypto/common/bitstring.cpp index c10a4ff33..5135cdf0d 100644 --- a/crypto/common/bitstring.cpp +++ b/crypto/common/bitstring.cpp @@ -130,7 +130,7 @@ void bits_memcpy(unsigned char* to, int to_offs, const unsigned char* from, int from_offs &= 7; to_offs &= 7; //fprintf(stderr, "bits_memcpy: from=%p (%02x) to=%p (%02x) from_offs=%d to_offs=%d count=%lu\n", from, *from, to, *to, from_offs, to_offs, bit_count); - int sz = (int)bit_count; + int sz = static_cast(bit_count); bit_count += from_offs; if (from_offs == to_offs) { if (bit_count < 8) { @@ -206,7 +206,7 @@ void bits_memset(unsigned char* to, int to_offs, bool val, std::size_t bit_count } to += (to_offs >> 3); to_offs &= 7; - int sz = (int)bit_count; + int sz = static_cast(bit_count); bit_count += to_offs; int c = *to; if (bit_count <= 8) { diff --git a/crypto/fift/lib/Asm.fif b/crypto/fift/lib/Asm.fif index d9cee5d83..a0bfe6429 100644 --- a/crypto/fift/lib/Asm.fif +++ b/crypto/fift/lib/Asm.fif @@ -461,19 +461,109 @@ x{B7A3} @Defop QNEGATE x{B7A4} @Defop QINC x{B7A5} @Defop QDEC x{B7A8} @Defop QMUL + x{B7A904} @Defop QDIV x{B7A905} @Defop QDIVR x{B7A906} @Defop QDIVC x{B7A908} @Defop QMOD +x{B7A909} @Defop QMODR +x{B7A90A} @Defop QMODC x{B7A90C} @Defop QDIVMOD x{B7A90D} @Defop QDIVMODR x{B7A90E} @Defop QDIVMODC x{B7A900} @Defop QADDDIVMOD x{B7A901} @Defop QADDDIVMODR x{B7A902} @Defop QADDDIVMODC + +x{B7A925} @Defop QRSHIFTR +x{B7A926} @Defop QRSHIFTC +x{B7A928} @Defop QMODPOW2 +x{B7A929} @Defop QMODPOW2R +x{B7A92A} @Defop QMODPOW2C +x{B7A92C} @Defop QRSHIFTMOD +x{B7A92D} @Defop QRSHIFTMODR +x{B7A92E} @Defop QRSHIFTMODC +x{B7A920} @Defop QADDRSHIFTMOD +x{B7A921} @Defop QADDRSHIFTMODR +x{B7A922} @Defop QADDRSHIFTMODC + +x{B7A935} @Defop(8u+1) QRSHIFTR# +x{B7A936} @Defop(8u+1) QRSHIFTC# +x{B7A938} @Defop(8u+1) QMODPOW2# +x{B7A939} @Defop(8u+1) QMODPOW2R# +x{B7A93A} @Defop(8u+1) QMODPOW2C# +x{B7A93C} @Defop(8u+1) QRSHIFT#MOD +x{B7A93D} @Defop(8u+1) QRSHIFTR#MOD +x{B7A93E} @Defop(8u+1) QRSHIFTC#MOD +x{B7A930} @Defop(8u+1) QADDRSHIFT#MOD +x{B7A931} @Defop(8u+1) QADDRSHIFTR#MOD +x{B7A932} @Defop(8u+1) QADDRSHIFTC#MOD + +x{B7A984} @Defop QMULDIV x{B7A985} @Defop QMULDIVR +x{B7A986} @Defop QMULDIVC +x{B7A988} @Defop QMULMOD +x{B7A989} @Defop QMULMODR +x{B7A98A} @Defop QMULMODC x{B7A98C} @Defop QMULDIVMOD -x{B7A980} @Defop QADDMULDIVMOD +x{B7A98D} @Defop QMULDIVMODR +x{B7A98E} @Defop QMULDIVMODC +x{B7A980} @Defop QMULADDDIVMOD +x{B7A981} @Defop QMULADDDIVMODR +x{B7A982} @Defop QMULADDDIVMODC + +x{B7A9A4} @Defop QMULRSHIFT +x{B7A9A5} @Defop QMULRSHIFTR +x{B7A9A6} @Defop QMULRSHIFTC +x{B7A9A8} @Defop QMULMODPOW2 +x{B7A9A9} @Defop QMULMODPOW2R +x{B7A9AA} @Defop QMULMODPOW2C +x{B7A9AC} @Defop QMULRSHIFTMOD +x{B7A9AD} @Defop QMULRSHIFTRMOD +x{B7A9AE} @Defop QMULRSHIFTCMOD +x{B7A9A0} @Defop QMULADDRSHIFTMOD +x{B7A9A1} @Defop QMULADDRSHIFTRMOD +x{B7A9A2} @Defop QMULADDRSHIFTCMOD + +x{B7A9B4} @Defop(8u+1) QMULRSHIFT# +x{B7A9B5} @Defop(8u+1) QMULRSHIFTR# +x{B7A9B6} @Defop(8u+1) QMULRSHIFTC# +x{B7A9B8} @Defop(8u+1) QMULMODPOW2# +x{B7A9B9} @Defop(8u+1) QMULMODPOW2R# +x{B7A9BA} @Defop(8u+1) QMULMODPOW2C# +x{B7A9BC} @Defop(8u+1) QMULRSHIFT#MOD +x{B7A9BD} @Defop(8u+1) QMULRSHIFTR#MOD +x{B7A9BE} @Defop(8u+1) QMULRSHIFTC#MOD +x{B7A9B0} @Defop(8u+1) QMULADDRSHIFT#MOD +x{B7A9B1} @Defop(8u+1) QMULADDRSHIFTR#MOD +x{B7A9B2} @Defop(8u+1) QMULADDRSHIFTC#MOD + +x{B7A9C4} @Defop QLSHIFTDIV +x{B7A9C5} @Defop QLSHIFTDIVR +x{B7A9C6} @Defop QLSHIFTDIVC +x{B7A9C8} @Defop QLSHIFTMOD +x{B7A9C9} @Defop QLSHIFTMODR +x{B7A9CA} @Defop QLSHIFTMODC +x{B7A9CC} @Defop QLSHIFTDIVMOD +x{B7A9CD} @Defop QLSHIFTDIVMODR +x{B7A9CE} @Defop QLSHIFTDIVMODC +x{B7A9C0} @Defop QLSHIFTADDDIVMOD +x{B7A9C1} @Defop QLSHIFTADDDIVMODR +x{B7A9C2} @Defop QLSHIFTADDDIVMODC + +x{B7A9D4} @Defop(8u+1) QLSHIFT#DIV +x{B7A9D5} @Defop(8u+1) QLSHIFT#DIVR +x{B7A9D6} @Defop(8u+1) QLSHIFT#DIVC +x{B7A9D8} @Defop(8u+1) QLSHIFT#MOD +x{B7A9D9} @Defop(8u+1) QLSHIFT#MODR +x{B7A9DA} @Defop(8u+1) QLSHIFT#MODC +x{B7A9DC} @Defop(8u+1) QLSHIFT#DIVMOD +x{B7A9DD} @Defop(8u+1) QLSHIFT#DIVMODR +x{B7A9DE} @Defop(8u+1) QLSHIFT#DIVMODC +x{B7A9D0} @Defop(8u+1) QLSHIFT#ADDDIVMOD +x{B7A9D1} @Defop(8u+1) QLSHIFT#ADDDIVMODR +x{B7A9D2} @Defop(8u+1) QLSHIFT#ADDDIVMODC + x{B7AC} @Defop QLSHIFT x{B7AD} @Defop QRSHIFT x{B7AE} @Defop QPOW2 @@ -1185,7 +1275,7 @@ x{F4BF} @Defop DICTUGETEXECZ x{F800} @Defop ACCEPT x{F801} @Defop SETGASLIMIT -x{F802} @Defop GASCONSUMED +x{F806} @Defop GASCONSUMED x{F80F} @Defop COMMIT x{F810} @Defop RANDU256 diff --git a/crypto/fift/words.cpp b/crypto/fift/words.cpp index 56dd4de22..8d652afcc 100644 --- a/crypto/fift/words.cpp +++ b/crypto/fift/words.cpp @@ -3512,7 +3512,7 @@ void init_words_ton(Dictionary& d) { void init_words_vm(Dictionary& d, bool enable_debug) { using namespace std::placeholders; - vm::init_op_cp0(enable_debug); + vm::init_vm(enable_debug).ensure(); // vm run d.def_word("vmlibs ", LitCont::literal(vm_libraries)); // d.def_ctx_word("runvmcode ", std::bind(interpret_run_vm, _1, 0x40)); diff --git a/crypto/func/auto-tests/legacy_tester.py b/crypto/func/auto-tests/legacy_tester.py index e852a0434..9a9905012 100644 --- a/crypto/func/auto-tests/legacy_tester.py +++ b/crypto/func/auto-tests/legacy_tester.py @@ -8,37 +8,37 @@ add_pragmas = [] #["allow-post-modification", "compute-asm-ltr"]; tests = [ - # note, that deployed version of elector,config and multisig differ since it is compilled with func-0.1.0. - # Newer compillators optimize arithmetic and logic expression that can be calculated at the compile time - ["elector/elector-code.fc", 115226404411715505328583639896096915745686314074575650766750648324043316883483], - ["config/config-code.fc", 10913070768607625342121305745084703121685937915388357634624451844356456145601], - ["eth-bridge-multisig/multisig-code.fc", 101509909129354488841890823627011033360100627957439967918234053299675481277954], - - ["bsc-bridge-collector/votes-collector.fc", 62190447221288642706570413295807615918589884489514159926097051017036969900417], - ["uni-lock-wallet/uni-lockup-wallet.fc", 61959738324779104851267145467044677651344601417998258530238254441977103654381], - ["nft-collection/nft-collection-editable.fc", 45561997735512210616567774035540357815786262097548276229169737015839077731274], - ["dns-collection/nft-collection.fc", 107999822699841936063083742021519765435859194241091312445235370766165379261859], - - - # note, that deployed version of tele-nft-item differs since it is compilled with func-0.3.0. - # After introducing of try/catch construction, c2 register is not always the default one. - # Thus it is necessary to save it upon jumps, differences of deployed and below compilled is that - # "c2 SAVE" is added to the beginning of recv_internal. It does not change behavior. - ["tele-nft-item/nft-item.fc", 69777543125381987786450436977742010705076866061362104025338034583422166453344], - - ["storage/storage-contract.fc", 91377830060355733016937375216020277778264560226873154627574229667513068328151], - ["storage/storage-provider.fc", 13618336676213331164384407184540461509022654507176709588621016553953760588122], - ["nominator-pool/pool.fc", 69767057279163099864792356875696330339149706521019810113334238732928422055375], - ["jetton-minter/jetton-minter.fc", 9028309926287301331466371999814928201427184114165428257502393474125007156494], - ["gg-marketplace/nft-marketplace-v2.fc", 92199806964112524639740773542356508485601908152150843819273107618799016205930], - ["jetton-wallet/jetton-wallet.fc", 86251125787443633057458168028617933212663498001665054651523310772884328206542], - ["whales-nominators/nominators.fc", 8941364499854379927692172316865293429893094891593442801401542636695127885153], - - - ["tact-examples/treasure_Treasure.code.fc", 13962538639825790677138656603323869918938565499584297120566680287245364723897], - ["tact-examples/jetton_SampleJetton.code.fc", 94076762218493729104783735200107713211245710256802265203823917715299139499110], - ["tact-examples/jetton_JettonDefaultWallet.code.fc", 29421313492520031238091587108198906058157443241743283101866538036369069620563], - ["tact-examples/maps_MapTestContract.code.fc", 22556550222249123835909180266811414538971143565993192846012583552876721649744], + # note, that deployed version of elector,config and multisig differ since it is compilled with func-0.1.0. + # Newer compillators optimize arithmetic and logic expression that can be calculated at the compile time + ["elector/elector-code.fc", 115226404411715505328583639896096915745686314074575650766750648324043316883483], + ["config/config-code.fc", 10913070768607625342121305745084703121685937915388357634624451844356456145601], + ["eth-bridge-multisig/multisig-code.fc", 101509909129354488841890823627011033360100627957439967918234053299675481277954], + + ["bsc-bridge-collector/votes-collector.fc", 62190447221288642706570413295807615918589884489514159926097051017036969900417], + ["uni-lock-wallet/uni-lockup-wallet.fc", 61959738324779104851267145467044677651344601417998258530238254441977103654381], + ["nft-collection/nft-collection-editable.fc", 45561997735512210616567774035540357815786262097548276229169737015839077731274], + ["dns-collection/nft-collection.fc", 107999822699841936063083742021519765435859194241091312445235370766165379261859], + + + # note, that deployed version of tele-nft-item differs since it is compilled with func-0.3.0. + # After introducing of try/catch construction, c2 register is not always the default one. + # Thus it is necessary to save it upon jumps, differences of deployed and below compilled is that + # "c2 SAVE" is added to the beginning of recv_internal. It does not change behavior. + ["tele-nft-item/nft-item.fc", 69777543125381987786450436977742010705076866061362104025338034583422166453344], + + ["storage/storage-contract.fc", 91377830060355733016937375216020277778264560226873154627574229667513068328151], + ["storage/storage-provider.fc", 13618336676213331164384407184540461509022654507176709588621016553953760588122], + ["nominator-pool/pool.fc", 69767057279163099864792356875696330339149706521019810113334238732928422055375], + ["jetton-minter/jetton-minter.fc", 9028309926287301331466371999814928201427184114165428257502393474125007156494], + ["gg-marketplace/nft-marketplace-v2.fc", 92199806964112524639740773542356508485601908152150843819273107618799016205930], + ["jetton-wallet/jetton-wallet.fc", 86251125787443633057458168028617933212663498001665054651523310772884328206542], + ["whales-nominators/nominators.fc", 8941364499854379927692172316865293429893094891593442801401542636695127885153], + + + ["tact-examples/treasure_Treasure.code.fc", 13962538639825790677138656603323869918938565499584297120566680287245364723897], + ["tact-examples/jetton_SampleJetton.code.fc", 94076762218493729104783735200107713211245710256802265203823917715299139499110], + ["tact-examples/jetton_JettonDefaultWallet.code.fc", 29421313492520031238091587108198906058157443241743283101866538036369069620563], + ["tact-examples/maps_MapTestContract.code.fc", 22556550222249123835909180266811414538971143565993192846012583552876721649744], ] def getenv(name, default=None): @@ -51,7 +51,6 @@ def getenv(name, default=None): FUNC_EXECUTABLE = getenv("FUNC_EXECUTABLE", "func") FIFT_EXECUTABLE = getenv("FIFT_EXECUTABLE", "fift") -FIFT_LIBS = getenv("FIFTPATH") TMP_DIR = tempfile.mkdtemp() COMPILED_FIF = os.path.join(TMP_DIR, "compiled.fif") @@ -63,49 +62,49 @@ class ExecutionError(Exception): pass def pre_process_func(f): - shutil.copyfile(f, f+"_backup") - with open(f, "r") as src: - sources = src.read() - with open(f, "w") as src: - for pragma in add_pragmas: - src.write("#pragma %s;\n"%pragma) - src.write(sources) + shutil.copyfile(f, f+"_backup") + with open(f, "r") as src: + sources = src.read() + with open(f, "w") as src: + for pragma in add_pragmas: + src.write("#pragma %s;\n"%pragma) + src.write(sources) def post_process_func(f): - shutil.move(f+"_backup", f) + shutil.move(f+"_backup", f) def compile_func(f): res = None try: pre_process_func(f) if "storage-provider.fc" in f : - # This contract requires building of storage-contract to include it as ref - with open(f, "r") as src: - sources = src.read() + # This contract requires building of storage-contract to include it as ref + with open(f, "r") as src: + sources = src.read() + COMPILED_ST_BOC = os.path.join(TMP_DIR, "storage-contract-code.boc") + sources = sources.replace("storage-contract-code.boc", COMPILED_ST_BOC) + with open(f, "w") as src: + src.write(sources) + COMPILED_ST_FIF = os.path.join(TMP_DIR, "storage-contract.fif") COMPILED_ST_BOC = os.path.join(TMP_DIR, "storage-contract-code.boc") - sources = sources.replace("storage-contract-code.boc", COMPILED_ST_BOC) - with open(f, "w") as src: - src.write(sources) - COMPILED_ST_FIF = os.path.join(TMP_DIR, "storage-contract.fif") - COMPILED_ST_BOC = os.path.join(TMP_DIR, "storage-contract-code.boc") - COMPILED_BUILD_BOC = os.path.join(TMP_DIR, "build-boc.fif") - res = subprocess.run([FUNC_EXECUTABLE, "-o", COMPILED_ST_FIF, "-SPA", f.replace("storage-provider.fc","storage-contract.fc")], capture_output=False, timeout=10) - with open(COMPILED_BUILD_BOC, "w") as scr: - scr.write("\"%s\" include boc>B \"%s\" B>file "%(COMPILED_ST_FIF, COMPILED_ST_BOC)) - res = subprocess.run([FIFT_EXECUTABLE, COMPILED_BUILD_BOC ], capture_output=True, timeout=10) - - + COMPILED_BUILD_BOC = os.path.join(TMP_DIR, "build-boc.fif") + res = subprocess.run([FUNC_EXECUTABLE, "-o", COMPILED_ST_FIF, "-SPA", f.replace("storage-provider.fc","storage-contract.fc")], capture_output=False, timeout=10) + with open(COMPILED_BUILD_BOC, "w") as scr: + scr.write("\"%s\" include boc>B \"%s\" B>file "%(COMPILED_ST_FIF, COMPILED_ST_BOC)) + res = subprocess.run([FIFT_EXECUTABLE, COMPILED_BUILD_BOC ], capture_output=True, timeout=10) + + res = subprocess.run([FUNC_EXECUTABLE, "-o", COMPILED_FIF, "-SPA", f], capture_output=True, timeout=10) except Exception as e: - post_process_func(f) - raise e + post_process_func(f) + raise e else: - post_process_func(f) + post_process_func(f) if res.returncode != 0: raise ExecutionError(str(res.stderr, "utf-8")) def run_runner(): - res = subprocess.run([FIFT_EXECUTABLE, "-I", FIFT_LIBS, RUNNER_FIF], capture_output=True, timeout=10) + res = subprocess.run([FIFT_EXECUTABLE, RUNNER_FIF], capture_output=True, timeout=10) if res.returncode != 0: raise ExecutionError(str(res.stderr, "utf-8")) s = str(res.stdout, "utf-8") @@ -138,16 +137,15 @@ def get_version(): try: func_out = run_runner() if func_out != th: - raise ExecutionError("Error : expected '%d', found '%d'" % (th, func_out)) + raise ExecutionError("Error : expected '%d', found '%d'" % (th, func_out)) success += 1 except ExecutionError as e: print(e, file=sys.stderr) - #print("Compiled:", file=sys.stderr) - #with open(COMPILED_FIF, "r") as f: - # print(f.read(), file=sys.stderr) - #exit(2) + print("Compiled:", file=sys.stderr) + with open(COMPILED_FIF, "r") as f: + print(f.read(), file=sys.stderr) + exit(2) print(" OK ", file=sys.stderr) print(get_version()) -print("Done: Success %d, Error: %d"%(success, len(tests)-success), file=sys.stderr) - +print("Done: Success %d, Error: %d"%(success, len(tests)-success), file=sys.stderr) \ No newline at end of file diff --git a/crypto/func/auto-tests/run_tests.py b/crypto/func/auto-tests/run_tests.py index 0f12332d0..158e871b8 100644 --- a/crypto/func/auto-tests/run_tests.py +++ b/crypto/func/auto-tests/run_tests.py @@ -4,6 +4,7 @@ import sys import tempfile + def getenv(name, default=None): if name in os.environ: return os.environ[name] @@ -12,10 +13,9 @@ def getenv(name, default=None): exit(1) return default + FUNC_EXECUTABLE = getenv("FUNC_EXECUTABLE", "func") FIFT_EXECUTABLE = getenv("FIFT_EXECUTABLE", "fift") -#FUNC_STDLIB = getenv("FUNC_STDLIB") -FIFT_LIBS = getenv("FIFT_LIBS") TMP_DIR = tempfile.mkdtemp() COMPILED_FIF = os.path.join(TMP_DIR, "compiled.fif") RUNNER_FIF = os.path.join(TMP_DIR, "runner.fif") @@ -25,22 +25,26 @@ def getenv(name, default=None): exit(1) TESTS_DIR = sys.argv[1] + class ExecutionError(Exception): pass + def compile_func(f): res = subprocess.run([FUNC_EXECUTABLE, "-o", COMPILED_FIF, "-SPA", f], capture_output=True, timeout=10) if res.returncode != 0: raise ExecutionError(str(res.stderr, "utf-8")) + def run_runner(): - res = subprocess.run([FIFT_EXECUTABLE, "-I", FIFT_LIBS, RUNNER_FIF], capture_output=True, timeout=10) + res = subprocess.run([FIFT_EXECUTABLE, RUNNER_FIF], capture_output=True, timeout=10) if res.returncode != 0: raise ExecutionError(str(res.stderr, "utf-8")) s = str(res.stdout, "utf-8") s = [x.strip() for x in s.split("\n")] return [x for x in s if x != ""] + tests = [s for s in os.listdir(TESTS_DIR) if s.endswith(".fc")] tests.sort() print("Found", len(tests), "tests", file=sys.stderr) @@ -68,18 +72,18 @@ def run_runner(): # preprocess arithmetics in input for i in range(len(cases)): - inputs = cases[i][1].split(" ") - processed_inputs = "" - for in_arg in inputs: - if "x{" in in_arg: - processed_inputs += in_arg - continue - # filter and execute - # is it safe enough? - filtered_in = "".join(filter(lambda x: x in "0x123456789()+-*/<>", in_arg)) - if(filtered_in): - processed_inputs += str(eval(filtered_in)) + " "; - cases[i][1] = processed_inputs.strip() + inputs = cases[i][1].split(" ") + processed_inputs = "" + for in_arg in inputs: + if "x{" in in_arg: + processed_inputs += in_arg + continue + # filter and execute + # is it safe enough? + filtered_in = "".join(filter(lambda x: x in "0x123456789()+-*/<>", in_arg)) + if filtered_in: + processed_inputs += str(eval(filtered_in)) + " " + cases[i][1] = processed_inputs.strip() with open(RUNNER_FIF, "w") as f: print("\"%s\" include >(std::istream& is, Bignum& x) { return is; } -bool is_prime(const Bignum& p, int nchecks, bool trial_div) { - return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), trial_div, 0); +bool is_prime(const Bignum& p) { +#if OPENSSL_VERSION_MAJOR >= 3 + int result = BN_check_prime(p.bn_ptr(), get_ctx(), nullptr); + LOG_IF(FATAL, result == -1); + return result; +#else + return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), true, 0); +#endif } } // namespace arith diff --git a/crypto/openssl/bignum.h b/crypto/openssl/bignum.h index 2a8dd8a02..032dbb025 100644 --- a/crypto/openssl/bignum.h +++ b/crypto/openssl/bignum.h @@ -335,7 +335,7 @@ const Bignum sqr(const Bignum& x); std::ostream& operator<<(std::ostream& os, const Bignum& x); std::istream& operator>>(std::istream& is, Bignum& x); -bool is_prime(const Bignum& p, int nchecks = 64, bool trial_div = true); +bool is_prime(const Bignum& p); inline int cmp(const Bignum& x, const Bignum& y) { return BN_cmp(x.bn_ptr(), y.bn_ptr()); diff --git a/crypto/parser/lexer.cpp b/crypto/parser/lexer.cpp index 624d8dd2b..117f1df5a 100644 --- a/crypto/parser/lexer.cpp +++ b/crypto/parser/lexer.cpp @@ -250,7 +250,6 @@ const Lexem& Lexer::next() { } if (is_multiline_quote(src.get_ptr(), src.get_end_ptr())) { src.advance(multiline_quote.size()); - const char* begin = src.get_ptr(); const char* end = nullptr; SrcLocation here = src.here(); std::string body; diff --git a/crypto/smc-envelope/ManualDns.h b/crypto/smc-envelope/ManualDns.h index b5dee59a2..d24cd0234 100644 --- a/crypto/smc-envelope/ManualDns.h +++ b/crypto/smc-envelope/ManualDns.h @@ -305,7 +305,7 @@ class ManualDns : public ton::SmartContract, public DnsInterface { if (!info.known_category.insert(action.category).second) { continue; } - if (action.category == 0) { + if (action.category.is_zero()) { info.closed = true; auto old_actions = std::move(info.actions); bool is_empty = true; @@ -327,7 +327,7 @@ class ManualDns : public ton::SmartContract, public DnsInterface { if (info.closed) { CombinedActions ca; ca.name = it.first; - ca.category = 0; + ca.category = td::Bits256::zero(); if (!info.actions.empty() || info.non_empty) { ca.actions = std::move(info.actions); } diff --git a/crypto/smc-envelope/SmartContract.cpp b/crypto/smc-envelope/SmartContract.cpp index 64e269444..b56810b03 100644 --- a/crypto/smc-envelope/SmartContract.cpp +++ b/crypto/smc-envelope/SmartContract.cpp @@ -181,7 +181,7 @@ SmartContract::Answer run_smartcont(SmartContract::State state, td::Ref config) { auto gas_credit = gas.gas_credit; - vm::init_op_cp0(debug_enabled); + vm::init_vm(debug_enabled).ensure(); vm::DictionaryBase::get_empty_dictionary(); class Logger : public td::LogInterface { diff --git a/crypto/test/fift.cpp b/crypto/test/fift.cpp index 049507fdf..2b1ed54e2 100644 --- a/crypto/test/fift.cpp +++ b/crypto/test/fift.cpp @@ -33,7 +33,7 @@ std::string load_test(std::string name) { return td::read_file_str(current_dir() + "fift/" + name).move_as_ok(); } -td::Status run_fift(std::string name, bool expect_error = false, bool preload_fift = true) { +td::Status run_fift(std::string name, bool expect_error = false) { auto res = fift::mem_run_fift(load_test(name)); if (expect_error) { res.ensure_error(); diff --git a/crypto/test/fift/rist255.fif b/crypto/test/fift/rist255.fif index 630eebb1a..ddd9b619a 100644 --- a/crypto/test/fift/rist255.fif +++ b/crypto/test/fift/rist255.fif @@ -9,6 +9,9 @@ [[ <{ RIST255_MULBASE DUP RIST255_VALIDATE }>s ]] 0 runvmx abort"Exitcode != 0" @' n . dup (x.) type cr @' ans <> abort"Invalid result" + @' n + [[ <{ 1 INT RIST255_MULBASE SWAP RIST255_MUL DUP RIST255_VALIDATE }>s ]] 0 runvmx abort"Exitcode != 0" + @' ans <> abort"Invalid result" } : test-basepoint 0 0x0000000000000000000000000000000000000000000000000000000000000000 test-basepoint diff --git a/crypto/test/modbigint.cpp b/crypto/test/modbigint.cpp index b34411f3b..75051fa62 100644 --- a/crypto/test/modbigint.cpp +++ b/crypto/test/modbigint.cpp @@ -180,7 +180,7 @@ struct MixedRadix { template const MixedRadix& as_shorter() const { - static_assert(M <= N); + static_assert(M <= N,"error"); return *reinterpret_cast*>(this); } @@ -458,7 +458,7 @@ struct ModArray { } template ModArray(const ModArray& other) { - static_assert(M >= N); + static_assert(M >= N,"error"); std::copy(other.a, other.a + N, a); } ModArray(const int* p) : a(p) { @@ -819,7 +819,7 @@ struct ModArray { template const ModArray& as_shorter() const { - static_assert(M <= N); + static_assert(M <= N,"error"); return *reinterpret_cast*>(this); } diff --git a/crypto/test/test-bigint.cpp b/crypto/test/test-bigint.cpp index 7525c83a1..a6f6e8d67 100644 --- a/crypto/test/test-bigint.cpp +++ b/crypto/test/test-bigint.cpp @@ -16,12 +16,12 @@ */ #include #include -#include #include #include #include #include #include +#include #include "common/refcnt.hpp" #include "common/bigint.hpp" #include "common/refint.h" @@ -211,7 +211,7 @@ bool coin() { // returns 0 with probability 1/2, 1 with prob. 1/4, ..., k with prob. 1/2^(k+1) int randexp(int max = 63, int min = 0) { - return min + __builtin_clzll(Random() | (1ULL << (63 - max + min))); + return min + td::count_leading_zeroes64(Random() | (1ULL << (63 - max + min))); } void bin_add_small(unsigned char bin[64], long long val, int shift = 0) { @@ -363,7 +363,7 @@ void check_one_int_repr(td::RefInt256 x, int mode, int in_range, const BInt* val if (is_small) { // special check for small (64-bit) values CHECK(x->to_long() == xval); - CHECK((long long)__builtin_bswap64(*(long long*)(bytes + 64 - 8)) == xval); + CHECK((long long)td::bswap64(*(long long*)(bytes + 64 - 8)) == xval); CHECK(in_range); // check sign CHECK(x->sgn() == (xval > 0 ? 1 : (xval < 0 ? -1 : 0))); diff --git a/crypto/test/test-db.cpp b/crypto/test/test-db.cpp index 413d774fa..35727ee36 100644 --- a/crypto/test/test-db.cpp +++ b/crypto/test/test-db.cpp @@ -127,12 +127,12 @@ class BenchSha256Low : public td::Benchmark { void run(int n) override { int res = 0; - SHA256_CTX ctx; + td::Sha256State ctx; for (int i = 0; i < n; i++) { - SHA256_Init(&ctx); - SHA256_Update(&ctx, "abcd", 4); + ctx.init(); + ctx.feed("abcd"); unsigned char buf[32]; - SHA256_Final(buf, &ctx); + ctx.extract(td::MutableSlice{buf, 32}); res += buf[0]; } td::do_not_optimize_away(res); diff --git a/crypto/test/test-smartcont.cpp b/crypto/test/test-smartcont.cpp index d3f188132..98534bc5e 100644 --- a/crypto/test/test-smartcont.cpp +++ b/crypto/test/test-smartcont.cpp @@ -958,7 +958,7 @@ class MapDns { } return; } - if (!actions.category.is_zero()) { + if (actions.category.is_zero()) { entries_.erase(actions.name); LOG(ERROR) << "CLEAR " << actions.name; if (!actions.actions) { @@ -1003,7 +1003,7 @@ class CheckedDns { explicit CheckedDns(bool check_smc = true, bool check_combine = true) { if (check_smc) { key_ = td::Ed25519::generate_private_key().move_as_ok(); - dns_ = ManualDns::create(ManualDns::create_init_data_fast(key_.value().get_public_key().move_as_ok(), 123)); + dns_ = ManualDns::create(ManualDns::create_init_data_fast(key_.value().get_public_key().move_as_ok(), 123), -1); } if (check_combine) { combined_map_dns_ = MapDns(); @@ -1094,9 +1094,10 @@ class CheckedDns { } }; -static td::Bits256 intToCat(int x) { - td::Bits256 cat = td::Bits256::zero(); - cat.as_slice().copy_from(td::Slice((char*)&x, sizeof(x))); +static td::Bits256 intToCat(td::uint32 x) { + auto y = td::make_refint(x); + td::Bits256 cat; + y->export_bytes(cat.data(), 32, false); return cat; } @@ -1182,7 +1183,7 @@ TEST(Smartcont, DnsManual) { auto key = td::Ed25519::generate_private_key().move_as_ok(); - auto manual = ManualDns::create(ManualDns::create_init_data_fast(key.get_public_key().move_as_ok(), 123)); + auto manual = ManualDns::create(ManualDns::create_init_data_fast(key.get_public_key().move_as_ok(), 123), -1); CHECK(manual->get_wallet_id().move_as_ok() == 123); auto init_query = manual->create_init_query(key).move_as_ok(); LOG(ERROR) << "A"; diff --git a/crypto/test/vm.cpp b/crypto/test/vm.cpp index 3227f8fa6..0f1b04429 100644 --- a/crypto/test/vm.cpp +++ b/crypto/test/vm.cpp @@ -28,7 +28,7 @@ #include "td/utils/StringBuilder.h" std::string run_vm(td::Ref cell) { - vm::init_op_cp0(); + vm::init_vm().ensure(); vm::DictionaryBase::get_empty_dictionary(); class Logger : public td::LogInterface { diff --git a/crypto/tl/tlbc-gen-cpp.cpp b/crypto/tl/tlbc-gen-cpp.cpp index dedec15d4..6edd0a121 100644 --- a/crypto/tl/tlbc-gen-cpp.cpp +++ b/crypto/tl/tlbc-gen-cpp.cpp @@ -159,7 +159,6 @@ std::string CppIdentSet::compute_cpp_ident(std::string orig_ident, int count) { } if (!cnt) { os << '_'; - prev_skip = true; } if (count) { os << count; diff --git a/crypto/tl/tlbc.cpp b/crypto/tl/tlbc.cpp index 409ac538e..b48bc472e 100644 --- a/crypto/tl/tlbc.cpp +++ b/crypto/tl/tlbc.cpp @@ -2252,11 +2252,9 @@ TypeExpr* parse_expr10(Lexer& lex, Constructor& cs, int mode) { } if (op == '>') { std::swap(expr, expr2); - op = '<'; op_name = Less_name; } else if (op == src::_Geq) { std::swap(expr, expr2); - op = src::_Leq; op_name = Leq_name; } auto sym_def = sym::lookup_symbol(op_name, 2); diff --git a/crypto/vm/arithops.cpp b/crypto/vm/arithops.cpp index 7da535673..1d3111b2f 100644 --- a/crypto/vm/arithops.cpp +++ b/crypto/vm/arithops.cpp @@ -285,8 +285,11 @@ int exec_divmod(VmState* st, unsigned args, int quiet) { typename td::BigInt256::DoubleInt tmp{*x}, quot; tmp += *w; tmp.mod_div(*y, quot, round_mode); - stack.push_int_quiet(td::make_refint(quot), quiet); - stack.push_int_quiet(td::make_refint(tmp), quiet); + auto q = td::make_refint(quot), r = td::make_refint(tmp); + q.write().normalize(); + r.write().normalize(); + stack.push_int_quiet(std::move(q), quiet); + stack.push_int_quiet(std::move(r), quiet); } else { switch (d) { case 1: @@ -399,6 +402,7 @@ std::string dump_shrmod(CellSlice&, unsigned args, int mode) { if (mode & 1) { os << 'Q'; } + std::string end; switch (args & 12) { case 4: os << "RSHIFT"; @@ -407,17 +411,22 @@ std::string dump_shrmod(CellSlice&, unsigned args, int mode) { os << "MODPOW2"; break; case 12: - os << "RSHIFTMOD"; + os << "RSHIFT"; + end = "MOD"; break; case 0: - os << "ADDRSHIFTMOD"; + os << "ADDRSHIFT"; + end = "MOD"; break; } + if (!(mode & 2)) { + os << end; + } if (round_mode) { os << "FRC"[round_mode]; } if (mode & 2) { - os << ' ' << y; + os << "#" << end << ' ' << y; } return os.str(); } @@ -519,7 +528,7 @@ int exec_mulshrmod(VmState* st, unsigned args, int mode) { if (add) { tmp = *w; } - tmp.add_mul(*x, *y); + tmp.add_mul(*x, *y).normalize(); switch (d) { case 1: tmp.rshift(z, round_mode).normalize(); @@ -553,6 +562,7 @@ std::string dump_mulshrmod(CellSlice&, unsigned args, int mode) { if (mode & 1) { os << 'Q'; } + std::string end; switch (args & 12) { case 4: os << "MULRSHIFT"; @@ -561,15 +571,21 @@ std::string dump_mulshrmod(CellSlice&, unsigned args, int mode) { os << "MULMODPOW2"; break; case 12: - os << "MULRSHIFTMOD"; + os << "MULRSHIFT"; + end = "MOD"; break; case 0: - os << "MULADDRSHIFTMOD"; + os << "MULADDRSHIFT"; + end = "MOD"; break; } if (round_mode) { os << "FRC"[round_mode]; } + if (mode & 2) { + os << "#"; + } + os << end; if (mode & 2) { os << ' ' << y; } @@ -644,18 +660,22 @@ std::string dump_shldivmod(CellSlice&, unsigned args, int mode) { if (mode & 1) { os << "Q"; } + os << "LSHIFT"; + if (mode & 2) { + os << "#"; + } switch (args & 12) { case 4: - os << "LSHIFTDIV"; + os << "DIV"; break; case 8: - os << "LSHIFTMOD"; + os << "MOD"; break; case 12: - os << "LSHIFTDIVMOD"; + os << "DIVMOD"; break; case 0: - os << "LSHIFTADDDIVMOD"; + os << "ADDDIVMOD"; break; } if (round_mode) { diff --git a/crypto/vm/tonops.cpp b/crypto/vm/tonops.cpp index 0dd15d805..f491d252c 100644 --- a/crypto/vm/tonops.cpp +++ b/crypto/vm/tonops.cpp @@ -101,7 +101,7 @@ void register_basic_gas_ops(OpcodeTable& cp0) { using namespace std::placeholders; cp0.insert(OpcodeInstr::mksimple(0xf800, 16, "ACCEPT", exec_accept)) .insert(OpcodeInstr::mksimple(0xf801, 16, "SETGASLIMIT", exec_set_gas_limit)) - .insert(OpcodeInstr::mksimple(0xf802, 16, "GASCONSUMED", exec_gas_consumed)->require_version(4)) + .insert(OpcodeInstr::mksimple(0xf806, 16, "GASCONSUMED", exec_gas_consumed)->require_version(4)) .insert(OpcodeInstr::mksimple(0xf80f, 16, "COMMIT", exec_commit)); } @@ -620,7 +620,6 @@ int exec_ristretto255_from_hash(VmState* st) { if (!x2->export_bytes(xb + 32, 32, false)) { throw VmError{Excno::range_chk, "x2 must fit in an unsigned 256-bit integer"}; } - CHECK(sodium_init() >= 0); crypto_core_ristretto255_from_hash(rb, xb); td::RefInt256 r{true}; CHECK(r.write().import_bytes(rb, 32, false)); @@ -633,8 +632,7 @@ int exec_ristretto255_validate(VmState* st, bool quiet) { Stack& stack = st->get_stack(); auto x = stack.pop_int(); st->consume_gas(VmState::rist255_validate_gas_price); - unsigned char xb[64]; - CHECK(sodium_init() >= 0); + unsigned char xb[32]; if (!x->export_bytes(xb, 32, false) || !crypto_core_ristretto255_is_valid_point(xb)) { if (quiet) { stack.push_bool(false); @@ -656,7 +654,6 @@ int exec_ristretto255_add(VmState* st, bool quiet) { auto x = stack.pop_int(); st->consume_gas(VmState::rist255_add_gas_price); unsigned char xb[32], yb[32], rb[32]; - CHECK(sodium_init() >= 0); if (!x->export_bytes(xb, 32, false) || !y->export_bytes(yb, 32, false) || crypto_core_ristretto255_add(rb, xb, yb)) { if (quiet) { stack.push_bool(false); @@ -681,7 +678,6 @@ int exec_ristretto255_sub(VmState* st, bool quiet) { auto x = stack.pop_int(); st->consume_gas(VmState::rist255_add_gas_price); unsigned char xb[32], yb[32], rb[32]; - CHECK(sodium_init() >= 0); if (!x->export_bytes(xb, 32, false) || !y->export_bytes(yb, 32, false) || crypto_core_ristretto255_sub(rb, xb, yb)) { if (quiet) { stack.push_bool(false); @@ -719,17 +715,20 @@ int exec_ristretto255_mul(VmState* st, bool quiet) { auto n = stack.pop_int() % get_ristretto256_l(); auto x = stack.pop_int(); st->consume_gas(VmState::rist255_mul_gas_price); + if (n->sgn() == 0) { + stack.push_smallint(0); + if (quiet) { + stack.push_bool(true); + } + return 0; + } unsigned char xb[32], nb[32], rb[32]; - memset(rb, 255, sizeof(rb)); - CHECK(sodium_init() >= 0); if (!x->export_bytes(xb, 32, false) || !export_bytes_little(n, nb) || crypto_scalarmult_ristretto255(rb, nb, xb)) { - if (std::all_of(rb, rb + 32, [](unsigned char c) { return c == 255; })) { - if (quiet) { - stack.push_bool(false); - return 0; - } - throw VmError{Excno::range_chk, "invalid x or n"}; + if (quiet) { + stack.push_bool(false); + return 0; } + throw VmError{Excno::range_chk, "invalid x or n"}; } td::RefInt256 r{true}; CHECK(r.write().import_bytes(rb, 32, false)); @@ -747,7 +746,6 @@ int exec_ristretto255_mul_base(VmState* st, bool quiet) { st->consume_gas(VmState::rist255_mulbase_gas_price); unsigned char nb[32], rb[32]; memset(rb, 255, sizeof(rb)); - CHECK(sodium_init() >= 0); if (!export_bytes_little(n, nb) || crypto_scalarmult_ristretto255_base(rb, nb)) { if (std::all_of(rb, rb + 32, [](unsigned char c) { return c == 255; })) { if (quiet) { @@ -833,7 +831,7 @@ int exec_bls_verify(VmState* st) { VM_LOG(st) << "execute BLS_VERIFY"; Stack& stack = st->get_stack(); stack.check_underflow(3); - st->consume_gas(st->bls_verify_gas_price); + st->consume_gas(VmState::bls_verify_gas_price); bls::P2 sig = slice_to_bls_p2(*stack.pop_cellslice()); td::BufferSlice msg = slice_to_bls_msg(*stack.pop_cellslice()); bls::P1 pub = slice_to_bls_p1(*stack.pop_cellslice()); @@ -845,8 +843,7 @@ int exec_bls_aggregate(VmState* st) { VM_LOG(st) << "execute BLS_AGGREGATE"; Stack& stack = st->get_stack(); int n = stack.pop_smallint_range(stack.depth() - 1, 1); - st->consume_gas( - std::max(0LL, VmState::bls_aggregate_base_gas_price + (long long)n * VmState::bls_aggregate_element_gas_price)); + st->consume_gas(VmState::bls_aggregate_base_gas_price + (long long)n * VmState::bls_aggregate_element_gas_price); std::vector sigs(n); for (int i = n - 1; i >= 0; --i) { sigs[i] = slice_to_bls_p2(*stack.pop_cellslice()); diff --git a/crypto/vm/vm.cpp b/crypto/vm/vm.cpp index 4d3e67af9..3f595a00e 100644 --- a/crypto/vm/vm.cpp +++ b/crypto/vm/vm.cpp @@ -21,6 +21,8 @@ #include "vm/dict.h" #include "vm/log.h" #include "vm/vm.h" +#include "cp0.h" +#include namespace vm { @@ -770,4 +772,15 @@ void VmState::restore_parent_vm(int res) { } } +td::Status init_vm(bool enable_debug) { + if (!init_op_cp0(enable_debug)) { + return td::Status::Error("Failed to init TVM: failed to init cp0"); + } + auto code = sodium_init(); + if (code < 0) { + return td::Status::Error(PSTRING() << "Failed to init TVM: sodium_init, code=" << code); + } + return td::Status::OK(); +} + } // namespace vm diff --git a/crypto/vm/vm.h b/crypto/vm/vm.h index e3fda3186..2066db4c1 100644 --- a/crypto/vm/vm.h +++ b/crypto/vm/vm.h @@ -423,4 +423,6 @@ int run_vm_code(Ref _code, Stack& _stack, int flags = 0, Ref* d Ref lookup_library_in(td::ConstBitPtr key, Ref lib_root); +td::Status init_vm(bool enable_debug = false); + } // namespace vm diff --git a/dht-server/CMakeLists.txt b/dht-server/CMakeLists.txt index 889b3f300..6daac0334 100644 --- a/dht-server/CMakeLists.txt +++ b/dht-server/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/dht/CMakeLists.txt b/dht/CMakeLists.txt index e50a74972..95ee70691 100644 --- a/dht/CMakeLists.txt +++ b/dht/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/emulator/CMakeLists.txt b/emulator/CMakeLists.txt index c23f071c5..969f9a88a 100644 --- a/emulator/CMakeLists.txt +++ b/emulator/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) option(BUILD_SHARED_LIBS "Use \"OFF\" for a static build." ON) diff --git a/emulator/emulator-extern.cpp b/emulator/emulator-extern.cpp index 3a4398317..4b65dd066 100644 --- a/emulator/emulator-extern.cpp +++ b/emulator/emulator-extern.cpp @@ -139,7 +139,7 @@ const char *transaction_emulator_emulate_transaction(void *transaction_emulator, now = (unsigned)std::time(nullptr); } bool is_special = wc == ton::masterchainId && emulator->get_config().is_special_smartcontract(addr); - if (!account.unpack(vm::load_cell_slice_ref(shard_account_cell.move_as_ok()), td::Ref(), now, is_special)) { + if (!account.unpack(vm::load_cell_slice_ref(shard_account_cell.move_as_ok()), now, is_special)) { ERROR_RESPONSE(PSTRING() << "Can't unpack shard account"); } @@ -217,7 +217,7 @@ const char *transaction_emulator_emulate_tick_tock_transaction(void *transaction now = (unsigned)std::time(nullptr); } bool is_special = wc == ton::masterchainId && emulator->get_config().is_special_smartcontract(addr); - if (!account.unpack(vm::load_cell_slice_ref(shard_account_cell.move_as_ok()), td::Ref(), now, is_special)) { + if (!account.unpack(vm::load_cell_slice_ref(shard_account_cell.move_as_ok()), now, is_special)) { ERROR_RESPONSE(PSTRING() << "Can't unpack shard account"); } diff --git a/emulator/transaction-emulator.cpp b/emulator/transaction-emulator.cpp index 505c0c370..81cf2e9fd 100644 --- a/emulator/transaction-emulator.cpp +++ b/emulator/transaction-emulator.cpp @@ -1,7 +1,7 @@ #include #include "transaction-emulator.h" #include "crypto/common/refcnt.hpp" -#include "vm/cp0.h" +#include "vm/vm.h" #include "tdutils/td/utils/Time.h" using td::Ref; @@ -34,7 +34,7 @@ td::Result> TransactionEmu return fetch_res.move_as_error_prefix("cannot fetch config params "); } - vm::init_op_cp0(debug_enabled_); + TRY_STATUS(vm::init_vm(debug_enabled_)); if (!lt) { lt = lt_; diff --git a/fec/CMakeLists.txt b/fec/CMakeLists.txt index b1ac37b10..2a3056071 100644 --- a/fec/CMakeLists.txt +++ b/fec/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/fec/fec.cpp b/fec/fec.cpp index 102df0389..f6379fd74 100644 --- a/fec/fec.cpp +++ b/fec/fec.cpp @@ -99,7 +99,7 @@ td::uint32 FecType::symbol_size() const { } td::Result FecType::create(tl_object_ptr obj) { - td::int32 data_size_int, symbol_size_int, symbols_count_int; + td::int32 data_size_int = 0, symbol_size_int = 0, symbols_count_int = 0; ton_api::downcast_call(*obj, td::overloaded([&](const auto &obj) { data_size_int = obj.data_size_; symbol_size_int = obj.symbol_size_; diff --git a/flake.lock b/flake.lock index ca44d4c02..d22f15d3b 100644 --- a/flake.lock +++ b/flake.lock @@ -36,8 +36,8 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1682600000, - "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=", + "lastModified": 1698846319, + "narHash": "sha256-4jyW/dqFBVpWFnhl0nvP6EN4lP7/ZqPxYRjl6var0Oc=", "owner": "nixos", "repo": "nixpkgs", "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0", @@ -45,7 +45,7 @@ }, "original": { "owner": "nixos", - "ref": "nixos-22.05", + "ref": "nixos-23.05", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index cb70b5bb0..4e993ac5d 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-22.05"; + nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-23.05"; nixpkgs-trunk.url = "github:nixos/nixpkgs"; flake-compat = { url = "github:edolstra/flake-compat"; @@ -28,14 +28,14 @@ # then we can skip these manual overrides # and switch between pkgsStatic and pkgsStatic.pkgsMusl for static glibc and musl builds if !staticExternalDeps then [ - openssl_1_1 + openssl zlib libmicrohttpd libsodium secp256k1 ] else [ - (openssl_1_1.override { static = true; }).dev + (openssl.override { static = true; }).dev (zlib.override { shared = false; }).dev ] ++ optionals (!stdenv.isDarwin) [ pkgsStatic.libmicrohttpd.dev pkgsStatic.libsodium.dev secp256k1 ] @@ -50,6 +50,8 @@ ] ++ optionals (staticGlibc || staticMusl) [ "-DCMAKE_LINK_SEARCH_START_STATIC=ON" "-DCMAKE_LINK_SEARCH_END_STATIC=ON" + ] ++ optionals (stdenv.isDarwin) [ + "-DCMAKE_CXX_FLAGS=-stdlib=libc++" "-DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=11.7" ]; LDFLAGS = optional staticExternalDeps (concatStringsSep " " [ diff --git a/http/CMakeLists.txt b/http/CMakeLists.txt index dbc57ec21..4a3fccf82 100644 --- a/http/CMakeLists.txt +++ b/http/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(HTTP_SOURCE http.h diff --git a/keyring/CMakeLists.txt b/keyring/CMakeLists.txt index 29e48ee99..f8f610f2f 100644 --- a/keyring/CMakeLists.txt +++ b/keyring/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(KEYRING_SOURCE keyring.h diff --git a/keys/CMakeLists.txt b/keys/CMakeLists.txt index 486119de6..e80436b7b 100644 --- a/keys/CMakeLists.txt +++ b/keys/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(KEYS_SOURCE keys.cpp diff --git a/lite-client/CMakeLists.txt b/lite-client/CMakeLists.txt index b84495162..53e09d772 100644 --- a/lite-client/CMakeLists.txt +++ b/lite-client/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_library(lite-client-common lite-client-common.cpp lite-client-common.h) target_link_libraries(lite-client-common PUBLIC tdutils tdactor adnllite tl_api tl_lite_api tl-lite-utils ton_crypto ton_block) diff --git a/lite-client/lite-client.cpp b/lite-client/lite-client.cpp index feedbe40b..dd6df40f7 100644 --- a/lite-client/lite-client.cpp +++ b/lite-client/lite-client.cpp @@ -4307,7 +4307,7 @@ int main(int argc, char* argv[]) { }); #endif - vm::init_op_cp0(true); // enable vm debug + vm::init_vm(true).ensure(); // enable vm debug td::actor::Scheduler scheduler({2}); diff --git a/memprof/CMakeLists.txt b/memprof/CMakeLists.txt index 8559c4d9c..2ccf11dfd 100644 --- a/memprof/CMakeLists.txt +++ b/memprof/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(MEMPROF_SOURCE memprof/memprof.cpp diff --git a/overlay/CMakeLists.txt b/overlay/CMakeLists.txt index 7adc05842..ab9722a60 100644 --- a/overlay/CMakeLists.txt +++ b/overlay/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/rldp-http-proxy/CMakeLists.txt b/rldp-http-proxy/CMakeLists.txt index 92cb01ac5..f7e30c802 100644 --- a/rldp-http-proxy/CMakeLists.txt +++ b/rldp-http-proxy/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_executable(rldp-http-proxy rldp-http-proxy.cpp DNSResolver.h DNSResolver.cpp) target_include_directories(rldp-http-proxy PUBLIC $) diff --git a/rldp/CMakeLists.txt b/rldp/CMakeLists.txt index 813d346da..39e0d3ca8 100644 --- a/rldp/CMakeLists.txt +++ b/rldp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/rldp2/CMakeLists.txt b/rldp2/CMakeLists.txt index 1bfeb0bbb..c144ec01d 100644 --- a/rldp2/CMakeLists.txt +++ b/rldp2/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt index a5f36ff20..0208a33d7 100644 --- a/storage/CMakeLists.txt +++ b/storage/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/storage/storage-daemon/CMakeLists.txt b/storage/storage-daemon/CMakeLists.txt index 4880eeceb..c987858f6 100644 --- a/storage/storage-daemon/CMakeLists.txt +++ b/storage/storage-daemon/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_executable(embed-provider-code smartcont/embed-provider-code.cpp) diff --git a/storage/test/storage.cpp b/storage/test/storage.cpp index e7a97352b..ff5a4831a 100644 --- a/storage/test/storage.cpp +++ b/storage/test/storage.cpp @@ -400,7 +400,6 @@ class NetChannel : public td::actor::Actor { break; } else if (l > alive_end - eps) { alive_begin += alive_step + sleep_step; - alive_end = alive_begin + alive_step; } else { double new_l = td::min(alive_end, r); res += (new_l - l) * speed; @@ -516,9 +515,7 @@ class NetChannel : public td::actor::Actor { queue_ = {}; } - bool ok = false; while (!queue_.empty() && (double)queue_.front().size < got_) { - ok = true; auto query = queue_.pop(); got_ -= (double)query.size; total_size_ -= (double)query.size; diff --git a/tdactor/CMakeLists.txt b/tdactor/CMakeLists.txt index 3490eb173..46dd03356 100644 --- a/tdactor/CMakeLists.txt +++ b/tdactor/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) #SOURCE SETS set(TDACTOR_SOURCE diff --git a/tdactor/benchmark/CMakeLists.txt b/tdactor/benchmark/CMakeLists.txt index e01d33dc8..c4ff79a1b 100644 --- a/tdactor/benchmark/CMakeLists.txt +++ b/tdactor/benchmark/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(BENCHMARK_SOURCE benchmark.cpp diff --git a/tdactor/test/actors_core.cpp b/tdactor/test/actors_core.cpp index ae10eb9be..96cd6239e 100644 --- a/tdactor/test/actors_core.cpp +++ b/tdactor/test/actors_core.cpp @@ -720,7 +720,7 @@ TEST(Actor2, actor_function_result) { } TEST(Actor2, actor_ping_pong) { - Scheduler scheduler{{3}, Scheduler::Paused}; + Scheduler scheduler{{3}, false, Scheduler::Paused}; sb.clear(); scheduler.start(); @@ -799,7 +799,7 @@ TEST(Actor2, Schedulers) { for (auto run_count : {0, 1, 2}) { for (auto stop_count : {0, 1, 2}) { for (size_t threads : {0, 1}) { - Scheduler scheduler({threads}, mode); + Scheduler scheduler({threads}, false, mode); for (int i = 0; i < start_count; i++) { scheduler.start(); } diff --git a/tdactor/test/actors_promise.cpp b/tdactor/test/actors_promise.cpp index f1d570697..5717b394c 100644 --- a/tdactor/test/actors_promise.cpp +++ b/tdactor/test/actors_promise.cpp @@ -210,7 +210,7 @@ TEST(Actor, promise_future) { TEST(Actor2, actor_lost_promise) { using namespace td::actor; using namespace td; - Scheduler scheduler({1}, Scheduler::Paused); + Scheduler scheduler({1}, false, Scheduler::Paused); auto watcher = td::create_shared_destructor([] { LOG(ERROR) << "STOP"; diff --git a/tddb/CMakeLists.txt b/tddb/CMakeLists.txt index 1acd54202..89730b954 100644 --- a/tddb/CMakeLists.txt +++ b/tddb/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) #SOURCE SETS set(TDDB_UTILS_SOURCE diff --git a/tddb/td/db/utils/BlobView.cpp b/tddb/td/db/utils/BlobView.cpp index 7011a00ed..ebfbc6d54 100644 --- a/tddb/td/db/utils/BlobView.cpp +++ b/tddb/td/db/utils/BlobView.cpp @@ -311,6 +311,7 @@ td::Result FileMemoryMappingBlobView::create(td::CSlice file_path, td: class CyclicBlobViewImpl : public BlobViewImpl { public: CyclicBlobViewImpl(td::BufferSlice data, td::uint64 total_size) : data_(std::move(data)), total_size_(total_size) { + CHECK(!data_.empty()); } td::Result view_impl(td::MutableSlice slice, td::uint64 offset) override { auto res = slice; diff --git a/tdfec/CMakeLists.txt b/tdfec/CMakeLists.txt index adfe2fdbc..828ff90d5 100644 --- a/tdfec/CMakeLists.txt +++ b/tdfec/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(TDFEC_SOURCE td/fec/raptorq/Rfc.cpp diff --git a/tdfec/benchmark/CMakeLists.txt b/tdfec/benchmark/CMakeLists.txt index 93ec575da..ee8f72cbf 100644 --- a/tdfec/benchmark/CMakeLists.txt +++ b/tdfec/benchmark/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_executable(benchmark-fec benchmark.cpp ) target_include_directories(benchmark-fec PUBLIC $) diff --git a/tdfec/td/fec/raptorq/Rfc.h b/tdfec/td/fec/raptorq/Rfc.h index 1f5c27f01..e3a331316 100644 --- a/tdfec/td/fec/raptorq/Rfc.h +++ b/tdfec/td/fec/raptorq/Rfc.h @@ -61,7 +61,7 @@ class Rfc { template void encoding_row_for_each(EncodingRow t, F &&f) const { f(t.b); - for (uint16 j = 1; j < t.d; ++j) { + for (uint32 j = 1; j < t.d; ++j) { t.b = (t.b + t.a) % W; f(t.b); } diff --git a/tdnet/CMakeLists.txt b/tdnet/CMakeLists.txt index d5ae7086b..bc00a6769 100644 --- a/tdnet/CMakeLists.txt +++ b/tdnet/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(TDNET_SOURCE td/net/FdListener.cpp diff --git a/tdtl/CMakeLists.txt b/tdtl/CMakeLists.txt index b0f83cd98..482bd0f7b 100644 --- a/tdtl/CMakeLists.txt +++ b/tdtl/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) #SOURCE SETS set(TDTL_SOURCE diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt index 7b577e4f8..f1e4b1ea5 100644 --- a/tdutils/CMakeLists.txt +++ b/tdutils/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) option(TDUTILS_MIME_TYPE "Generate mime types conversion (gperf is required)" ON) @@ -314,7 +314,7 @@ if (WIN32) # find_library(WS2_32_LIBRARY ws2_32) # find_library(MSWSOCK_LIBRARY Mswsock) # target_link_libraries(tdutils PRIVATE ${WS2_32_LIBRARY} ${MSWSOCK_LIBRARY}) - target_link_libraries(tdutils PRIVATE ws2_32 Mswsock Normaliz psapi) + target_link_libraries(tdutils PRIVATE ws2_32 Mswsock Normaliz psapi DbgHelp) endif() if (NOT CMAKE_CROSSCOMPILING AND TDUTILS_MIME_TYPE) add_dependencies(tdutils tdmime_auto) diff --git a/tdutils/generate/CMakeLists.txt b/tdutils/generate/CMakeLists.txt index 07353e519..194fda391 100644 --- a/tdutils/generate/CMakeLists.txt +++ b/tdutils/generate/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) # Generates files for MIME type <-> extension conversions # DEPENDS ON: gperf grep bash/powershell diff --git a/tdutils/td/utils/BigNum.cpp b/tdutils/td/utils/BigNum.cpp index 36dde064c..9de11fcae 100644 --- a/tdutils/td/utils/BigNum.cpp +++ b/tdutils/td/utils/BigNum.cpp @@ -159,7 +159,11 @@ bool BigNum::is_bit_set(int num) const { } bool BigNum::is_prime(BigNumContext &context) const { +#if OPENSSL_VERSION_MAJOR >= 3 + int result = BN_check_prime(impl_->big_num, context.impl_->big_num_context, nullptr); +#else int result = BN_is_prime_ex(impl_->big_num, BN_prime_checks, context.impl_->big_num_context, nullptr); +#endif LOG_IF(FATAL, result == -1); return result == 1; } diff --git a/tdutils/td/utils/BufferedUdp.h b/tdutils/td/utils/BufferedUdp.h index bf4aa1b80..3fa93e9da 100644 --- a/tdutils/td/utils/BufferedUdp.h +++ b/tdutils/td/utils/BufferedUdp.h @@ -106,6 +106,7 @@ class UdpReader { } if (status.is_error() && !UdpSocketFd::is_critical_read_error(status)) { queue.push(UdpMessage{{}, {}, std::move(status)}); + return td::Status::OK(); } return status; } diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index 27313cf30..ea1efbe79 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -25,7 +25,6 @@ #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/port/RwMutex.h" -#include "td/utils/port/thread_local.h" #include "td/utils/Random.h" #include "td/utils/ScopeGuard.h" #include "td/utils/SharedSlice.h" @@ -598,16 +597,23 @@ void aes_ige_decrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlic static void aes_cbc_xcrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlice to, bool encrypt_flag) { CHECK(aes_key.size() == 32); CHECK(aes_iv.size() == 16); - AES_KEY key; - int err; + CHECK(from.size() <= to.size()); + CHECK(from.size() % 16 == 0); + int out_len = 0; + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + CHECK(ctx); if (encrypt_flag) { - err = AES_set_encrypt_key(aes_key.ubegin(), 256, &key); + CHECK(EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, aes_key.ubegin(), aes_iv.ubegin()) == 1); + CHECK(EVP_CIPHER_CTX_set_padding(ctx, 0) == 1); + CHECK(EVP_EncryptUpdate(ctx, to.ubegin(), &out_len, from.ubegin(), td::narrow_cast(from.size())) == 1); + CHECK(EVP_EncryptFinal_ex(ctx, to.ubegin() + out_len, &out_len) == 1); } else { - err = AES_set_decrypt_key(aes_key.ubegin(), 256, &key); + CHECK(EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, aes_key.ubegin(), aes_iv.ubegin()) == 1); + CHECK(EVP_CIPHER_CTX_set_padding(ctx, 0) == 1); + CHECK(EVP_DecryptUpdate(ctx, to.ubegin(), &out_len, from.ubegin(), td::narrow_cast(from.size())) == 1); + CHECK(EVP_DecryptFinal_ex(ctx, to.ubegin() + out_len, &out_len) == 1); } - LOG_IF(FATAL, err != 0); - CHECK(from.size() <= to.size()); - AES_cbc_encrypt(from.ubegin(), to.ubegin(), from.size(), &key, aes_iv.ubegin(), encrypt_flag); + EVP_CIPHER_CTX_free(ctx); } void aes_cbc_encrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlice to) { @@ -723,7 +729,18 @@ string sha512(Slice data) { class Sha256State::Impl { public: - SHA256_CTX ctx_; + EVP_MD_CTX *ctx_ = nullptr; + + Impl() { + ctx_ = EVP_MD_CTX_new(); + CHECK(ctx_); + } + + ~Impl() { + if (ctx_) { + EVP_MD_CTX_free(ctx_); + } + } }; Sha256State::Sha256State() = default; @@ -755,24 +772,23 @@ void Sha256State::init() { impl_ = make_unique(); } CHECK(!is_inited_); - int err = SHA256_Init(&impl_->ctx_); - LOG_IF(FATAL, err != 1); + CHECK(EVP_DigestInit_ex(impl_->ctx_, EVP_sha256(), nullptr) == 1); is_inited_ = true; } void Sha256State::feed(Slice data) { CHECK(impl_); CHECK(is_inited_); - int err = SHA256_Update(&impl_->ctx_, data.ubegin(), data.size()); - LOG_IF(FATAL, err != 1); + CHECK(EVP_DigestUpdate(impl_->ctx_, data.ubegin(), data.size()) == 1); } void Sha256State::extract(MutableSlice output, bool destroy) { CHECK(output.size() >= 32); CHECK(impl_); CHECK(is_inited_); - int err = SHA256_Final(output.ubegin(), &impl_->ctx_); - LOG_IF(FATAL, err != 1); + unsigned size; + CHECK(EVP_DigestFinal_ex(impl_->ctx_, output.ubegin(), &size) == 1); + CHECK(size == 32); is_inited_ = false; if (destroy) { impl_.reset(); diff --git a/tdutils/td/utils/crypto.h b/tdutils/td/utils/crypto.h index 592a8a00a..4494ef481 100644 --- a/tdutils/td/utils/crypto.h +++ b/tdutils/td/utils/crypto.h @@ -151,7 +151,7 @@ class Sha256State { bool is_inited_ = false; }; -void md5(Slice input, MutableSlice output); +[[deprecated("MD5 is not cryptographically secure")]] void md5(Slice input, MutableSlice output); void pbkdf2_sha256(Slice password, Slice salt, int iteration_count, MutableSlice dest); void pbkdf2_sha512(Slice password, Slice salt, int iteration_count, MutableSlice dest); diff --git a/tdutils/td/utils/port/stacktrace.cpp b/tdutils/td/utils/port/stacktrace.cpp index 2c025d2e5..e89daec67 100644 --- a/tdutils/td/utils/port/stacktrace.cpp +++ b/tdutils/td/utils/port/stacktrace.cpp @@ -20,9 +20,13 @@ #include "td/utils/port/signals.h" -#if __GLIBC__ +#if TD_WINDOWS +#include +#else +#if TD_DARWIN || __GLIBC__ #include #endif +#endif #if TD_LINUX || TD_FREEBSD #include @@ -39,13 +43,48 @@ namespace td { namespace { void print_backtrace(void) { -#if __GLIBC__ +#if TD_WINDOWS + void *stack[100]; + HANDLE process = GetCurrentProcess(); + SymInitialize(process, nullptr, 1); + unsigned frames = CaptureStackBackTrace(0, 100, stack, nullptr); + signal_safe_write("------- Stack Backtrace -------\n", false); + for (unsigned i = 0; i < frames; i++) { + td::uint8 symbol_buf[sizeof(SYMBOL_INFO) + 256]; + auto symbol = (SYMBOL_INFO *)symbol_buf; + memset(symbol_buf, 0, sizeof(symbol_buf)); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + SymFromAddr(process, (DWORD64)(stack[i]), nullptr, symbol); + // Don't use sprintf here because it is not signal-safe + char buf[256 + 32]; + char* buf_ptr = buf; + if (frames - i - 1 < 10) { + strcpy(buf_ptr, " "); + buf_ptr += strlen(buf_ptr); + } + _itoa(frames - i - 1, buf_ptr, 10); + buf_ptr += strlen(buf_ptr); + strcpy(buf_ptr, ": ["); + buf_ptr += strlen(buf_ptr); + _ui64toa(td::uint64(symbol->Address), buf_ptr, 16); + buf_ptr += strlen(buf_ptr); + strcpy(buf_ptr, "] "); + buf_ptr += strlen(buf_ptr); + strcpy(buf_ptr, symbol->Name); + buf_ptr += strlen(buf_ptr); + strcpy(buf_ptr, "\n"); + signal_safe_write(td::Slice{buf, strlen(buf)}, false); + } +#else +#if TD_DARWIN || __GLIBC__ void *buffer[128]; int nptrs = backtrace(buffer, 128); signal_safe_write("------- Stack Backtrace -------\n", false); backtrace_symbols_fd(buffer, nptrs, 2); signal_safe_write("-------------------------------\n", false); #endif +#endif } void print_backtrace_gdb(void) { @@ -129,7 +168,7 @@ void Stacktrace::print_to_stderr(const PrintOptions &options) { } void Stacktrace::init() { -#if __GLIBC__ +#if TD_DARWIN || __GLIBC__ // backtrace needs to be called once to ensure that next calls are async-signal-safe void *buffer[1]; backtrace(buffer, 1); diff --git a/tdutils/test/MpmcWaiter.cpp b/tdutils/test/MpmcWaiter.cpp index 9cb5b3635..d0a9fc84e 100644 --- a/tdutils/test/MpmcWaiter.cpp +++ b/tdutils/test/MpmcWaiter.cpp @@ -75,9 +75,9 @@ void test_waiter_stress_one_one() { TEST(MpmcEagerWaiter, stress_one_one) { test_waiter_stress_one_one(); } -TEST(MpmcSleepyWaiter, stress_one_one) { - test_waiter_stress_one_one(); -} +// TEST(MpmcSleepyWaiter, stress_one_one) { +// test_waiter_stress_one_one(); +// } template void test_waiter_stress() { diff --git a/terminal/CMakeLists.txt b/terminal/CMakeLists.txt index ae8c70bd8..af51153f3 100644 --- a/terminal/CMakeLists.txt +++ b/terminal/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/test/ed25519_crypto.cpp b/test/ed25519_crypto.cpp deleted file mode 100644 index 371b72471..000000000 --- a/test/ed25519_crypto.cpp +++ /dev/null @@ -1,2053 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include -#include -#include -#include -#include - -// ****************************************************** - -namespace openssl { -#include -} - -namespace arith { -struct dec_string { - std::string str; - explicit dec_string(const std::string& s) : str(s) { - } -}; - -struct hex_string { - std::string str; - explicit hex_string(const std::string& s) : str(s) { - } -}; -} // namespace arith - -namespace arith { - -using namespace openssl; - -inline void bn_assert(int cond); -BN_CTX* get_ctx(); - -class BignumBitref { - BIGNUM* ptr; - int n; - - public: - BignumBitref(BIGNUM& x, int _n) : ptr(&x), n(_n){}; - operator bool() const { - return BN_is_bit_set(ptr, n); - } - BignumBitref& operator=(bool val); -}; - -class Bignum { - BIGNUM val; - - public: - class bignum_error {}; - Bignum() { - BN_init(&val); - } - Bignum(long x) { - BN_init(&val); - set_long(x); - } - ~Bignum() { - BN_free(&val); - } - Bignum(const dec_string& ds) { - BN_init(&val); - set_dec_str(ds.str); - } - Bignum(const hex_string& hs) { - BN_init(&val); - set_hex_str(hs.str); - } - Bignum(const Bignum& x) { - BN_init(&val); - BN_copy(&val, &x.val); - } - //Bignum (Bignum&& x) { val = x.val; } - void clear() { - BN_clear(&val); - } // use this for sensitive data - Bignum& operator=(const Bignum& x) { - BN_copy(&val, &x.val); - return *this; - } - Bignum& operator=(Bignum&& x) { - swap(x); - return *this; - } - Bignum& operator=(long x) { - return set_long(x); - } - Bignum& operator=(const dec_string& ds) { - return set_dec_str(ds.str); - } - Bignum& operator=(const hex_string& hs) { - return set_hex_str(hs.str); - } - Bignum& swap(Bignum& x) { - BN_swap(&val, &x.val); - return *this; - } - BIGNUM* bn_ptr() { - return &val; - } - const BIGNUM* bn_ptr() const { - return &val; - } - bool is_zero() const { - return BN_is_zero(&val); - } - int sign() const { - return BN_is_zero(&val) ? 0 : (BN_is_negative(&val) ? -1 : 1); - } - bool odd() const { - return BN_is_odd(&val); - } - int num_bits() const { - return BN_num_bits(&val); - } - int num_bytes() const { - return BN_num_bytes(&val); - } - bool operator[](int n) const { - return BN_is_bit_set(&val, n); - } - BignumBitref operator[](int n) { - return BignumBitref(val, n); - } - void export_msb(unsigned char* buffer, std::size_t size) const; - Bignum& import_msb(const unsigned char* buffer, std::size_t size); - Bignum& import_msb(const std::string& s) { - return import_msb((const unsigned char*)s.c_str(), s.size()); - } - void export_lsb(unsigned char* buffer, std::size_t size) const; - Bignum& import_lsb(const unsigned char* buffer, std::size_t size); - Bignum& import_lsb(const std::string& s) { - return import_lsb((const unsigned char*)s.c_str(), s.size()); - } - - Bignum& set_dec_str(std::string s) { - BIGNUM* tmp = &val; - bn_assert(BN_dec2bn(&tmp, s.c_str())); - return *this; - } - - Bignum& set_hex_str(std::string s) { - BIGNUM* tmp = &val; - bn_assert(BN_hex2bn(&tmp, s.c_str())); - return *this; - } - - Bignum& set_ulong(unsigned long x) { - bn_assert(BN_set_word(&val, x)); - return *this; - } - - Bignum& set_long(long x) { - set_ulong(std::abs(x)); - return x < 0 ? negate() : *this; - } - - Bignum& negate() { - BN_set_negative(&val, !BN_is_negative(&val)); - return *this; - } - - Bignum& operator+=(const Bignum& y) { - bn_assert(BN_add(&val, &val, &y.val)); - return *this; - } - - Bignum& operator+=(long y) { - bn_assert((y >= 0 ? BN_add_word : BN_sub_word)(&val, std::abs(y))); - return *this; - } - - Bignum& operator-=(long y) { - bn_assert((y >= 0 ? BN_sub_word : BN_add_word)(&val, std::abs(y))); - return *this; - } - - Bignum& operator*=(const Bignum& y) { - bn_assert(BN_mul(&val, &val, &y.val, get_ctx())); - return *this; - } - - Bignum& operator*=(long y) { - if (y < 0) { - negate(); - } - bn_assert(BN_mul_word(&val, std::abs(y))); - return *this; - } - - Bignum& operator<<=(int r) { - bn_assert(BN_lshift(&val, &val, r)); - return *this; - } - - Bignum& operator>>=(int r) { - bn_assert(BN_rshift(&val, &val, r)); - return *this; - } - - Bignum& operator/=(const Bignum& y) { - Bignum w; - bn_assert(BN_div(&val, &w.val, &val, &y.val, get_ctx())); - return *this; - } - - Bignum& operator/=(long y) { - bn_assert(BN_div_word(&val, std::abs(y)) != (BN_ULONG)(-1)); - return y < 0 ? negate() : *this; - } - - Bignum& operator%=(const Bignum& y) { - bn_assert(BN_mod(&val, &val, &y.val, get_ctx())); - return *this; - } - - Bignum& operator%=(long y) { - BN_ULONG rem = BN_mod_word(&val, std::abs(y)); - bn_assert(rem != (BN_ULONG)(-1)); - return set_long(y < 0 ? -rem : rem); - } - - unsigned long divmod(unsigned long y) { - BN_ULONG rem = BN_div_word(&val, y); - bn_assert(rem != (BN_ULONG)(-1)); - return rem; - } - - const Bignum divmod(const Bignum& y); - - std::string to_str() const; - std::string to_hex() const; -}; - -inline void bn_assert(int cond) { - if (!cond) { - throw Bignum::bignum_error(); - } -} - -BN_CTX* get_ctx(void) { - static BN_CTX* ctx = BN_CTX_new(); - return ctx; -} - -BignumBitref& BignumBitref::operator=(bool val) { - if (val) { - BN_set_bit(ptr, n); - } else { - BN_clear_bit(ptr, n); - } - return *this; -} - -const Bignum operator+(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_add(z.bn_ptr(), x.bn_ptr(), y.bn_ptr())); - return z; -} - -const Bignum operator+(const Bignum& x, long y) { - if (y > 0) { - Bignum z(x); - bn_assert(BN_add_word(z.bn_ptr(), y)); - return z; - } else if (y < 0) { - Bignum z(x); - bn_assert(BN_sub_word(z.bn_ptr(), -y)); - return z; - } else { - return x; - } -} - -/* - const Bignum operator+ (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_add_word (x.bn_ptr(), y)); - } else if (y < 0) { - bn_assert (BN_sub_word (x.bn_ptr(), -y)); - } - return std::move (x); - } - */ - -const Bignum operator+(long y, const Bignum& x) { - return x + y; -} - -/* - const Bignum operator+ (long y, Bignum&& x) { - return x + y; - } - */ - -const Bignum operator-(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_sub(z.bn_ptr(), x.bn_ptr(), y.bn_ptr())); - return z; -} - -const Bignum operator-(const Bignum& x, long y) { - return x + (-y); -} - -/* - const Bignum operator- (Bignum&& x, long y) { - return x + (-y); - } - */ - -const Bignum operator*(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_mul(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -const Bignum operator*(const Bignum& x, long y) { - if (y > 0) { - Bignum z(x); - bn_assert(BN_mul_word(z.bn_ptr(), y)); - return z; - } else if (y < 0) { - Bignum z(x); - z.negate(); - bn_assert(BN_mul_word(z.bn_ptr(), -y)); - return z; - } else { - Bignum z(0); - return z; - } -} - -/* - const Bignum operator* (Bignum&& x, long y) { - if (y > 0) { - bn_assert (BN_mul_word (x.bn_ptr(), y)); - } else if (y < 0) { - x.negate(); - bn_assert (BN_mul_word (x.bn_ptr(), -y)); - } else { - x = 0; - } - return std::move (x); - } - */ - -const Bignum operator*(long y, const Bignum& x) { - return x * y; -} - -const Bignum operator/(const Bignum& x, const Bignum& y) { - Bignum z, w; - bn_assert(BN_div(z.bn_ptr(), w.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -const Bignum Bignum::divmod(const Bignum& y) { - Bignum w; - bn_assert(BN_div(&val, w.bn_ptr(), &val, y.bn_ptr(), get_ctx())); - return w; -} - -const Bignum operator%(const Bignum& x, const Bignum& y) { - Bignum z; - bn_assert(BN_mod(z.bn_ptr(), x.bn_ptr(), y.bn_ptr(), get_ctx())); - return z; -} - -unsigned long operator%(const Bignum& x, unsigned long y) { - BN_ULONG rem = BN_mod_word(x.bn_ptr(), y); - bn_assert(rem != (BN_ULONG)(-1)); - return rem; -} - -const Bignum operator<<(const Bignum& x, int r) { - Bignum z; - bn_assert(BN_lshift(z.bn_ptr(), x.bn_ptr(), r)); - return z; -} - -const Bignum operator>>(const Bignum& x, int r) { - Bignum z; - bn_assert(BN_rshift(z.bn_ptr(), x.bn_ptr(), r)); - return z; -} - -const Bignum abs(const Bignum& x) { - Bignum T(x); - if (T.sign() < 0) { - T.negate(); - } - return T; -} - -const Bignum sqr(const Bignum& x) { - Bignum z; - bn_assert(BN_sqr(z.bn_ptr(), x.bn_ptr(), get_ctx())); - return z; -} - -void Bignum::export_msb(unsigned char* buffer, std::size_t size) const { - bn_assert(size >= 0 && size <= (1 << 20)); - bn_assert(sign() >= 0); - int n = BN_num_bytes(&val); - bn_assert(n >= 0 && (unsigned)n <= size); - bn_assert(BN_bn2bin(&val, buffer + size - n) == n); - std::memset(buffer, 0, size - n); -} - -Bignum& Bignum::import_msb(const unsigned char* buffer, std::size_t size) { - bn_assert(size >= 0 && size <= (1 << 20)); - std::size_t i = 0; - while (i < size && !buffer[i]) { - i++; - } - bn_assert(BN_bin2bn(buffer + i, size - i, &val) == &val); - return *this; -} - -void Bignum::export_lsb(unsigned char* buffer, std::size_t size) const { - bn_assert(size >= 0 && size <= (1 << 20)); - bn_assert(sign() >= 0); - std::size_t n = BN_num_bytes(&val); - bn_assert(n >= 0 && (unsigned)n <= size); - bn_assert(BN_bn2bin(&val, buffer) == (int)n); - std::memset(buffer + n, 0, size - n); - for (std::size_t i = 0; 2 * i + 1 < n; i++) { - std::swap(buffer[i], buffer[n - 1 - i]); - } -} - -Bignum& Bignum::import_lsb(const unsigned char* buffer, std::size_t size) { - bn_assert(size >= 0 && size <= (1 << 20)); - while (size > 0 && !buffer[size - 1]) { - size--; - } - if (!size) { - bn_assert(BN_zero(&val)); - return *this; - } - unsigned char tmp[size], *ptr = tmp + size; - for (std::size_t i = 0; i < size; i++) { - *--ptr = buffer[i]; - } - bn_assert(BN_bin2bn(tmp, size, &val) == &val); - return *this; -} - -int cmp(const Bignum& x, const Bignum& y) { - return BN_cmp(x.bn_ptr(), y.bn_ptr()); -} - -bool operator==(const Bignum& x, const Bignum& y) { - return cmp(x, y) == 0; -} - -bool operator!=(const Bignum& x, const Bignum& y) { - return cmp(x, y) != 0; -} - -bool operator<(const Bignum& x, const Bignum& y) { - return cmp(x, y) < 0; -} - -bool operator<=(const Bignum& x, const Bignum& y) { - return cmp(x, y) <= 0; -} - -bool operator>(const Bignum& x, const Bignum& y) { - return cmp(x, y) > 0; -} - -bool operator>=(const Bignum& x, const Bignum& y) { - return cmp(x, y) >= 0; -} - -bool operator==(const Bignum& x, long y) { - if (y >= 0) { - return BN_is_word(x.bn_ptr(), y); - } else { - return x == Bignum(y); - } -} - -bool operator!=(const Bignum& x, long y) { - if (y >= 0) { - return !BN_is_word(x.bn_ptr(), y); - } else { - return x != Bignum(y); - } -} - -std::string Bignum::to_str() const { - char* ptr = BN_bn2dec(&val); - std::string z(ptr); - OPENSSL_free(ptr); - return z; -} - -std::string Bignum::to_hex() const { - char* ptr = BN_bn2hex(&val); - std::string z(ptr); - OPENSSL_free(ptr); - return z; -} - -std::ostream& operator<<(std::ostream& os, const Bignum& x) { - return os << x.to_str(); -} - -std::istream& operator>>(std::istream& is, Bignum& x) { - std::string word; - is >> word; - x = dec_string(word); - return is; -} - -bool is_prime(const Bignum& p, int nchecks = 64, bool trial_div = true) { - return BN_is_prime_fasttest_ex(p.bn_ptr(), BN_prime_checks, get_ctx(), trial_div, 0); -} -} // namespace arith - -namespace arith { -using namespace openssl; - -class Residue; -class ResidueRing; - -class ResidueRing { - public: - struct bad_modulus {}; - struct elem_cnt_mismatch { - int cnt; - elem_cnt_mismatch(int x) : cnt(x) { - } - }; - - private: - const Bignum modulus; - mutable int cnt; - bool prime; - void cnt_assert(bool b) { - if (!b) { - throw elem_cnt_mismatch(cnt); - } - } - Residue* Zero; - Residue* One; - Residue* Img_i; - void init(); - - public: - typedef Residue element; - explicit ResidueRing(Bignum mod) : modulus(mod), cnt(0), prime(arith::is_prime(mod)), Zero(0), One(0) { - init(); - } - ~ResidueRing(); - int incr_count() { - return ++cnt; - } - int decr_count() { - --cnt; - cnt_assert(cnt >= 0); - return cnt; - } - const Bignum& get_modulus() const { - return modulus; - } - bool is_prime() const { - return prime; - } - const Residue& zero() const { - return *Zero; - } - const Residue& one() const { - return *One; - } - const Residue& img_i(); - Residue frac(long num, long denom = 1); - Residue convert(long num); - Residue convert(const Bignum& x); - - Bignum reduce(const Bignum& x) { - Bignum r = x % modulus; - if (r.sign() < 0) { - r += modulus; - } - return r; - } - - Bignum& do_reduce(Bignum& x) { - x %= modulus; - if (x.sign() < 0) { - x += modulus; - } - return x; - } -}; - -class Residue { - public: - struct not_same_ring {}; - - private: - ResidueRing* ring; - mutable Bignum val; - Residue& reduce() { - ring->do_reduce(val); - return *this; - } - - public: - explicit Residue(ResidueRing& R) : ring(&R) { - R.incr_count(); - } - Residue(const Bignum& x, ResidueRing& R) : ring(&R), val(R.reduce(x)) { - R.incr_count(); - } - ~Residue() { - ring->decr_count(); - ring = 0; - } - Residue(const Residue& x) : ring(x.ring), val(x.val) { - ring->incr_count(); - } - Bignum extract() const { - return val; - } - const Bignum& extract_raw() const { - return val; - } - const Bignum& modulus() const { - return ring->get_modulus(); - } - void same_ring(const Residue& y) const { - if (ring != y.ring) { - throw not_same_ring(); - } - } - ResidueRing& ring_of() const { - return *ring; - } - bool is_zero() const { - return (val == 0); - } - Residue& operator=(const Residue& x) { - same_ring(x); - val = x.val; - return *this; - } - Residue& operator=(const Bignum& x) { - val = ring->reduce(x); - return *this; - } - Residue& operator+=(const Residue& y); - Residue& operator-=(const Residue& y); - Residue& operator*=(const Residue& y); - Residue& operator+=(long y) { - val += y; - return reduce(); - } - Residue& operator-=(long y) { - val -= y; - return reduce(); - } - Residue& operator*=(long y) { - val *= y; - return reduce(); - } - Residue& negate() { - val.negate(); - return reduce(); - } - friend const Residue operator+(const Residue& x, const Residue& y); - friend const Residue operator-(const Residue& x, const Residue& y); - friend const Residue operator*(const Residue& x, const Residue& y); - friend const Residue operator-(const Residue& x); - friend Residue sqr(const Residue& x); - friend Residue power(const Residue& x, const Bignum& y); - friend Residue inverse(const Residue& x); - std::string to_str() const; -}; - -void ResidueRing::init() { - Zero = new Residue(0, *this); - One = new Residue(1, *this); -} - -ResidueRing::~ResidueRing() { - delete Zero; - delete One; - Zero = One = 0; - cnt_assert(!cnt); -} - -const Residue operator+(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_of()); - bn_assert(BN_mod_add(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator-(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_of()); - bn_assert(BN_mod_sub(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator*(const Residue& x, const Residue& y) { - x.same_ring(y); - Residue z(x.ring_of()); - bn_assert(BN_mod_mul(z.val.bn_ptr(), x.val.bn_ptr(), y.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -const Residue operator-(const Residue& x) { - Residue z(x); - z.val.negate(); - return z.reduce(); -} - -Residue& Residue::operator+=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_add(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -Residue& Residue::operator-=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_sub(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -Residue& Residue::operator*=(const Residue& y) { - same_ring(y); - bn_assert(BN_mod_mul(val.bn_ptr(), val.bn_ptr(), y.val.bn_ptr(), modulus().bn_ptr(), get_ctx())); - return *this; -} - -bool operator==(const Residue& x, const Residue& y) { - x.same_ring(y); - return x.extract() == y.extract(); -} - -bool operator!=(const Residue& x, const Residue& y) { - x.same_ring(y); - return x.extract() != y.extract(); -} - -Residue sqr(const Residue& x) { - Residue z(x.ring_of()); - bn_assert(BN_mod_sqr(z.val.bn_ptr(), x.val.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -Residue power(const Residue& x, const Bignum& y) { - Residue z(x.ring_of()); - bn_assert(BN_mod_exp(z.val.bn_ptr(), x.val.bn_ptr(), y.bn_ptr(), x.modulus().bn_ptr(), get_ctx())); - return z; -} - -Residue inverse(const Residue& x) { - assert(x.ring_of().is_prime()); - return power(x, x.ring_of().get_modulus() - 2); -} - -const Residue& ResidueRing::img_i() { - if (!Img_i) { - assert(is_prime()); - assert(modulus % 4 == 1); - int g = 2; - Bignum n = (modulus - 1) / 4; - while (true) { - Residue t = power(frac(g), n); - if (t != one() && t != frac(-1)) { - Img_i = new Residue(t); - break; - } - } - } - return *Img_i; -} - -Residue sqrt(const Residue& x) { - assert(x.ring_of().is_prime()); - ResidueRing& R = x.ring_of(); - const Bignum& p = R.get_modulus(); - if (x.is_zero() || !p.odd()) { - return x; - } - if (p[1]) { // p=3 (mod 4) - return power(x, (p + 1) >> 2); - } else if (p[2]) { - // p=5 (mod 8) - Residue t = power(x, (p + 3) >> 3); - return (sqr(t) == x) ? t : R.img_i() * t; - } else { - assert(p[2]); - return R.zero(); - } -} - -Residue ResidueRing::frac(long num, long denom) { - assert(denom); - if (denom < 0) { - num = -num; - denom = -denom; - } - if (!(num % denom)) { - return Residue(num / denom, *this); - } else { - return Residue(num, *this) * inverse(Residue(denom, *this)); - } -} - -inline Residue ResidueRing::convert(long x) { - return Residue(x, *this); -} - -inline Residue ResidueRing::convert(const Bignum& x) { - return Residue(x, *this); -} - -std::string Residue::to_str() const { - return "Mod(" + val.to_str() + "," + modulus().to_str() + ")"; -} - -std::ostream& operator<<(std::ostream& os, const Residue& x) { - return os << x.to_str(); -} - -std::istream& operator>>(std::istream& is, Residue& x) { - std::string word; - is >> word; - x = dec_string(word); - return is; -} -} // namespace arith - -// ****************************************************** - -namespace ellcurve { -using namespace arith; - -const Bignum& P25519() { - static Bignum P25519 = (Bignum(1) << 255) - 19; - return P25519; -} - -ResidueRing& Fp25519() { - static ResidueRing Fp25519(P25519()); - return Fp25519; -} -} // namespace ellcurve - -// ****************************************************** - -namespace ellcurve { -using namespace arith; - -class MontgomeryCurve { - ResidueRing& ring; - int A_short; // v^2 = u^2 + Au + 1 - int Gu_short; // u(G) - int a_short; // (A+2)/4 - Residue A; - Residue Gu; - Bignum P; - Bignum L; - Bignum Order; - Bignum cofactor; - int cofactor_short; - - void init(); - - public: - MontgomeryCurve(int _A, int _Gu, ResidueRing& _R) - : ring(_R) - , A_short(_A) - , Gu_short(_Gu) - , a_short((_A + 2) / 4) - , A(_A, _R) - , Gu(_Gu, _R) - , P(_R.get_modulus()) - , cofactor_short(0) { - init(); - } - - const Residue& get_gen_u() const { - return Gu; - } - const Bignum& get_ell() const { - return L; - } - const Bignum& get_order() const { - return Order; - } - ResidueRing& get_base_ring() const { - return ring; - } - const Bignum& get_p() const { - return P; - } - - void set_order_cofactor(const Bignum& order, int cof); - - struct PointXZ { - Residue X, Z; - PointXZ(Residue x, Residue z) : X(x), Z(z) { - x.same_ring(z); - } - PointXZ(ResidueRing& r) : X(r.one()), Z(r.zero()) { - } - explicit PointXZ(Residue u) : X(u), Z(u.ring_of().one()) { - } - explicit PointXZ(Residue y, bool) : X(y.ring_of().one() - y), Z(y + y.ring_of().one()) { - } - PointXZ(const PointXZ& P) : X(P.X), Z(P.Z) { - } - PointXZ& operator=(const PointXZ& P) { - X = P.X; - Z = P.Z; - return *this; - } - Residue get_u() const { - return X * inverse(Z); - } - Residue get_v(bool sign_v = false) const; - bool is_infty() const { - return Z.is_zero(); - } - Residue get_y() const { - return (X - Z) * inverse(X + Z); - } - bool export_point_y(unsigned char buffer[32]) const; - bool export_point_u(unsigned char buffer[32]) const; - void zeroize() { - X = Z = Z.ring_of().zero(); - } - }; - - PointXZ power_gen_xz(const Bignum& n) const; - PointXZ power_xz(const Residue& u, const Bignum& n) const; - PointXZ power_xz(const PointXZ& P, const Bignum& n) const; - PointXZ add_xz(const PointXZ& P, const PointXZ& Q) const; - PointXZ double_xz(const PointXZ& P) const; - - PointXZ import_point_u(const unsigned char point[32]) const; - PointXZ import_point_y(const unsigned char point[32]) const; -}; - -void MontgomeryCurve::init() { - assert(!((a_short + 2) & 3) && a_short >= 0); -} - -void MontgomeryCurve::set_order_cofactor(const Bignum& order, int cof) { - assert(order > 0); - assert(cof >= 0); - assert(cof == 0 || (order % cof) == 0); - Order = order; - cofactor = cofactor_short = cof; - if (cof > 0) { - L = order / cof; - assert(is_prime(L)); - } - assert(!power_gen_xz(1).is_infty()); - assert(power_gen_xz(Order).is_infty()); -} - -// computes u(P+Q)*u(P-Q) as X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::add_xz(const MontgomeryCurve::PointXZ& P, - const MontgomeryCurve::PointXZ& Q) const { - Residue u = (P.X + P.Z) * (Q.X - Q.Z); - Residue v = (P.X - P.Z) * (Q.X + Q.Z); - return MontgomeryCurve::PointXZ(sqr(u + v), sqr(u - v)); -} - -// computes u(2P) as X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::double_xz(const MontgomeryCurve::PointXZ& P) const { - Residue u = sqr(P.X + P.Z); - Residue v = sqr(P.X - P.Z); - Residue w = u - v; - return PointXZ(u * v, w * (v + Residue(a_short, ring) * w)); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::power_gen_xz(const Bignum& n) const { - return power_xz(Gu, n); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const Residue& u, const Bignum& n) const { - return power_xz(PointXZ(u), n); -} - -// computes u([n]P) in form X/Z -MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const PointXZ& A, const Bignum& n) const { - assert(n >= 0); - if (n == 0) { - return PointXZ(ring); - } - - int k = n.num_bits(); - PointXZ P(A); - PointXZ Q(double_xz(P)); - for (int i = k - 2; i >= 0; --i) { - PointXZ PQ(add_xz(P, Q)); - PQ.X *= A.Z; - PQ.Z *= A.X; - if (n[i]) { - P = PQ; - Q = double_xz(Q); - } else { - Q = PQ; - P = double_xz(P); - } - } - return P; -} - -bool MontgomeryCurve::PointXZ::export_point_y(unsigned char buffer[32]) const { - if ((X + Z).is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } else { - get_y().extract().export_lsb(buffer, 32); - return true; - } -} - -bool MontgomeryCurve::PointXZ::export_point_u(unsigned char buffer[32]) const { - if (Z.is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } else { - get_u().extract().export_lsb(buffer, 32); - return true; - } -} - -MontgomeryCurve::PointXZ MontgomeryCurve::import_point_u(const unsigned char point[32]) const { - Bignum u; - u.import_lsb(point, 32); - u[255] = 0; - return PointXZ(Residue(u, ring)); -} - -MontgomeryCurve::PointXZ MontgomeryCurve::import_point_y(const unsigned char point[32]) const { - Bignum y; - y.import_lsb(point, 32); - y[255] = 0; - return PointXZ(Residue(y, ring), true); -} - -MontgomeryCurve& Curve25519() { - static MontgomeryCurve Curve25519(486662, 9, Fp25519()); - static bool init = false; - if (!init) { - Curve25519.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8); - init = true; - } - return Curve25519; -} -} // namespace ellcurve - -// ****************************************************** - -namespace ellcurve { -using namespace arith; - -class TwEdwardsCurve; - -class TwEdwardsCurve { - public: - struct SegrePoint { - Residue XY, X, Y, Z; // if x=X/Z and y=Y/T, stores (xy,x,y,1)*Z*T - SegrePoint(ResidueRing& R) : XY(R), X(R), Y(R), Z(R) { - } - SegrePoint(const Residue& x, const Residue& y) : XY(x * y), X(x), Y(y), Z(y.ring_of().one()) { - } - SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign); - SegrePoint(const SegrePoint& P) : XY(P.XY), X(P.X), Y(P.Y), Z(P.Z) { - } - SegrePoint& operator=(const SegrePoint& P) { - XY = P.XY; - X = P.X; - Y = P.Y; - Z = P.Z; - return *this; - } - bool is_zero() const { - return X.is_zero() && (Y == Z); - } - bool is_valid() const { - return (XY * Z == X * Y) && !(XY.is_zero() && X.is_zero() && Y.is_zero() && Z.is_zero()); - } - bool is_finite() const { - return !Z.is_zero(); - } - bool is_normalized() const { - return Z == Z.ring_of().one(); - } - SegrePoint& normalize() { - auto f = inverse(Z); - XY *= f; - X *= f; - Y *= f; - Z = Z.ring_of().one(); - return *this; - } - SegrePoint& zeroize() { - XY = X = Y = Z = Z.ring_of().zero(); - return *this; - } - bool export_point(unsigned char buffer[32], bool need_x = true) const; - bool export_point_y(unsigned char buffer[32]) const { - return export_point(buffer, false); - } - bool export_point_u(unsigned char buffer[32]) const; - Residue get_y() const { - return Y * inverse(Z); - } - Residue get_x() const { - return X * inverse(Z); - } - Residue get_u() const { - return (Z + Y) * inverse(Z - Y); - } - void negate() { - XY.negate(); - X.negate(); - } - }; - - private: - ResidueRing& ring; - Residue D; - Residue D2; - Residue Gy; - Bignum P; - Bignum L; - Bignum Order; - Bignum cofactor; - int cofactor_short; - SegrePoint G; - SegrePoint O; - void init(); - - public: - TwEdwardsCurve(const Residue& _D, const Residue& _Gy, ResidueRing& _R) - : ring(_R), D(_D), D2(_D + _D), Gy(_Gy), P(_R.get_modulus()), cofactor_short(0), G(_R), O(_R) { - init(); - } - - const Residue& get_gen_y() const { - return Gy; - } - const Bignum& get_ell() const { - return L; - } - const Bignum& get_order() const { - return Order; - } - ResidueRing& get_base_ring() const { - return ring; - } - const Bignum& get_p() const { - return P; - } - const SegrePoint& get_base_point() const { - return G; - } - - void set_order_cofactor(const Bignum& order, int cof); - bool recover_x(Residue& x, const Residue& y, bool x_sign) const; - - void add_points(SegrePoint& R, const SegrePoint& P, const SegrePoint& Q) const; - SegrePoint add_points(const SegrePoint& P, const SegrePoint& Q) const; - void double_point(SegrePoint& R, const SegrePoint& P) const; - SegrePoint double_point(const SegrePoint& P) const; - SegrePoint power_point(const SegrePoint& A, const Bignum& n) const; - SegrePoint power_gen(const Bignum& n) const; - - SegrePoint import_point(const unsigned char point[32], bool& ok) const; -}; - -std::ostream& operator<<(std::ostream& os, const TwEdwardsCurve::SegrePoint& P) { - return os << "[" << P.XY << ":" << P.X << ":" << P.Y << ":" << P.Z << "]"; -} - -void TwEdwardsCurve::init() { - assert(D != ring.zero() && D != ring.convert(-1)); - O.X = O.Z = ring.one(); - G = SegrePoint(*this, Gy, 0); - assert(!G.XY.is_zero()); -} - -void TwEdwardsCurve::set_order_cofactor(const Bignum& order, int cof) { - assert(order > 0); - assert(cof >= 0); - assert(cof == 0 || (order % cof) == 0); - Order = order; - cofactor = cofactor_short = cof; - if (cof > 0) { - L = order / cof; - assert(is_prime(L)); - assert(!power_gen(1).is_zero()); - assert(power_gen(L).is_zero()); - } -} - -TwEdwardsCurve::SegrePoint::SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign) - : XY(y), X(E.get_base_ring()), Y(y), Z(E.get_base_ring().one()) { - Residue x(y.ring_of()); - if (E.recover_x(x, y, x_sign)) { - XY *= x; - X = x; - } else { - XY = Y = Z = E.get_base_ring().zero(); - } -} - -bool TwEdwardsCurve::recover_x(Residue& x, const Residue& y, bool x_sign) const { - // recovers x from equation -x^2+y^2 = 1+d*x^2*y^2 - Residue z = inverse(ring.one() + D * sqr(y)); - if (z.is_zero()) { - return false; - } - z *= sqr(y) - ring.one(); - Residue t = sqrt(z); - if (sqr(t) == z) { - x = (t.extract().odd() == x_sign) ? t : -t; - //std::cout << "x=" << x << ", y=" << y << std::endl; - return true; - } else { - return false; - } -} - -void TwEdwardsCurve::add_points(SegrePoint& Res, const SegrePoint& P, const SegrePoint& Q) const { - Residue a((P.X + P.Y) * (Q.X + Q.Y)); - Residue b((P.X - P.Y) * (Q.X - Q.Y)); - Residue c(P.Z * Q.Z * ring.convert(2)); - Residue d(P.XY * Q.XY * D2); - Residue x_num(a - b); // 2(x1y2+x2y1) - Residue y_num(a + b); // 2(x1x2+y1y2) - Residue x_den(c + d); // 2(1+dx1x2y1y2) - Residue y_den(c - d); // 2(1-dx1x2y1y2) - Res.X = x_num * y_den; // x = x_num/x_den, y = y_num/y_den - Res.Y = y_num * x_den; - Res.XY = x_num * y_num; - Res.Z = x_den * y_den; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::add_points(const SegrePoint& P, const SegrePoint& Q) const { - SegrePoint Res(ring); - add_points(Res, P, Q); - return Res; -} - -void TwEdwardsCurve::double_point(SegrePoint& Res, const SegrePoint& P) const { - add_points(Res, P, P); -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::double_point(const SegrePoint& P) const { - SegrePoint Res(ring); - double_point(Res, P); - return Res; -} - -// computes u([n]P) in form (xy,x,y,1)*Z -TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_point(const SegrePoint& A, const Bignum& n) const { - assert(n >= 0); - if (n == 0) { - return O; - } - - int k = n.num_bits(); - SegrePoint P(A); - SegrePoint Q(double_point(A)); - for (int i = k - 2; i >= 0; --i) { - if (n[i]) { - add_points(P, P, Q); - double_point(Q, Q); - } else { - // we do more operations than necessary for uniformicity - add_points(Q, P, Q); - double_point(P, P); - } - } - return P; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_gen(const Bignum& n) const { - return power_point(G, n); -} - -bool TwEdwardsCurve::SegrePoint::export_point(unsigned char buffer[32], bool need_x) const { - if (!is_normalized()) { - if (Z.is_zero()) { - std::memset(buffer, 0xff, 32); - return false; - } - Residue f(inverse(Z)); - Bignum y((Y * f).extract()); - assert(!y[255]); - if (need_x) { - y[255] = (X * f).extract().odd(); - } - y.export_lsb(buffer, 32); - } else { - Bignum y(Y.extract()); - assert(!y[255]); - if (need_x) { - y[255] = X.extract().odd(); - } - y.export_lsb(buffer, 32); - } - return true; -} - -bool TwEdwardsCurve::SegrePoint::export_point_u(unsigned char buffer[32]) const { - if (Z == Y) { - std::memset(buffer, 0xff, 32); - return false; - } - Residue f(inverse(Z - Y)); - ((Z + Y) * f).extract().export_lsb(buffer, 32); - assert(!(buffer[31] & 0x80)); - return true; -} - -TwEdwardsCurve::SegrePoint TwEdwardsCurve::import_point(const unsigned char point[32], bool& ok) const { - Bignum y; - y.import_lsb(point, 32); - bool x_sign = y[255]; - y[255] = 0; - Residue yr(y, ring); - Residue xr(ring); - ok = recover_x(xr, yr, x_sign); - return ok ? SegrePoint(xr, yr) : SegrePoint(ring); -} - -TwEdwardsCurve& Ed25519() { - static TwEdwardsCurve Ed25519(Fp25519().frac(-121665, 121666), Fp25519().frac(4, 5), Fp25519()); - static bool init = false; - if (!init) { - Ed25519.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8); - init = true; - } - return Ed25519; -} -} // namespace ellcurve - -// ****************************************************** - -namespace openssl { -#include -} - -namespace digest { -using namespace openssl; - -struct OpensslEVP_SHA1 { - enum { digest_bytes = 20 }; - static const EVP_MD* get_evp() { - return EVP_sha1(); - } -}; - -struct OpensslEVP_SHA256 { - enum { digest_bytes = 32 }; - static const EVP_MD* get_evp() { - return EVP_sha256(); - } -}; - -struct OpensslEVP_SHA512 { - enum { digest_bytes = 64 }; - static const EVP_MD* get_evp() { - return EVP_sha512(); - } -}; - -template -class HashCtx { - EVP_MD_CTX ctx; - void init(); - void clear(); - - public: - enum { digest_bytes = H::digest_bytes }; - HashCtx() { - init(); - } - HashCtx(const void* data, std::size_t len) { - init(); - feed(data, len); - } - ~HashCtx() { - clear(); - } - void feed(const void* data, std::size_t len); - std::size_t extract(unsigned char buffer[digest_bytes]); - std::string extract(); -}; - -template -void HashCtx::init() { - EVP_MD_CTX_init(&ctx); - EVP_DigestInit_ex(&ctx, H::get_evp(), 0); -} - -template -void HashCtx::clear() { - EVP_MD_CTX_cleanup(&ctx); -} - -template -void HashCtx::feed(const void* data, std::size_t len) { - EVP_DigestUpdate(&ctx, data, len); -} - -template -std::size_t HashCtx::extract(unsigned char buffer[digest_bytes]) { - unsigned olen = 0; - EVP_DigestFinal_ex(&ctx, buffer, &olen); - assert(olen == digest_bytes); - return olen; -} - -template -std::string HashCtx::extract() { - unsigned char buffer[digest_bytes]; - unsigned olen = 0; - EVP_DigestFinal_ex(&ctx, buffer, &olen); - assert(olen == digest_bytes); - return std::string((char*)buffer, olen); -} - -typedef HashCtx SHA1; -typedef HashCtx SHA256; -typedef HashCtx SHA512; - -template -std::size_t hash_str(unsigned char buffer[T::digest_bytes], const void* data, std::size_t size) { - T hasher(data, size); - return hasher.extract(buffer); -} - -template -std::size_t hash_two_str(unsigned char buffer[T::digest_bytes], const void* data1, std::size_t size1, const void* data2, - std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(buffer); -} - -template -std::string hash_str(const void* data, std::size_t size) { - T hasher(data, size); - return hasher.extract(); -} - -template -std::string hash_two_str(const void* data1, std::size_t size1, const void* data2, std::size_t size2) { - T hasher(data1, size1); - hasher.feed(data2, size2); - return hasher.extract(); -} -} // namespace digest - -// ****************************************************** - -namespace openssl { -#include -} - -#include -#include - -namespace prng { - -int os_get_random_bytes(void* buf, int n) { - using namespace std; - int r = 0, h = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (h >= 0) { - r = read(h, buf, n); - if (r > 0) { - //std::cerr << "added " << r << " bytes of real entropy to secure random numbers seed" << std::endl; - } else { - r = 0; - } - close(h); - } - - if (r < n) { - h = open("/dev/urandom", O_RDONLY); - if (h < 0) { - return r; - } - int s = read(h, (char*)buf + r, n - r); - close(h); - if (s < 0) { - return r; - } - r += s; - } - - if (r >= 8) { - *(long*)buf ^= lrand48(); - srand48(*(long*)buf); - } - - return r; -} -} // namespace prng - -namespace prng { -using namespace openssl; - -class RandomGen { - public: - struct rand_error {}; - void randomize(bool force = true); - void seed_add(const void* data, std::size_t size, double entropy = 0); - bool ok() const { - return RAND_status(); - } - RandomGen() { - randomize(false); - } - RandomGen(const void* seed, std::size_t size) { - seed_add(seed, size); - randomize(false); - } - bool rand_bytes(void* data, std::size_t size, bool strong = false); - bool strong_rand_bytes(void* data, std::size_t size) { - return rand_bytes(data, size, true); - } - template - bool rand_obj(T& obj) { - return rand_bytes(&obj, sizeof(T)); - } - template - bool rand_objs(T* ptr, std::size_t count) { - return rand_bytes(ptr, sizeof(T) * count); - } - std::string rand_string(std::size_t size, bool strong = false); -}; - -void RandomGen::seed_add(const void* data, std::size_t size, double entropy) { - RAND_add(data, size, entropy > 0 ? entropy : size); -} - -void RandomGen::randomize(bool force) { - if (!force && ok()) { - return; - } - unsigned char buffer[128]; - int n = os_get_random_bytes(buffer, 128); - seed_add(buffer, n); - assert(ok()); -} - -bool RandomGen::rand_bytes(void* data, std::size_t size, bool strong) { - int res = (strong ? RAND_bytes : RAND_pseudo_bytes)((unsigned char*)data, size); - if (res != 0 && res != 1) { - throw rand_error(); - } - return res; -} - -std::string RandomGen::rand_string(std::size_t size, bool strong) { - char buffer[size]; - if (!rand_bytes(buffer, size, strong)) { - throw rand_error(); - } - return std::string(buffer, size); -} - -RandomGen& rand_gen() { - static RandomGen MainPRNG; - return MainPRNG; -} - -} // namespace prng - -// ****************************************************** - -namespace crypto { -namespace Ed25519 { - -const int privkey_bytes = 32; -const int pubkey_bytes = 32; -const int sign_bytes = 64; -const int shared_secret_bytes = 32; - -bool all_bytes_same(const unsigned char* str, std::size_t size) { - unsigned char c = str[0]; - for (std::size_t i = 0; i < size; i++) { - if (str[i] != c) { - return false; - } - } - return true; -} - -class PublicKey { - enum { pk_empty, pk_xz, pk_init } inited; - unsigned char pubkey[pubkey_bytes]; - ellcurve::TwEdwardsCurve::SegrePoint PubKey; - ellcurve::MontgomeryCurve::PointXZ PubKey_xz; - - public: - PublicKey() : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - } - PublicKey(const unsigned char pub_key[pubkey_bytes]); - PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint& Pub_Key); - - bool import_public_key(const unsigned char pub_key[pubkey_bytes]); - bool import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint& Pub_Key); - bool export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const; - bool check_message_signature(unsigned char signature[sign_bytes], const unsigned char* message, std::size_t msg_size); - - void clear(); - bool ok() const { - return inited == pk_init; - } - - const unsigned char* get_pubkey_ptr() const { - return inited == pk_init ? pubkey : 0; - } - const ellcurve::TwEdwardsCurve::SegrePoint& get_point() const { - return PubKey; - } - const ellcurve::MontgomeryCurve::PointXZ& get_point_xz() const { - return PubKey_xz; - } -}; - -void PublicKey::clear(void) { - if (inited != pk_empty) { - std::memset(pubkey, 0, pubkey_bytes); - PubKey.zeroize(); - PubKey_xz.zeroize(); - } - inited = pk_empty; -} - -PublicKey::PublicKey(const unsigned char pub_key[pubkey_bytes]) - : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - import_public_key(pub_key); -} - -PublicKey::PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint& Pub_Key) - : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) { - import_public_key(Pub_Key); -} - -bool PublicKey::import_public_key(const unsigned char pub_key[pubkey_bytes]) { - clear(); - if (all_bytes_same(pub_key, pubkey_bytes)) { - return false; - } - bool ok = false; - PubKey = ellcurve::Ed25519().import_point(pub_key, ok); - if (!ok) { - clear(); - return false; - } - std::memcpy(pubkey, pub_key, pubkey_bytes); - PubKey_xz.X = PubKey.Z + PubKey.Y; - PubKey_xz.Z = PubKey.Z - PubKey.Y; - inited = pk_init; - return true; -} - -bool PublicKey::import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint& Pub_Key) { - clear(); - if (!Pub_Key.is_valid()) { - return false; - } - PubKey = Pub_Key; - PubKey_xz.X = PubKey.Z + PubKey.Y; - PubKey_xz.Z = PubKey.Z - PubKey.Y; - inited = pk_init; - - if (!PubKey.export_point(pubkey)) { - clear(); - return false; - } - return true; -} - -bool PublicKey::export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const { - if (inited != pk_init) { - std::memset(pubkey_buffer, 0, pubkey_bytes); - return false; - } else { - std::memcpy(pubkey_buffer, pubkey, pubkey_bytes); - return true; - } -} - -bool PublicKey::check_message_signature(unsigned char signature[sign_bytes], const unsigned char* message, - std::size_t msg_size) { - if (inited != pk_init) { - return false; - } - unsigned char hash[64]; - { - digest::SHA512 hasher(signature, 32); - hasher.feed(pubkey, 32); - hasher.feed(message, msg_size); - hasher.extract(hash); - } - auto& E = ellcurve::Ed25519(); - const arith::Bignum& L = E.get_ell(); - arith::Bignum H, S; - S.import_lsb(signature + 32, 32); - H.import_lsb(hash, 64); - H %= L; - H = L - H; - auto sG = E.power_gen(S); - auto hA = E.power_point(PubKey, H); - auto pR1 = E.add_points(sG, hA); - unsigned char pR1_bytes[32]; - if (!pR1.export_point(pR1_bytes)) { - return false; - } - return !std::memcmp(pR1_bytes, signature, 32); -} - -class PrivateKey { - public: - struct priv_key_no_copy {}; - PrivateKey() : inited(false) { - std::memset(privkey, 0, privkey_bytes); - } - PrivateKey(const unsigned char pk[privkey_bytes]) : inited(false) { - std::memset(privkey, 0, privkey_bytes); - import_private_key(pk); - } - ~PrivateKey() { - clear(); - } - bool random_private_key(bool strong = false); - bool import_private_key(const unsigned char pk[privkey_bytes]); - bool export_private_key(unsigned char pk[privkey_bytes]) const; // careful! - bool export_public_key(unsigned char pubk[pubkey_bytes]) const { - return PubKey.export_public_key(pubk); - } - void clear(); - bool ok() const { - return inited; - } - - // used for EdDSA (sign) - bool sign_message(unsigned char signature[sign_bytes], const unsigned char* message, std::size_t msg_size); - // used for ECDH (encrypt / decrypt) - bool compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey& Pub); - // used for EC asymmetric decryption - bool compute_temp_shared_secret(unsigned char secret[shared_secret_bytes], - const unsigned char temp_pub_key[pubkey_bytes]); - - const PublicKey& get_public_key() const { - return PubKey; - } - - private: - bool inited; - unsigned char privkey[privkey_bytes]; - unsigned char priv_salt[32]; - arith::Bignum priv_exp; - PublicKey PubKey; - - bool process_private_key(); - PrivateKey(const PrivateKey&) { - throw priv_key_no_copy(); - } - PrivateKey& operator=(const PrivateKey&) { - throw priv_key_no_copy(); - } -}; - -bool PrivateKey::random_private_key(bool strong) { - inited = false; - if (!prng::rand_gen().rand_bytes(privkey, privkey_bytes, strong)) { - clear(); - return false; - } - return process_private_key(); -} - -void PrivateKey::clear(void) { - std::memset(privkey, 0, privkey_bytes); - std::memset(priv_salt, 0, sizeof(priv_salt)); - priv_exp.clear(); - PubKey.clear(); - inited = false; -} - -bool PrivateKey::import_private_key(const unsigned char pk[privkey_bytes]) { - clear(); - if (all_bytes_same(pk, privkey_bytes)) { - return false; - } - std::memcpy(privkey, pk, privkey_bytes); - return process_private_key(); -} - -bool PrivateKey::export_private_key(unsigned char pk[privkey_bytes]) const { // careful! - if (!inited) { - std::memset(pk, 0, privkey_bytes); - return false; - } else { - std::memcpy(pk, privkey, privkey_bytes); - return true; - } -} - -bool PrivateKey::process_private_key() { - unsigned char buff[64]; - digest::hash_str(buff, privkey, privkey_bytes); - std::memcpy(priv_salt, buff + 32, 32); - buff[0] &= -8; - buff[31] = ((buff[31] | 0x40) & ~0x80); - priv_exp.import_lsb(buff, 32); - PubKey = ellcurve::Ed25519().power_gen(priv_exp); - inited = PubKey.ok(); - if (!inited) { - clear(); - } - return inited; -} - -bool PrivateKey::compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey& Pub) { - if (!inited || !Pub.ok()) { - std::memset(secret, 0, shared_secret_bytes); - *(long*)secret = lrand48(); - return false; - } - auto P = ellcurve::Curve25519().power_xz(Pub.get_point_xz(), priv_exp); - if (P.is_infty()) { - std::memset(secret, 0, shared_secret_bytes); - *(long*)secret = lrand48(); - return false; - } - P.export_point_y(secret); - return true; -} - -bool PrivateKey::compute_temp_shared_secret(unsigned char secret[shared_secret_bytes], - const unsigned char temp_pub_key[pubkey_bytes]) { - PublicKey tempPubkey(temp_pub_key); - if (!tempPubkey.ok()) { - return false; - } - return compute_shared_secret(secret, tempPubkey); -} - -bool PrivateKey::sign_message(unsigned char signature[sign_bytes], const unsigned char* message, std::size_t msg_size) { - if (!inited) { - std::memset(signature, 0, sign_bytes); - return false; - } - unsigned char r_bytes[64]; - digest::hash_two_str(r_bytes, priv_salt, 32, message, msg_size); - const arith::Bignum& L = ellcurve::Ed25519().get_ell(); - arith::Bignum eR; - eR.import_lsb(r_bytes, 64); - eR %= L; - - auto pR = ellcurve::Ed25519().power_gen(eR); - - assert(pR.export_point(signature, 32)); - { - digest::SHA512 hasher(signature, 32); - hasher.feed(PubKey.get_pubkey_ptr(), 32); - hasher.feed(message, msg_size); - hasher.extract(r_bytes); - } - arith::Bignum S; - S.import_lsb(r_bytes, 64); - S %= L; - S *= priv_exp; - S += eR; - S %= L; - S.export_lsb(signature + 32, 32); - return true; -} - -// use one TempKeyGenerator object a lot of times -class TempKeyGenerator { - enum { salt_size = 64 }; - unsigned char random_salt[salt_size]; - unsigned char buffer[privkey_bytes]; - - public: - TempKeyGenerator() { - prng::rand_gen().strong_rand_bytes(random_salt, salt_size); - } - ~TempKeyGenerator() { - std::memset(random_salt, 0, salt_size); - std::memset(buffer, 0, privkey_bytes); - } - - unsigned char* get_temp_private_key(unsigned char* to, const unsigned char* message, std::size_t size, - const unsigned char* rand = 0, std::size_t rand_size = 0); // rand may be 0 - void create_temp_private_key(PrivateKey& pk, const unsigned char* message, std::size_t size, - const unsigned char* rand = 0, std::size_t rand_size = 0); - - // sets temp_pub_key and shared_secret for one-time asymmetric encryption of message - bool create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes], unsigned char secret[shared_secret_bytes], - const PublicKey& recipientPubKey, const unsigned char* message, std::size_t size, - const unsigned char* rand = 0, std::size_t rand_size = 0); -}; - -unsigned char* TempKeyGenerator::get_temp_private_key(unsigned char* to, const unsigned char* message, std::size_t size, - const unsigned char* rand, - std::size_t rand_size) { // rand may be 0 - digest::SHA256 hasher(message, size); - hasher.feed(random_salt, salt_size); - if (rand && rand_size) { - hasher.feed(rand, rand_size); - } - if (!to) { - to = buffer; - } - hasher.extract(to); - //++ *((long *)random_salt); - return to; -} - -void TempKeyGenerator::create_temp_private_key(PrivateKey& pk, const unsigned char* message, std::size_t size, - const unsigned char* rand, std::size_t rand_size) { - pk.import_private_key(get_temp_private_key(buffer, message, size, rand, rand_size)); - std::memset(buffer, 0, privkey_bytes); -} - -bool TempKeyGenerator::create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes], - unsigned char shared_secret[shared_secret_bytes], - const PublicKey& recipientPubKey, const unsigned char* message, - std::size_t size, const unsigned char* rand, std::size_t rand_size) { - PrivateKey tmpPk; - create_temp_private_key(tmpPk, message, size, rand, rand_size); - return tmpPk.export_public_key(temp_pub_key) && tmpPk.compute_shared_secret(shared_secret, recipientPubKey); -} - -} // namespace Ed25519 -} // namespace crypto - -// ****************************************************** - -void print_buffer(const unsigned char buffer[32]) { - for (int i = 0; i < 32; i++) { - char buff[4]; - sprintf(buff, "%02x", buffer[i]); - std::cout << buff; - } -} - -std::string buffer_to_hex(const unsigned char* buffer, std::size_t size = 32) { - char str[2 * size + 1]; - for (std::size_t i = 0; i < size; i++) { - sprintf(str + 2 * i, "%02x", buffer[i]); - } - return str; -} - -int main(void) { - arith::Bignum x = (3506824292LL << 31); - x = (2948877059LL << 31); - arith::Bignum L = (((36 * x + 36) * x + 18) * x + 6) * x + 1; - arith::Bignum P = L + 6 * sqr(x); - std::cout << "x= " << x << "; l= " << L << "; p= " << P << std::endl; - std::cout << "x= " << x.to_hex() << "; l= " << L.to_hex() << "; p= " << P.to_hex() << std::endl; - std::cout << "x mod 3=" << x % 3 << "; p mod 9=" << P % 9 << "; x/2^31=" << (x >> 31).to_hex() << "=" << (x >> 31) - << std::endl; - - crypto::Ed25519::PrivateKey PK1, PK2, PK3; - PK1.random_private_key(); - PK2.random_private_key(); - unsigned char priv2_export[32]; - bool ok = PK2.export_private_key(priv2_export); - std::cout << "PK2 = " << ok << " " << buffer_to_hex(priv2_export) << std::endl; - PK3.import_private_key(priv2_export); - std::cout << "PK3 = " << PK3.ok() << std::endl; - - unsigned char pub_export[32]; - ok = PK1.export_public_key(pub_export); - std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - crypto::Ed25519::PublicKey PubK1(pub_export); - ok = PK2.export_public_key(pub_export); - std::cout << "PubK2 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - crypto::Ed25519::PublicKey PubK2(pub_export); - ok = PK3.export_public_key(pub_export); - std::cout << "PubK3 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - crypto::Ed25519::PublicKey PubK3(pub_export); - ok = PubK1.export_public_key(pub_export); - std::cout << "PubK1 = " << ok << " " << buffer_to_hex(pub_export) << std::endl; - - unsigned char secret12[32], secret21[32]; - ok = PK1.compute_shared_secret(secret12, PK3.get_public_key()); - std::cout << "secret(PK1,PubK2)=" << ok << " " << buffer_to_hex(secret12) << std::endl; - ok = PK2.compute_shared_secret(secret21, PubK1); - std::cout << "secret(PK2,PubK1)=" << ok << " " << buffer_to_hex(secret21) << std::endl; - - unsigned char signature[64]; - ok = PK1.sign_message(signature, (const unsigned char*)"abc", 3); - std::cout << "PK1.signature=" << ok << " " << buffer_to_hex(signature) << std::endl; - - // signature[63] ^= 1; - ok = PubK1.check_message_signature(signature, (const unsigned char*)"abc", 3); - std::cout << "PubK1.check_signature=" << ok << std::endl; - - unsigned char temp_pubkey[32]; - crypto::Ed25519::TempKeyGenerator TKG; // use one generator a lot of times - - TKG.create_temp_shared_secret(temp_pubkey, secret12, PubK1, (const unsigned char*)"abc", 3); - std::cout << "secret12=" << buffer_to_hex(secret12) << "; temp_pubkey=" << buffer_to_hex(temp_pubkey) << std::endl; - - PK1.compute_temp_shared_secret(secret21, temp_pubkey); - std::cout << "secret21=" << buffer_to_hex(secret21) << std::endl; -} diff --git a/test/regression-tests.ans b/test/regression-tests.ans index e2057210c..0e07e3d61 100644 --- a/test/regression-tests.ans +++ b/test/regression-tests.ans @@ -13,7 +13,7 @@ Test_Fift_test_bls_ops_default fb0a81d4f247ab806318b051d12158f7f1aacc5513db5f8cb Test_Fift_test_deep_stack_ops_default df812efbadfffa8a3f553416f68c8c4435bac07266f84562cf98fe5f0dd62a52 Test_Fift_test_default 4e44b3382963ec89f7b5c8f2ebd85da3bc8aebad5b49f5b11b14075061477b4d Test_Fift_test_dict_default a9c8cbcfdece5573185022cea07f59f1bc404e5d879e5157a5745757f8ee0525 -Test_Fift_test_disasm_default dacaa555f5f217b2373e01e3bcd59634e480f5759dcc43edbdef35273ae38492 +Test_Fift_test_disasm_default 412cf37d37c5d9d81f44dbf4e3d3e7cda173c23b890614eb8a3bc5f2b92f13e6 Test_Fift_test_fiftext_default 2b0db5d4d4bfbc705b959cc787540d7b3a21a71469eac54756e76953f0d9afca Test_Fift_test_fixed_default 278a19d56b773102caf5c1fe2997ea6c8d0d9e720eff8503feede6398a197eec Test_Fift_test_hash_ext_default 686fc5680feca5b3bb207768215b27f6872a95128762dee0d7f2c88bc492d62d @@ -37,40 +37,40 @@ Test_Fift_testvm8_default 17c9e2205ccecfd8549328b4a501d07dde0336899a7a496e747e10 Test_Fift_testvm_default ee4cbfec76c050b6de7877cfc39817d594cd1e175b6265b76fb642e30b940437 Test_Fift_testvmprog_default e5d0b2c68ee568280877c8495be558bfd0054ca5d99a99eebb525bbeca8a65af Test_RefInt_main_default 768493e0aef8e09a401a6d369edd1ef503a9215fb09dc460f52b27a8bde767cb -Test_VM_assert_code_not_null_default 05bc07e129181c972b976442f200de9487dee8bfb5ac53dd36ff61c5d4d4291d -Test_VM_assert_extract_minmax_key_default c352309c61bdf62ba7a0ba7280d303c88b0696fe7efa550c05feb2c662275297 -Test_VM_assert_lookup_prefix_default c5b45999b46d324e4008c07e5ce671bbcd833f4e15fb21a4a5136f7b980ca6fc -Test_VM_assert_pfx_dict_lookup_default fa6e3f96b31cf2ed9a9dac6b279ec05acfedf13b8ed7b815789f167d1ed7352f +Test_VM_assert_code_not_null_default 09f75cb845e0df27f3ec92405ccb4018484711a79813fd47fe8e158762c1cb93 +Test_VM_assert_extract_minmax_key_default 756337c2b2ce489243956a6608d6934ba9f76124a9435f045fc3a3b65c113d41 +Test_VM_assert_lookup_prefix_default f7683f9d2010bca53b1ef20c0e82427fb04ed62fa5fea1ee986f005ecfc9a27a +Test_VM_assert_pfx_dict_lookup_default 6d7c80d94dbc6d3ae4bafa216667b95ede4f2cbd44a59384abace84270417ef8 Test_VM_bigint_default feeb473a4ac51133989e1c145d0f49defa77117d2ae8b66bd7d12e3579e91b9f -Test_VM_bug_div_short_any_default f69aca6873f75d53dd37b6952151a2d858407a04589330762827dbc96d8b7c04 -Test_VM_bug_exec_dict_getnear_default db314c2e25b49c1f7f044d271e225f36da546c66242a8ab12f6afae37628a81e -Test_VM_bug_stack_overflow_default 7e0e3e96ca438ac96648d569c55213aa82154cf004e80265b1c481b1c4219719 -Test_VM_infinity_loop_1_default 670beda76229922806805e558d50d8f320017c642c3e7e34a7e1f2b7edb83cee -Test_VM_infinity_loop_2_default 22d9bd8cb41ff7b6cced5825e4ab73275b2fc07b1e3cd4588de815e2e6df2963 -Test_VM_memory_leak_default e10dc118f3538720a16bcbd39be9a68c3ea07f76b3d2ed5719a5e866d91f0ab3 -Test_VM_memory_leak_new_default fd2eec0a1d5ae49fb5ff8ba4b938fd9d0fe330be4a07b2b8be12bab249b00d90 -Test_VM_memory_leak_old_default f3076ae38d14000c021597b824d2f0e51de4f00601429ec3e23cca1b32dba844 -Test_VM_oom_1_default 90862ddf3270840fbc9263c003c628ddd4a8bf6548b9bd3d53eb35a5c34bc325 -Test_VM_report3_1_default 7bc6a8e66f9a0e40cd131e9829ff36fed16b464170d27c0b365a3f549df57282 -Test_VM_report3_2_default 2231bc352cf431e72a84abad2261969bd5b0ee3d9051bb7a53b69fd8ea05f951 -Test_VM_report3_3_default 9416187eb0600ed247795837ca820bccaffb39841bd9d2ff625816bfbba35d6d -Test_VM_report3_4_default 11661eb00ea37c68e3483a8e048f922f73070c6da8219247663e3d6471c5c0cc -Test_VM_report3_6_default 1d7be98a8b07f803e80168247459e620ce4b91df634ad896e878d21a3ed757c0 -Test_VM_report3_int_overflow_1_default a0c2414ca2c9672d54409ee375a6aad6e2233306eaa3dfd33a82de3c90bba3ba -Test_VM_report3_int_overflow_2_default 01cd461802e532a6830705ad50eaa1760278737ff7beeb654e3c59ceb4aa8e2e -Test_VM_report3_loop_1_default b28b35d057a1b4fa2282d6f422ecd822b18cc4344733d923ef7b002f64bc4d72 -Test_VM_report3_loop_2_default 9f8236535902b04e403d412fcf1f79e64d0f2eb25b3cc014b7d61b2d7a34b9ef -Test_VM_report3_loop_3_default 7ee05ea553c48a2476035817b9d860f614a355927c9e011b2f824dc6e5f7b0cf -Test_VM_report3_loop_4_default 4b6c2f65fda3c9e9c6660b6cbbcb1b2103c5b52870cb5daa8876bbed0ca9bbc9 -Test_VM_report3_loop_5_default 0d5d504884172ef8513757d7f6b2a3870dbd28efd5960857441c032e1c67d836 -Test_VM_report3_loop_6_default 5c35b92144debdb61b2020d690669bffbdd96f75ecde827fd0c75c05da22b5a0 -Test_VM_report3_qnot_default dc280444c7e3886cc3412f96f44c803c45287a07fcb9c638643e21bcdfe3905d -Test_VM_simple_default f6733549069427c2beb1a85ee25635540e27aa68cb8ad101d8435e19afeae862 -Test_VM_unhandled_exception_1_default 0abe2740dd3b6a6b91eb67fee573f638086fecc72653d2d81c956782186b5d78 -Test_VM_unhandled_exception_2_default 5ca67db5a0e957cc106bb47b744177ca959632a352f3629df376c34cbf03d51b -Test_VM_unhandled_exception_3_default b354e897e35a1177fd66d2c6ad7d77ae33a4e18f8678a518d79fea1388853307 -Test_VM_unhandled_exception_4_default 412cbfe13745fde55cdcc5e41d7b15ba4d09f0e723f8e4421ae0b7066ca07b8f -Test_VM_unhandled_exception_5_default d760e540cd9c200c207f71c540cdaf06d11c96e32ec19860b9c1046cb1e38855 +Test_VM_bug_div_short_any_default 49c9588b2b25b08979016f8b7ca42ae9fa4904a1dc6a2093a7dae6dce0cdf42f +Test_VM_bug_exec_dict_getnear_default 0b0cb6c1fef773f8b5a4aab8d575ba941f3b85dd449f85051296954028e59781 +Test_VM_bug_stack_overflow_default 31950eb2ed62bd1ce1c18e0031a81390ff3a3feee61ff23a09181995917137d0 +Test_VM_infinity_loop_1_default 6b8cc0ff85efa6882ffdf6e9e4333967976a29c4ce32a25b42c4c53370ad3024 +Test_VM_infinity_loop_2_default 4be08957dc86dfde3dfadd8c2f961ef2f1fa839788bbf7affea754115cee9e18 +Test_VM_memory_leak_default da588f89f3bc3ef7496bbab61e2d993f0c84bba80bb28d9c20c6eac0f7f57dd3 +Test_VM_memory_leak_new_default d25e8602c88c454ded6271d0f7afbc556820cc9942c56de9e0bd95b329f8783e +Test_VM_memory_leak_old_default 563f5a02130f231823099985c77d09913db07d2d8782edf431822f6afe4911b8 +Test_VM_oom_1_default 354934173c82e4f7bca5063846abd35cb47c4fcf1c3ba8c2fd04a4b186fcbf18 +Test_VM_report3_1_default 26bb43b5100e94791911a66226ec6545422749e0ea9e6279983b00ef4b506601 +Test_VM_report3_2_default 07a84726217f362fd71b3ceab96112ffc7aa40ed44636cf0128205d85798c66c +Test_VM_report3_3_default 0d9a92491c88ada92283691debd123724db2b7c1bd345200a53c057032e9cc07 +Test_VM_report3_4_default eb23c8e1219aed91b1b4f519efcac87018a5cf8e0ce473cfa641f8221f3c5d20 +Test_VM_report3_6_default 769ce8f9bb6fb9b8619afdb8e9d621b6199466f07c37eeea8edf3c21bf05a101 +Test_VM_report3_int_overflow_1_default 7aaf32ec7ace54b93d6b55f3ac9642572f348ebd64412afdda24849f8e4eb1dc +Test_VM_report3_int_overflow_2_default 572d197681654c94951280448ea3cf448613391633383c2424d719b03b6ec939 +Test_VM_report3_loop_1_default c9b00b32a024c65e0a8019c86e94ee365a823ff26e2420e1797902841abab57c +Test_VM_report3_loop_2_default 3654949987ddb44d8e11e84fe907d43707eaed910b9d0ad15dd68b531df1444a +Test_VM_report3_loop_3_default c1fc7e0d160b334fe8a4735a2a9d36c3b10530edaad5c1859df88382ff82a2d9 +Test_VM_report3_loop_4_default 5ad7cc51a6e553ee3d4a427229908a51692e117624838190311c7023df7a5e5b +Test_VM_report3_loop_5_default 068f81caecc344132a601259d9f73eea7089b1399793661ba1954483e0d5682c +Test_VM_report3_loop_6_default bf2e45709fceeed0192ec34af618cba3b85b90f71071e018afba686167618a90 +Test_VM_report3_qnot_default 7fcbda7e3fc4853a36e6b02e9d346f039690b1879d40850f561ea4123452d3ec +Test_VM_simple_default c96d70ea853828c89cd38fcf22543289335f3086a53301a1d0f186753ba9975b +Test_VM_unhandled_exception_1_default 80fe0e4c2ae19ae73e67e4355548d0afa59ea286be2d75a91db4529618dba008 +Test_VM_unhandled_exception_2_default 1362ba3a6ddbf5a30aba07ad58e8c24b0f85bdc53525e3eaa27af7248c62525a +Test_VM_unhandled_exception_3_default e381ce751cbd0e2994d7f60df7746b9ed7783198cfbcb31dccf02fafe68b6733 +Test_VM_unhandled_exception_4_default 51dd501ec0514f3b388145761b252f09d6ef3e831ea450605ae30511688dd708 +Test_VM_unhandled_exception_5_default 8231cfe1fb6ce6107b592f2c8f6a4eae0d123fc399163c81e8e0d5228b68bc91 Test_base64_main_default e90d541bd810871c4a81e162f1fffb555024b72807cb895414d16bc11494b789 Test_bigexp_main_default 45a1f51fb2abcc1ebf8569e1a57bebee04c334a15e03535ff5869bc9a9db8956 Test_bits256_scan_main_default 3ec7434e1cabc8e08eb2e79064e67747ffbfed177473c7873b88c144a7ed6f42 diff --git a/test/test-adnl.cpp b/test/test-adnl.cpp index d9ae4abef..85e965a4e 100644 --- a/test/test-adnl.cpp +++ b/test/test-adnl.cpp @@ -52,7 +52,7 @@ int main() { td::to_integer_safe("0").ensure(); - std::string db_root_ = "tmp-ee"; + std::string db_root_ = "tmp-dir-test-adnl"; td::rmrf(db_root_).ignore(); td::mkdir(db_root_).ensure(); diff --git a/test/test-catchain.cpp b/test/test-catchain.cpp index 53b329248..149ea3e38 100644 --- a/test/test-catchain.cpp +++ b/test/test-catchain.cpp @@ -219,7 +219,7 @@ int main(int argc, char *argv[]) { SET_VERBOSITY_LEVEL(verbosity_INFO); td::set_default_failure_signal_handler().ensure(); - std::string db_root_ = "tmp-ee"; + std::string db_root_ = "tmp-dir-test-catchain"; td::rmrf(db_root_).ignore(); td::mkdir(db_root_).ensure(); @@ -274,8 +274,6 @@ int main(int argc, char *argv[]) { } }); - auto t = td::Timestamp::in(1.0); - ton::catchain::CatChainSessionId unique_id; td::Random::secure_bytes(unique_id.as_slice()); @@ -287,7 +285,7 @@ int main(int argc, char *argv[]) { } }); - t = td::Timestamp::in(10.0); + auto t = td::Timestamp::in(10.0); while (scheduler.run(1)) { if (t.is_in_past()) { break; @@ -300,7 +298,7 @@ int main(int argc, char *argv[]) { scheduler.run_in_context([&] { td::actor::send_closure(inst[0], &CatChainInst::create_fork); }); - t = td::Timestamp::in(10.0); + t = td::Timestamp::in(1.0); while (scheduler.run(1)) { if (t.is_in_past()) { break; diff --git a/test/test-dht.cpp b/test/test-dht.cpp index 2391fd9c4..8d814f6e0 100644 --- a/test/test-dht.cpp +++ b/test/test-dht.cpp @@ -41,7 +41,7 @@ int main() { SET_VERBOSITY_LEVEL(verbosity_INFO); - std::string db_root_ = "tmp-ee"; + std::string db_root_ = "tmp-dir-test-dht"; td::rmrf(db_root_).ignore(); td::mkdir(db_root_).ensure(); diff --git a/test/test-ext-client.cpp b/test/test-ext-client.cpp deleted file mode 100644 index a1187d781..000000000 --- a/test/test-ext-client.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl/adnl.h" -#include "adnl/utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "dht/dht.h" -#include "overlay/overlays.h" -#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/port/signals.h" -#include "td/utils/port/FileFd.h" -#include "adnl/adnl-ext-client.h" - -#if TD_DARWIN || TD_LINUX -#include -#endif -#include -#include - -template -std::ostream &operator<<(std::ostream &stream, const td::UInt &x) { - for (size_t i = 0; i < size / 8; i++) { - stream << td::format::hex_digit((x.raw[i] >> 4) & 15) << td::format::hex_digit(x.raw[i] & 15); - } - - return stream; -} - -class TestNode : public td::actor::Actor { - private: - std::string local_config_ = "ton-local.config"; - std::string global_config_ = "ton-global.config"; - - td::actor::ActorOwn client_; - - std::unique_ptr 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 id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - bool ready_ = false; - std::string db_root_; - - public: - void conn_ready() { - LOG(ERROR) << "conn ready"; - ready_ = true; - } - void conn_closed() { - ready_ = false; - } - void set_local_config(std::string str) { - local_config_ = str; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void set_db_root(std::string db_root) { - db_root_ = db_root; - } - void start_up() override { - } - void alarm() override { - if (ready_ && !client_.empty()) { - LOG(ERROR) << "sending query"; - auto P = td::PromiseCreator::lambda([](td::Result R) { - if (R.is_error()) { - LOG(ERROR) << "failed query: " << R.move_as_error(); - return; - } - auto F = ton::fetch_tl_object(R.move_as_ok(), true); - if (F.is_error()) { - LOG(ERROR) << "failed to pasrse answer: " << F.move_as_error(); - return; - } - auto obj = F.move_as_ok(); - LOG(ERROR) << "got answer: " << ton::ton_api::to_string(obj); - }); - td::BufferSlice b = ton::serialize_tl_object(ton::create_tl_object(), true); - td::actor::send_closure(client_, &ton::adnl::AdnlExtClient::send_query, "query", std::move(b), - td::Timestamp::in(10.0), std::move(P)); - } - alarm_timestamp() = td::Timestamp::in(2.0); - } - TestNode() { - } - void run() { - auto L = td::read_file(local_config_).move_as_ok(); - auto lc_j = td::json_decode(L.as_slice()).move_as_ok(); - ton::ton_api::config_local lc; - ton::ton_api::from_json(lc, lc_j.get_object()).ensure(); - - 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::config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - - CHECK(gc.liteclients_.size() > 0); - auto &cli = gc.liteclients_[0]; - td::IPAddress addr; - addr.init_host_port(td::IPAddress::ipv4_to_str(cli->ip_), cli->port_).ensure(); - - client_ = ton::adnl::AdnlExtClient::create(ton::adnl::AdnlNodeIdFull::create(cli->id_).move_as_ok(), addr, - make_callback()); - alarm_timestamp() = td::Timestamp::in(2.0); - } -}; - -td::Result get_uint256(std::string str) { - if (str.size() != 64) { - return td::Status::Error("uint256 must have 64 bytes"); - } - td::UInt256 res; - for (size_t i = 0; i < 32; i++) { - res.raw[i] = static_cast(td::hex_to_int(str[2 * i]) * 16 + td::hex_to_int(str[2 * i + 1])); - } - return res; -} - -int main(int argc, char *argv[]) { - SET_VERBOSITY_LEVEL(verbosity_DEBUG); - td::set_default_failure_signal_handler().ensure(); - - td::actor::ActorOwn x; - - td::OptionParser p; - p.set_description("test basic adnl functionality"); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb(td::MutableSlice{b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('c', "local-config", "file to read local config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_local_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('D', "db", "root for dbs", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_db_root, fname.str()); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()), - td::FileFd::Flags::Create | td::FileFd::Flags::Append | td::FileFd::Flags::Write) - .move_as_ok(); - - dup2(FileLog.get_native_fd().fd(), 1); - dup2(FileLog.get_native_fd().fd(), 2); - return td::Status::OK(); - }); -#endif - - td::actor::Scheduler scheduler({2}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { td::actor::send_closure(x, &TestNode::run); }); - scheduler.run(); - - return 0; -} diff --git a/test/test-ext-server.cpp b/test/test-ext-server.cpp deleted file mode 100644 index b4b787283..000000000 --- a/test/test-ext-server.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl/adnl.h" -#include "adnl/utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "dht/dht.h" -#include "overlay/overlays.h" -#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/port/signals.h" -#include "td/utils/port/FileFd.h" - -#if TD_DARWIN || TD_LINUX -#include -#endif -#include -#include - -template -std::ostream &operator<<(std::ostream &stream, const td::UInt &x) { - for (size_t i = 0; i < size / 8; i++) { - stream << td::format::hex_digit((x.raw[i] >> 4) & 15) << td::format::hex_digit(x.raw[i] & 15); - } - - return stream; -} - -class TestNode : public td::actor::Actor { - private: - td::actor::ActorOwn keyring_; - td::actor::ActorOwn adnl_; - - std::string local_config_ = "ton-local.config"; - std::string global_config_ = "ton-global.config"; - - std::unique_ptr make_callback() { - class Callback : public ton::adnl::Adnl::Callback { - public: - void receive_message(ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, - td::BufferSlice data) override { - td::actor::send_closure(id_, &TestNode::adnl_receive_message, src, dst, std::move(data)); - } - void receive_query(ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data, - td::Promise promise) override { - td::actor::send_closure(id_, &TestNode::adnl_receive_query, src, dst, std::move(data), std::move(promise)); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - std::string db_root_; - - public: - void adnl_receive_message(ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data) { - LOG(ERROR) << "ADNL MESSAGE FROM " << src << ": size=" << data.size() << "\n"; - } - - void adnl_receive_query(ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data, - td::Promise promise) { - LOG(ERROR) << "ADNL QUERY FROM " << src << ": size=" << data.size() << "\n"; - promise.set_value(ton::serialize_tl_object(ton::create_tl_object("xxx"), true)); - } - void set_local_config(std::string str) { - local_config_ = str; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void set_db_root(std::string db_root) { - db_root_ = db_root; - } - void start_up() override { - } - void alarm() override { - } - TestNode() { - } - void run() { - keyring_ = ton::keyring::Keyring::create(db_root_ + "/keyring/"); - adnl_ = ton::adnl::Adnl::create(db_root_, keyring_.get()); - - auto L = td::read_file(local_config_).move_as_ok(); - auto lc_j = td::json_decode(L.as_slice()).move_as_ok(); - ton::ton_api::config_local lc; - ton::ton_api::from_json(lc, lc_j.get_object()).ensure(); - - 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::config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - - for (auto &port : lc.udp_ports_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_listening_udp_port, "0.0.0.0", - static_cast(port)); - } - - //td::actor::send_closure(network_manager_, &ton::adnl::AdnlNetworkManager::load_local_config, std::move(lc.net_)); - //td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ids_from_config, std::move(lc.local_ids_)); - if (gc.adnl_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_static_nodes_from_config, - std::move(gc.adnl_->static_nodes_)); - } - for (auto &x : lc.liteservers_) { - auto pk = ton::PrivateKey{x->id_}; - auto pub_k = ton::adnl::AdnlNodeIdFull{pk.compute_public_key()}; - auto id = pub_k.compute_short_id(); - - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, std::move(pk), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, pub_k, ton::adnl::AdnlAddressList{}); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::subscribe, id, - ton::adnl::Adnl::int_to_bytestring(ton::ton_api::getTestObject::ID), make_callback()); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ext_local_id, id); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ext_tcp_port, static_cast(x->port_)); - } - } -}; - -td::Result get_uint256(std::string str) { - if (str.size() != 64) { - return td::Status::Error("uint256 must have 64 bytes"); - } - td::UInt256 res; - for (size_t i = 0; i < 32; i++) { - res.raw[i] = static_cast(td::hex_to_int(str[2 * i]) * 16 + td::hex_to_int(str[2 * i + 1])); - } - return res; -} - -int main(int argc, char *argv[]) { - SET_VERBOSITY_LEVEL(verbosity_DEBUG); - td::set_default_failure_signal_handler().ensure(); - - td::actor::ActorOwn x; - - td::OptionParser p; - p.set_description("test basic adnl functionality"); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb(td::MutableSlice{b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('c', "local-config", "file to read local config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_local_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('D', "db", "root for dbs", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_db_root, fname.str()); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()), - td::FileFd::Flags::Create | td::FileFd::Flags::Append | td::FileFd::Flags::Write) - .move_as_ok(); - - dup2(FileLog.get_native_fd().fd(), 1); - dup2(FileLog.get_native_fd().fd(), 2); - return td::Status::OK(); - }); -#endif - - td::actor::Scheduler scheduler({2}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { td::actor::send_closure(x, &TestNode::run); }); - scheduler.run(); - - return 0; -} diff --git a/test/test-node.cpp b/test/test-node.cpp deleted file mode 100644 index d771d3aeb..000000000 --- a/test/test-node.cpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl/adnl.h" -#include "adnl/utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "dht/dht.h" -#include "overlay/overlays.h" -#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/port/signals.h" -#include "td/utils/port/FileFd.h" -#include "catchain/catchain.h" - -#include "crypto/common/refvector.hpp" - -#if TD_DARWIN || TD_LINUX -#include -#endif -#include -#include - -template -std::ostream &operator<<(std::ostream &stream, const td::UInt &x) { - for (size_t i = 0; i < size / 8; i++) { - stream << td::format::hex_digit((x.raw[i] >> 4) & 15) << td::format::hex_digit(x.raw[i] & 15); - } - - return stream; -} - -class TestNode : public td::actor::Actor { - private: - std::vector ping_ids_; - td::Timestamp next_dht_dump_; - - td::actor::ActorOwn adnl_; - std::vector> dht_nodes_; - td::actor::ActorOwn overlay_manager_; - std::vector> overlays_; - std::vector> catchains_; - - std::string local_config_ = "ton-local.config"; - std::string global_config_ = "ton-global.config"; - - td::int32 broadcast_size_ = 100; - - void receive_message(td::UInt256 src, td::UInt256 dst, td::BufferSlice data) { - LOG(ERROR) << "MESSAGE FROM " << src << " to " << dst << " of size " << std::to_string(data.size()) << "\n"; - } - - void receive_broadcast(td::UInt256 overlay_id, td::BufferSlice data) { - LOG(ERROR) << "BROADCAST IN " << overlay_id << " hash=" << td::sha256(data.as_slice()) << "\n"; - } - - void receive_query(td::UInt256 src, td::UInt256 dst, td::BufferSlice data, td::Promise promise) { - auto Q = ton::fetch_tl_object(std::move(data), true); - CHECK(Q.is_ok()); - auto R = Q.move_as_ok(); - LOG(ERROR) << "QUERY " - << " FROM " << src << " to " << dst << ": " << ton::ton_api::to_string(R) << "\n"; - promise.set_value(serialize_tl_object(ton::create_tl_object(), true)); - } - - void catchain_new_block(td::UInt256 src, td::uint64 height, td::BufferSlice data) { - LOG(ERROR) << "CATCHAIN BLOCK: " << src << "@" << height << ": " << td::sha256_uint256(data.as_slice()) << "\n"; - } - void catchain_bad_block(td::UInt256 src) { - LOG(ERROR) << "CATCHAIN BAD BLOCK\n"; - } - void catchain_broadcast(td::BufferSlice data) { - LOG(ERROR) << "CATCHAIN BROADCAST " << td::sha256_uint256(data.as_slice()) << "\n"; - } - - std::unique_ptr make_callback() { - class Callback : public ton::adnl::Adnl::Callback { - public: - void receive_message(td::UInt256 src, td::UInt256 dst, td::BufferSlice data) override { - td::actor::send_closure(id_, &TestNode::receive_message, src, dst, std::move(data)); - } - void receive_query(td::UInt256 src, td::UInt256 dst, td::BufferSlice data, - td::Promise promise) override { - td::actor::send_closure(id_, &TestNode::receive_query, src, dst, std::move(data), std::move(promise)); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - std::unique_ptr make_catchain_callback() { - class Callback : public ton::CatChainActor::Callback { - public: - void new_block(td::UInt256 src, td::uint64 height, td::BufferSlice data) override { - td::actor::send_closure(id_, &TestNode::catchain_new_block, src, height, std::move(data)); - } - void bad_block(td::UInt256 src) override { - td::actor::send_closure(id_, &TestNode::catchain_bad_block, src); - } - void broadcast(td::BufferSlice data) override { - td::actor::send_closure(id_, &TestNode::catchain_broadcast, std::move(data)); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - std::unique_ptr make_overlay_callback() { - class Callback : public ton::overlay::Overlays::Callback { - public: - void receive_message(td::UInt256 src, td::UInt256 overlay_id, td::BufferSlice data) override { - } - void receive_query(td::UInt256 src, td::uint64 query_id, td::UInt256 overlay_id, td::BufferSlice data) override { - } - - void receive_broadcast(td::UInt256 overlay_id, td::BufferSlice data) override { - td::actor::send_closure(id_, &TestNode::receive_broadcast, overlay_id, std::move(data)); - } - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - public: - void set_broadcast_size(td::int32 size) { - broadcast_size_ = size; - } - void set_local_config(std::string str) { - local_config_ = str; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void start_up() override { - alarm_timestamp() = td::Timestamp::in(1); - } - void alarm() override { - /*if (overlays_.size() > 0 && broadcast_size_ > 0) { - td::BufferSlice s(broadcast_size_); - td::Random::secure_bytes(s.as_slice()); - - td::actor::send_closure(overlay_manager_, &ton::overlay::OverlayManager::send_broadcast_fer, overlays_[0].first, - overlays_[0].second, ton::create_tl_object(s.as_slice().str())); - }*/ - for (auto &chain : catchains_) { - td::BufferSlice s(broadcast_size_); - td::Random::secure_bytes(s.as_slice()); - - td::actor::send_closure(chain, &ton::CatChainActor::add_event, std::move(s)); - } - alarm_timestamp() = td::Timestamp::in(1.0); - if (next_dht_dump_.is_in_past()) { - /*for (auto &node : dht_nodes_) { - char b[10240]; - td::StringBuilder sb({b, 10000}); - node->get_actor_unsafe().dump(sb); - LOG(DEBUG) << sb.as_cslice().c_str(); - }*/ - next_dht_dump_ = td::Timestamp::in(60.0); - } - } - TestNode() { - adnl_ = ton::adnl::Adnl::create("/var/ton-work/db.adnl"); - } - void run() { - auto L = td::read_file(local_config_).move_as_ok(); - auto lc_j = td::json_decode(L.as_slice()).move_as_ok(); - ton::ton_api::config_local lc; - ton::ton_api::from_json(lc, lc_j.get_object()).ensure(); - - 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::config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - - for (auto &port : lc.udp_ports_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_listening_udp_port, "0.0.0.0", - static_cast(port)); - } - /*if (!lc.net_) { - LOG(FATAL) << "local config does not contain NET section"; - }*/ - - //td::actor::send_closure(network_manager_, &ton::adnl::AdnlNetworkManager::load_local_config, std::move(lc.net_)); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ids_from_config, std::move(lc.local_ids_)); - if (gc.adnl_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_static_nodes_from_config, - std::move(gc.adnl_->static_nodes_)); - } - if (!gc.dht_) { - LOG(FATAL) << "global config does not contain dht section"; - } - - for (auto &it : lc.dht_) { - if (it->get_id() == ton::ton_api::dht_config_local::ID) { - auto R = ton::dht::Dht::create_from_json( - ton::clone_tl_object(gc.dht_), ton::move_tl_object_as(it), adnl_.get()); - if (R.is_error()) { - LOG(FATAL) << "fail creating dht node: " << R.move_as_error(); - } - dht_nodes_.push_back(R.move_as_ok()); - } else { - auto I = ton::move_tl_object_as(it); - for (int i = 0; i < I->cnt_; i++) { - auto R = ton::dht::Dht::create_random(ton::clone_tl_object(gc.dht_), ton::clone_tl_object(I->addr_list_), - adnl_.get()); - if (R.is_error()) { - LOG(FATAL) << "fail creating dht node: " << R.move_as_error(); - } - dht_nodes_.push_back(R.move_as_ok()); - } - } - } - - CHECK(dht_nodes_.size() > 0); - - td::actor::send_closure(adnl_, &ton::adnl::Adnl::register_dht_node, dht_nodes_[0].get()); - //td::actor::send_closure(overlay_manager_, &ton::overlay::Overlays::register_dht_node, dht_nodes_[0].get()); - - overlay_manager_ = ton::overlay::Overlays::create(adnl_.get(), dht_nodes_[0].get()); - - for (auto &it : lc.public_overlays_) { - if (it->get_id() == ton::ton_api::overlay_config_local::ID) { - auto X = ton::move_tl_object_as(it); - auto id = ton::create_tl_object(X->name_.clone()); - auto Id = ton::move_tl_object_as(id); - auto sid = ton::adnl_short_id(Id); - overlays_.emplace_back(X->id_->id_, sid); - td::actor::send_closure(overlay_manager_, &ton::overlay::Overlays::create_public_overlay, X->id_->id_, - std::move(Id), make_overlay_callback()); - } else { - auto X = ton::move_tl_object_as(it); - for (int i = 0; i < X->cnt_; i++) { - auto pk = ton::adnl_generate_random_pk(); - auto local_id = ton::adnl_short_id(ton::get_public_key(pk)); - - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, std::move(pk), ton::clone_tl_object(X->addr_list_)); - - auto id = ton::create_tl_object(X->name_.clone()); - auto Id = ton::move_tl_object_as(id); - auto sid = ton::adnl_short_id(Id); - overlays_.emplace_back(local_id, sid); - td::actor::send_closure(overlay_manager_, &ton::overlay::Overlays::create_public_overlay, local_id, - std::move(Id), make_overlay_callback()); - } - } - } - - //auto C = ton::CatChainActor::create(nullptr, adnl_.get(), overlay_manager_.get(), - // std::vector>()); - - for (auto &it : lc.catchains_) { - auto tag = it->tag_; - for (auto &V : gc.catchains_) { - if (V->tag_ == tag) { - auto v = std::move(clone_tl_object(V)->nodes_); - auto C = ton::CatChainActor::create(make_catchain_callback(), adnl_.get(), overlay_manager_.get(), - std::move(v), it->id_->id_, tag); - catchains_.push_back(std::move(C)); - } - } - } - } -}; - -td::Result get_uint256(std::string str) { - if (str.size() != 64) { - return td::Status::Error("uint256 must have 64 bytes"); - } - td::UInt256 res; - for (size_t i = 0; i < 32; i++) { - res.raw[i] = static_cast(td::hex_to_int(str[2 * i]) * 16 + td::hex_to_int(str[2 * i + 1])); - } - return res; -} - -int main(int argc, char *argv[]) { - SET_VERBOSITY_LEVEL(verbosity_DEBUG); - td::set_default_failure_signal_handler().ensure(); - - td::actor::ActorOwn x; - - td::OptionParser p; - p.set_description("test basic adnl functionality"); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb({b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('c', "local-config", "file to read local config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_local_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('s', "broadcast-size", "size of broadcast", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_broadcast_size, std::atoi(fname.str().c_str())); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()), - td::FileFd::Flags::Create | td::FileFd::Flags::Append | td::FileFd::Flags::Write) - .move_as_ok(); - - dup2(FileLog.get_native_fd().fd(), 1); - dup2(FileLog.get_native_fd().fd(), 2); - return td::Status::OK(); - }); -#endif - - td::actor::Scheduler scheduler({2}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { td::actor::send_closure(x, &TestNode::run); }); - scheduler.run(); - - return 0; -} diff --git a/test/test-rldp.cpp b/test/test-rldp.cpp index 11344c55b..b07f5f7dc 100644 --- a/test/test-rldp.cpp +++ b/test/test-rldp.cpp @@ -40,7 +40,7 @@ int main() { SET_VERBOSITY_LEVEL(verbosity_INFO); - std::string db_root_ = "tmp-ee"; + std::string db_root_ = "tmp-dir-test-rldp"; td::rmrf(db_root_).ignore(); td::mkdir(db_root_).ensure(); diff --git a/test/test-rldp2.cpp b/test/test-rldp2.cpp index 5367ffd3e..646b27d5d 100644 --- a/test/test-rldp2.cpp +++ b/test/test-rldp2.cpp @@ -40,7 +40,7 @@ int main() { SET_VERBOSITY_LEVEL(verbosity_INFO); - std::string db_root_ = "tmp-ee"; + std::string db_root_ = "tmp-dir-test-rldp2"; td::rmrf(db_root_).ignore(); td::mkdir(db_root_).ensure(); diff --git a/test/test-ton-collator.cpp b/test/test-ton-collator.cpp index 9ed5c7814..b76dd5ebb 100644 --- a/test/test-ton-collator.cpp +++ b/test/test-ton-collator.cpp @@ -50,7 +50,7 @@ #include "validator/fabric.h" #include "validator/impl/collator.h" -#include "crypto/vm/cp0.h" +#include "crypto/vm/vm.h" #include "crypto/block/block-db.h" #include "common/errorlog.h" @@ -408,7 +408,7 @@ int main(int argc, char *argv[]) { SET_VERBOSITY_LEVEL(verbosity_INFO); td::set_default_failure_signal_handler().ensure(); - CHECK(vm::init_op_cp0()); + vm::init_vm().ensure(); td::actor::ActorOwn x; diff --git a/test/test-validator-session-state.cpp b/test/test-validator-session-state.cpp index 819c1cc2d..5ed08add7 100644 --- a/test/test-validator-session-state.cpp +++ b/test/test-validator-session-state.cpp @@ -48,6 +48,7 @@ class Description : public ton::validatorsession::ValidatorSessionDescription { return 0; } void *alloc(size_t size, size_t align, bool temp) override { + size = (size + 15) / 16 * 16; td::uint32 idx = temp ? 1 : 0; auto s = pdata_cur_[idx].fetch_add(size); CHECK(s + size <= pdata_size_[idx]); diff --git a/test/test-validator-session.cpp b/test/test-validator-session.cpp deleted file mode 100644 index e986795ad..000000000 --- a/test/test-validator-session.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl/adnl.h" -#include "rldp/rldp.h" -#include "adnl/utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "dht/dht.h" -#include "overlay/overlays.h" -#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/port/signals.h" -#include "td/utils/port/FileFd.h" -#include "td/utils/overloaded.h" -#include "catchain/catchain.h" -#include "validator-session/validator-session.h" - -#if TD_DARWIN || TD_LINUX -#include -#endif -#include -#include - -class TestNode : public td::actor::Actor { - private: - td::actor::ActorOwn keyring_; - td::actor::ActorOwn adnl_; - td::actor::ActorOwn rldp_; - std::vector> dht_nodes_; - td::actor::ActorOwn overlay_manager_; - std::vector> validator_sessions_; - - std::string local_config_ = "ton-local.config"; - std::string global_config_ = "ton-global.config"; - - std::unique_ptr make_vs_callback() { - class Callback : public ton::validatorsession::ValidatorSession::Callback { - public: - void on_candidate(td::uint32 round, ton::PublicKeyHash source, - ton::validatorsession::ValidatorSessionRootHash root_hash, td::BufferSlice data, - td::BufferSlice extra, - td::Promise promise) override { - td::actor::send_closure(id_, &TestNode::on_candidate, round, source, root_hash, std::move(data), - std::move(extra), std::move(promise)); - } - void on_generate_slot(td::uint32 round, td::Promise promise) override { - td::actor::send_closure(id_, &TestNode::on_generate_slot, round, std::move(promise)); - } - void on_block_committed(td::uint32 round, ton::PublicKeyHash src, - ton::validatorsession::ValidatorSessionRootHash root_hash, - ton::validatorsession::ValidatorSessionFileHash file_hash, td::BufferSlice data, - std::vector> signatures, - ton::validatorsession::ValidatorSessionStats stats) override { - td::actor::send_closure(id_, &TestNode::on_block_committed, round, root_hash, std::move(data), - std::move(signatures)); - } - /*void on_missing_block_committed( - td::uint32 round, ton::validatorsession::ValidatorSessionRootHash root_hash, ton::validatorsession::ValidatorSessionFileHash file_hash, - td::BufferSlice data, std::vector> signatures) override { - td::actor::send_closure(id_, &TestNode::on_block_committed_abscent, round, root_hash, file_hash, - std::move(data), std::move(signatures)); - }*/ - void on_block_skipped(td::uint32 round) override { - td::actor::send_closure(id_, &TestNode::on_block_skipped, round); - } - void get_approved_candidate(ton::validatorsession::ValidatorSessionRootHash root_hash, - ton::validatorsession::ValidatorSessionFileHash file_hash, - ton::validatorsession::ValidatorSessionFileHash collated_data_file_hash, - td::Promise promise) override { - UNREACHABLE(); - } - - Callback(td::actor::ActorId id) : id_(std::move(id)) { - } - - private: - td::actor::ActorId id_; - }; - - return std::make_unique(actor_id(this)); - } - - td::uint64 height_ = 0; - - public: - void on_candidate(td::uint32 round, ton::PublicKeyHash source, - ton::validatorsession::ValidatorSessionRootHash root_hash, td::BufferSlice data, - td::BufferSlice collated, - td::Promise promise) { - auto sh = sha256_bits256(data.as_slice()); - auto B = ton::fetch_tl_object(std::move(data), true); - if (B.is_error()) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{B.move_as_error().to_string(), td::BufferSlice()}); - return; - } - if (collated.size() != 32) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{"bad collated data length", td::BufferSlice()}); - return; - } - td::Bits256 x; - x.as_slice().copy_from(collated.as_slice().truncate(32)); - if (x != sh) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{"bad block hash", td::BufferSlice()}); - return; - } - auto block = B.move_as_ok(); - if (block->root_hash_ != root_hash) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{"bad root hash", td::BufferSlice()}); - return; - } - if (block->root_hash_ != sha256_bits256(block->data_.as_slice())) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{"bad root hash (2)", td::BufferSlice()}); - return; - } - if (block->height_ != static_cast(height_) + 1) { - promise.set_result( - ton::validatorsession::ValidatorSession::CandidateDecision{"bad root height", td::BufferSlice()}); - return; - } - promise.set_result(ton::validatorsession::ValidatorSession::CandidateDecision{0}); - } - void on_generate_slot(td::uint32 round, td::Promise promise) { - auto data = td::BufferSlice{10000}; - td::Random::secure_bytes(data.as_slice()); - auto root_hash = sha256_bits256(data.as_slice()); - auto block = - ton::create_tl_object(root_hash, height_ + 1, std::move(data)); - - auto B = ton::serialize_tl_object(block, true); - auto hash = sha256_bits256(B.as_slice()); - auto collated = td::BufferSlice{32}; - collated.as_slice().copy_from(as_slice(hash)); - - /*BlockId id; - BlockStatus status; - RootHash root_hash; - FileHash file_hash; - FileHash collated_file_hash; - td::BufferSlice data; - td::BufferSlice collated_data;*/ - auto collated_file_hash = td::sha256_bits256(collated.as_slice()); - ton::BlockCandidate candidate{ton::BlockIdExt{ton::BlockId{0, 0, 0}, root_hash, td::sha256_bits256(B.as_slice())}, - collated_file_hash, std::move(B), std::move(collated)}; - promise.set_result(std::move(candidate)); - } - void on_block_committed(td::uint32 round, ton::validatorsession::ValidatorSessionRootHash root_hash, - td::BufferSlice data, - std::vector> signatures) { - LOG(ERROR) << "COMITTED BLOCK: ROUND=" << round << " ROOT_HASH=" << root_hash - << " DATA_HASH=" << sha256_bits256(data.as_slice()) << " SIGNED BY " << signatures.size(); - } - void on_block_skipped(td::uint32 round) { - LOG(ERROR) << "SKIPPED ROUND=" << round; - } - - void set_local_config(std::string str) { - local_config_ = str; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void start_up() override { - } - void alarm() override { - } - TestNode() { - } - void run() { - keyring_ = ton::keyring::Keyring::create("/var/ton-work/db.keyring"); - adnl_ = ton::adnl::Adnl::create("/var/ton-work/db.adnl", keyring_.get()); - rldp_ = ton::rldp::Rldp::create(adnl_.get()); - - auto L = td::read_file(local_config_).move_as_ok(); - auto lc_j = td::json_decode(L.as_slice()).move_as_ok(); - ton::ton_api::config_local lc; - ton::ton_api::from_json(lc, lc_j.get_object()).ensure(); - - 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::config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - - for (auto &port : lc.udp_ports_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_listening_udp_port, "0.0.0.0", - static_cast(port)); - } - /*if (!lc.net_) { - LOG(FATAL) << "local config does not contain NET section"; - }*/ - - //td::actor::send_closure(network_manager_, &ton::adnl::AdnlNetworkManager::load_local_config, std::move(lc.net_)); - //td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ids_from_config, std::move(lc.local_ids_)); - if (gc.adnl_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_static_nodes_from_config, - std::move(gc.adnl_->static_nodes_)); - } - if (!gc.dht_) { - LOG(FATAL) << "global config does not contain dht section"; - } - auto dhtR = ton::dht::Dht::create_global_config(std::move(gc.dht_)); - if (dhtR.is_error()) { - LOG(FATAL) << "bad dht config: " << dhtR.move_as_error(); - } - auto dht = dhtR.move_as_ok(); - - for (auto &it : lc.dht_) { - std::vector adnl_ids; - ton::ton_api::downcast_call( - *it.get(), td::overloaded( - [&](ton::ton_api::dht_config_local &obj) { - adnl_ids.push_back(ton::adnl::AdnlNodeIdShort{obj.id_->id_}); - }, - [&](ton::ton_api::dht_config_random_local &obj) { - auto addrR = ton::adnl::AdnlAddressList::create(std::move(obj.addr_list_)); - addrR.ensure(); - auto addr = addrR.move_as_ok(); - for (td::int32 i = 0; i < obj.cnt_; i++) { - auto pk = ton::PrivateKey{ton::privkeys::Ed25519::random()}; - auto pub = pk.compute_public_key(); - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, std::move(pk), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, - addr); - auto adnl_id = ton::adnl::AdnlNodeIdShort{pub.compute_short_id()}; - adnl_ids.push_back(adnl_id); - } - })); - for (auto &id : adnl_ids) { - auto R = ton::dht::Dht::create(id, "/var/ton-work/db/", dht, keyring_.get(), adnl_.get()); - R.ensure(); - dht_nodes_.push_back(R.move_as_ok()); - } - } - - CHECK(dht_nodes_.size() > 0); - - td::actor::send_closure(adnl_, &ton::adnl::Adnl::register_dht_node, dht_nodes_[0].get()); - //td::actor::send_closure(overlay_manager_, &ton::overlay::Overlays::register_dht_node, dht_nodes_[0].get()); - - overlay_manager_ = - ton::overlay::Overlays::create("/var/ton-work/db.overlays", keyring_.get(), adnl_.get(), dht_nodes_[0].get()); - - //auto C = ton::CatChainActor::create(nullptr, adnl_.get(), overlay_manager_.get(), - // std::vector>()); - - for (auto &it : lc.catchains_) { - auto tag = it->tag_; - for (auto &V : gc.catchains_) { - if (V->tag_ == tag) { - auto v = std::move(clone_tl_object(V)->nodes_); - - std::vector w; - w.resize(v.size()); - for (size_t i = 0; i < w.size(); i++) { - w[i].pub_key = ton::PublicKey{v[i]}; - w[i].adnl_id = ton::adnl::AdnlNodeIdShort{w[i].pub_key.compute_short_id()}; - w[i].weight = 1; - } - - auto C = ton::validatorsession::ValidatorSession::create( - tag, ton::PublicKeyHash{it->id_->id_}, std::move(w), make_vs_callback(), keyring_.get(), adnl_.get(), - rldp_.get(), overlay_manager_.get(), "/var/ton-work/db/"); - td::actor::send_closure(C, &ton::validatorsession::ValidatorSession::start); - validator_sessions_.emplace_back(std::move(C)); - } - } - } - } -}; - -int main(int argc, char *argv[]) { - SET_VERBOSITY_LEVEL(verbosity_INFO); - td::set_default_failure_signal_handler().ensure(); - - td::actor::ActorOwn x; - - td::OptionParser p; - p.set_description("test basic adnl functionality"); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb(td::MutableSlice{b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('c', "local-config", "file to read local config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_local_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - auto FileLog = td::FileFd::open(td::CSlice(fname.str().c_str()), - td::FileFd::Flags::Create | td::FileFd::Flags::Append | td::FileFd::Flags::Write) - .move_as_ok(); - - dup2(FileLog.get_native_fd().fd(), 1); - dup2(FileLog.get_native_fd().fd(), 2); - return td::Status::OK(); - }); -#endif - - td::actor::Scheduler scheduler({7}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { td::actor::send_closure(x, &TestNode::run); }); - scheduler.run(); - - return 0; -} diff --git a/test/test-validator.cpp b/test/test-validator.cpp deleted file mode 100644 index 7bc018f74..000000000 --- a/test/test-validator.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - This file is part of TON Blockchain source code. - - TON Blockchain is free software; you can redistribute it and/or - modify it under the terms of the GNU 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 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with TON Blockchain. If not, see . - - In addition, as a special exception, the copyright holders give permission - to link the code of portions of this program with the OpenSSL library. - You must obey the GNU General Public License in all respects for all - of the code used other than OpenSSL. If you modify file(s) with this - exception, you may extend this exception to your version of the file(s), - but you are not obligated to do so. If you do not wish to do so, delete this - exception statement from your version. If you delete this exception statement - from all source files in the program, then also delete it here. - - Copyright 2017-2020 Telegram Systems LLP -*/ -#include "adnl/adnl.h" -#include "rldp/rldp.h" -#include "adnl/utils.hpp" -#include "auto/tl/ton_api_json.h" -#include "auto/tl/ton_api.hpp" -#include "dht/dht.h" -#include "overlay/overlays.h" -#include "td/utils/OptionParser.h" -#include "td/utils/Time.h" -#include "td/utils/TsFileLog.h" -#include "td/utils/filesystem.h" -#include "td/utils/format.h" -#include "td/utils/Random.h" -#include "td/utils/port/signals.h" -#include "td/utils/port/FileFd.h" -#include "catchain/catchain.h" -#include "validator-session/validator-session.h" -#include "ton-node/ton-node.h" -#include "validator/manager.h" -#include "td/utils/filesystem.h" -#include "td/utils/ThreadSafeCounter.h" -#include "td/utils/port/path.h" -#include "crypto/vm/cp0.h" -#include "td/utils/overloaded.h" - -#include "memprof/memprof.h" - -#if TD_DARWIN || TD_LINUX -#include -#endif -#include -#include -#include - -class TestNode : public td::actor::Actor { - private: - td::actor::ActorOwn keyring_; - td::actor::ActorOwn adnl_; - td::actor::ActorOwn rldp_; - std::vector> dht_nodes_; - td::actor::ActorOwn overlay_manager_; - td::actor::ActorOwn validator_manager_; - td::actor::ActorOwn ton_node_; - - std::string local_config_ = "ton-local.config"; - std::string global_config_ = "ton-global.config"; - - std::string db_root_ = "/var/ton-work/db/"; - std::string zero_state_ = ""; - - public: - void set_local_config(std::string str) { - local_config_ = str; - } - void set_global_config(std::string str) { - global_config_ = str; - } - void set_db_root(std::string db_root) { - db_root_ = db_root; - } - void set_zero_state(std::string zero_state) { - zero_state_ = zero_state; - } - void start_up() override { - } - void alarm() override { - } - TestNode() { - } - void run() { - td::mkdir(db_root_).ensure(); - - keyring_ = ton::keyring::Keyring::create(db_root_ + "/keyring"); - adnl_ = ton::adnl::Adnl::create(db_root_, keyring_.get()); - rldp_ = ton::rldp::Rldp::create(adnl_.get()); - - auto L = td::read_file(local_config_).move_as_ok(); - auto lc_j = td::json_decode(L.as_slice()).move_as_ok(); - ton::ton_api::config_local lc; - ton::ton_api::from_json(lc, lc_j.get_object()).ensure(); - - 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::config_global gc; - ton::ton_api::from_json(gc, gc_j.get_object()).ensure(); - - for (auto &port : lc.udp_ports_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_listening_udp_port, "0.0.0.0", - static_cast(port)); - } - /*if (!lc.net_) { - LOG(FATAL) << "local config does not contain NET section"; - }*/ - - //td::actor::send_closure(network_manager_, &ton::adnl::AdnlNetworkManager::load_local_config, std::move(lc.net_)); - //td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_ids_from_config, std::move(lc.local_ids_)); - for (auto &local_id : lc.local_ids_) { - auto pk = ton::PrivateKey{local_id->id_}; - auto pub = pk.compute_public_key(); - auto addr_list = ton::adnl::AdnlAddressList::create(local_id->addr_list_); - addr_list.ensure(); - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, std::move(pk), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, addr_list.move_as_ok()); - } - if (gc.adnl_) { - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_static_nodes_from_config, - std::move(gc.adnl_->static_nodes_)); - } - if (!gc.dht_) { - LOG(FATAL) << "global config does not contain dht section"; - } - - auto dhtR = ton::dht::Dht::create_global_config(std::move(gc.dht_)); - if (dhtR.is_error()) { - LOG(FATAL) << "bad dht config: " << dhtR.move_as_error(); - } - auto dht = dhtR.move_as_ok(); - - for (auto &it : lc.dht_) { - std::vector adnl_ids; - ton::ton_api::downcast_call( - *it.get(), td::overloaded( - [&](ton::ton_api::dht_config_local &obj) { - adnl_ids.push_back(ton::adnl::AdnlNodeIdShort{obj.id_->id_}); - }, - [&](ton::ton_api::dht_config_random_local &obj) { - auto addrR = ton::adnl::AdnlAddressList::create(std::move(obj.addr_list_)); - addrR.ensure(); - auto addr = addrR.move_as_ok(); - for (td::int32 i = 0; i < obj.cnt_; i++) { - auto pk = ton::PrivateKey{ton::privkeys::Ed25519::random()}; - auto pub = pk.compute_public_key(); - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, std::move(pk), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, ton::adnl::AdnlNodeIdFull{pub}, - addr); - auto adnl_id = ton::adnl::AdnlNodeIdShort{pub.compute_short_id()}; - adnl_ids.push_back(adnl_id); - } - })); - for (auto &id : adnl_ids) { - auto R = ton::dht::Dht::create(id, db_root_, dht, keyring_.get(), adnl_.get()); - R.ensure(); - dht_nodes_.push_back(R.move_as_ok()); - } - } - - CHECK(dht_nodes_.size() > 0); - - td::actor::send_closure(adnl_, &ton::adnl::Adnl::register_dht_node, dht_nodes_[0].get()); - overlay_manager_ = ton::overlay::Overlays::create(db_root_, keyring_.get(), adnl_.get(), dht_nodes_[0].get()); - - CHECK(lc.validators_.size() <= 1); - CHECK(gc.validators_.size() <= 1); - - bool is_validator = false; - if (lc.validators_.size() == 1) { - CHECK(gc.validators_.size() == 1); - auto zero_state_id = - ton::BlockIdExt{ton::masterchainId, ton::shardIdAll, 0, gc.validators_[0]->zero_state_root_hash_, - gc.validators_[0]->zero_state_file_hash_}; - ton::PublicKeyHash id; - ton::adnl::AdnlNodeIdShort adnl_id; - ton::ton_api::downcast_call(*lc.validators_[0].get(), - td::overloaded( - [&](ton::ton_api::validator_config_local &cfg) { - id = ton::PublicKeyHash{cfg.id_->id_}; - adnl_id = ton::adnl::AdnlNodeIdShort{id}; - is_validator = true; - }, - [&](ton::ton_api::validator_config_random_local &cfg) { - auto privkey = ton::PrivateKey{ton::privkeys::Ed25519::random()}; - auto pubkey = ton::adnl::AdnlNodeIdFull{privkey.compute_public_key()}; - auto addrR = ton::adnl::AdnlAddressList::create(std::move(cfg.addr_list_)); - addrR.ensure(); - auto addr = addrR.move_as_ok(); - id = privkey.compute_short_id(); - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, - std::move(privkey), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, pubkey, addr); - adnl_id = ton::adnl::AdnlNodeIdShort{id}; - })); - - auto opts = ton::ValidatorManagerOptions::create( - zero_state_id, std::vector{ton::ShardIdFull{ton::basechainId, ton::shardIdAll}}); - CHECK(!opts.is_null()); - opts.write().set_allow_blockchain_init(is_validator); - validator_manager_ = - ton::ValidatorManagerFactory::create(is_validator ? id : ton::PublicKeyHash::zero(), opts, db_root_, - keyring_.get(), adnl_.get(), rldp_.get(), overlay_manager_.get()); - ton_node_ = - ton::TonNodeManager::create(adnl_id, gc.validators_[0]->zero_state_file_hash_, adnl_.get(), rldp_.get(), - dht_nodes_[0].get(), overlay_manager_.get(), validator_manager_.get(), db_root_); - - for (auto &x : lc.liteservers_) { - auto pk = ton::PrivateKey{x->id_}; - auto pub_k = ton::adnl::AdnlNodeIdFull{pk.compute_public_key()}; - auto id = pub_k.compute_short_id(); - - td::actor::send_closure(keyring_, &ton::keyring::Keyring::add_key, std::move(pk), false); - td::actor::send_closure(adnl_, &ton::adnl::Adnl::add_id, pub_k, ton::adnl::AdnlAddressList{}); - td::actor::send_closure(validator_manager_, &ton::ValidatorManager::add_ext_server_id, id); - td::actor::send_closure(validator_manager_, &ton::ValidatorManager::add_ext_server_port, - static_cast(x->port_)); - } - } - } -}; - -td::Result get_uint256(std::string str) { - if (str.size() != 64) { - return td::Status::Error("uint256 must have 64 bytes"); - } - td::UInt256 res; - for (size_t i = 0; i < 32; i++) { - res.raw[i] = static_cast(td::hex_to_int(str[2 * i]) * 16 + td::hex_to_int(str[2 * i + 1])); - } - return res; -} - -std::atomic need_stats_flag{false}; -void need_stats(int sig) { - need_stats_flag.store(true); -} -void dump_memory_stats() { - if (!is_memprof_on()) { - return; - } - LOG(WARNING) << "memory_dump"; - std::vector v; - dump_alloc([&](const AllocInfo &info) { v.push_back(info); }); - std::sort(v.begin(), v.end(), [](const AllocInfo &a, const AllocInfo &b) { return a.size > b.size; }); - size_t total_size = 0; - size_t other_size = 0; - int cnt = 0; - for (auto &info : v) { - if (cnt++ < 50) { - LOG(WARNING) << td::format::as_size(info.size) << td::format::as_array(info.backtrace); - } else { - other_size += info.size; - } - total_size += info.size; - } - LOG(WARNING) << td::tag("other", td::format::as_size(other_size)); - LOG(WARNING) << td::tag("total", td::format::as_size(total_size)); - LOG(WARNING) << td::tag("total traces", get_ht_size()); - LOG(WARNING) << td::tag("fast_backtrace_success_rate", get_fast_backtrace_success_rate()); -} -void dump_stats() { - dump_memory_stats(); - LOG(WARNING) << td::NamedThreadSafeCounter::get_default(); -} - -int main(int argc, char *argv[]) { - SET_VERBOSITY_LEVEL(verbosity_INFO); - - td::set_default_failure_signal_handler().ensure(); - - CHECK(vm::init_op_cp0()); - - td::actor::ActorOwn x; - td::unique_ptr logger_; - SCOPE_EXIT { - td::log_interface = td::default_log_interface; - }; - - td::OptionParser p; - p.set_description("test basic adnl functionality"); - p.add_option('v', "verbosity", "set verbosity level", [&](td::Slice arg) { - int v = VERBOSITY_NAME(FATAL) + (td::to_integer(arg)); - SET_VERBOSITY_LEVEL(v); - return td::Status::OK(); - }); - p.add_option('h', "help", "prints_help", [&]() { - char b[10240]; - td::StringBuilder sb(td::MutableSlice{b, 10000}); - sb << p; - std::cout << sb.as_cslice().c_str(); - std::exit(2); - return td::Status::OK(); - }); - p.add_option('C', "global-config", "file to read global config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_global_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('c', "local-config", "file to read local config", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_local_config, fname.str()); - return td::Status::OK(); - }); - p.add_option('i', "id", "id of instance", [&](td::Slice fname) { return td::Status::OK(); }); - p.add_option('D', "db", "root for dbs", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_db_root, fname.str()); - return td::Status::OK(); - }); - p.add_option('z', "zero-state", "file with serialized zero state", [&](td::Slice fname) { - td::actor::send_closure(x, &TestNode::set_zero_state, fname.str()); - return td::Status::OK(); - }); - p.add_option('d', "daemonize", "set SIGHUP", [&]() { - td::set_signal_handler(td::SignalType::HangUp, [](int sig) { -#if TD_DARWIN || TD_LINUX - close(0); - setsid(); -#endif - }).ensure(); - return td::Status::OK(); - }); -#if TD_DARWIN || TD_LINUX - p.add_option('l', "logname", "log to file", [&](td::Slice fname) { - logger_ = td::TsFileLog::create(fname.str()).move_as_ok(); - td::log_interface = logger_.get(); - return td::Status::OK(); - }); -#endif - td::set_runtime_signal_handler(1, need_stats).ensure(); - - td::actor::Scheduler scheduler({7}); - - scheduler.run_in_context([&] { x = td::actor::create_actor("testnode"); }); - - scheduler.run_in_context([&] { p.run(argc, argv).ensure(); }); - scheduler.run_in_context([&] { td::actor::send_closure(x, &TestNode::run); }); - while (scheduler.run(1)) { - if (need_stats_flag.exchange(false)) { - dump_stats(); - } - } - - return 0; -} diff --git a/third-party/blst b/third-party/blst index e9dfc5ee7..3dd0f804b 160000 --- a/third-party/blst +++ b/third-party/blst @@ -1 +1 @@ -Subproject commit e9dfc5ee724b5b25d50a3b6226bee8c2c9d5e65d +Subproject commit 3dd0f804b1819e5d03fb22ca2e6fac105932043a diff --git a/third-party/rocksdb b/third-party/rocksdb index fcf3d75f3..cb7a5e02e 160000 --- a/third-party/rocksdb +++ b/third-party/rocksdb @@ -1 +1 @@ -Subproject commit fcf3d75f3f022a6a55ff1222d6b06f8518d38c7c +Subproject commit cb7a5e02edeb883193eb5b4901d5943f58e9add9 diff --git a/tl-utils/CMakeLists.txt b/tl-utils/CMakeLists.txt index b17b7dc98..d5c52d48a 100644 --- a/tl-utils/CMakeLists.txt +++ b/tl-utils/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(TL_UTILS_SOURCE common-utils.hpp diff --git a/tl/CMakeLists.txt b/tl/CMakeLists.txt index 8adabedae..d0760a349 100644 --- a/tl/CMakeLists.txt +++ b/tl/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_subdirectory(generate) set_source_files_properties(${TL_TON_API} PROPERTIES GENERATED TRUE) diff --git a/tl/generate/CMakeLists.txt b/tl/generate/CMakeLists.txt index 61d66c932..083d39737 100644 --- a/tl/generate/CMakeLists.txt +++ b/tl/generate/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) file(MAKE_DIRECTORY auto/tl) diff --git a/tl/tl/tl_json.h b/tl/tl/tl_json.h index 489bd6e81..8eee3aad5 100644 --- a/tl/tl/tl_json.h +++ b/tl/tl/tl_json.h @@ -108,12 +108,13 @@ inline Status from_json(std::int32_t &to, JsonValue from) { inline Status from_json(bool &to, JsonValue from) { if (from.type() != JsonValue::Type::Boolean) { int32 x; + auto type = from.type(); auto status = from_json(x, std::move(from)); if (status.is_ok()) { to = x != 0; return Status::OK(); } - return Status::Error(PSLICE() << "Expected bool, got " << from.type()); + return Status::Error(PSLICE() << "Expected bool, got " << type); } to = from.get_boolean(); return Status::OK(); diff --git a/tonlib/CMakeLists.txt b/tonlib/CMakeLists.txt index 72c59c4da..dc3e90300 100644 --- a/tonlib/CMakeLists.txt +++ b/tonlib/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) option(BUILD_SHARED_LIBS "Use \"OFF\" for a static build." ON) diff --git a/tonlib/test/offline.cpp b/tonlib/test/offline.cpp index a1e5a0f61..35a95f5b1 100644 --- a/tonlib/test/offline.cpp +++ b/tonlib/test/offline.cpp @@ -609,7 +609,30 @@ TEST(Tonlib, ConfigCache) { "seqno": 0, "root_hash": "gj+B8wb/AmlPk1z1AhVI484rhrUpgSr2oSFIh56VoSg=", "file_hash": "Z+IKwYS54DmmJmesw/nAD5DzWadnOCMzee+kdgSYDOg=" - } + }, + "hardforks": [ + { + "file_hash": "jF3RTD+OyOoP+OI9oIjdV6M8EaOh9E+8+c3m5JkPYdg=", + "seqno": 5141579, + "root_hash": "6JSqIYIkW7y8IorxfbQBoXiuY3kXjcoYgQOxTJpjXXA=", + "workchain": -1, + "shard": -9223372036854775808 + }, + { + "file_hash": "WrNoMrn5UIVPDV/ug/VPjYatvde8TPvz5v1VYHCLPh8=", + "seqno": 5172980, + "root_hash": "054VCNNtUEwYGoRe1zjH+9b1q21/MeM+3fOo76Vcjes=", + "workchain": -1, + "shard": -9223372036854775808 + }, + { + "file_hash": "xRaxgUwgTXYFb16YnR+Q+VVsczLl6jmYwvzhQ/ncrh4=", + "seqno": 5176527, + "root_hash": "SoPLqMe9Dz26YJPOGDOHApTSe5i0kXFtRmRh/zPMGuI=", + "workchain": -1, + "shard": -9223372036854775808 + } + ] } })abc"; auto custom = R"abc({ diff --git a/tonlib/tonlib/TonlibClient.cpp b/tonlib/tonlib/TonlibClient.cpp index 0eabe142d..9ec664bba 100644 --- a/tonlib/tonlib/TonlibClient.cpp +++ b/tonlib/tonlib/TonlibClient.cpp @@ -1971,7 +1971,7 @@ class RunEmulator : public TonlibQueryActor { ton::UnixTime now = account_state_->get_sync_time(); bool is_special = address.workchain == ton::masterchainId && config->is_special_smartcontract(address.addr); block::Account account(address.workchain, address.addr.bits()); - if (!account.unpack(std::move(shard_account), td::Ref(), now, is_special)) { + if (!account.unpack(std::move(shard_account), now, is_special)) { check(td::Status::Error("Can't unpack shard account")); return; } diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 3d029c938..0149e06e1 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/utils/opcode-timing.cpp b/utils/opcode-timing.cpp index f50d7041f..4f5c8ab41 100644 --- a/utils/opcode-timing.cpp +++ b/utils/opcode-timing.cpp @@ -64,7 +64,6 @@ typedef struct { vm::Stack prepare_stack(td::Slice command) { const auto cell = to_cell(command); - vm::init_op_cp0(); vm::DictionaryBase::get_empty_dictionary(); vm::Stack stack; try { @@ -80,7 +79,6 @@ vm::Stack prepare_stack(td::Slice command) { runInfo time_run_vm(td::Slice command, td::Ref stack) { const auto cell = to_cell(command); - vm::init_op_cp0(); vm::DictionaryBase::get_empty_dictionary(); CHECK(stack.is_unique()); try { @@ -171,6 +169,7 @@ int main(int argc, char** argv) { setup = argv[1]; code = argv[2]; } + vm::init_vm().ensure(); const auto time = timeInstruction(setup, code); std::cout << std::fixed << std::setprecision(9) << code << "," << time.runtime.mean << "," << time.runtime.stddev << "," << time.gasUsage.mean << "," << time.gasUsage.stddev << "," << (int)time.errored << std::endl; diff --git a/validator-engine-console/CMakeLists.txt b/validator-engine-console/CMakeLists.txt index 487169603..634a5b8b4 100644 --- a/validator-engine-console/CMakeLists.txt +++ b/validator-engine-console/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) add_executable (validator-engine-console validator-engine-console.cpp validator-engine-console.h validator-engine-console-query.cpp diff --git a/validator-engine/CMakeLists.txt b/validator-engine/CMakeLists.txt index d369a2c35..5df720fe6 100644 --- a/validator-engine/CMakeLists.txt +++ b/validator-engine/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index aaa4f8496..23cc93473 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -38,7 +38,7 @@ #include "common/errorlog.h" -#include "crypto/vm/cp0.h" +#include "crypto/vm/vm.h" #include "crypto/fift/utils.h" #include "td/utils/filesystem.h" @@ -3774,7 +3774,7 @@ int main(int argc, char *argv[]) { td::actor::Scheduler scheduler({threads}); scheduler.run_in_context([&] { - CHECK(vm::init_op_cp0()); + vm::init_vm().ensure(); x = td::actor::create_actor("validator-engine"); for (auto &act : acts) { act(); diff --git a/validator-session/CMakeLists.txt b/validator-session/CMakeLists.txt index 4931e464d..c769f4d86 100644 --- a/validator-session/CMakeLists.txt +++ b/validator-session/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/validator/CMakeLists.txt b/validator/CMakeLists.txt index 573cd8e5a..068569de8 100644 --- a/validator/CMakeLists.txt +++ b/validator/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/validator/impl/CMakeLists.txt b/validator/impl/CMakeLists.txt index 459e77244..f4b967a8e 100644 --- a/validator/impl/CMakeLists.txt +++ b/validator/impl/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR) +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) if (NOT OPENSSL_FOUND) find_package(OpenSSL REQUIRED) diff --git a/validator/impl/collator-impl.h b/validator/impl/collator-impl.h index abbe904c6..c2088f47b 100644 --- a/validator/impl/collator-impl.h +++ b/validator/impl/collator-impl.h @@ -202,7 +202,7 @@ class Collator final : public td::actor::Actor { // block::Account* lookup_account(td::ConstBitPtr addr) const; std::unique_ptr make_account_from(td::ConstBitPtr addr, Ref account, - Ref extra, bool force_create = false); + bool force_create); td::Result make_account(td::ConstBitPtr addr, bool force_create = false); td::actor::ActorId get_self() { return actor_id(this); @@ -269,10 +269,6 @@ class Collator final : public td::actor::Actor { void after_get_external_messages(td::Result>> res); td::Result register_external_message_cell(Ref ext_msg, const ExtMessage::Hash& ext_hash); // td::Result register_external_message(td::Slice ext_msg_boc); - td::Result register_ihr_message_cell(Ref ihr_msg); - td::Result register_ihr_message(td::Slice ihr_msg_boc); - td::Result register_shard_signatures_cell(Ref shard_blk_signatures); - td::Result register_shard_signatures(td::Slice shard_blk_signatures_boc); void register_new_msg(block::NewOutMsg msg); void register_new_msgs(block::transaction::Transaction& trans); bool process_new_messages(bool enqueue_only = false); @@ -285,7 +281,7 @@ class Collator final : public td::actor::Actor { bool enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_remaining, ton::LogicalTime enqueued_lt); bool enqueue_transit_message(Ref msg, Ref old_msg_env, ton::AccountIdPrefixFull prev_prefix, ton::AccountIdPrefixFull cur_prefix, ton::AccountIdPrefixFull dest_prefix, - td::RefInt256 fwd_fee_remaining, ton::LogicalTime enqueued_lt); + td::RefInt256 fwd_fee_remaining); bool delete_out_msg_queue_msg(td::ConstBitPtr key); bool insert_in_msg(Ref in_msg); bool insert_out_msg(Ref out_msg); diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 54941f217..d133278f3 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -54,6 +54,20 @@ static inline bool dbg(int c) { return true; } +/** + * Constructs a Collator object. + * + * @param shard The shard of the new block. + * @param is_hardfork A boolean indicating whether the new block is a hardfork. + * @param min_ts The minimum UnixTime for the new block. + * @param min_masterchain_block_id The the minimum reference masterchain block. + * @param prev A vector of BlockIdExt representing the previous blocks. + * @param validator_set A reference to the ValidatorSet. + * @param collator_id The public key of the block creator. + * @param manager The ActorId of the ValidatorManager. + * @param timeout The timeout for the collator. + * @param promise The promise to return the result. + */ Collator::Collator(ShardIdFull shard, bool is_hardfork, UnixTime min_ts, BlockIdExt min_masterchain_block_id, std::vector prev, td::Ref validator_set, Ed25519_PublicKey collator_id, td::actor::ActorId manager, td::Timestamp timeout, @@ -77,6 +91,14 @@ Collator::Collator(ShardIdFull shard, bool is_hardfork, UnixTime min_ts, BlockId }) { } +/** + * Starts the Collator. + * + * This function initializes the Collator by performing various checks and queries to the ValidatorManager. + * It checks the validity of the shard, the previous blocks, and the workchain. + * If all checks pass, it proceeds to query the ValidatorManager for the top masterchain state block, shard states, block data, external messages, and shard blocks. + * The results of these queries are handled by corresponding callback functions. + */ void Collator::start_up() { LOG(DEBUG) << "Collator for shard " << shard_.to_str() << " started"; LOG(DEBUG) << "Previous block #1 is " << prev_blocks.at(0).to_str(); @@ -250,10 +272,21 @@ void Collator::start_up() { CHECK(pending); } +/** + * Raises an error when timeout is reached. + */ void Collator::alarm() { fatal_error(ErrorCode::timeout, "timeout"); } +/** + * Generates a string representation of a shard. + * + * @param workchain The workchain ID of the shard. + * @param shard The shard ID. + * + * @returns A string representation of the shard. + */ std::string show_shard(ton::WorkchainId workchain, ton::ShardId shard) { char tmp[128]; char* ptr = tmp + snprintf(tmp, 31, "%d:", workchain); @@ -268,14 +301,35 @@ std::string show_shard(ton::WorkchainId workchain, ton::ShardId shard) { return {tmp, ptr}; } +/** + * Returns a string representation of the shard of the given block. + * + * @param blk_id The BlockId object. + * + * @returns A string representation of the shard. + */ std::string show_shard(const ton::BlockId blk_id) { return show_shard(blk_id.workchain, blk_id.shard); } +/** + * Converts a `ShardIdFull` object to a string representation. + * + * @param blk_id The `ShardIdFull` object to convert. + * + * @returns The string representation of the `ShardIdFull` object. + */ std::string show_shard(const ton::ShardIdFull blk_id) { return show_shard(blk_id.workchain, blk_id.shard); } +/** + * Handles a fatal error encountered during block candidate generation. + * + * @param error The error encountered. + * + * @returns False to indicate that a fatal error occurred. + */ bool Collator::fatal_error(td::Status error) { error.ensure_error(); LOG(ERROR) << "cannot generate block candidate for " << show_shard(shard_) << " : " << error.to_string(); @@ -287,14 +341,39 @@ bool Collator::fatal_error(td::Status error) { return false; } +/** + * Handles a fatal error encountered during block candidate generation. + * + * @param err_code The error code. + * @param err_msg The error message. + * + * @returns False to indicate that a fatal error occurred. + */ bool Collator::fatal_error(int err_code, std::string err_msg) { return fatal_error(td::Status::Error(err_code, err_msg)); } +/** + * Handles a fatal error encountered during block candidate generation. + * + * @param err_msg The error message. + * @param err_code The error code. + * + * @returns False to indicate that a fatal error occurred. + */ bool Collator::fatal_error(std::string err_msg, int err_code) { return fatal_error(td::Status::Error(err_code, err_msg)); } +/** + * Checks if there are any pending tasks. + * + * If there are no pending tasks, it continues collation. + * If collation fails, it raises a fatal error. + * If an exception is caught during collation, it raises a fatal error with the corresponding error message. + * + * @returns None + */ void Collator::check_pending() { // LOG(DEBUG) << "pending = " << pending; if (!pending) { @@ -309,6 +388,13 @@ void Collator::check_pending() { } } +/** + * Registers a masterchain state. + * + * @param other_mc_state The masterchain state to register. + * + * @returns True if the registration is successful, false otherwise. + */ bool Collator::register_mc_state(Ref other_mc_state) { if (other_mc_state.is_null() || mc_state_.is_null()) { return false; @@ -334,6 +420,14 @@ bool Collator::register_mc_state(Ref other_mc_state) { return true; } +/** + * Requests the auxiliary masterchain state. + * + * @param seqno The seqno of the block. + * @param state A reference to the auxiliary masterchain state. + * + * @returns True if the auxiliary masterchain state is successfully requested, false otherwise. + */ bool Collator::request_aux_mc_state(BlockSeqno seqno, Ref& state) { if (mc_state_.is_null()) { return fatal_error(PSTRING() << "cannot find masterchain block with seqno " << seqno @@ -366,6 +460,13 @@ bool Collator::request_aux_mc_state(BlockSeqno seqno, Ref& st return true; } +/** + * Retrieves the auxiliary masterchain state for a given block sequence number. + * + * @param seqno The sequence number of the block. + * + * @returns A reference to the auxiliary masterchain state if found, otherwise an empty reference. + */ Ref Collator::get_aux_mc_state(BlockSeqno seqno) const { auto it = aux_mc_states_.find(seqno); if (it != aux_mc_states_.end()) { @@ -375,6 +476,13 @@ Ref Collator::get_aux_mc_state(BlockSeqno seqno) const { } } +/** + * Callback function called after retrieving the auxiliary shard state. + * Handles the retrieved shard state and performs necessary checks and registrations. + * + * @param blkid The BlockIdExt of the shard state. + * @param res The result of retrieving the shard state. + */ void Collator::after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result> res) { LOG(DEBUG) << "in Collator::after_get_aux_shard_state(" << blkid.to_str() << ")"; --pending; @@ -400,6 +508,14 @@ void Collator::after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result, BlockIdExt>> res) { LOG(DEBUG) << "in Collator::after_get_mc_state()"; --pending; @@ -455,6 +576,12 @@ void Collator::after_get_mc_state(td::Result, Bl check_pending(); } +/** + * Callback function called after retrieving the shard state for a previous block. + * + * @param idx The index of the previous shard block (0 or 1). + * @param res The retrieved shard state. + */ void Collator::after_get_shard_state(int idx, td::Result> res) { LOG(DEBUG) << "in Collator::after_get_shard_state(" << idx << ")"; --pending; @@ -482,6 +609,12 @@ void Collator::after_get_shard_state(int idx, td::Result> res) { check_pending(); } +/** + * Callback function called after retrieving block data for a previous block. + * + * @param idx The index of the previous block (0 or 1). + * @param res The retreived block data. + */ void Collator::after_get_block_data(int idx, td::Result> res) { LOG(DEBUG) << "in Collator::after_get_block_data(" << idx << ")"; --pending; @@ -513,6 +646,11 @@ void Collator::after_get_block_data(int idx, td::Result> res) { check_pending(); } +/** + * Callback function called after retrieving shard block descriptions for masterchain. + * + * @param res The retrieved shard block descriptions. + */ void Collator::after_get_shard_blocks(td::Result>> res) { --pending; if (res.is_error()) { @@ -525,6 +663,11 @@ void Collator::after_get_shard_blocks(td::Resultget_neighbor_shard_hash_ids(shard_); @@ -634,6 +787,12 @@ bool Collator::request_neighbor_msg_queues() { return true; } +/** + * Handles the result of obtaining the outbound queue for a neighbor. + * + * @param i The index of the neighbor. + * @param res The obtained outbound queue. + */ void Collator::got_neighbor_out_queue(int i, td::Result> res) { LOG(DEBUG) << "obtained outbound queue for neighbor #" << i; --pending; @@ -692,6 +851,12 @@ void Collator::got_neighbor_out_queue(int i, td::Result> res) check_pending(); } +/** + * Unpacks and merges the states of two previous blocks. + * Used if the block is after_merge. + * + * @returns True if the unpacking and merging was successful, false otherwise. + */ bool Collator::unpack_merge_last_state() { LOG(DEBUG) << "unpack/merge last states"; // 0. mechanically merge two ShardStateUnsplit into split_state constructor @@ -730,6 +895,12 @@ bool Collator::unpack_merge_last_state() { return import_shard_state_data(ss0); } +/** + * Unpacks the state of the previous block. + * Used if the block is not after_merge. + * + * @returns True if the unpacking is successful, false otherwise. + */ bool Collator::unpack_last_state() { if (after_merge_) { if (!unpack_merge_last_state()) { @@ -749,6 +920,15 @@ bool Collator::unpack_last_state() { import_shard_state_data(ss); } +/** + * Unpacks the state of a previous block and performs necessary checks. + * + * @param ss The ShardState object to unpack the state into. + * @param blkid The BlockIdExt of the previous block. + * @param prev_state_root The root of the state. + * + * @returns True if the unpacking and checks are successful, false otherwise. + */ bool Collator::unpack_one_last_state(block::ShardState& ss, BlockIdExt blkid, Ref prev_state_root) { auto res = ss.unpack_state_ext(blkid, std::move(prev_state_root), global_id_, prev_mc_block_seqno, after_split_, after_split_ | after_merge_, [self = this](ton::BlockSeqno mc_seqno) { @@ -767,6 +947,14 @@ bool Collator::unpack_one_last_state(block::ShardState& ss, BlockIdExt blkid, Re return true; } +/** + * Splits the state of previous block. + * Used if the block is after_split. + * + * @param ss The ShardState object representing the previous state. The result is stored here. + * + * @returns True if the split operation is successful, false otherwise. + */ bool Collator::split_last_state(block::ShardState& ss) { LOG(INFO) << "Splitting previous state " << ss.id_.to_str() << " to subshard " << shard_.to_str(); CHECK(after_split_); @@ -788,11 +976,19 @@ bool Collator::split_last_state(block::ShardState& ss) { return true; } -// SETS: account_dict, shard_libraries_, mc_state_extra -// total_balance_ = old_total_balance_, total_validator_fees_ -// SETS: overload_history_, underload_history_ -// SETS: prev_state_utime_, prev_state_lt_, prev_vert_seqno_ -// SETS: out_msg_queue, processed_upto_, ihr_pending +/** + * Imports the shard state data into the Collator object. + * + * SETS: account_dict, shard_libraries_, mc_state_extra + * total_balance_ = old_total_balance_, total_validator_fees_ + * SETS: overload_history_, underload_history_ + * SETS: prev_state_utime_, prev_state_lt_, prev_vert_seqno_ + * SETS: out_msg_queue, processed_upto_, ihr_pending + * + * @param ss The ShardState object containing the shard state data. + * + * @returns True if the import was successful, False otherwise. + */ bool Collator::import_shard_state_data(block::ShardState& ss) { account_dict = std::move(ss.account_dict_); shard_libraries_ = std::move(ss.shard_libraries_); @@ -813,6 +1009,12 @@ bool Collator::import_shard_state_data(block::ShardState& ss) { return true; } +/** + * Adds trivials neighbor after merging two shards. + * Trivial neighbors are the two previous blocks. + * + * @returns True if the operation is successful, false otherwise. + */ bool Collator::add_trivial_neighbor_after_merge() { LOG(DEBUG) << "in add_trivial_neighbor_after_merge()"; CHECK(prev_blocks.size() == 2); @@ -847,6 +1049,12 @@ bool Collator::add_trivial_neighbor_after_merge() { return true; } +/** + * Adds a trivial neighbor. + * A trivial neighbor is the previous block. + * + * @returns True if the operation is successful, false otherwise. + */ bool Collator::add_trivial_neighbor() { LOG(DEBUG) << "in add_trivial_neighbor()"; if (after_merge_) { @@ -982,6 +1190,15 @@ bool Collator::add_trivial_neighbor() { return true; } +/** + * Checks the previous block against the block registered in the masterchain. + * + * @param listed The BlockIdExt of the top block of this shard registered in the masterchain. + * @param prev The BlockIdExt of the previous block. + * @param chk_chain_len Flag indicating whether to check the chain length. + * + * @returns True if the previous block is valid, false otherwise. + */ bool Collator::check_prev_block(const BlockIdExt& listed, const BlockIdExt& prev, bool chk_chain_len) { if (listed.seqno() > prev.seqno()) { return fatal_error(PSTRING() << "cannot generate a shardchain block after previous block " << prev.to_str() @@ -1001,6 +1218,14 @@ bool Collator::check_prev_block(const BlockIdExt& listed, const BlockIdExt& prev return true; } +/** + * Checks the previous block against the block registered in the masterchain. + * + * @param listed The BlockIdExt of the top block of this shard registered in the masterchain. + * @param prev The BlockIdExt of the previous block. + * + * @returns True if the previous block is equal to the one registered in the masterchain, false otherwise. + */ bool Collator::check_prev_block_exact(const BlockIdExt& listed, const BlockIdExt& prev) { if (listed != prev) { return fatal_error(PSTRING() << "cannot generate shardchain block for shard " << shard_.to_str() @@ -1011,6 +1236,11 @@ bool Collator::check_prev_block_exact(const BlockIdExt& listed, const BlockIdExt return true; } +/** + * Checks the validity of the shard configuration of the current shard. + * + * @returns True if the shard configuration is valid, false otherwise. + */ bool Collator::check_this_shard_mc_info() { wc_info_ = config_->get_workchain_info(workchain()); if (wc_info_.is_null()) { @@ -1145,6 +1375,11 @@ bool Collator::check_this_shard_mc_info() { return true; } +/** + * Initializes the block limits for the collator. + * + * @returns True if the block limits were successfully initialized, false otherwise. + */ bool Collator::init_block_limits() { CHECK(block_limits_); CHECK(state_usage_tree_); @@ -1153,6 +1388,11 @@ bool Collator::init_block_limits() { return true; } +/** + * Performs pre-initialization steps for the Collator. + * + * @returns True if pre-initialization is successful, false otherwise. + */ bool Collator::do_preinit() { CHECK(prev_blocks.size() == 1U + after_merge_); last_block_seqno = prev_blocks[0].seqno(); @@ -1209,6 +1449,12 @@ bool Collator::do_preinit() { return true; } +/** + * Adjusts the shard configuration by adding new workchains to the shard configuration in the masterchain state. + * Used in masterchain collator. + * + * @returns True if the shard configuration was successfully adjusted, false otherwise. + */ bool Collator::adjust_shard_config() { CHECK(is_masterchain() && config_ && shard_conf_); const block::WorkchainSet& wset = config_->get_workchain_list(); @@ -1237,12 +1483,30 @@ bool Collator::adjust_shard_config() { return true; } +/** + * Compares two ShardTopBlockDescription references based on their block IDs. + * + * @param a The first ShardTopBlockDescription reference. + * @param b The second ShardTopBlockDescription reference. + * + * @returns True if a is considered less than b, false otherwise. + */ static bool cmp_shard_block_descr_ref(const Ref& a, const Ref& b) { BlockId x = a->block_id().id, y = b->block_id().id; return x.workchain < y.workchain || (x.workchain == y.workchain && (x.shard < y.shard || (x.shard == y.shard && x.seqno > y.seqno))); } +/** + * Stores the fees imported from a shard blocks to `fees_import_dict_`. + * Used in masterchain collator. + * + * @param shard The shard identifier. + * @param fees The fees imported from the block. + * @param created The fee for creating shard blocks. + * + * @returns True if the fees were successfully stored, false otherwise. + */ bool Collator::store_shard_fees(ShardIdFull shard, const block::CurrencyCollection& fees, const block::CurrencyCollection& created) { if (shard.is_valid() && fees.is_valid()) { @@ -1258,6 +1522,14 @@ bool Collator::store_shard_fees(ShardIdFull shard, const block::CurrencyCollecti } } +/** + * Stores the fees imported from a shard blocks to `fees_import_dict_`. + * Used in masterchain collator. + * + * @param descr A reference to the McShardHash object containing the shard information. + * + * @returns True if the shard fees and funds created were successfully stored, false otherwise. + */ bool Collator::store_shard_fees(Ref descr) { CHECK(descr.not_null()); CHECK(descr->fees_collected_.is_valid()); @@ -1266,6 +1538,11 @@ bool Collator::store_shard_fees(Ref descr) { return true; } +/** + * Imports new top shard blocks and updates the shard configuration. + * + * @returns True if the import was successful, false otherwise. + */ bool Collator::import_new_shard_top_blocks() { if (shard_block_descr_.empty()) { return true; @@ -1404,6 +1681,13 @@ bool Collator::import_new_shard_top_blocks() { return true; } +/** + * Registers the shard block creators to block_create_count_ + * + * @param creator_list A vector of Bits256 representing the shard block creators. + * + * @returns True if the registration was successful, False otherwise. + */ bool Collator::register_shard_block_creators(std::vector creator_list) { for (const auto& x : creator_list) { LOG(DEBUG) << "registering block creator " << x.to_hex(); @@ -1418,6 +1702,11 @@ bool Collator::register_shard_block_creators(std::vector creator_li return true; } +/** + * Performs pre-initialization and collates the new block. + * + * @returns True if collation is successful, false otherwise. + */ bool Collator::try_collate() { if (!preinit_complete) { LOG(DEBUG) << "running do_preinit()"; @@ -1477,6 +1766,14 @@ bool Collator::try_collate() { return do_collate(); } +/** + * Adjusts one entry from the processed up to information using the masterchain state that is referenced in the entry. + * + * @param proc The MsgProcessedUpto object. + * @param owner The shard that the MsgProcessesUpto information is taken from. + * + * @returns True if the processed up to information was successfully adjusted, false otherwise. + */ bool Collator::fix_one_processed_upto(block::MsgProcessedUpto& proc, const ton::ShardIdFull& owner) { if (proc.compute_shard_end_lt) { return true; @@ -1493,6 +1790,13 @@ bool Collator::fix_one_processed_upto(block::MsgProcessedUpto& proc, const ton:: return (bool)proc.compute_shard_end_lt; } +/** + * Adjusts the processed up to collection using the using the auxilliary masterchain states. + * + * @param upto The MsgProcessedUptoCollection to be adjusted. + * + * @returns True if all entries were successfully adjusted, False otherwise. + */ bool Collator::fix_processed_upto(block::MsgProcessedUptoCollection& upto) { for (auto& entry : upto.list) { if (!fix_one_processed_upto(entry, upto.owner)) { @@ -1502,6 +1806,14 @@ bool Collator::fix_processed_upto(block::MsgProcessedUptoCollection& upto) { return true; } +/** + * Initializes the unix time for the new block. + * + * Unix time is set based on the current time, and the timestamps of the previous blocks. + * If the previous block has a timestamp too far in the past then skipping importing external messages and new shard blocks is allowed. + * + * @returns True if the initialization is successful, false otherwise. + */ bool Collator::init_utime() { CHECK(config_); // consider unixtime and lt from previous block(s) of the same shardchain @@ -1547,6 +1859,9 @@ bool Collator::init_utime() { return true; } +/** + * Initializes the logical time of the new block. + */ bool Collator::init_lt() { CHECK(config_); start_lt = config_->lt; @@ -1569,6 +1884,11 @@ bool Collator::init_lt() { return true; } +/** + * Fetches and initializes the configuration parameters using the masterchain configuration. + * + * @returns True if the configuration parameters were successfully fetched and initialized, false otherwise. + */ bool Collator::fetch_config_params() { auto res = block::FetchConfigParams::fetch_config_params(*config_, &old_mparams_, &storage_prices_, &storage_phase_cfg_, @@ -1583,6 +1903,13 @@ bool Collator::fetch_config_params() { return true; } +/** + * Computes the amount of extra currencies to be minted. + * + * @param to_mint A reference to the CurrencyCollection object to store the minted amount. + * + * @returns True if the computation is successful, false otherwise. + */ bool Collator::compute_minted_amount(block::CurrencyCollection& to_mint) { if (!is_masterchain()) { return to_mint.set_zero(); @@ -1633,6 +1960,11 @@ bool Collator::compute_minted_amount(block::CurrencyCollection& to_mint) { return true; } +/** + * Initializes value_flow_ and computes fees for creating the new block. + * + * @returns True if the initialization is successful, false otherwise. + */ bool Collator::init_value_create() { value_flow_.created.set_zero(); value_flow_.minted.set_zero(); @@ -1663,6 +1995,9 @@ bool Collator::init_value_create() { return true; } +/** + * Performs the collation of the new block. + */ bool Collator::do_collate() { // After do_collate started it will not be interrupted by timeout alarm_timestamp() = td::Timestamp::never(); @@ -1786,6 +2121,14 @@ bool Collator::do_collate() { return true; } +/** + * Dequeues an outbound message from the message queue of this shard. + * + * @param msg_envelope The message envelope to dequeue. + * @param delivered_lt The logical time at which the message was delivered. + * + * @returns True if the message was successfully dequeued, false otherwise. + */ bool Collator::dequeue_message(Ref msg_envelope, ton::LogicalTime delivered_lt) { LOG(DEBUG) << "dequeueing outbound message"; vm::CellBuilder cb; @@ -1805,6 +2148,13 @@ bool Collator::dequeue_message(Ref msg_envelope, ton::LogicalTime deli } } +/** + * Cleans up the outbound message queue by removing messages that have already been imported by neighbors. + * + * Cleanup may be interrupted early if it takes too long. + * + * @returns True if the cleanup operation was successful, false otherwise. + */ bool Collator::out_msg_queue_cleanup() { LOG(INFO) << "cleaning outbound queue from messages already imported by neighbors"; if (verbosity >= 2) { @@ -1884,8 +2234,17 @@ bool Collator::out_msg_queue_cleanup() { return register_out_msg_queue_op(true); } +/** + * Creates a new Account object from the given address and serialized account data. + * + * @param addr A pointer to the 256-bit address of the account. + * @param account A cell slice with an account serialized using ShardAccount TLB-scheme. + * @param force_create A flag indicating whether to force the creation of a new account if `account` is null. + * + * @returns A unique pointer to the created Account object, or nullptr if the creation failed. + */ std::unique_ptr Collator::make_account_from(td::ConstBitPtr addr, Ref account, - Ref extra, bool force_create) { + bool force_create) { if (account.is_null() && !force_create) { return nullptr; } @@ -1894,19 +2253,35 @@ std::unique_ptr Collator::make_account_from(td::ConstBitPtr addr if (!ptr->init_new(now_)) { return nullptr; } - } else if (!ptr->unpack(std::move(account), std::move(extra), now_, - is_masterchain() && config_->is_special_smartcontract(addr))) { + } else if (!ptr->unpack(std::move(account), now_, is_masterchain() && config_->is_special_smartcontract(addr))) { return nullptr; } ptr->block_lt = start_lt; return ptr; } +/** + * Looks up an account in the Collator's account map. + * + * @param addr A pointer to the 256-bit address of the account to be looked up. + * + * @returns A pointer to the Account object if found, otherwise returns nullptr. + */ block::Account* Collator::lookup_account(td::ConstBitPtr addr) const { auto found = accounts.find(addr); return found != accounts.end() ? found->second.get() : nullptr; } +/** + * Retreives an Account object from the data in the shard state. + * Accounts are cached in the Collator's map. + * + * @param addr The 256-bit address of the account. + * @param force_create Flag indicating whether to create a new account if it does not exist. + * + * @returns A Result object containing a pointer to the account if found or created successfully, or an error status. + * Returns nullptr if account does not exist and not force_create. + */ td::Result Collator::make_account(td::ConstBitPtr addr, bool force_create) { auto found = lookup_account(addr); if (found) { @@ -1918,7 +2293,7 @@ td::Result Collator::make_account(td::ConstBitPtr addr, bool fo return nullptr; } } - auto new_acc = make_account_from(addr, std::move(dict_entry.first), std::move(dict_entry.second), force_create); + auto new_acc = make_account_from(addr, std::move(dict_entry.first), force_create); if (!new_acc) { return td::Status::Error(PSTRING() << "cannot load account " << addr.to_hex(256) << " from previous state"); } @@ -1934,6 +2309,11 @@ td::Result Collator::make_account(td::ConstBitPtr addr, bool fo return ins.first->second.get(); } +/** + * Combines account transactions and updates the ShardAccountBlocks and ShardAccounts. + * + * @returns True if the operation is successful, false otherwise. + */ bool Collator::combine_account_transactions() { vm::AugmentedDictionary dict{256, block::tlb::aug_ShardAccountBlocks}; for (auto& z : accounts) { @@ -2046,6 +2426,15 @@ bool Collator::combine_account_transactions() { return true; } +/** + * Creates a special transaction to recover a specified amount of currency to a destination address. + * + * @param amount The amount of currency to recover. + * @param dest_addr_cell The cell containing the destination address. + * @param in_msg The reference to the input message. + * + * @returns True if the special transaction was created successfully, false otherwise. + */ bool Collator::create_special_transaction(block::CurrencyCollection amount, Ref dest_addr_cell, Ref& in_msg) { if (amount.is_zero()) { @@ -2086,12 +2475,27 @@ bool Collator::create_special_transaction(block::CurrencyCollection amount, Ref< return true; } +/** + * Creates special transactions for retreiving fees and minted currencies. + * Used in masterchain collator. + * + * @returns True if both special transactions were + */ bool Collator::create_special_transactions() { CHECK(is_masterchain()); return create_special_transaction(value_flow_.recovered, config_->get_config_param(3, 1), recover_create_msg_) && create_special_transaction(value_flow_.minted, config_->get_config_param(2, 0), mint_msg_); } +/** + * Creates a tick-tock transaction for a given smart contract. + * + * @param smc_addr The address of the smart contract. + * @param req_start_lt The requested start logical time for the transaction. + * @param mask The value indicating wheter the thansaction is tick (mask == 2) or tock (mask == 1). + * + * @returns True if the transaction was created successfully, false otherwise. + */ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, ton::LogicalTime req_start_lt, int mask) { auto acc_res = make_account(smc_addr.cbits(), false); @@ -2145,6 +2549,13 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t return true; } +/** + * Creates an ordinary transaction using a given message. + * + * @param msg_root The root of the message to be processed serialized using Message TLB-scheme. + * + * @returns The root of the serialized transaction, or an empty reference if the transaction creation fails. + */ Ref Collator::create_ordinary_transaction(Ref msg_root) { ton::StdSmcAddress addr; auto cs = vm::load_cell_slice(msg_root); @@ -2219,8 +2630,23 @@ Ref Collator::create_ordinary_transaction(Ref msg_root) { return trans_root; } -// If td::status::error_code == 669 - Fatal Error block can not be produced -// if td::status::error_code == 701 - Transaction can not be included into block, but it's ok (external or too early internal) +/** + * Creates an ordinary transaction using given parameters. + * + * @param msg_root The root of the message to be processed serialized using Message TLB-scheme. + * @param acc The account for which the transaction is being created. + * @param utime The Unix time of the transaction. + * @param lt The minimal logical time of the transaction. + * @param storage_phase_cfg The configuration for the storage phase of the transaction. + * @param compute_phase_cfg The configuration for the compute phase of the transaction. + * @param action_phase_cfg The configuration for the action phase of the transaction. + * @param external Flag indicating if the message is external. + * @param after_lt The logical time after which the transaction should occur. Used only for external messages. + * + * @returns A Result object containing the created transaction. + * Returns error_code == 669 if the error is fatal and the block can not be produced. + * Returns error_code == 701 if the transaction can not be included into block, but it's ok (external or too early internal). + */ td::Result> Collator::impl_create_ordinary_transaction(Ref msg_root, block::Account* acc, UnixTime utime, LogicalTime lt, @@ -2301,6 +2727,11 @@ td::Result> Collator::impl_crea return std::move(trans); } +/** + * Updates the maximum logical time if the given logical time is greater than the current maximum logical time. + * + * @param lt The logical time to be compared. + */ void Collator::update_max_lt(ton::LogicalTime lt) { CHECK(lt >= start_lt); if (lt > max_lt) { @@ -2308,6 +2739,13 @@ void Collator::update_max_lt(ton::LogicalTime lt) { } } +/** + * Updates information on the last processed internal message with a new logical time and hash. + * + * @param new_lt_hash The new logical time and hash pair. + * + * @returns True if the last processed internal message was successfully updated, false otherwise. + */ bool Collator::update_last_proc_int_msg(const std::pair& new_lt_hash) { if (last_proc_int_msg_ < new_lt_hash) { last_proc_int_msg_ = new_lt_hash; @@ -2322,6 +2760,14 @@ bool Collator::update_last_proc_int_msg(const std::pair addr_ref) const { return is_our_address(block::tlb::t_MsgAddressInt.get_prefix(std::move(addr_ref))); } +/** + * Checks if the given account ID prefix belongs to the current shard. + * + * @param addr_pfx The account ID prefix to check. + * + * @returns True if the account ID prefix belongs to the current shard, False otherwise. + */ bool Collator::is_our_address(ton::AccountIdPrefixFull addr_pfx) const { return ton::shard_contains(shard_, addr_pfx); } +/** + * Checks if the given address belongs to the current shard. + * + * @param addr The address to check. + * + * @returns True if the address belongs to the current shard, False otherwise. + */ bool Collator::is_our_address(const ton::StdSmcAddress& addr) const { return ton::shard_contains(get_shard(), addr); } -// 1 = processed, 0 = enqueued, 3 = processed, all future messages must be enqueued +/** + * Processes a message generated in this block. + * + * @param msg The new message to be processed. + * @param enqueue_only Flag indicating whether the message should only be enqueued. + * @param is_special New message if creating a special transaction, nullptr otherwise. + * + * @returns Returns: + * 0 - message was enqueued. + * 1 - message was processed. + * 3 - message was processed, all future messages must be enqueued. + * -1 - error occured. + */ int Collator::process_one_new_message(block::NewOutMsg msg, bool enqueue_only, Ref* is_special) { Ref src, dest; bool enqueue, external; @@ -2460,11 +2939,22 @@ int Collator::process_one_new_message(block::NewOutMsg msg, bool enqueue_only, R return 1; } -// very similar to enqueue_message(), but for transit messages +/** + * Enqueues a transit message. + * Very similar to enqueue_message(), but for transit messages. + * + * @param msg The message to be enqueued. + * @param old_msg_env The previous message envelope. + * @param prev_prefix The account ID prefix for this shard. + * @param cur_prefix The account ID prefix for the next hop. + * @param dest_prefix The prefix of the destination account ID. + * @param fwd_fee_remaining The remaining forward fee. + * + * @returns True if the transit message is successfully enqueued, false otherwise. + */ bool Collator::enqueue_transit_message(Ref msg, Ref old_msg_env, ton::AccountIdPrefixFull prev_prefix, ton::AccountIdPrefixFull cur_prefix, - ton::AccountIdPrefixFull dest_prefix, td::RefInt256 fwd_fee_remaining, - ton::LogicalTime enqueued_lt) { + ton::AccountIdPrefixFull dest_prefix, td::RefInt256 fwd_fee_remaining) { LOG(DEBUG) << "enqueueing transit message " << msg->get_hash().bits().to_hex(256); bool requeue = is_our_address(prev_prefix); // 1. perform hypercube routing @@ -2535,6 +3025,13 @@ bool Collator::enqueue_transit_message(Ref msg, Ref old_msg_ return register_out_msg_queue_op(); } +/** + * Deletes a message from the outbound message queue. + * + * @param key The key of the message to be deleted. + * + * @returns True if the message was successfully deleted, false otherwise. + */ bool Collator::delete_out_msg_queue_msg(td::ConstBitPtr key) { Ref queue_rec; try { @@ -2550,6 +3047,17 @@ bool Collator::delete_out_msg_queue_msg(td::ConstBitPtr key) { return register_out_msg_queue_op(); } +/** + * Processes an inbound message from a neighbor's outbound queue. + * The message may create a transaction or be enqueued. + * + * @param enq_msg The inbound message serialized using EnqueuedMsg TLB-scheme. + * @param lt The logical time of the message. + * @param key The 32+64+256-bit key of the message. + * @param src_nb The description of the source neighbor shard. + * + * @returns True if the message was processed successfully, false otherwise. + */ bool Collator::process_inbound_message(Ref enq_msg, ton::LogicalTime lt, td::ConstBitPtr key, const block::McShardDescr& src_nb) { ton::LogicalTime enqueued_lt = 0; @@ -2676,7 +3184,7 @@ bool Collator::process_inbound_message(Ref enq_msg, ton::LogicalT // destination is outside our shard, relay transit message // (very similar to enqueue_message()) if (!enqueue_transit_message(std::move(env.msg), std::move(msg_env), cur_prefix, next_prefix, dest_prefix, - std::move(env.fwd_fee_remaining), max_lt)) { + std::move(env.fwd_fee_remaining))) { return fatal_error("cannot enqueue transit internal message with key "s + key.to_hex(352)); } return !our || delete_out_msg_queue_msg(key); @@ -2718,6 +3226,12 @@ bool Collator::process_inbound_message(Ref enq_msg, ton::LogicalT return true; } +/** + * Processes inbound internal messages from message queues of the neighbors. + * Messages are processed until the normal limit is reached, soft timeout is reached or there are no more messages. + * + * @returns True if the processing was successful, false otherwise. + */ bool Collator::process_inbound_internal_messages() { while (!block_full_ && !nb_out_msgs_->is_eof()) { block_full_ = !block_limit_status_->fits(block::ParamLimits::cl_normal); @@ -2752,6 +3266,12 @@ bool Collator::process_inbound_internal_messages() { return true; } +/** + * Processes inbound external messages. + * Messages are processed until the soft limit is reached, medium timeout is reached or there are no more messages. + * + * @returns True if the processing was successful, false otherwise. + */ bool Collator::process_inbound_external_messages() { if (skip_extmsg_) { LOG(INFO) << "skipping processing of inbound external messages"; @@ -2790,7 +3310,17 @@ bool Collator::process_inbound_external_messages() { return true; } -// 1 = processed, 0 = skipped, 3 = processed, all future messages must be skipped (block overflown) +/** + * Processes an external message. + * + * @param msg The message to be processed serialized as Message TLB-scheme. + * + * @returns The result of processing the message: + * -1 if a fatal error occurred. + * 0 if the message is rejected. + * 1 if the message was processed. + * 3 if the message was processed and all future messages must be skipped (block overflown). + */ int Collator::process_external_message(Ref msg) { auto cs = load_cell_slice(msg); td::RefInt256 fwd_fees; @@ -2827,7 +3357,13 @@ int Collator::process_external_message(Ref msg) { return 1; } -// inserts an InMsg into InMsgDescr +/** + * Inserts an InMsg into the block's InMsgDescr. + * + * @param in_msg The input message to be inserted. + * + * @returns True if the insertion is successful, false otherwise. + */ bool Collator::insert_in_msg(Ref in_msg) { if (verbosity > 2) { std::cerr << "InMsg being inserted into InMsgDescr: "; @@ -2862,7 +3398,13 @@ bool Collator::insert_in_msg(Ref in_msg) { ((in_descr_cnt_ & 63) || block_limit_status_->add_cell(in_msg_dict->get_root_cell())); } -// inserts an OutMsg into OutMsgDescr +/** + * Inserts an OutMsg into the block's OutMsgDescr. + * + * @param out_msg The outgoing message to be inserted. + * + * @returns True if the insertion was successful, false otherwise. + */ bool Collator::insert_out_msg(Ref out_msg) { if (verbosity > 2) { std::cerr << "OutMsg being inserted into OutMsgDescr: "; @@ -2885,6 +3427,14 @@ bool Collator::insert_out_msg(Ref out_msg) { return insert_out_msg(std::move(out_msg), msg->get_hash().bits()); } +/** + * Inserts an outgoing message into the block's OutMsgDescr dictionary. + * + * @param out_msg The outgoing message to be inserted. + * @param msg_hash The 256-bit hash of the outgoing message. + * + * @returns True if the insertion was successful, false otherwise. + */ bool Collator::insert_out_msg(Ref out_msg, td::ConstBitPtr msg_hash) { bool ok; try { @@ -2901,7 +3451,15 @@ bool Collator::insert_out_msg(Ref out_msg, td::ConstBitPtr msg_hash) { ((out_descr_cnt_ & 63) || block_limit_status_->add_cell(out_msg_dict->get_root_cell())); } -// enqueues a new Message into OutMsgDescr and OutMsgQueue +/** + * Enqueues a new message into the block's outbound message queue and OutMsgDescr. + * + * @param msg The new outbound message to enqueue. + * @param fwd_fees_remaining The remaining forward fees for the message. + * @param enqueued_lt The logical time at which the message is enqueued. + * + * @returns True if the message was successfully enqueued, false otherwise. + */ bool Collator::enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_remaining, ton::LogicalTime enqueued_lt) { // 0. unpack src_addr and dest_addr block::gen::CommonMsgInfo::Record_int_msg_info info; @@ -2966,6 +3524,13 @@ bool Collator::enqueue_message(block::NewOutMsg msg, td::RefInt256 fwd_fees_rema return register_out_msg_queue_op(); } +/** + * Processes new messages that were generated in this block. + * + * @param enqueue_only If true, only enqueue the new messages without creating transactions. + * + * @returns True if all new messages were processed successfully, false otherwise. + */ bool Collator::process_new_messages(bool enqueue_only) { while (!new_msgs.empty()) { block::NewOutMsg msg = new_msgs.top(); @@ -2987,6 +3552,11 @@ bool Collator::process_new_messages(bool enqueue_only) { return true; } +/** + * Registers a new output message. + * + * @param new_msg The new output message to be registered. + */ void Collator::register_new_msg(block::NewOutMsg new_msg) { if (new_msg.lt < min_new_msg_lt) { min_new_msg_lt = new_msg.lt; @@ -2995,6 +3565,11 @@ void Collator::register_new_msg(block::NewOutMsg new_msg) { block_limit_status_->extra_out_msgs++; } +/** + * Registers new messages that were created in the transaction. + * + * @param trans The transaction containing the messages. + */ void Collator::register_new_msgs(block::transaction::Transaction& trans) { CHECK(trans.root.not_null()); for (unsigned i = 0; i < trans.out_msgs.size(); i++) { @@ -3008,6 +3583,15 @@ void Collator::register_new_msgs(block::transaction::Transaction& trans) { * */ +/** + * Stores an external block reference to a CellBuilder object. + * + * @param cb The CellBuilder object to store the reference in. + * @param id_ext The block ID. + * @param end_lt The end logical time of the block. + * + * @returns True if the reference was successfully stored, false otherwise. + */ bool store_ext_blk_ref_to(vm::CellBuilder& cb, const ton::BlockIdExt& id_ext, ton::LogicalTime end_lt) { return cb.store_long_bool(end_lt, 64) // end_lt:uint64 && cb.store_long_bool(id_ext.seqno(), 32) // seq_no:uint32 @@ -3015,6 +3599,15 @@ bool store_ext_blk_ref_to(vm::CellBuilder& cb, const ton::BlockIdExt& id_ext, to && cb.store_bits_bool(id_ext.file_hash); // file_hash:bits256 } +/** + * Stores an external block reference to a CellBuilder. + * + * @param cb The CellBuilder to store the reference in. + * @param id_ext The block ID. + * @param blk_root The root of the block. + * + * @returns True if the reference was successfully stored, false otherwise. + */ bool store_ext_blk_ref_to(vm::CellBuilder& cb, const ton::BlockIdExt& id_ext, Ref blk_root) { block::gen::Block::Record rec; block::gen::BlockInfo::Record info; @@ -3029,6 +3622,19 @@ bool store_ext_blk_ref_to(vm::CellBuilder& cb, const ton::BlockIdExt& id_ext, Re && store_ext_blk_ref_to(cb, id_ext, info.end_lt); // store } +/** + * Updates one shard description in the masterchain shard configuration. + * Used in masterchain collator. + * + * @param info The shard information to be updated. + * @param sibling The sibling shard information. + * @param wc_info The workchain information. + * @param now The current Unix time. + * @param ccvc The Catchain validators configuration. + * @param update_cc Flag indicating whether to update the Catchain seqno. + * + * @returns A boolean value indicating whether the shard description has changed. + */ static int update_one_shard(block::McShardHash& info, const block::McShardHash* sibling, const block::WorkchainInfo* wc_info, ton::UnixTime now, const block::CatchainValidatorsConfig& ccvc, bool update_cc) { @@ -3081,6 +3687,16 @@ static int update_one_shard(block::McShardHash& info, const block::McShardHash* return changed; } +/** + * Updates the shard configuration in the masterchain. + * Used in masterchain collator. + * + * @param wc_set The set of workchains. + * @param ccvc The Catchain validators configuration. + * @param update_cc A boolean indicating whether to update the Catchain seqno. + * + * @returns True if the shard configuration was successfully updated, false otherwise. + */ bool Collator::update_shard_config(const block::WorkchainSet& wc_set, const block::CatchainValidatorsConfig& ccvc, bool update_cc) { LOG(DEBUG) << "updating shard configuration (update_cc=" << update_cc << ")"; @@ -3107,6 +3723,12 @@ bool Collator::update_shard_config(const block::WorkchainSet& wc_set, const bloc }); } +/** + * Creates McStateExtra. + * Used in masterchain collator. + * + * @returns True if the creation is successful, false otherwise. + */ bool Collator::create_mc_state_extra() { if (!is_masterchain()) { CHECK(mc_state_extra_.is_null()); @@ -3325,6 +3947,16 @@ bool Collator::create_mc_state_extra() { return true; } +/** + * Updates the `block_creator_stats_` for a given key. + * Used in masterchain collator. + * + * @param key The 256-bit key of the creator. + * @param shard_incr The increment value for the shardchain block counter. + * @param mc_incr The increment value for the masterchain block counter. + * + * @returns True if the block creator count was successfully updated, false otherwise. + */ bool Collator::update_block_creator_count(td::ConstBitPtr key, unsigned shard_incr, unsigned mc_incr) { LOG(DEBUG) << "increasing CreatorStats for " << key.to_hex(256) << " by (" << mc_incr << ", " << shard_incr << ")"; block::DiscountedCounter mc_cnt, shard_cnt; @@ -3351,6 +3983,17 @@ bool Collator::update_block_creator_count(td::ConstBitPtr key, unsigned shard_in return true; } +/** + * Determines if the creator count is outdated for a given key. + * Used in masterchain collator. + * + * @param key The key of the creator. + * @param cs The CellSlice containing the CreatorStats. + * + * @returns -1 if there was a fatal error. + * 0 if the CreatorStats should be removed as they are stale, + * 1 if the CreatorStats are still valid. + */ int Collator::creator_count_outdated(td::ConstBitPtr key, vm::CellSlice& cs) { block::DiscountedCounter mc_cnt, shard_cnt; if (!(block::fetch_CreatorStats(cs, mc_cnt, shard_cnt) && cs.empty_ext())) { @@ -3369,6 +4012,11 @@ int Collator::creator_count_outdated(td::ConstBitPtr key, vm::CellSlice& cs) { } } +/** + * Updates `block_create_stats_` using information about creators of all new blocks. + * + * @returns True if the update was successful, false otherwise. + */ bool Collator::update_block_creator_stats() { if (!create_stats_enabled_) { return true; @@ -3419,10 +4067,25 @@ bool Collator::update_block_creator_stats() { return cnt >= 0; } +/** + * Retrieves the global masterchain config from the config contract. + * + * @param cfg_addr The address of the configuration smart contract. + * + * @returns A Result object containing a reference to the configuration data. + */ td::Result> Collator::get_config_data_from_smc(const ton::StdSmcAddress& cfg_addr) { return block::get_config_data_from_smc(account_dict->lookup_ref(cfg_addr)); } +/** + * Fetches and validates a new configuration from the configuration smart contract. + * + * @param cfg_addr The address of the configuration smart contract. + * @param new_config A reference to a vm::Cell object to store the new configuration. + * + * @returns True if the new configuration was successfully fetched, false otherwise. + */ bool Collator::try_fetch_new_config(const ton::StdSmcAddress& cfg_addr, Ref& new_config) { auto cfg_res = get_config_data_from_smc(cfg_addr); if (cfg_res.is_error()) { @@ -3440,11 +4103,24 @@ bool Collator::try_fetch_new_config(const ton::StdSmcAddress& cfg_addr, Reflookup(key, 256); @@ -3527,6 +4213,17 @@ bool Collator::remove_public_library(td::ConstBitPtr key, td::ConstBitPtr addr) return true; } +/** + * Processes adding a library to the collection of public libraries of an account. + * Updates the global collection of public libraries. + * Used in masterchain collator. + * + * @param key The key of the public library. + * @param addr The address of the account where the library is added. + * @param library The root cell of the library. + * + * @returns True if the public library was successfully added, false otherwise. + */ bool Collator::add_public_library(td::ConstBitPtr key, td::ConstBitPtr addr, Ref library) { LOG(INFO) << "Adding public library " << key.to_hex(256) << " of account " << addr.to_hex(256); CHECK(library.not_null() && !library->get_hash().bits().compare(key, 256)); @@ -3565,6 +4262,17 @@ bool Collator::add_public_library(td::ConstBitPtr key, td::ConstBitPtr addr, Ref return true; } +/** + * Processes changes in libraries of an account. + * Updates the global collection of public libraries. + * Used in masterchain collator. + * + * @param orig_libs The original libraries of the account. + * @param final_libs The final libraries of the account. + * @param addr The address associated with the account. + * + * @returns True if the update was successful, false otherwise. + */ bool Collator::update_account_public_libraries(Ref orig_libs, Ref final_libs, const td::Bits256& addr) { vm::Dictionary dict1{std::move(orig_libs), 256}, dict2{std::move(final_libs), 256}; @@ -3582,6 +4290,13 @@ bool Collator::update_account_public_libraries(Ref orig_libs, Ref msg_q_info; vm::CellBuilder cb, cb2; @@ -3676,11 +4411,20 @@ bool Collator::create_shard_state() { return true; } -// stores BlkMasterInfo (for non-masterchain blocks) +/** + * Stores BlkMasterInfo (for non-masterchain blocks) in the provided CellBuilder. + * + * @param cb The CellBuilder to store the reference in. + * + * @returns True if the reference is successfully stored, false otherwise. + */ bool Collator::store_master_ref(vm::CellBuilder& cb) { return mc_block_root.not_null() && store_ext_blk_ref_to(cb, mc_block_id_, mc_block_root); } +/** + * Updates the processed_upto information for the new block based on the information on the last processed inbound message. + */ bool Collator::update_processed_upto() { auto ref_mc_seqno = is_masterchain() ? new_block_seqno : prev_mc_block_seqno; update_min_mc_seqno(ref_mc_seqno); @@ -3695,6 +4439,13 @@ bool Collator::update_processed_upto() { return processed_upto_->compactify(); } +/** + * Computes the outbound message queue. + * + * @param out_msg_queue_info A reference to a vm::Cell object to store the computed queue. + * + * @returns True if the computation is successful, False otherwise. + */ bool Collator::compute_out_msg_queue_info(Ref& out_msg_queue_info) { if (verbosity >= 2) { auto rt = out_msg_queue_->get_root(); @@ -3709,6 +4460,11 @@ bool Collator::compute_out_msg_queue_info(Ref& out_msg_queue_info) { && cb.finalize_to(out_msg_queue_info); } +/** + * Computes the total balance of the shard state. + * + * @returns True if the total balance computation is successful, false otherwise. + */ bool Collator::compute_total_balance() { // 1. compute total_balance_ from the augmentation value of ShardAccounts auto accounts_extra = account_dict->get_root_extra(); @@ -3759,6 +4515,13 @@ bool Collator::compute_total_balance() { return true; } +/** + * Creates BlockInfo of the new block. + * + * @param block_info A reference to the cell to put the serialized info to. + * + * @returns True if the block info cell was successfully created, false otherwise. + */ bool Collator::create_block_info(Ref& block_info) { vm::CellBuilder cb, cb2; bool mc = is_masterchain(); @@ -3796,10 +4559,24 @@ bool Collator::create_block_info(Ref& block_info) { && cb.finalize_to(block_info); } +/** + * Stores the version information in a CellBuilder. + * + * @param cb The CellBuilder object to store the version information. + * + * @returns True if the version information was successfully stored, false otherwise. + */ bool Collator::store_version(vm::CellBuilder& cb) const { return block::gen::t_GlobalVersion.pack_capabilities(cb, supported_version(), supported_capabilities()); } +/** + * Stores the zero state reference in the given CellBuilder. + * + * @param cb The CellBuilder to store the zero state reference in. + * + * @returns True if the zero state reference is successfully stored, false otherwise. + */ bool Collator::store_zero_state_ref(vm::CellBuilder& cb) { CHECK(prev_state_root_.not_null()); RootHash root_hash = prev_state_root_->get_hash().bits(); @@ -3812,6 +4589,14 @@ bool Collator::store_zero_state_ref(vm::CellBuilder& cb) { && cb.store_bits_bool(prev_blocks[0].file_hash); // file_hash:bits256 } +/** + * Stores the previous block references to the given CellBuilder. + * + * @param cb The CellBuilder object to store the references. + * @param is_after_merge A boolean indicating whether the new block after a merge. + * + * @returns True if the references are successfully stored, false otherwise. + */ bool Collator::store_prev_blk_ref(vm::CellBuilder& cb, bool is_after_merge) { if (is_after_merge) { auto root2 = prev_block_data.at(1)->root_cell(); @@ -3829,6 +4614,11 @@ bool Collator::store_prev_blk_ref(vm::CellBuilder& cb, bool is_after_merge) { } } +/** + * Validates the value flow of the block. + * + * @returns True if the value flow is correct, false otherwise. + */ bool Collator::check_value_flow() { if (!value_flow_.validate()) { LOG(ERROR) << "incorrect value flow in new block : " << value_flow_.to_str(); @@ -3838,6 +4628,13 @@ bool Collator::check_value_flow() { return true; } +/** + * Creates the BlockExtra of the new block. + * + * @param block_extra A reference to the cell to put the serialized info to. + * + * @returns True if the block extra data was successfully created, false otherwise. + */ bool Collator::create_block_extra(Ref& block_extra) { bool mc = is_masterchain(); Ref mc_block_extra; @@ -3853,6 +4650,14 @@ bool Collator::create_block_extra(Ref& block_extra) { && cb.finalize_to(block_extra); // = BlockExtra; } +/** + * Creates the McBlockExtra of the new masterchain block. + * Used in masterchain collator. + * + * @param mc_block_extra A reference to the cell to put the serialized info to. + * + * @returns True if the extra data was successfully created, false otherwise. + */ bool Collator::create_mc_block_extra(Ref& mc_block_extra) { if (!is_masterchain()) { return false; @@ -3870,6 +4675,18 @@ bool Collator::create_mc_block_extra(Ref& mc_block_extra) { && cb.finalize_to(mc_block_extra); // = McBlockExtra } +/** + * Serialized the new block. + * + * This function performs the following steps: + * 1. Creates a BlockInfo for the new block. + * 2. Checks the value flow for the new block. + * 3. Creates a BlockExtra for the new block. + * 4. Builds a new block using the created BlockInfo, value flow, state update, and BlockExtra. + * 5. Verifies the new block if the verification is enabled. + * + * @returns True if the new block is successfully created, false otherwise. + */ bool Collator::create_block() { Ref block_info, extra; if (!create_block_info(block_info)) { @@ -3908,6 +4725,15 @@ bool Collator::create_block() { return true; } +/** + * Collates the shard block description set. + * Used in masterchain collator. + * + * This function creates a dictionary and populates it with the shard block descriptions. + * + * @returns A `Ref` containing the serialized `TopBlockDescrSet` record. + * If serialization fails, an empty `Ref` is returned. + */ Ref Collator::collate_shard_block_descr_set() { vm::Dictionary dict{96}; for (const auto& descr : used_shard_block_descr_) { @@ -3932,6 +4758,11 @@ Ref Collator::collate_shard_block_descr_set() { return cell; } +/** + * Creates collated data for the block. + * + * @returns True if the collated data was successfully created, false otherwise. + */ bool Collator::create_collated_data() { // TODO: store something into collated_roots_ // 1. store the set of used shard block descriptions @@ -3947,6 +4778,18 @@ bool Collator::create_collated_data() { return true; } +/** + * Creates a block candidate for the Collator. + * + * This function serializes the new block and collated data, and creates a BlockCandidate object + * with the necessary information. It then checks if the size of the block candidate exceeds the + * limits specified in the consensus configuration. + * + * Finally, the block candidate is saved to the disk. + * If there are any bad external messages or delayed external messages, the ValidatorManager is called to handle them. + * + * @returns True if the block candidate was created successfully, false otherwise. + */ bool Collator::create_block_candidate() { // 1. serialize block LOG(INFO) << "serializing new Block"; @@ -4021,6 +4864,11 @@ bool Collator::create_block_candidate() { return true; } +/** + * Returns a block candidate to the Promise. + * + * @param saved The result of saving the block candidate to the disk. + */ void Collator::return_block_candidate(td::Result saved) { // 6. return data to the original "caller" if (saved.is_error()) { @@ -4042,6 +4890,18 @@ void Collator::return_block_candidate(td::Result saved) { * */ +/** + * Registers an external message to the list of external messages in the Collator. + * + * @param ext_msg The reference to the external message cell. + * @param ext_hash The hash of the external message. + * + * @returns Result indicating the success or failure of the registration. + * - If the external message is invalid, returns an error. + * - If the external message has been previously rejected, returns an error + * - If the external message has been previuosly registered and accepted, returns false. + * - Otherwise returns true. + */ td::Result Collator::register_external_message_cell(Ref ext_msg, const ExtMessage::Hash& ext_hash) { if (ext_msg->get_level() != 0) { return td::Status::Error("external message must have zero level"); @@ -4090,23 +4950,11 @@ td::Result Collator::register_external_message_cell(Ref ext_msg, return true; } -/* -td::Result Collator::register_external_message(td::Slice ext_msg_boc) { - if (ext_msg_boc.size() > max_ext_msg_size) { - return td::Status::Error("external message too large, rejecting"); - } - vm::BagOfCells boc; - auto res = boc.deserialize(ext_msg_boc); - if (res.is_error()) { - return res.move_as_error(); - } - if (boc.get_root_count() != 1) { - return td::Status::Error("external message is not a valid bag of cells"); // not a valid bag-of-Cells - } - return register_external_message_cell(boc.get_root_cell(0)); -} -*/ - +/** + * Callback function called after retrieving external messages. + * + * @param res The result of the external message retrieval operation. + */ void Collator::after_get_external_messages(td::Result>> res) { --pending; if (res.is_error()) { @@ -4130,44 +4978,6 @@ void Collator::after_get_external_messages(td::Result Collator::register_ihr_message_cell(Ref ihr_msg) { - return false; -} - -td::Result Collator::register_ihr_message(td::Slice ihr_msg_boc) { - if (ihr_msg_boc.size() > max_ihr_msg_size) { - return td::Status::Error("IHR message too large, rejecting"); - } - vm::BagOfCells boc; - auto res = boc.deserialize(ihr_msg_boc); - if (res.is_error()) { - return res.move_as_error(); - } - if (boc.get_root_count() != 1) { - return td::Status::Error("IHR message is not a valid bag of cells"); // not a valid bag-of-Cells - } - return register_ihr_message_cell(boc.get_root_cell(0)); -} - -td::Result Collator::register_shard_signatures_cell(Ref signatures) { - return false; -} - -td::Result Collator::register_shard_signatures(td::Slice signatures_boc) { - if (signatures_boc.size() > max_blk_sign_size) { - return td::Status::Error("Shardchain signatures block too large, rejecting"); - } - vm::BagOfCells boc; - auto res = boc.deserialize(signatures_boc); - if (res.is_error()) { - return res.move_as_error(); - } - if (boc.get_root_count() != 1) { - return td::Status::Error("Shardchain signatures block is not a valid bag of cells"); // not a valid bag-of-Cells - } - return register_shard_signatures_cell(boc.get_root_cell(0)); -} - } // namespace validator } // namespace ton diff --git a/validator/impl/external-message.cpp b/validator/impl/external-message.cpp index 9383e7342..5c1848aab 100644 --- a/validator/impl/external-message.cpp +++ b/validator/impl/external-message.cpp @@ -114,7 +114,7 @@ void ExtMessageQ::run_message(td::BufferSlice data, block::SizeLimitsConfig::Ext auto utime = std::get<1>(tuple); auto lt = std::get<2>(tuple); auto config = std::move(std::get<3>(tuple)); - if (!acc.unpack(shard_acc, {}, utime, false)) { + if (!acc.unpack(shard_acc, utime, false)) { promise.set_error(td::Status::Error(PSLICE() << "Failed to unpack account state")); } else { auto status = run_message_on_account(wc, &acc, utime, lt + 1, msg_root, std::move(config)); diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index 4e4100f51..b134e1b34 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -39,6 +39,11 @@ namespace validator { using td::Ref; using namespace std::literals::string_literals; +/** + * Converts the error context to a string representation to show it in case of validation error. + * + * @returns The error context as a string. + */ std::string ErrorCtx::as_string() const { std::string a; for (const auto& s : entries_) { @@ -48,6 +53,20 @@ std::string ErrorCtx::as_string() const { return a; } +/** + * Constructs a ValidateQuery object. + * + * @param shard The shard of the block being validated. + * @param min_ts The minimum allowed UnixTime for the block. + * @param min_masterchain_block_id The minimum allowed masterchain block reference for the block. + * @param prev A vector of BlockIdExt representing the previous blocks. + * @param candidate The BlockCandidate to be validated. + * @param validator_set A reference to the ValidatorSet. + * @param manager The ActorId of the ValidatorManager. + * @param timeout The timeout for the validation. + * @param promise The Promise to return the ValidateCandidateResult to. + * @param is_fake A boolean indicating if the validation is fake (performed when creating a hardfork). + */ ValidateQuery::ValidateQuery(ShardIdFull shard, UnixTime min_ts, BlockIdExt min_masterchain_block_id, std::vector prev, BlockCandidate candidate, Ref validator_set, td::actor::ActorId manager, td::Timestamp timeout, @@ -71,14 +90,30 @@ ValidateQuery::ValidateQuery(ShardIdFull shard, UnixTime min_ts, BlockIdExt min_ proc_hash_.zero(); } +/** + * Raises an error when timeout is reached. + */ void ValidateQuery::alarm() { abort_query(td::Status::Error(ErrorCode::timeout, "timeout")); } +/** + * Aborts the validation with the given error. + * + * @param error The error encountered. + */ void ValidateQuery::abort_query(td::Status error) { (void)fatal_error(std::move(error)); } +/** + * Rejects the validation and logs an error message. + * + * @param error The error message to be logged. + * @param reason The reason for rejecting the validation. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::reject_query(std::string error, td::BufferSlice reason) { error = error_ctx() + error; LOG(ERROR) << "REJECT: aborting validation of block candidate for " << shard_.to_str() << " : " << error; @@ -94,11 +129,28 @@ bool ValidateQuery::reject_query(std::string error, td::BufferSlice reason) { return false; } +/** + * Rejects the validation and logs an error message. + * + * @param err_msg The error message to be displayed. + * @param error The error status. + * @param reason The reason for rejecting the query. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::reject_query(std::string err_msg, td::Status error, td::BufferSlice reason) { error.ensure_error(); return reject_query(err_msg + " : " + error.to_string(), std::move(reason)); } +/** + * Rejects the validation and logs an error message. + * + * @param error The error message to be logged. + * @param reason The reason for rejecting the validation. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::soft_reject_query(std::string error, td::BufferSlice reason) { error = error_ctx() + error; LOG(ERROR) << "SOFT REJECT: aborting validation of block candidate for " << shard_.to_str() << " : " << error; @@ -114,6 +166,13 @@ bool ValidateQuery::soft_reject_query(std::string error, td::BufferSlice reason) return false; } +/** + * Handles a fatal error during validation. + * + * @param error The error status. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::fatal_error(td::Status error) { error.ensure_error(); LOG(ERROR) << "aborting validation of block candidate for " << shard_.to_str() << " : " << error.to_string(); @@ -132,19 +191,47 @@ bool ValidateQuery::fatal_error(td::Status error) { return false; } +/** + * Handles a fatal error during validation. + * + * @param err_code Error code. + * @param error Error message. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::fatal_error(int err_code, std::string err_msg) { return fatal_error(td::Status::Error(err_code, error_ctx() + err_msg)); } +/** + * Handles a fatal error during validation. + * + * @param err_code Error code. + * @param err_msg Error message. + * @param error Error status. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::fatal_error(int err_code, std::string err_msg, td::Status error) { error.ensure_error(); return fatal_error(err_code, err_msg + " : " + error.to_string()); } +/** + * Handles a fatal error during validation. + * + * @param error Error message. + * @param err_code Error code. + * + * @returns False indicating that the validation failed. + */ bool ValidateQuery::fatal_error(std::string err_msg, int err_code) { return fatal_error(td::Status::Error(err_code, error_ctx() + err_msg)); } +/** + * Finishes the query and sends the result to the promise. + */ void ValidateQuery::finish_query() { if (main_promise) { main_promise.set_result(now_); @@ -158,6 +245,12 @@ void ValidateQuery::finish_query() { * */ +/** + * Starts the validation process. + * + * This function performs various checks on the validation parameters and the block candidate. + * Then the function also sends requests to the ValidatorManager to fetch blocks and shard stated. + */ void ValidateQuery::start_up() { LOG(INFO) << "validate query for " << block_candidate.id.to_str() << " started"; alarm_timestamp() = timeout; @@ -307,7 +400,16 @@ void ValidateQuery::start_up() { CHECK(pending); } -// unpack block candidate, and check root hash and file hash +/** + * Unpacks and validates a block candidate. + * + * This function unpacks the block candidate data and performs various validation checks to ensure its integrity. + * It checks the file hash and root hash of the block candidate against the expected values. + * It then parses the block header and checks its validity. + * Finally, it deserializes the collated data and extracts the collated roots. + * + * @returns True if the block candidate was successfully unpacked, false otherwise. + */ bool ValidateQuery::unpack_block_candidate() { vm::BagOfCells boc1, boc2; // 1. deserialize block itself @@ -359,6 +461,11 @@ bool ValidateQuery::unpack_block_candidate() { return extract_collated_data(); } +/** + * Initializes the validation by parsing and checking the block header. + * + * @returns True if the initialization is successful, false otherwise. + */ bool ValidateQuery::init_parse() { CHECK(block_root_.not_null()); std::vector prev_blks; @@ -486,6 +593,14 @@ bool ValidateQuery::init_parse() { return true; } +/** + * Extracts collated data from a cell. + * + * @param croot The root cell containing the collated data. + * @param idx The index of the root. + * + * @returns True if the extraction is successful, false otherwise. + */ bool ValidateQuery::extract_collated_data_from(Ref croot, int idx) { bool is_special = false; auto cs = vm::load_cell_slice_special(croot, is_special); @@ -523,7 +638,11 @@ bool ValidateQuery::extract_collated_data_from(Ref croot, int idx) { return true; } -// processes further and sorts data in collated_roots_ +/** + * Extracts collated data from a list of collated roots. + * + * @returns True if the extraction is successful, False otherwise. + */ bool ValidateQuery::extract_collated_data() { int i = -1; for (auto croot : collated_roots_) { @@ -542,6 +661,11 @@ bool ValidateQuery::extract_collated_data() { return true; } +/** + * Callback function called after retrieving the latest masterchain state. + * + * @param res The result of the retrieval of the latest masterchain state. + */ void ValidateQuery::after_get_latest_mc_state(td::Result, BlockIdExt>> res) { LOG(DEBUG) << "in ValidateQuery::after_get_latest_mc_state()"; --pending; @@ -578,6 +702,11 @@ void ValidateQuery::after_get_latest_mc_state(td::Result> res) { LOG(DEBUG) << "in ValidateQuery::after_get_mc_state() for " << mc_blkid_.to_str(); --pending; @@ -596,6 +725,11 @@ void ValidateQuery::after_get_mc_state(td::Result> res) { } } +/** + * Callback function for handling the result of retrieving a masterchain block handle referenced in the block. + * + * @param res The result of retrieving the masterchain block handle. + */ void ValidateQuery::got_mc_handle(td::Result res) { LOG(DEBUG) << "in ValidateQuery::got_mc_handle() for " << mc_blkid_.to_str(); --pending; @@ -611,6 +745,12 @@ void ValidateQuery::got_mc_handle(td::Result res) { } } +/** + * Callback function called after retrieving the shard state for a previous block. + * + * @param idx The index of the previous block (0 or 1). + * @param res The result of the shard state retrieval. + */ void ValidateQuery::after_get_shard_state(int idx, td::Result> res) { LOG(DEBUG) << "in ValidateQuery::after_get_shard_state(" << idx << ")"; --pending; @@ -643,6 +783,13 @@ void ValidateQuery::after_get_shard_state(int idx, td::Result> r } } +/** + * Processes the retreived masterchain state. + * + * @param mc_state The reference to the masterchain state. + * + * @returns True if the masterchain state is successfully processed, false otherwise. + */ bool ValidateQuery::process_mc_state(Ref mc_state) { if (mc_state.is_null()) { return fatal_error("could not obtain reference masterchain state "s + mc_blkid_.to_str()); @@ -664,6 +811,11 @@ bool ValidateQuery::process_mc_state(Ref mc_state) { return register_mc_state(mc_state_); } +/** + * Tries to unpack the masterchain state and perform necessary checks. + * + * @returns True if the unpacking and checks are successful, false otherwise. + */ bool ValidateQuery::try_unpack_mc_state() { LOG(DEBUG) << "unpacking reference masterchain state"; auto guard = error_ctx_add_guard("unpack last mc state"); @@ -750,7 +902,12 @@ bool ValidateQuery::try_unpack_mc_state() { return true; } -// almost the same as in Collator +/** + * Fetches and validates configuration parameters from the masterchain configuration. + * Almost the same as in Collator. + * + * @returns True if all configuration parameters were successfully fetched and validated, false otherwise. + */ bool ValidateQuery::fetch_config_params() { old_mparams_ = config_->get_config_param(9); { @@ -839,7 +996,16 @@ bool ValidateQuery::fetch_config_params() { return true; } -// almost the same as in Collator +/** + * Checks the previous block against the block registered in the masterchain. + * Almost the same as in Collator. + * + * @param listed The BlockIdExt of the top block of this shard registered in the masterchain. + * @param prev The BlockIdExt of the previous block. + * @param chk_chain_len Flag indicating whether to check the chain length. + * + * @returns True if the previous block is valid, false otherwise. + */ bool ValidateQuery::check_prev_block(const BlockIdExt& listed, const BlockIdExt& prev, bool chk_chain_len) { if (listed.seqno() > prev.seqno()) { return reject_query(PSTRING() << "cannot generate a shardchain block after previous block " << prev.to_str() @@ -859,7 +1025,15 @@ bool ValidateQuery::check_prev_block(const BlockIdExt& listed, const BlockIdExt& return true; } -// almost the same as in Collator +/** + * Checks the previous block against the block registered in the masterchain. + * Almost the same as in Collator + * + * @param listed The BlockIdExt of the top block of this shard registered in the masterchain. + * @param prev The BlockIdExt of the previous block. + * + * @returns True if the previous block is equal to the one registered in the masterchain, false otherwise. + */ bool ValidateQuery::check_prev_block_exact(const BlockIdExt& listed, const BlockIdExt& prev) { if (listed != prev) { return reject_query(PSTRING() << "cannot generate shardchain block for shard " << shard_.to_str() @@ -870,8 +1044,12 @@ bool ValidateQuery::check_prev_block_exact(const BlockIdExt& listed, const Block return true; } -// almost the same as in Collator -// (main change: fatal_error -> reject_query) +/** + * Checks the validity of the shard configuration of the current shard. + * Almost the same as in Collator (main change: fatal_error -> reject_query). + * + * @returns True if the shard's configuration is valid, False otherwise. + */ bool ValidateQuery::check_this_shard_mc_info() { wc_info_ = config_->get_workchain_info(workchain()); if (wc_info_.is_null()) { @@ -1016,6 +1194,11 @@ bool ValidateQuery::check_this_shard_mc_info() { * */ +/** + * Computes the previous shard state. + * + * @returns True if the previous state is computed successfully, false otherwise. + */ bool ValidateQuery::compute_prev_state() { CHECK(prev_states.size() == 1u + after_merge_); // Extend validator timeout if previous block is too old @@ -1045,6 +1228,9 @@ bool ValidateQuery::compute_prev_state() { return true; } +/** + * Computes the next shard state using the previous state and the block's Merkle update. + */ bool ValidateQuery::compute_next_state() { LOG(DEBUG) << "computing next state"; auto res = vm::MerkleUpdate::validate(state_update_); @@ -1120,7 +1306,13 @@ bool ValidateQuery::compute_next_state() { return true; } -// similar to Collator::unpack_merge_last_state() +/** + * Unpacks and merges the states of two previous blocks. + * Used if the block is after_merge. + * Similar to Collator::unpack_merge_last_state() + * + * @returns True if the unpacking and merging was successful, false otherwise. + */ bool ValidateQuery::unpack_merge_prev_state() { LOG(DEBUG) << "unpack/merge previous states"; CHECK(prev_states.size() == 2); @@ -1148,7 +1340,13 @@ bool ValidateQuery::unpack_merge_prev_state() { return true; } -// similar to Collator::unpack_last_state() +/** + * Unpacks the state of the previous block. + * Used if the block is not after_merge. + * Similar to Collator::unpack_last_state() + * + * @returns True if the unpacking is successful, false otherwise. + */ bool ValidateQuery::unpack_prev_state() { LOG(DEBUG) << "unpacking previous state(s)"; CHECK(prev_state_root_.not_null()); @@ -1163,7 +1361,16 @@ bool ValidateQuery::unpack_prev_state() { return unpack_one_prev_state(ps_, prev_blocks.at(0), prev_state_root_) && (!after_split_ || split_prev_state(ps_)); } -// similar to Collator::unpack_one_last_state() +/** + * Unpacks the state of a previous block and performs necessary checks. + * Similar to Collator::unpack_one_last_state() + * + * @param ss The ShardState object to unpack the state into. + * @param blkid The BlockIdExt of the previous block. + * @param prev_state_root The root of the state. + * + * @returns True if the unpacking and checks are successful, false otherwise. + */ bool ValidateQuery::unpack_one_prev_state(block::ShardState& ss, BlockIdExt blkid, Ref prev_state_root) { auto res = ss.unpack_state_ext(blkid, std::move(prev_state_root), global_id_, mc_seqno_, after_split_, after_split_ | after_merge_, [this](ton::BlockSeqno mc_seqno) { @@ -1180,7 +1387,15 @@ bool ValidateQuery::unpack_one_prev_state(block::ShardState& ss, BlockIdExt blki return true; } -// similar to Collator::split_last_state() +/** + * Splits the state of previous block. + * Used if the block is after_split. + * Similar to Collator::split_last_state() + * + * @param ss The ShardState object representing the previous state. The result is stored here. + * + * @returns True if the split operation is successful, false otherwise. + */ bool ValidateQuery::split_prev_state(block::ShardState& ss) { LOG(INFO) << "Splitting previous state " << ss.id_.to_str() << " to subshard " << shard_.to_str(); CHECK(after_split_); @@ -1202,6 +1417,11 @@ bool ValidateQuery::split_prev_state(block::ShardState& ss) { return true; } +/** + * Unpacks the next state (obtained by applying the Merkle update) and performs checks. + * + * @returns True if the next state is successfully unpacked and passes all checks, false otherwise. + */ bool ValidateQuery::unpack_next_state() { LOG(DEBUG) << "unpacking new state"; CHECK(state_root_.not_null()); @@ -1231,7 +1451,12 @@ bool ValidateQuery::unpack_next_state() { return true; } -// almost the same as in Collator +/** + * Requests the message queues of neighboring shards. + * Almost the same as in Collator. + * + * @returns True if the request for neighbor message queues was successful, false otherwise. + */ bool ValidateQuery::request_neighbor_queues() { CHECK(new_shard_conf_); auto neighbor_list = new_shard_conf_->get_neighbor_shard_hash_ids(shard_); @@ -1261,7 +1486,13 @@ bool ValidateQuery::request_neighbor_queues() { return true; } -// almost the same as in Collator +/** + * Handles the result of obtaining the outbound queue for a neighbor. + * Almost the same as in Collator. + * + * @param i The index of the neighbor. + * @param res The obtained outbound queue. + */ void ValidateQuery::got_neighbor_out_queue(int i, td::Result> res) { LOG(DEBUG) << "obtained outbound queue for neighbor #" << i; --pending; @@ -1323,7 +1554,14 @@ void ValidateQuery::got_neighbor_out_queue(int i, td::Result> } } -// almost the same as in Collator +/** + * Registers a masterchain state. + * Almost the same as in Collator. + * + * @param other_mc_state The masterchain state to register. + * + * @returns True if the registration is successful, false otherwise. + */ bool ValidateQuery::register_mc_state(Ref other_mc_state) { if (other_mc_state.is_null() || mc_state_.is_null()) { return false; @@ -1349,7 +1587,15 @@ bool ValidateQuery::register_mc_state(Ref other_mc_state) { return true; } -// almost the same as in Collator +/** + * Requests the auxiliary masterchain state. + * Almost the same as in Collator + * + * @param seqno The seqno of the block. + * @param state A reference to the auxiliary masterchain state. + * + * @returns True if the auxiliary masterchain state is successfully requested, false otherwise. + */ bool ValidateQuery::request_aux_mc_state(BlockSeqno seqno, Ref& state) { if (mc_state_.is_null()) { return fatal_error(PSTRING() << "cannot find masterchain block with seqno " << seqno @@ -1383,7 +1629,14 @@ bool ValidateQuery::request_aux_mc_state(BlockSeqno seqno, Ref ValidateQuery::get_aux_mc_state(BlockSeqno seqno) const { auto it = aux_mc_states_.find(seqno); if (it != aux_mc_states_.end()) { @@ -1393,7 +1646,14 @@ Ref ValidateQuery::get_aux_mc_state(BlockSeqno seqno) const { } } -// almost the same as in Collator +/** + * Callback function called after retrieving the auxiliary shard state. + * Handles the retrieved shard state and performs necessary checks and registrations. + * Almost the same as in Collator. + * + * @param blkid The BlockIdExt of the shard state. + * @param res The result of retrieving the shard state. + */ void ValidateQuery::after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result> res) { LOG(DEBUG) << "in ValidateQuery::after_get_aux_shard_state(" << blkid.to_str() << ")"; --pending; @@ -1420,6 +1680,17 @@ void ValidateQuery::after_get_aux_shard_state(ton::BlockIdExt blkid, td::Result< } // similar to Collator::update_one_shard() +/** + * Checks one shard description in the masterchain shard configuration. + * Used in masterchain validation. + * + * @param info The shard information to be updated. + * @param sibling The sibling shard information. + * @param wc_info The workchain information. + * @param ccvc The Catchain validators configuration. + * + * @returns True if the validation wasa successful, false othewise. + */ bool ValidateQuery::check_one_shard(const block::McShardHash& info, const block::McShardHash* sibling, const block::WorkchainInfo* wc_info, const block::CatchainValidatorsConfig& ccvc) { auto shard = info.shard(); @@ -1706,8 +1977,14 @@ bool ValidateQuery::check_one_shard(const block::McShardHash& info, const block: return true; } -// checks old_shard_conf_ -> new_shard_conf_ transition using top_shard_descr_dict_ from collated data -// similar to Collator::update_shard_config() +/** + * Checks the shard configuration in the masterchain. + * Used in masterchain collator. + * Checks old_shard_conf_ -> new_shard_conf_ transition using top_shard_descr_dict_ from collated data. + * Similar to Collator::update_shard_config() + * + * @returns True if the shard layout is valid, false otherwise. + */ bool ValidateQuery::check_shard_layout() { prev_now_ = config_->utime; if (prev_now_ > now_) { @@ -1761,7 +2038,14 @@ bool ValidateQuery::check_shard_layout() { return check_mc_validator_info(is_key_block_ || (now_ / ccvc.mc_cc_lifetime > prev_now_ / ccvc.mc_cc_lifetime)); } -// similar to Collator::register_shard_block_creators +/** + * Registers the shard block creators to block_create_count_ + * Similar to Collator::register_shard_block_creators + * + * @param creator_list A vector of Bits256 representing the shard block creators. + * + * @returns True if the registration was successful, False otherwise. + */ bool ValidateQuery::register_shard_block_creators(std::vector creator_list) { for (const auto& x : creator_list) { LOG(DEBUG) << "registering block creator " << x.to_hex(); @@ -1776,7 +2060,12 @@ bool ValidateQuery::register_shard_block_creators(std::vector creat return true; } -// similar to Collator::check_cur_validator_set() +/** + * Checks that the current validator set is entitled to create blocks in this shard and has a correct catchain seqno. + * Similar to Collator::check_cur_validator_set() + * + * @returns True if the current validator set is valid, false otherwise. + */ bool ValidateQuery::check_cur_validator_set() { CatchainSeqno cc_seqno = 0; auto nodes = config_->compute_validator_set_cc(shard_, now_, &cc_seqno); @@ -1799,8 +2088,14 @@ bool ValidateQuery::check_cur_validator_set() { return true; } -// parallel to 4. of Collator::create_mc_state_extra() -// checks validator_info in mc_state_extra +/** + * Checks validator_info in mc_state_extra. + * NB: could be run in parallel to 4. of Collator::create_mc_state_extra() + * + * @param update_mc_cc Flag indicating whether the masterchain catchain seqno should be updated. + * + * @returns True if the validator information is valid, false otherwise. + */ bool ValidateQuery::check_mc_validator_info(bool update_mc_cc) { block::gen::McStateExtra::Record old_state_extra; block::gen::ValidatorInfo::Record old_val_info; @@ -1842,6 +2137,11 @@ bool ValidateQuery::check_mc_validator_info(bool update_mc_cc) { return true; } +/** + * Checks if the Unix time and logical time of the block are valid. + * + * @returns True if the utime and logical time pass checks, False otherwise. + */ bool ValidateQuery::check_utime_lt() { if (start_lt_ <= ps_.lt_) { return reject_query(PSTRING() << "block has start_lt " << start_lt_ << " less than or equal to lt " << ps_.lt_ @@ -1888,8 +2188,16 @@ bool ValidateQuery::check_utime_lt() { * */ -// almost the same as in Collator -// (but it can take into account the new state of the masterchain) +/** + * Adjusts one entry from the processed up to information using the masterchain state that is referenced in the entry. + * Almost the same as in Collator (but it can take into account the new state of the masterchain). + * + * @param proc The MsgProcessedUpto object. + * @param owner The shard that the MsgProcessesUpto information is taken from. + * @param allow_cur Allow using the new state of the msaterchain. + * + * @returns True if the processed up to information was successfully adjusted, false otherwise. + */ bool ValidateQuery::fix_one_processed_upto(block::MsgProcessedUpto& proc, ton::ShardIdFull owner, bool allow_cur) { if (proc.compute_shard_end_lt) { return true; @@ -1912,7 +2220,15 @@ bool ValidateQuery::fix_one_processed_upto(block::MsgProcessedUpto& proc, ton::S return (bool)proc.compute_shard_end_lt; } -// almost the same as in Collator +/** + * Adjusts the processed up to collection using the using the auxilliary masterchain states. + * Almost the same as in Collator. + * + * @param upto The MsgProcessedUptoCollection to be adjusted. + * @param allow_cur Allow using the new state of the msaterchain. + * + * @returns True if all entries were successfully adjusted, False otherwise. + */ bool ValidateQuery::fix_processed_upto(block::MsgProcessedUptoCollection& upto, bool allow_cur) { for (auto& entry : upto.list) { if (!fix_one_processed_upto(entry, upto.owner, allow_cur)) { @@ -1922,6 +2238,11 @@ bool ValidateQuery::fix_processed_upto(block::MsgProcessedUptoCollection& upto, return true; } +/** + * Adjusts the processed_upto values for all shard states, including neighbors. + * + * @returns True if all processed_upto values were successfully adjusted, false otherwise. + */ bool ValidateQuery::fix_all_processed_upto() { CHECK(ps_.processed_upto_); if (!fix_processed_upto(*ps_.processed_upto_)) { @@ -1942,7 +2263,13 @@ bool ValidateQuery::fix_all_processed_upto() { return true; } -// almost the same as in Collator +/** + * Adds trivials neighbor after merging two shards. + * Trivial neighbors are the two previous blocks. + * Almost the same as in Collator. + * + * @returns True if the operation is successful, false otherwise. + */ bool ValidateQuery::add_trivial_neighbor_after_merge() { LOG(DEBUG) << "in add_trivial_neighbor_after_merge()"; CHECK(prev_blocks.size() == 2); @@ -1977,7 +2304,13 @@ bool ValidateQuery::add_trivial_neighbor_after_merge() { return true; } -// almost the same as in Collator +/** + * Adds a trivial neighbor. + * A trivial neighbor is the previous block. + * Almost the same as in Collator. + * + * @returns True if the operation is successful, false otherwise. + */ bool ValidateQuery::add_trivial_neighbor() { LOG(DEBUG) << "in add_trivial_neighbor()"; if (after_merge_) { @@ -2113,6 +2446,11 @@ bool ValidateQuery::add_trivial_neighbor() { return true; } +/** + * Unpacks block data and performs validation checks. + * + * @returns True if the block data is successfully unpacked and passes all validation checks, false otherwise. + */ bool ValidateQuery::unpack_block_data() { LOG(DEBUG) << "unpacking block structures"; block::gen::Block::Record blk; @@ -2152,6 +2490,13 @@ bool ValidateQuery::unpack_block_data() { return unpack_precheck_value_flow(std::move(blk.value_flow)); } +/** + * Validates and unpacks the value flow of a new block. + * + * @param value_flow_root The root of the value flow to be unpacked and validated. + * + * @returns True if the value flow is valid and unpacked successfully, false otherwise. + */ bool ValidateQuery::unpack_precheck_value_flow(Ref value_flow_root) { vm::CellSlice cs{vm::NoVmOrd(), value_flow_root}; if (!(cs.is_valid() && value_flow_.fetch(cs) && cs.empty_ext())) { @@ -2269,7 +2614,14 @@ bool ValidateQuery::unpack_precheck_value_flow(Ref value_flow_root) { return true; } -// similar to Collator::compute_minted_amount() +/** + * Computes the amount of extra currencies to be minted. + * Similar to Collator::compute_minted_amount() + * + * @param to_mint A reference to the CurrencyCollection object to store the minted amount. + * + * @returns True if the computation is successful, false otherwise. + */ bool ValidateQuery::compute_minted_amount(block::CurrencyCollection& to_mint) { if (!is_masterchain()) { return to_mint.set_zero(); @@ -2321,6 +2673,15 @@ bool ValidateQuery::compute_minted_amount(block::CurrencyCollection& to_mint) { return true; } +/** + * Pre-validates the update of an account in a query. + * + * @param acc_id The 256-bit account address. + * @param old_value The old value of the account serialized as ShardAccount. Can be null. + * @param new_value The new value of the account serialized as ShardAccount. Can be null. + * + * @returns True if the accounts passes preliminary checks, false otherwise. + */ bool ValidateQuery::precheck_one_account_update(td::ConstBitPtr acc_id, Ref old_value, Ref new_value) { LOG(DEBUG) << "checking update of account " << acc_id.to_hex(256); @@ -2380,6 +2741,11 @@ bool ValidateQuery::precheck_one_account_update(td::ConstBitPtr acc_id, Ref trans_csr, ton::Bits256& prev_trans_hash, ton::LogicalTime& prev_trans_lt, unsigned& prev_trans_lt_len, @@ -2467,6 +2846,14 @@ bool ValidateQuery::precheck_one_transaction(td::ConstBitPtr acc_id, ton::Logica } // NB: could be run in parallel for different accounts +/** + * Pre-validates an AccountBlock and all transactions in it. + * + * @param acc_id The 256-bit account address. + * @param acc_blk_root The root of the AccountBlock. + * + * @returns True if the AccountBlock passes pre-checks, false otherwise. + */ bool ValidateQuery::precheck_one_account_block(td::ConstBitPtr acc_id, Ref acc_blk_root) { LOG(DEBUG) << "checking AccountBlock for " << acc_id.to_hex(256); if (!acc_id.equals(shard_pfx_.bits(), shard_pfx_len_)) { @@ -2548,6 +2935,11 @@ bool ValidateQuery::precheck_one_account_block(td::ConstBitPtr acc_id, Ref ValidateQuery::lookup_transaction(const ton::StdSmcAddress& addr, ton::LogicalTime lt) const { CHECK(account_blocks_dict_); block::gen::AccountBlock::Record ab_rec; @@ -2578,7 +2978,13 @@ Ref ValidateQuery::lookup_transaction(const ton::StdSmcAddress& addr, return trans_dict.lookup_ref(td::BitArray<64>{(long long)lt}); } -// checks that a ^Transaction refers to a transaction present in the ShardAccountBlocks +/** + * Checks that a Transaction cell refers to a transaction present in the ShardAccountBlocks. + * + * @param trans_ref The reference to the serialized transaction root. + * + * @returns True if the transaction reference is valid, False otherwise. + */ bool ValidateQuery::is_valid_transaction_ref(Ref trans_ref) const { ton::StdSmcAddress addr; ton::LogicalTime lt; @@ -2598,8 +3004,16 @@ bool ValidateQuery::is_valid_transaction_ref(Ref trans_ref) const { return true; } -// checks that any change in OutMsgQueue in the state is accompanied by an OutMsgDescr record in the block -// also checks that the keys are correct +/** + * Checks that any change in OutMsgQueue in the state is accompanied by an OutMsgDescr record in the block. + * Also checks that the keys are correct. + * + * @param out_msg_id The 32+64+256-bit ID of the outbound message. + * @param old_value The old value of the message queue entry. + * @param new_value The new value of the message queue entry. + * + * @returns True if the update is valid, false otherwise. + */ bool ValidateQuery::precheck_one_message_queue_update(td::ConstBitPtr out_msg_id, Ref old_value, Ref new_value) { LOG(DEBUG) << "checking update of enqueued outbound message " << out_msg_id.get_int(32) << ":" @@ -2765,6 +3179,11 @@ bool ValidateQuery::precheck_one_message_queue_update(td::ConstBitPtr out_msg_id return true; } +/** + * Performs a pre-check on the difference between the old and new outbound message queues. + * + * @returns True if the pre-check is successful, false otherwise. + */ bool ValidateQuery::precheck_message_queue_update() { LOG(INFO) << "pre-checking the difference between the old and the new outbound message queues"; try { @@ -2787,6 +3206,14 @@ bool ValidateQuery::precheck_message_queue_update() { return true; } +/** + * Updates the maximum processed logical time and hash value. + * + * @param lt The logical time to compare against the current maximum processed logical time. + * @param hash The hash value to compare against the current maximum processed hash value. + * + * @returns True if the update was successful, false otherwise. + */ bool ValidateQuery::update_max_processed_lt_hash(ton::LogicalTime lt, const ton::Bits256& hash) { if (proc_lt_ < lt || (proc_lt_ == lt && proc_hash_ < hash)) { proc_lt_ = lt; @@ -2795,6 +3222,14 @@ bool ValidateQuery::update_max_processed_lt_hash(ton::LogicalTime lt, const ton: return true; } +/** + * Updates the minimum enqueued logical time and hash values. + * + * @param lt The logical time to compare. + * @param hash The hash value to compare. + * + * @returns True if the update was successful, false otherwise. + */ bool ValidateQuery::update_min_enqueued_lt_hash(ton::LogicalTime lt, const ton::Bits256& hash) { if (lt < min_enq_lt_ || (lt == min_enq_lt_ && hash < min_enq_hash_)) { min_enq_lt_ = lt; @@ -2803,7 +3238,13 @@ bool ValidateQuery::update_min_enqueued_lt_hash(ton::LogicalTime lt, const ton:: return true; } -// check that the enveloped message (MsgEnvelope) was present in the output queue of a neighbor, and that it has not been processed before +/** + * Checks that the MsgEnvelope was present in the output queue of a neighbor, and that it has not been processed before. + * + * @param msg_env The message envelope of the imported message. + * + * @returns True if the imported internal message passes checks, false otherwise. + */ bool ValidateQuery::check_imported_message(Ref msg_env) { block::tlb::MsgEnvelope::Record_std env; block::gen::CommonMsgInfo::Record_int_msg_info info; @@ -2863,11 +3304,27 @@ bool ValidateQuery::check_imported_message(Ref msg_env) { " has previous address not belonging to any neighbor"); } +/** + * Checks if the given input message is a special message. + * A message is considered special if it recovers fees or mints extra currencies. + * + * @param in_msg The input message to be checked. + * + * @returns True if the input message is special, False otherwise. + */ bool ValidateQuery::is_special_in_msg(const vm::CellSlice& in_msg) const { return (recover_create_msg_.not_null() && vm::load_cell_slice(recover_create_msg_).contents_equal(in_msg)) || (mint_msg_.not_null() && vm::load_cell_slice(mint_msg_).contents_equal(in_msg)); } +/** + * Checks the validity of an inbound message listed in InMsgDescr. + * + * @param key The 256-bit key of the inbound message. + * @param in_msg The inbound message to be checked serialized using InMsg TLB-scheme. + * + * @returns True if the inbound message is valid, false otherwise. + */ bool ValidateQuery::check_in_msg(td::ConstBitPtr key, Ref in_msg) { LOG(DEBUG) << "checking InMsg with key " << key.to_hex(256); CHECK(in_msg.not_null()); @@ -3274,6 +3731,11 @@ bool ValidateQuery::check_in_msg(td::ConstBitPtr key, Ref in_msg) return true; } +/** + * Checks the validity of the inbound messages listed in the InMsgDescr dictionary. + * + * @returns True if the inbound messages dictionary is valid, false otherwise. + */ bool ValidateQuery::check_in_msg_descr() { LOG(INFO) << "checking inbound messages listed in InMsgDescr"; try { @@ -3293,6 +3755,14 @@ bool ValidateQuery::check_in_msg_descr() { return true; } +/** + * Checks the validity of an outbound message listed in OutMsgDescr. + * + * @param key The 256-bit key of the outbound message. + * @param in_msg The outbound message to be checked serialized using OutMsg TLB-scheme. + * + * @returns True if the outbound message is valid, false otherwise. + */ bool ValidateQuery::check_out_msg(td::ConstBitPtr key, Ref out_msg) { LOG(DEBUG) << "checking OutMsg with key " << key.to_hex(256); CHECK(out_msg.not_null()); @@ -3810,6 +4280,11 @@ bool ValidateQuery::check_out_msg(td::ConstBitPtr key, Ref out_ms return true; } +/** + * Checks the validity of the outbound messages listed in the OutMsgDescr dictionary. + * + * @returns True if the outbound messages dictionary is valid, false otherwise. + */ bool ValidateQuery::check_out_msg_descr() { LOG(INFO) << "checking outbound messages listed in OutMsgDescr"; try { @@ -3828,7 +4303,12 @@ bool ValidateQuery::check_out_msg_descr() { return true; } -// compare to Collator::update_processed_upto() +/** + * Checks if the processed up to information is valid and consistent. + * Compare to Collator::update_processed_upto() + * + * @returns True if the processed up to information is valid and consistent, false otherwise. + */ bool ValidateQuery::check_processed_upto() { LOG(INFO) << "checking ProcessedInfo"; CHECK(ps_.processed_upto_); @@ -3884,7 +4364,18 @@ bool ValidateQuery::check_processed_upto() { return true; } -// similar to Collator::process_inbound_message +/** + * Checks the validity of an outbound message in the neighbor's queue. + * Similar to Collator::process_inbound_message. + * + * @param enq_msg The enqueued message to validate. + * @param lt The logical time of the message. + * @param key The 32+64+256-bit key of the message. + * @param nb The neighbor's description. + * @param unprocessed A boolean flag that will be set to true if the message is unprocessed, false otherwise. + * + * @returns True if the message is valid, false otherwise. + */ bool ValidateQuery::check_neighbor_outbound_message(Ref enq_msg, ton::LogicalTime lt, td::ConstBitPtr key, const block::McShardDescr& nb, bool& unprocessed) { @@ -4023,6 +4514,11 @@ bool ValidateQuery::check_neighbor_outbound_message(Ref enq_msg, return true; } +/** + * Checks messages from the outbound queues of the neighbors. + * + * @returns True if the messages are valid, false otherwise. + */ bool ValidateQuery::check_in_queue() { block::OutputQueueMerger nb_out_msgs(shard_, neighbors_); while (!nb_out_msgs.is_eof()) { @@ -4054,9 +4550,12 @@ bool ValidateQuery::check_in_queue() { return true; } -// checks that all messages imported from our outbound queue into neighbor shards have been dequeued -// similar to Collator::out_msg_queue_cleanup() -// (but scans new outbound queue instead of the old) +/** + * Checks that all messages imported from our outbound queue into neighbor shards have been dequeued + * Similar to Collator::out_msg_queue_cleanup() (but scans the new outbound queue instead of the old). + * + * @returns True if the delivery status of all messages has been checked successfully, false otherwise. + */ bool ValidateQuery::check_delivered_dequeued() { LOG(INFO) << "scanning new outbound queue and checking delivery status of all messages"; bool ok = false; @@ -4103,26 +4602,42 @@ bool ValidateQuery::check_delivered_dequeued() { }) || ok; } -// similar to Collator::make_account_from() -std::unique_ptr ValidateQuery::make_account_from(td::ConstBitPtr addr, Ref account, - Ref extra) { +/** + * Creates a new Account object from the given address and serialized account data. + * Creates a new Account if not found. + * Similar to Collator::make_account_from() + * + * @param addr A pointer to the 256-bit address of the account. + * @param account A cell slice with an account serialized using ShardAccount TLB-scheme. + * + * @returns A unique pointer to the created Account object, or nullptr if the creation failed. + */ +std::unique_ptr ValidateQuery::make_account_from(td::ConstBitPtr addr, Ref account) { auto ptr = std::make_unique(workchain(), addr); if (account.is_null()) { if (!ptr->init_new(now_)) { return nullptr; } - } else if (!ptr->unpack(std::move(account), std::move(extra), now_, - is_masterchain() && config_->is_special_smartcontract(addr))) { + } else if (!ptr->unpack(std::move(account), now_, is_masterchain() && config_->is_special_smartcontract(addr))) { return nullptr; } ptr->block_lt = start_lt_; return ptr; } -// similar to Collator::make_account() +/** + * Retreives an Account object from the data in the shard state. + * Accounts are cached in the ValidatorQuery's map. + * Similar to Collator::make_account() + * + * @param addr The 256-bit address of the account. + * + * @returns Pointer to the account if found or created successfully. + * Returns nullptr if an error occured. + */ std::unique_ptr ValidateQuery::unpack_account(td::ConstBitPtr addr) { auto dict_entry = ps_.account_dict_->lookup_extra(addr, 256); - auto new_acc = make_account_from(addr, std::move(dict_entry.first), std::move(dict_entry.second)); + auto new_acc = make_account_from(addr, std::move(dict_entry.first)); if (!new_acc) { reject_query("cannot load state of account "s + addr.to_hex(256) + " from previous shardchain state"); return {}; @@ -4135,6 +4650,18 @@ std::unique_ptr ValidateQuery::unpack_account(td::ConstBitPtr ad return new_acc; } +/** + * Checks the validity of a single transaction for a given account. + * Performs transaction execution. + * + * @param account The account of the transaction. + * @param lt The logical time of the transaction. + * @param trans_root The root of the transaction. + * @param is_first Flag indicating if this is the first transaction of the account. + * @param is_last Flag indicating if this is the last transaction of the account. + * + * @returns True if the transaction is valid, false otherwise. + */ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalTime lt, Ref trans_root, bool is_first, bool is_last) { if (!check_timeout()) { @@ -4598,7 +5125,15 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT return true; } -// NB: may be run in parallel for different accounts +/** + * Checks the validity of transactions for a given account block. + * NB: may be run in parallel for different accounts + * + * @param acc_addr The address of the account. + * @param acc_blk_root The root of the AccountBlock. + * + * @returns True if the account transactions are valid, false otherwise. + */ bool ValidateQuery::check_account_transactions(const StdSmcAddress& acc_addr, Ref acc_blk_root) { block::gen::AccountBlock::Record acc_blk; CHECK(tlb::csr_unpack(std::move(acc_blk_root), acc_blk) && acc_blk.account_addr == acc_addr); @@ -4630,6 +5165,11 @@ bool ValidateQuery::check_account_transactions(const StdSmcAddress& acc_addr, Re } } +/** + * Checks all transactions in the account blocks. + * + * @returns True if all transactions pass the check, False otherwise. + */ bool ValidateQuery::check_transactions() { LOG(INFO) << "checking all transactions"; return account_blocks_dict_->check_for_each_extra( @@ -4639,7 +5179,17 @@ bool ValidateQuery::check_transactions() { }); } -// similar to Collator::update_account_public_libraries() +/** + * Processes changes in libraries of an account. + * Used in masterchain validation. + * Similar to Collator::update_account_public_libraries() + * + * @param orig_libs The original libraries of the account. + * @param final_libs The final libraries of the account. + * @param addr The address of the account. + * + * @returns True if the update was successful, false otherwise. + */ bool ValidateQuery::scan_account_libraries(Ref orig_libs, Ref final_libs, const td::Bits256& addr) { vm::Dictionary dict1{std::move(orig_libs), 256}, dict2{std::move(final_libs), 256}; return dict1.scan_diff( @@ -4657,6 +5207,12 @@ bool ValidateQuery::scan_account_libraries(Ref orig_libs, Ref in_msg_root, const block::CurrencyCollection& amount, Ref addr_cell) { if (in_msg_root.is_null()) { @@ -4786,11 +5357,28 @@ bool ValidateQuery::check_special_message(Ref in_msg_root, const block return true; } +/** + * Checks if all necessary special messages are valid and exist in the incoming messages dictionary. + * Used in masterchain validation. + * + * @returns True if special messages are valid, false otherwise. + */ bool ValidateQuery::check_special_messages() { return check_special_message(recover_create_msg_, value_flow_.recovered, config_->get_config_param(3, 1)) && check_special_message(mint_msg_, value_flow_.minted, config_->get_config_param(2, 0)); } +/** + * Checks if an update of LibDescr of as single library update is valid. + * Compares updates in LibDescr against updates of account states. + * Used in masterchain validation. + * + * @param key The 256-bit key of the library. + * @param old_value The old value of the LibDescr + * @param new_value The new value of the LibDescr. + * + * @returns True if the library update is valid, false otherwise. + */ bool ValidateQuery::check_one_library_update(td::ConstBitPtr key, Ref old_value, Ref new_value) { // shared_lib_descr$00 lib:^Cell publishers:(Hashmap 256 True) = LibDescr; @@ -4841,6 +5429,12 @@ bool ValidateQuery::check_one_library_update(td::ConstBitPtr key, Refscan_diff( @@ -4861,6 +5455,11 @@ bool ValidateQuery::check_shard_libraries() { return true; } +/** + * Checks the validity of the new shard state. + * + * @returns True if the new state is valid, false otherwise. + */ bool ValidateQuery::check_new_state() { LOG(INFO) << "checking header of the new shardchain state"; block::gen::ShardStateUnsplit::Record info; @@ -4955,6 +5554,15 @@ bool ValidateQuery::check_new_state() { return true; } +/** + * Checks if a masterchain configuration update is valid. + * Used in masterchain validation. + * + * @param old_conf_params The old configuration parameters. + * @param new_conf_params The new configuration parameters. + * + * @returns True if the update is valid, false otherwise. + */ bool ValidateQuery::check_config_update(Ref old_conf_params, Ref new_conf_params) { if (!block::gen::t_ConfigParams.validate_csr(10000, new_conf_params)) { return reject_query("new configuration failed to pass automated validity checks"); @@ -5059,6 +5667,16 @@ bool ValidateQuery::check_config_update(Ref old_conf_params, Ref< "reason (the suggested configuration appears to be valid)"); } +/** + * Checks if a single entry in the dictionary of previous masterchain blocks is valid and consistent. + * Used in masterchain validation. + * + * @param seqno The sequence number of the entry. + * @param old_val_extra The old value of the entry. + * @param new_val_extra The new value of the entry. + * + * @returns True if the update is valid and consistent, false otherwise. + */ bool ValidateQuery::check_one_prev_dict_update(ton::BlockSeqno seqno, Ref old_val_extra, Ref new_val_extra) { if (old_val_extra.not_null() && new_val_extra.is_null()) { @@ -5113,7 +5731,13 @@ bool ValidateQuery::check_one_prev_dict_update(ton::BlockSeqno seqno, Ref old_val, Ref new_val) { LOG(DEBUG) << "checking update of CreatorStats for "s + key.to_hex(256); @@ -5365,7 +6009,13 @@ bool ValidateQuery::check_one_block_creator_update(td::ConstBitPtr key, Refget_shard_hash(shard); @@ -5433,6 +6093,12 @@ bool ValidateQuery::check_one_shard_fee(ShardIdFull shard, const block::Currency return true; } +/** + * Checks the validity of the McBlockExtra in a masterchain block. + * Used in masterchain validation. + * + * @returns True if the data is valid, false otherwise. + */ bool ValidateQuery::check_mc_block_extra() { if (!is_masterchain()) { return true; @@ -5484,6 +6150,11 @@ bool ValidateQuery::check_mc_block_extra() { return true; } +/** + * Validates the value flow of a block. + * + * @returns True if the value flow is valid, False otherwise. + */ bool ValidateQuery::postcheck_value_flow() { auto expected_fees = value_flow_.fees_imported + value_flow_.created + transaction_fees_ + import_fees_ - fees_burned_; @@ -5504,13 +6175,11 @@ bool ValidateQuery::postcheck_value_flow() { return true; } -/* - * - * MAIN VALIDATOR FUNCTION - * (invokes other methods in a suitable order) +/** + * MAIN VALIDATOR FUNCTION (invokes other methods in a suitable order). * + * @returns True if the validation is successful, False otherwise. */ - bool ValidateQuery::try_validate() { if (pending) { return true; @@ -5616,6 +6285,11 @@ bool ValidateQuery::try_validate() { return save_candidate(); } +/** + * Saves the candidate to disk. + * + * @returns True. + */ bool ValidateQuery::save_candidate() { auto P = td::PromiseCreator::lambda([SelfId = actor_id(this)](td::Result R) { if (R.is_error()) { @@ -5629,6 +6303,10 @@ bool ValidateQuery::save_candidate() { return true; } +/** + * Callback function called after saving block candidate. + * Finishes validation. + */ void ValidateQuery::written_candidate() { finish_query(); } diff --git a/validator/impl/validate-query.hpp b/validator/impl/validate-query.hpp index 7d15dcfe8..ff8cc83c8 100644 --- a/validator/impl/validate-query.hpp +++ b/validator/impl/validate-query.hpp @@ -342,8 +342,7 @@ class ValidateQuery : public td::actor::Actor { const block::McShardDescr& src_nb, bool& unprocessed); bool check_in_queue(); bool check_delivered_dequeued(); - std::unique_ptr make_account_from(td::ConstBitPtr addr, Ref account, - Ref extra); + std::unique_ptr make_account_from(td::ConstBitPtr addr, Ref account); std::unique_ptr unpack_account(td::ConstBitPtr addr); bool check_one_transaction(block::Account& account, LogicalTime lt, Ref trans_root, bool is_first, bool is_last);