mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Merge branch 'testnet' into block-generation
# Conflicts: # tonlib/tonlib/TonlibClient.cpp # validator-engine/validator-engine.hpp # validator/validator-options.hpp # validator/validator.h
This commit is contained in:
commit
2ee7cbc106
47 changed files with 1331 additions and 965 deletions
24
.github/workflows/create-release.yml
vendored
24
.github/workflows/create-release.yml
vendored
|
@ -191,6 +191,14 @@ jobs:
|
||||||
asset_name: tonlibjson.dll
|
asset_name: tonlibjson.dll
|
||||||
tag: ${{ steps.tag.outputs.TAG }}
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
|
- name: Upload Windows 2019 single artifact - libemulator
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: artifacts/ton-win-binaries/emulator.dll
|
||||||
|
asset_name: libemulator.dll
|
||||||
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
- name: Upload Windows 2019 single artifact - tonlib-cli
|
- name: Upload Windows 2019 single artifact - tonlib-cli
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -273,6 +281,14 @@ jobs:
|
||||||
asset_name: tonlibjson-mac-x86-64.dylib
|
asset_name: tonlibjson-mac-x86-64.dylib
|
||||||
tag: ${{ steps.tag.outputs.TAG }}
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
|
- name: Upload Mac x86-64 single artifact - libemulator
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: artifacts/ton-x86_64-macos-binaries/libemulator.dylib
|
||||||
|
asset_name: libemulator-mac-x86-64.dylib
|
||||||
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
- name: Upload Mac x86-64 single artifact - tonlib-cli
|
- name: Upload Mac x86-64 single artifact - tonlib-cli
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -355,6 +371,14 @@ jobs:
|
||||||
asset_name: tonlibjson-linux-x86_64.so
|
asset_name: tonlibjson-linux-x86_64.so
|
||||||
tag: ${{ steps.tag.outputs.TAG }}
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
|
- name: Upload Linux x86-64 single artifact - libemulator
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: artifacts/ton-x86_64-linux-binaries/libemulator.so
|
||||||
|
asset_name: libemulator-linux-x86_64.so
|
||||||
|
tag: ${{ steps.tag.outputs.TAG }}
|
||||||
|
|
||||||
- name: Upload Linux x86-64 single artifact - tonlib-cli
|
- name: Upload Linux x86-64 single artifact - tonlib-cli
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -182,7 +182,7 @@ pipeline {
|
||||||
timeout(time: 90, unit: 'MINUTES') {
|
timeout(time: 90, unit: 'MINUTES') {
|
||||||
bat '''
|
bat '''
|
||||||
copy assembly\\native\\build-windows.bat .
|
copy assembly\\native\\build-windows.bat .
|
||||||
build-windows.bat
|
build-windows.bat -t
|
||||||
'''
|
'''
|
||||||
bat '''
|
bat '''
|
||||||
cd artifacts
|
cd artifacts
|
||||||
|
|
|
@ -14,24 +14,26 @@ choco feature enable -n allowEmptyChecksums
|
||||||
|
|
||||||
echo Installing pkgconfiglite...
|
echo Installing pkgconfiglite...
|
||||||
choco install -y pkgconfiglite
|
choco install -y pkgconfiglite
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't install pkgconfiglite
|
echo Can't install pkgconfiglite
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
echo Installing ninja...
|
echo Installing ninja...
|
||||||
choco install -y ninja
|
choco install -y ninja
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't install ninja
|
echo Can't install ninja
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "zlib" (
|
if not exist "zlib" (
|
||||||
git clone https://github.com/madler/zlib.git
|
git clone https://github.com/madler/zlib.git
|
||||||
cd zlib\contrib\vstudio\vc14
|
cd zlib
|
||||||
|
git checkout v1.3.1
|
||||||
|
cd contrib\vstudio\vc14
|
||||||
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v143
|
msbuild zlibstat.vcxproj /p:Configuration=ReleaseWithoutAsm /p:platform=x64 -p:PlatformToolset=v143
|
||||||
|
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't install zlib
|
echo Can't install zlib
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -41,14 +43,20 @@ echo Using zlib...
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist "secp256k1" (
|
if not exist "secp256k1" (
|
||||||
git clone https://github.com/libbitcoin/secp256k1.git
|
git clone https://github.com/bitcoin-core/secp256k1.git
|
||||||
cd secp256k1\builds\msvc\vs2017
|
cd secp256k1
|
||||||
msbuild /p:Configuration=StaticRelease -p:PlatformToolset=v143 -p:Platform=x64
|
git checkout v0.3.2
|
||||||
IF errorlevel 1 (
|
cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DBUILD_SHARED_LIBS=OFF
|
||||||
|
IF %errorlevel% NEQ 0 (
|
||||||
|
echo Can't configure secp256k1
|
||||||
|
exit /b %errorlevel%
|
||||||
|
)
|
||||||
|
cmake --build build --config Release
|
||||||
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't install secp256k1
|
echo Can't install secp256k1
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
cd ..\..\..\..
|
cd ..
|
||||||
) else (
|
) else (
|
||||||
echo Using secp256k1...
|
echo Using secp256k1...
|
||||||
)
|
)
|
||||||
|
@ -56,7 +64,7 @@ echo Using secp256k1...
|
||||||
|
|
||||||
if not exist "libsodium" (
|
if not exist "libsodium" (
|
||||||
curl -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip
|
curl -Lo libsodium-1.0.18-stable-msvc.zip https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable-msvc.zip
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't download libsodium
|
echo Can't download libsodium
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -67,7 +75,7 @@ echo Using libsodium...
|
||||||
|
|
||||||
if not exist "openssl-3.1.4" (
|
if not exist "openssl-3.1.4" (
|
||||||
curl -Lo openssl-3.1.4.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-3.1.4.zip
|
curl -Lo openssl-3.1.4.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/openssl-3.1.4.zip
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't download OpenSSL
|
echo Can't download OpenSSL
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -78,7 +86,7 @@ echo Using openssl...
|
||||||
|
|
||||||
if not exist "libmicrohttpd-0.9.77-w32-bin" (
|
if not exist "libmicrohttpd-0.9.77-w32-bin" (
|
||||||
curl -Lo libmicrohttpd-0.9.77-w32-bin.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/libmicrohttpd-0.9.77-w32-bin.zip
|
curl -Lo libmicrohttpd-0.9.77-w32-bin.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/libmicrohttpd-0.9.77-w32-bin.zip
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't download libmicrohttpd
|
echo Can't download libmicrohttpd
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -89,7 +97,7 @@ echo Using libmicrohttpd...
|
||||||
|
|
||||||
if not exist "readline-5.0-1-lib" (
|
if not exist "readline-5.0-1-lib" (
|
||||||
curl -Lo readline-5.0-1-lib.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/readline-5.0-1-lib.zip
|
curl -Lo readline-5.0-1-lib.zip https://github.com/neodiX42/precompiled-openssl-win64/raw/main/readline-5.0-1-lib.zip
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't download readline
|
echo Can't download readline
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -110,7 +118,7 @@ cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^
|
||||||
-DSODIUM_USE_STATIC_LIBS=1 ^
|
-DSODIUM_USE_STATIC_LIBS=1 ^
|
||||||
-DSECP256K1_FOUND=1 ^
|
-DSECP256K1_FOUND=1 ^
|
||||||
-DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^
|
-DSECP256K1_INCLUDE_DIR=%root%\secp256k1\include ^
|
||||||
-DSECP256K1_LIBRARY=%root%\secp256k1\bin\x64\Release\v143\static\secp256k1.lib ^
|
-DSECP256K1_LIBRARY=%root%\secp256k1\build\src\Release\libsecp256k1.lib ^
|
||||||
-DMHD_FOUND=1 ^
|
-DMHD_FOUND=1 ^
|
||||||
-DMHD_LIBRARY=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static\libmicrohttpd.lib ^
|
-DMHD_LIBRARY=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static\libmicrohttpd.lib ^
|
||||||
-DMHD_INCLUDE_DIR=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static ^
|
-DMHD_INCLUDE_DIR=%root%\libmicrohttpd-0.9.77-w32-bin\x86_64\VS2019\Release-static ^
|
||||||
|
@ -118,10 +126,12 @@ cmake -GNinja -DCMAKE_BUILD_TYPE=Release ^
|
||||||
-DZLIB_INCLUDE_DIR=%root%\zlib ^
|
-DZLIB_INCLUDE_DIR=%root%\zlib ^
|
||||||
-DZLIB_LIBRARIES=%root%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
|
-DZLIB_LIBRARIES=%root%\zlib\contrib\vstudio\vc14\x64\ZlibStatReleaseWithoutAsm\zlibstat.lib ^
|
||||||
-DOPENSSL_FOUND=1 ^
|
-DOPENSSL_FOUND=1 ^
|
||||||
-DOPENSSL_INCLUDE_DIR=%root%/openssl-3.1.4/x64/include ^
|
-DOPENSSL_INCLUDE_DIR=%root%\openssl-3.1.4\x64\include ^
|
||||||
-DOPENSSL_CRYPTO_LIBRARY=%root%/openssl-3.1.4/x64/lib/libcrypto_static.lib ^
|
-DOPENSSL_CRYPTO_LIBRARY=%root%\openssl-3.1.4\x64\lib\libcrypto_static.lib ^
|
||||||
|
-DREADLINE_INCLUDE_DIR=%root%\readline-5.0-1-lib\include ^
|
||||||
|
-DREADLINE_LIBRARY=%root%\readline-5.0-1-lib\lib\readline.lib ^
|
||||||
-DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj" ..
|
-DCMAKE_CXX_FLAGS="/DTD_WINDOWS=1 /EHsc /bigobj" ..
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't configure TON
|
echo Can't configure TON
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -133,7 +143,7 @@ json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-ha
|
||||||
test-ed25519 test-ed25519-crypto test-bigint test-vm test-fift test-cells test-smartcont test-net ^
|
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-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
|
||||||
test-fec test-tddb test-db test-validator-session-state
|
test-fec test-tddb test-db test-validator-session-state
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't compile TON
|
echo Can't compile TON
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -141,14 +151,14 @@ IF errorlevel 1 (
|
||||||
ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tonlib tonlibjson ^
|
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 ^
|
tonlib-cli validator-engine lite-client pow-miner validator-engine-console generate-random-id ^
|
||||||
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator
|
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Can't compile TON
|
echo Can't compile TON
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
copy validator-engine\validator-engine.exe test
|
copy validator-engine\validator-engine.exe test
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo validator-engine.exe does not exist
|
echo validator-engine.exe does not exist
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
@ -156,8 +166,8 @@ IF errorlevel 1 (
|
||||||
IF "%1"=="-t" (
|
IF "%1"=="-t" (
|
||||||
echo Running tests...
|
echo Running tests...
|
||||||
REM ctest -C Release --output-on-failure -E "test-catchain|test-actors|test-validator-session-state"
|
REM ctest -C Release --output-on-failure -E "test-catchain|test-actors|test-validator-session-state"
|
||||||
ctest -C Release --output-on-failure --timeout 1800
|
ctest -C Release --output-on-failure -E "test-bigint" --timeout 1800
|
||||||
IF errorlevel 1 (
|
IF %errorlevel% NEQ 0 (
|
||||||
echo Some tests failed
|
echo Some tests failed
|
||||||
exit /b %errorlevel%
|
exit /b %errorlevel%
|
||||||
)
|
)
|
||||||
|
|
|
@ -174,7 +174,9 @@ td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args, td::Ref<vm::Cell> cod
|
||||||
if (args.config && args.config.value()->get_global_version() >= 6) {
|
if (args.config && args.config.value()->get_global_version() >= 6) {
|
||||||
tuple.push_back(args.config.value()->get_unpacked_config_tuple(now)); // unpacked_config_tuple
|
tuple.push_back(args.config.value()->get_unpacked_config_tuple(now)); // unpacked_config_tuple
|
||||||
tuple.push_back(td::zero_refint()); // due_payment
|
tuple.push_back(td::zero_refint()); // due_payment
|
||||||
tuple.push_back(vm::StackEntry()); // precompiled_gas_usage:Integer
|
// precomiled_gas_usage:(Maybe Integer)
|
||||||
|
auto precompiled = args.config.value()->get_precompiled_contracts_config().get_contract(code->get_hash().bits());
|
||||||
|
tuple.push_back(precompiled ? td::make_refint(precompiled.value().gas_usage) : vm::StackEntry());
|
||||||
}
|
}
|
||||||
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
||||||
//LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
//LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();
|
||||||
|
|
|
@ -71,7 +71,7 @@ void WalletInterface::store_gift_message(vm::CellBuilder &cb, const Gift &gift)
|
||||||
|
|
||||||
cb.store_zeroes(1);
|
cb.store_zeroes(1);
|
||||||
if (gift.is_encrypted) {
|
if (gift.is_encrypted) {
|
||||||
cb.store_long(0x2167da4b, 32);
|
cb.store_long(EncryptedCommentOp, 32);
|
||||||
} else {
|
} else {
|
||||||
cb.store_long(0, 32);
|
cb.store_long(0, 32);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
namespace ton {
|
namespace ton {
|
||||||
class WalletInterface : public SmartContract {
|
class WalletInterface : public SmartContract {
|
||||||
public:
|
public:
|
||||||
|
static constexpr uint32_t EncryptedCommentOp = 0x2167da4b;
|
||||||
struct Gift {
|
struct Gift {
|
||||||
block::StdAddress destination;
|
block::StdAddress destination;
|
||||||
td::int64 gramms;
|
td::int64 gramms;
|
||||||
|
|
|
@ -543,6 +543,66 @@ const char *tvm_emulator_run_get_method(void *tvm_emulator, int method_id, const
|
||||||
return strdup(jb.string_builder().as_cslice().c_str());
|
return strdup(jb.string_builder().as_cslice().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *tvm_emulator_emulate_run_method(uint32_t len, const char *params_boc, int64_t gas_limit) {
|
||||||
|
auto params_cell = vm::std_boc_deserialize(td::Slice(params_boc, len));
|
||||||
|
if (params_cell.is_error()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto params_cs = vm::load_cell_slice(params_cell.move_as_ok());
|
||||||
|
auto code = params_cs.fetch_ref();
|
||||||
|
auto data = params_cs.fetch_ref();
|
||||||
|
|
||||||
|
auto stack_cs = vm::load_cell_slice(params_cs.fetch_ref());
|
||||||
|
auto params = vm::load_cell_slice(params_cs.fetch_ref());
|
||||||
|
auto c7_cs = vm::load_cell_slice(params.fetch_ref());
|
||||||
|
auto libs = vm::Dictionary(params.fetch_ref(), 256);
|
||||||
|
|
||||||
|
auto method_id = params_cs.fetch_long(32);
|
||||||
|
|
||||||
|
td::Ref<vm::Stack> stack;
|
||||||
|
if (!vm::Stack::deserialize_to(stack_cs, stack)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
td::Ref<vm::Stack> c7;
|
||||||
|
if (!vm::Stack::deserialize_to(c7_cs, c7)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto emulator = new emulator::TvmEmulator(code, data);
|
||||||
|
emulator->set_vm_verbosity_level(0);
|
||||||
|
emulator->set_gas_limit(gas_limit);
|
||||||
|
emulator->set_c7_raw(c7->fetch(0).as_tuple());
|
||||||
|
if (libs.is_empty()) {
|
||||||
|
emulator->set_libraries(std::move(libs));
|
||||||
|
}
|
||||||
|
auto result = emulator->run_get_method(int(method_id), stack);
|
||||||
|
delete emulator;
|
||||||
|
|
||||||
|
vm::CellBuilder stack_cb;
|
||||||
|
if (!result.stack->serialize(stack_cb)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::CellBuilder cb;
|
||||||
|
cb.store_long(result.code, 32);
|
||||||
|
cb.store_long(result.gas_used, 64);
|
||||||
|
cb.store_ref(stack_cb.finalize());
|
||||||
|
|
||||||
|
auto ser = vm::std_boc_serialize(cb.finalize());
|
||||||
|
if (!ser.is_ok()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto sok = ser.move_as_ok();
|
||||||
|
|
||||||
|
auto sz = uint32_t(sok.size());
|
||||||
|
char* rn = (char*)malloc(sz + 4);
|
||||||
|
memcpy(rn, &sz, 4);
|
||||||
|
memcpy(rn+4, sok.data(), sz);
|
||||||
|
|
||||||
|
return rn;
|
||||||
|
}
|
||||||
|
|
||||||
const char *tvm_emulator_send_external_message(void *tvm_emulator, const char *message_body_boc) {
|
const char *tvm_emulator_send_external_message(void *tvm_emulator, const char *message_body_boc) {
|
||||||
auto message_body_cell = boc_b64_to_cell(message_body_boc);
|
auto message_body_cell = boc_b64_to_cell(message_body_boc);
|
||||||
if (message_body_cell.is_error()) {
|
if (message_body_cell.is_error()) {
|
||||||
|
|
|
@ -213,6 +213,16 @@ EMULATOR_EXPORT bool tvm_emulator_set_debug_enabled(void *tvm_emulator, bool deb
|
||||||
*/
|
*/
|
||||||
EMULATOR_EXPORT const char *tvm_emulator_run_get_method(void *tvm_emulator, int method_id, const char *stack_boc);
|
EMULATOR_EXPORT const char *tvm_emulator_run_get_method(void *tvm_emulator, int method_id, const char *stack_boc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Optimized version of "run get method" with all passed parameters in a single call
|
||||||
|
* @param len Length of params_boc buffer
|
||||||
|
* @param params_boc BoC serialized parameters, scheme: request$_ code:^Cell data:^Cell stack:^VmStack params:^[c7:^VmStack libs:^Cell] method_id:(## 32)
|
||||||
|
* @param gas_limit Gas limit
|
||||||
|
* @return Char* with first 4 bytes defining length, and the rest BoC serialized result
|
||||||
|
* Scheme: result$_ exit_code:(## 32) gas_used:(## 32) stack:^VmStack
|
||||||
|
*/
|
||||||
|
EMULATOR_EXPORT const char *tvm_emulator_emulate_run_method(uint32_t len, const char *params_boc, int64_t gas_limit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send external message
|
* @brief Send external message
|
||||||
* @param tvm_emulator Pointer to TVM emulator
|
* @param tvm_emulator Pointer to TVM emulator
|
||||||
|
|
|
@ -21,3 +21,4 @@ _tvm_emulator_run_get_method
|
||||||
_tvm_emulator_send_external_message
|
_tvm_emulator_send_external_message
|
||||||
_tvm_emulator_send_internal_message
|
_tvm_emulator_send_internal_message
|
||||||
_tvm_emulator_destroy
|
_tvm_emulator_destroy
|
||||||
|
_tvm_emulator_emulate_run_method
|
||||||
|
|
|
@ -33,6 +33,10 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_c7_raw(td::Ref<vm::Tuple> c7) {
|
||||||
|
args_.set_c7(std::move(c7));
|
||||||
|
}
|
||||||
|
|
||||||
void set_prev_blocks_info(td::Ref<vm::Tuple> tuple) {
|
void set_prev_blocks_info(td::Ref<vm::Tuple> tuple) {
|
||||||
args_.set_prev_blocks_info(std::move(tuple));
|
args_.set_prev_blocks_info(std::move(tuple));
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,8 @@ RocksDb RocksDb::clone() const {
|
||||||
return RocksDb{db_, statistics_};
|
return RocksDb{db_, statistics_};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<RocksDb> RocksDb::open(std::string path) {
|
Result<RocksDb> RocksDb::open(std::string path, std::shared_ptr<rocksdb::Statistics> statistics) {
|
||||||
rocksdb::OptimisticTransactionDB *db;
|
rocksdb::OptimisticTransactionDB *db;
|
||||||
auto statistics = rocksdb::CreateDBStatistics();
|
|
||||||
{
|
{
|
||||||
rocksdb::Options options;
|
rocksdb::Options options;
|
||||||
|
|
||||||
|
@ -94,6 +93,18 @@ Result<RocksDb> RocksDb::open(std::string path) {
|
||||||
return RocksDb(std::shared_ptr<rocksdb::OptimisticTransactionDB>(db), std::move(statistics));
|
return RocksDb(std::shared_ptr<rocksdb::OptimisticTransactionDB>(db), std::move(statistics));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<rocksdb::Statistics> RocksDb::create_statistics() {
|
||||||
|
return rocksdb::CreateDBStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RocksDb::statistics_to_string(const std::shared_ptr<rocksdb::Statistics> statistics) {
|
||||||
|
return statistics->ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RocksDb::reset_statistics(const std::shared_ptr<rocksdb::Statistics> statistics) {
|
||||||
|
statistics->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<KeyValueReader> RocksDb::snapshot() {
|
std::unique_ptr<KeyValueReader> RocksDb::snapshot() {
|
||||||
auto res = std::make_unique<RocksDb>(clone());
|
auto res = std::make_unique<RocksDb>(clone());
|
||||||
res->begin_snapshot().ensure();
|
res->begin_snapshot().ensure();
|
||||||
|
|
|
@ -38,7 +38,7 @@ class RocksDb : public KeyValue {
|
||||||
public:
|
public:
|
||||||
static Status destroy(Slice path);
|
static Status destroy(Slice path);
|
||||||
RocksDb clone() const;
|
RocksDb clone() const;
|
||||||
static Result<RocksDb> open(std::string path);
|
static Result<RocksDb> open(std::string path, std::shared_ptr<rocksdb::Statistics> statistics = nullptr);
|
||||||
|
|
||||||
Result<GetStatus> get(Slice key, std::string &value) override;
|
Result<GetStatus> get(Slice key, std::string &value) override;
|
||||||
Status set(Slice key, Slice value) override;
|
Status set(Slice key, Slice value) override;
|
||||||
|
@ -60,6 +60,10 @@ class RocksDb : public KeyValue {
|
||||||
std::unique_ptr<KeyValueReader> snapshot() override;
|
std::unique_ptr<KeyValueReader> snapshot() override;
|
||||||
std::string stats() const override;
|
std::string stats() const override;
|
||||||
|
|
||||||
|
static std::shared_ptr<rocksdb::Statistics> create_statistics();
|
||||||
|
static std::string statistics_to_string(const std::shared_ptr<rocksdb::Statistics> statistics);
|
||||||
|
static void reset_statistics(const std::shared_ptr<rocksdb::Statistics> statistics);
|
||||||
|
|
||||||
RocksDb(RocksDb &&);
|
RocksDb(RocksDb &&);
|
||||||
RocksDb &operator=(RocksDb &&);
|
RocksDb &operator=(RocksDb &&);
|
||||||
~RocksDb();
|
~RocksDb();
|
||||||
|
|
|
@ -153,9 +153,9 @@ string buffer_to_hex(Slice buffer) {
|
||||||
const char *hex = "0123456789ABCDEF";
|
const char *hex = "0123456789ABCDEF";
|
||||||
string res(2 * buffer.size(), '\0');
|
string res(2 * buffer.size(), '\0');
|
||||||
for (std::size_t i = 0; i < buffer.size(); i++) {
|
for (std::size_t i = 0; i < buffer.size(); i++) {
|
||||||
auto c = buffer.ubegin()[i];
|
unsigned char c = buffer[i];
|
||||||
res[2 * i] = hex[c & 15];
|
res[2 * i] = hex[c >> 4];
|
||||||
res[2 * i + 1] = hex[c >> 4];
|
res[2 * i + 1] = hex[c & 15];
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
abce
|
abce
|
||||||
Test_Bigint_main_default 76f38492ec19464a1d0eac51d389023a31ce10396b3894061361d159567ce8cd
|
Test_Bigint_main_default 76f38492ec19464a1d0eac51d389023a31ce10396b3894061361d159567ce8cd
|
||||||
Test_Bitstrings_main_default a8b08af3116923c4c2a14e138d168375abd0c059f2f780d3267b294929a1110e
|
Test_Bitstrings_main_default a8b08af3116923c4c2a14e138d168375abd0c059f2f780d3267b294929a1110e
|
||||||
Test_Cells_simple_default 832502642fe4fe5db70de82681aedb7d54d7f3530e0069861fff405fe6f6cf23
|
Test_Cells_simple_default 414f68da0a2f6fa09b2bdb99c453cdf919db48b5b4ca1c6ac1dfcd837e2d8170
|
||||||
Test_Fift_bug_div_default 1ac42861ce96b2896001c587f65e9afe1617db48859f19c2f4e3063a20ea60b0
|
Test_Fift_bug_div_default 1ac42861ce96b2896001c587f65e9afe1617db48859f19c2f4e3063a20ea60b0
|
||||||
Test_Fift_bug_newlize_default e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
Test_Fift_bug_newlize_default e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
||||||
Test_Fift_bug_ufits_default 51bf5a9f1ed7633a193f6fdd17a7a3af8e032dfe72a9669c85e8639aa8a7c195
|
Test_Fift_bug_ufits_default 51bf5a9f1ed7633a193f6fdd17a7a3af8e032dfe72a9669c85e8639aa8a7c195
|
||||||
|
|
|
@ -53,8 +53,10 @@ liteServer.partialBlockProof complete:Bool from:tonNode.blockIdExt to:tonNode.bl
|
||||||
liteServer.configInfo mode:# id:tonNode.blockIdExt state_proof:bytes config_proof:bytes = liteServer.ConfigInfo;
|
liteServer.configInfo mode:# id:tonNode.blockIdExt state_proof:bytes config_proof:bytes = liteServer.ConfigInfo;
|
||||||
liteServer.validatorStats mode:# id:tonNode.blockIdExt count:int complete:Bool state_proof:bytes data_proof:bytes = liteServer.ValidatorStats;
|
liteServer.validatorStats mode:# id:tonNode.blockIdExt count:int complete:Bool state_proof:bytes data_proof:bytes = liteServer.ValidatorStats;
|
||||||
liteServer.libraryResult result:(vector liteServer.libraryEntry) = liteServer.LibraryResult;
|
liteServer.libraryResult result:(vector liteServer.libraryEntry) = liteServer.LibraryResult;
|
||||||
|
liteServer.libraryResultWithProof id:tonNode.blockIdExt mode:# result:(vector liteServer.libraryEntry) state_proof:bytes data_proof:bytes = liteServer.LibraryResultWithProof;
|
||||||
liteServer.shardBlockLink id:tonNode.blockIdExt proof:bytes = liteServer.ShardBlockLink;
|
liteServer.shardBlockLink id:tonNode.blockIdExt proof:bytes = liteServer.ShardBlockLink;
|
||||||
liteServer.shardBlockProof masterchain_id:tonNode.blockIdExt links:(vector liteServer.shardBlockLink) = liteServer.ShardBlockProof;
|
liteServer.shardBlockProof masterchain_id:tonNode.blockIdExt links:(vector liteServer.shardBlockLink) = liteServer.ShardBlockProof;
|
||||||
|
liteServer.lookupBlockResult id:tonNode.blockIdExt mode:# mc_block_id:tonNode.blockIdExt client_mc_state_proof:bytes mc_block_proof:bytes shard_links:(vector liteServer.shardBlockLink) header:bytes prev_header:bytes = liteServer.LookupBlockResult;
|
||||||
|
|
||||||
liteServer.debug.verbosity value:int = liteServer.debug.Verbosity;
|
liteServer.debug.verbosity value:int = liteServer.debug.Verbosity;
|
||||||
|
|
||||||
|
@ -76,6 +78,7 @@ liteServer.getAllShardsInfo id:tonNode.blockIdExt = liteServer.AllShardsInfo;
|
||||||
liteServer.getOneTransaction id:tonNode.blockIdExt account:liteServer.accountId lt:long = liteServer.TransactionInfo;
|
liteServer.getOneTransaction id:tonNode.blockIdExt account:liteServer.accountId lt:long = liteServer.TransactionInfo;
|
||||||
liteServer.getTransactions count:# account:liteServer.accountId lt:long hash:int256 = liteServer.TransactionList;
|
liteServer.getTransactions count:# account:liteServer.accountId lt:long hash:int256 = liteServer.TransactionList;
|
||||||
liteServer.lookupBlock mode:# id:tonNode.blockId lt:mode.1?long utime:mode.2?int = liteServer.BlockHeader;
|
liteServer.lookupBlock mode:# id:tonNode.blockId lt:mode.1?long utime:mode.2?int = liteServer.BlockHeader;
|
||||||
|
liteServer.lookupBlockWithProof mode:# id:tonNode.blockId mc_block_id:tonNode.blockIdExt lt:mode.1?long utime:mode.2?int = liteServer.LookupBlockResult;
|
||||||
liteServer.listBlockTransactions id:tonNode.blockIdExt mode:# count:# after:mode.7?liteServer.transactionId3 reverse_order:mode.6?true want_proof:mode.5?true = liteServer.BlockTransactions;
|
liteServer.listBlockTransactions id:tonNode.blockIdExt mode:# count:# after:mode.7?liteServer.transactionId3 reverse_order:mode.6?true want_proof:mode.5?true = liteServer.BlockTransactions;
|
||||||
liteServer.listBlockTransactionsExt id:tonNode.blockIdExt mode:# count:# after:mode.7?liteServer.transactionId3 reverse_order:mode.6?true want_proof:mode.5?true = liteServer.BlockTransactionsExt;
|
liteServer.listBlockTransactionsExt id:tonNode.blockIdExt mode:# count:# after:mode.7?liteServer.transactionId3 reverse_order:mode.6?true want_proof:mode.5?true = liteServer.BlockTransactionsExt;
|
||||||
liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
|
liteServer.getBlockProof mode:# known_block:tonNode.blockIdExt target_block:mode.0?tonNode.blockIdExt = liteServer.PartialBlockProof;
|
||||||
|
@ -83,6 +86,7 @@ liteServer.getConfigAll mode:# id:tonNode.blockIdExt = liteServer.ConfigInfo;
|
||||||
liteServer.getConfigParams mode:# id:tonNode.blockIdExt param_list:(vector int) = liteServer.ConfigInfo;
|
liteServer.getConfigParams mode:# id:tonNode.blockIdExt param_list:(vector int) = liteServer.ConfigInfo;
|
||||||
liteServer.getValidatorStats#091a58bc mode:# id:tonNode.blockIdExt limit:int start_after:mode.0?int256 modified_after:mode.2?int = liteServer.ValidatorStats;
|
liteServer.getValidatorStats#091a58bc mode:# id:tonNode.blockIdExt limit:int start_after:mode.0?int256 modified_after:mode.2?int = liteServer.ValidatorStats;
|
||||||
liteServer.getLibraries library_list:(vector int256) = liteServer.LibraryResult;
|
liteServer.getLibraries library_list:(vector int256) = liteServer.LibraryResult;
|
||||||
|
liteServer.getLibrariesWithProof id:tonNode.blockIdExt mode:# library_list:(vector int256) = liteServer.LibraryResultWithProof;
|
||||||
liteServer.getShardBlockProof id:tonNode.blockIdExt = liteServer.ShardBlockProof;
|
liteServer.getShardBlockProof id:tonNode.blockIdExt = liteServer.ShardBlockProof;
|
||||||
|
|
||||||
liteServer.queryPrefix = Object;
|
liteServer.queryPrefix = Object;
|
||||||
|
|
Binary file not shown.
|
@ -83,7 +83,7 @@ using namespace tonlib;
|
||||||
TEST(Tonlib, PublicKey) {
|
TEST(Tonlib, PublicKey) {
|
||||||
block::PublicKey::parse("pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").ensure_error();
|
block::PublicKey::parse("pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").ensure_error();
|
||||||
auto key = block::PublicKey::parse("Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").move_as_ok();
|
auto key = block::PublicKey::parse("Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2").move_as_ok();
|
||||||
CHECK(td::buffer_to_hex(key.key) == "3EE9DC0A7A0B6CA01770CE34698792BD8ECB53A6949BFD6C81B6E3CA475B74D7");
|
CHECK(td::buffer_to_hex(key.key) == "E39ECDA0A7B0C60A7107EC43967829DBE8BC356A49B9DFC6186B3EAC74B5477D");
|
||||||
CHECK(key.serialize() == "Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2");
|
CHECK(key.serialize() == "Pubjns2gp7DGCnEH7EOWeCnb6Lw1akm538YYaz6sdLVHfRB2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
#include "CellString.h"
|
|
||||||
#include "td/utils/misc.h"
|
|
||||||
|
|
||||||
#include "vm/cells/CellSlice.h"
|
|
||||||
|
|
||||||
namespace vm {
|
|
||||||
td::Status CellString::store(CellBuilder &cb, td::Slice slice, unsigned int top_bits) {
|
|
||||||
td::uint32 size = td::narrow_cast<td::uint32>(slice.size() * 8);
|
|
||||||
return store(cb, td::BitSlice(slice.ubegin(), size), top_bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Status CellString::store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits) {
|
|
||||||
if (slice.size() > max_bytes * 8) {
|
|
||||||
return td::Status::Error("String is too long (1)");
|
|
||||||
}
|
|
||||||
unsigned int head = td::min(slice.size(), td::min(cb.remaining_bits(), top_bits)) / 8 * 8;
|
|
||||||
auto max_bits = vm::Cell::max_bits / 8 * 8;
|
|
||||||
auto depth = 1 + (slice.size() - head + max_bits - 1) / max_bits;
|
|
||||||
if (depth > max_chain_length) {
|
|
||||||
return td::Status::Error("String is too long (2)");
|
|
||||||
}
|
|
||||||
cb.append_bitslice(slice.subslice(0, head));
|
|
||||||
slice.advance(head);
|
|
||||||
if (slice.size() == 0) {
|
|
||||||
return td::Status::OK();
|
|
||||||
}
|
|
||||||
CellBuilder child_cb;
|
|
||||||
store(child_cb, std::move(slice));
|
|
||||||
cb.store_ref(child_cb.finalize());
|
|
||||||
return td::Status::OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class F>
|
|
||||||
void CellString::for_each(F &&f, CellSlice &cs, unsigned int top_bits) {
|
|
||||||
unsigned int head = td::min(cs.size(), top_bits);
|
|
||||||
f(cs.prefetch_bits(head));
|
|
||||||
if (!cs.have_refs()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto ref = cs.prefetch_ref();
|
|
||||||
while (true) {
|
|
||||||
auto cs = vm::load_cell_slice(ref);
|
|
||||||
f(cs.prefetch_bits(cs.size()));
|
|
||||||
if (!cs.have_refs()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ref = cs.prefetch_ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Result<td::string> CellString::load(CellSlice &cs, unsigned int top_bits) {
|
|
||||||
unsigned int size = 0;
|
|
||||||
for_each([&](auto slice) { size += slice.size(); }, cs, top_bits);
|
|
||||||
if (size % 8 != 0) {
|
|
||||||
return td::Status::Error("Size is not divisible by 8");
|
|
||||||
}
|
|
||||||
std::string res(size / 8, 0);
|
|
||||||
|
|
||||||
td::BitPtr to(td::MutableSlice(res).ubegin());
|
|
||||||
for_each([&](auto slice) { to.concat(slice); }, cs, top_bits);
|
|
||||||
CHECK(to.offs == (int)size);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
} // namespace vm
|
|
|
@ -1,22 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "td/utils/Status.h"
|
|
||||||
|
|
||||||
#include "vm/cells/CellBuilder.h"
|
|
||||||
|
|
||||||
namespace vm {
|
|
||||||
class CellString {
|
|
||||||
public:
|
|
||||||
static constexpr unsigned int max_bytes = 1024;
|
|
||||||
static constexpr unsigned int max_chain_length = 16;
|
|
||||||
|
|
||||||
static td::Status store(CellBuilder &cb, td::Slice slice, unsigned int top_bits = Cell::max_bits);
|
|
||||||
static td::Status store(CellBuilder &cb, td::BitSlice slice, unsigned int top_bits = Cell::max_bits);
|
|
||||||
static td::Result<td::string> load(CellSlice &cs, unsigned int top_bits = Cell::max_bits);
|
|
||||||
|
|
||||||
private:
|
|
||||||
template <class F>
|
|
||||||
static void for_each(F &&f, CellSlice &cs, unsigned int top_bits = Cell::max_bits);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace vm
|
|
|
@ -1,18 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2020 Telegram Systems LLP
|
|
||||||
*/
|
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2020 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "tonlib/TonlibCallback.h"
|
|
||||||
#include "tonlib/TonlibClient.h"
|
|
||||||
#include "auto/tl/tonlib_api.h"
|
|
||||||
|
|
||||||
namespace tonlinb {
|
|
||||||
class ClientActor : public td::actor::Actor {
|
|
||||||
public:
|
|
||||||
explicit ClientActor(td::unique_ptr<TonlibCallback> callback);
|
|
||||||
void request(td::uint64 id, tonlib_api::object_ptr<tonlib_api::Function> request);
|
|
||||||
static tonlib_api::object_ptr<tonlib_api::Object> execute(tonlib_api::object_ptr<tonlib_api::Function> request);
|
|
||||||
~ClientActor();
|
|
||||||
ClientActor(ClientActor&& other);
|
|
||||||
ClientActor& operator=(ClientActor&& other);
|
|
||||||
|
|
||||||
ClientActor(const ClientActor& other) = delete;
|
|
||||||
ClientActor& operator=(const ClientActor& other) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
td::actor::ActorOwn<TonlibClient> tonlib_;
|
|
||||||
};
|
|
||||||
} // namespace tonlinb
|
|
|
@ -1,80 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#include "tonlib/GenericAccount.h"
|
|
||||||
#include "tonlib/utils.h"
|
|
||||||
#include "block/block-auto.h"
|
|
||||||
namespace tonlib {
|
|
||||||
td::Ref<vm::Cell> GenericAccount::get_init_state(td::Ref<vm::Cell> code, td::Ref<vm::Cell> data) noexcept {
|
|
||||||
return vm::CellBuilder()
|
|
||||||
.append_cellslice(binary_bitstring_to_cellslice("b{00110}").move_as_ok())
|
|
||||||
.store_ref(std::move(code))
|
|
||||||
.store_ref(std::move(data))
|
|
||||||
.finalize();
|
|
||||||
}
|
|
||||||
block::StdAddress GenericAccount::get_address(ton::WorkchainId workchain_id,
|
|
||||||
const td::Ref<vm::Cell>& init_state) noexcept {
|
|
||||||
return block::StdAddress(workchain_id, init_state->get_hash().bits(), true /*bounce*/);
|
|
||||||
}
|
|
||||||
td::Ref<vm::Cell> GenericAccount::create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
|
|
||||||
td::Ref<vm::Cell> body) noexcept {
|
|
||||||
block::gen::Message::Record message;
|
|
||||||
/*info*/ {
|
|
||||||
block::gen::CommonMsgInfo::Record_ext_in_msg_info info;
|
|
||||||
/* src */
|
|
||||||
tlb::csr_pack(info.src, block::gen::MsgAddressExt::Record_addr_none{});
|
|
||||||
/* dest */ {
|
|
||||||
block::gen::MsgAddressInt::Record_addr_std dest;
|
|
||||||
dest.anycast = vm::CellBuilder().store_zeroes(1).as_cellslice_ref();
|
|
||||||
dest.workchain_id = address.workchain;
|
|
||||||
dest.address = address.addr;
|
|
||||||
|
|
||||||
tlb::csr_pack(info.dest, dest);
|
|
||||||
}
|
|
||||||
/* import_fee */ {
|
|
||||||
vm::CellBuilder cb;
|
|
||||||
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(0));
|
|
||||||
info.import_fee = cb.as_cellslice_ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
tlb::csr_pack(message.info, info);
|
|
||||||
}
|
|
||||||
/* init */ {
|
|
||||||
if (new_state.not_null()) {
|
|
||||||
// Just(Left(new_state))
|
|
||||||
message.init = vm::CellBuilder()
|
|
||||||
.store_ones(1)
|
|
||||||
.store_zeroes(1)
|
|
||||||
.append_cellslice(vm::load_cell_slice(new_state))
|
|
||||||
.as_cellslice_ref();
|
|
||||||
} else {
|
|
||||||
message.init = vm::CellBuilder().store_zeroes(1).as_cellslice_ref();
|
|
||||||
CHECK(message.init.not_null());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* body */ {
|
|
||||||
message.body = vm::CellBuilder().store_zeroes(1).append_cellslice(vm::load_cell_slice_ref(body)).as_cellslice_ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> res;
|
|
||||||
tlb::type_pack_cell(res, block::gen::t_Message_Any, message);
|
|
||||||
CHECK(res.not_null());
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
} // namespace tonlib
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include "vm/cells.h"
|
|
||||||
#include "block/block.h"
|
|
||||||
namespace tonlib {
|
|
||||||
class GenericAccount {
|
|
||||||
public:
|
|
||||||
static td::Ref<vm::Cell> get_init_state(td::Ref<vm::Cell> code, td::Ref<vm::Cell> data) noexcept;
|
|
||||||
static block::StdAddress get_address(ton::WorkchainId workchain_id, const td::Ref<vm::Cell>& init_state) noexcept;
|
|
||||||
static td::Ref<vm::Cell> create_ext_message(const block::StdAddress& address, td::Ref<vm::Cell> new_state,
|
|
||||||
td::Ref<vm::Cell> body) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace tonlib
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "td/utils/port/path.h"
|
#include "td/utils/port/path.h"
|
||||||
#include "td/utils/PathView.h"
|
#include "td/utils/PathView.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
@ -42,7 +43,11 @@ class KeyValueDir : public KeyValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status add(td::Slice key, td::Slice value) override {
|
td::Status add(td::Slice key, td::Slice value) override {
|
||||||
auto path = to_file_path(key.str());
|
auto key_str = key.str();
|
||||||
|
if (!is_valid_key(key_str)) {
|
||||||
|
return td::Status::Error("Invalid key");
|
||||||
|
}
|
||||||
|
auto path = to_file_path(key_str);
|
||||||
if (td::stat(path).is_ok()) {
|
if (td::stat(path).is_ok()) {
|
||||||
return td::Status::Error(PSLICE() << "File " << path << "already exists");
|
return td::Status::Error(PSLICE() << "File " << path << "already exists");
|
||||||
}
|
}
|
||||||
|
@ -50,15 +55,27 @@ class KeyValueDir : public KeyValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status set(td::Slice key, td::Slice value) override {
|
td::Status set(td::Slice key, td::Slice value) override {
|
||||||
return td::atomic_write_file(to_file_path(key.str()), value);
|
auto key_str = key.str();
|
||||||
|
if (!is_valid_key(key_str)) {
|
||||||
|
return td::Status::Error("Invalid key");
|
||||||
|
}
|
||||||
|
return td::atomic_write_file(to_file_path(key_str), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Result<td::SecureString> get(td::Slice key) override {
|
td::Result<td::SecureString> get(td::Slice key) override {
|
||||||
return td::read_file_secure(to_file_path(key.str()));
|
auto key_str = key.str();
|
||||||
|
if (!is_valid_key(key_str)) {
|
||||||
|
return td::Status::Error("Invalid key");
|
||||||
|
}
|
||||||
|
return td::read_file_secure(to_file_path(key_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
td::Status erase(td::Slice key) override {
|
td::Status erase(td::Slice key) override {
|
||||||
return td::unlink(to_file_path(key.str()));
|
auto key_str = key.str();
|
||||||
|
if (!is_valid_key(key_str)) {
|
||||||
|
return td::Status::Error("Invalid key");
|
||||||
|
}
|
||||||
|
return td::unlink(to_file_path(key_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void foreach_key(std::function<void(td::Slice)> f) override {
|
void foreach_key(std::function<void(td::Slice)> f) override {
|
||||||
|
@ -83,6 +100,20 @@ class KeyValueDir : public KeyValue {
|
||||||
std::string to_file_path(std::string key) {
|
std::string to_file_path(std::string key) {
|
||||||
return directory_ + TD_DIR_SLASH + key;
|
return directory_ + TD_DIR_SLASH + key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_valid_key(const std::string& key) {
|
||||||
|
if (key.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.find(TD_DIR_SLASH) != std::string::npos || key.find("..") != std::string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::all_of(key.begin(), key.end(), [](char c) {
|
||||||
|
return std::isalnum(c) || c == '_' || c == '-' || c == '.';
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyValueInmemory : public KeyValue {
|
class KeyValueInmemory : public KeyValue {
|
||||||
|
|
|
@ -32,13 +32,43 @@ void LastBlockStorage::set_key_value(std::shared_ptr<KeyValue> kv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
std::string buffer_to_hex_nibbles_reversed(td::Slice buffer) {
|
||||||
|
const char *hex = "0123456789ABCDEF";
|
||||||
|
std::string res(2 * buffer.size(), '\0');
|
||||||
|
for (std::size_t i = 0; i < buffer.size(); i++) {
|
||||||
|
unsigned char c = buffer[i];
|
||||||
|
res[2 * i + 1] = hex[c >> 4];
|
||||||
|
res[2 * i] = hex[c & 15];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_file_name_depr(td::Slice name) {
|
||||||
|
return buffer_to_hex_nibbles_reversed(name) + ".blkstate";
|
||||||
|
}
|
||||||
|
|
||||||
std::string get_file_name(td::Slice name) {
|
std::string get_file_name(td::Slice name) {
|
||||||
return td::buffer_to_hex(name) + ".blkstate";
|
return td::buffer_to_hex(name) + ".blkstate";
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
td::Result<LastBlockState> LastBlockStorage::get_state(td::Slice name) {
|
td::Result<LastBlockState> LastBlockStorage::get_state(td::Slice name) {
|
||||||
TRY_RESULT(data, kv_->get(get_file_name(name)));
|
// This migration addresses an issue in the old version of Tonlib, where the td::buffer_to_hex
|
||||||
|
// incorrectly reversed the order of nibbles in hex representation.
|
||||||
|
auto data_r = kv_->get(get_file_name(name));
|
||||||
|
if (data_r.is_error()) {
|
||||||
|
auto key_depr = get_file_name_depr(name);
|
||||||
|
auto data_depr = kv_->get(key_depr);
|
||||||
|
if (data_depr.is_ok()) {
|
||||||
|
kv_->set(get_file_name(name), data_depr.move_as_ok());
|
||||||
|
kv_->erase(key_depr);
|
||||||
|
data_r = std::move(data_depr);
|
||||||
|
} else {
|
||||||
|
return td::Status::Error("not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = data_r.move_as_ok();
|
||||||
if (data.size() < 8) {
|
if (data.size() < 8) {
|
||||||
return td::Status::Error("too short");
|
return td::Status::Error("too short");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#include "tonlib/TestGiver.h"
|
|
||||||
#include "tonlib/utils.h"
|
|
||||||
|
|
||||||
#include "td/utils/base64.h"
|
|
||||||
|
|
||||||
namespace tonlib {
|
|
||||||
const block::StdAddress& TestGiver::address() noexcept {
|
|
||||||
static block::StdAddress res =
|
|
||||||
block::StdAddress::parse("kf_8uRo6OBbQ97jCx2EIuKm8Wmt6Vb15-KsQHFLbKSMiYIny").move_as_ok();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm::CellHash TestGiver::get_init_code_hash() noexcept {
|
|
||||||
return vm::CellHash::from_slice(td::base64_decode("wDkZp0yR4xo+9+BnuAPfGVjBzK6FPzqdv2DwRq3z3KE=").move_as_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> TestGiver::make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept {
|
|
||||||
td::BigInt256 dest_addr;
|
|
||||||
dest_addr.import_bits(dest_address.addr.as_bitslice());
|
|
||||||
vm::CellBuilder cb;
|
|
||||||
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
|
|
||||||
.store_long(dest_address.bounceable, 1)
|
|
||||||
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
|
|
||||||
.store_long(dest_address.workchain, 8)
|
|
||||||
.store_int256(dest_addr, 256);
|
|
||||||
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
|
|
||||||
|
|
||||||
cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4);
|
|
||||||
vm::CellString::store(cb, message, 35 * 8).ensure();
|
|
||||||
auto message_inner = cb.finalize();
|
|
||||||
return vm::CellBuilder().store_long(seqno, 32).store_long(1, 8).store_ref(message_inner).finalize();
|
|
||||||
}
|
|
||||||
} // namespace tonlib
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#include "block/block.h"
|
|
||||||
#include "CellString.h"
|
|
||||||
namespace tonlib {
|
|
||||||
class TestGiver {
|
|
||||||
public:
|
|
||||||
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
|
|
||||||
static const block::StdAddress& address() noexcept;
|
|
||||||
static vm::CellHash get_init_code_hash() noexcept;
|
|
||||||
static td::Ref<vm::Cell> make_a_gift_message(td::uint32 seqno, td::uint64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace tonlib
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#include "tonlib/TestWallet.h"
|
|
||||||
#include "tonlib/GenericAccount.h"
|
|
||||||
#include "tonlib/utils.h"
|
|
||||||
|
|
||||||
#include "vm/boc.h"
|
|
||||||
#include "td/utils/base64.h"
|
|
||||||
|
|
||||||
namespace tonlib {
|
|
||||||
td::Ref<vm::Cell> TestWallet::get_init_state(const td::Ed25519::PublicKey& public_key) noexcept {
|
|
||||||
auto code = get_init_code();
|
|
||||||
auto data = get_init_data(public_key);
|
|
||||||
return GenericAccount::get_init_state(std::move(code), std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> TestWallet::get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept {
|
|
||||||
std::string seq_no(4, 0);
|
|
||||||
auto signature =
|
|
||||||
private_key.sign(vm::CellBuilder().store_bytes(seq_no).finalize()->get_hash().as_slice()).move_as_ok();
|
|
||||||
return vm::CellBuilder().store_bytes(signature).store_bytes(seq_no).finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> TestWallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
|
|
||||||
td::int64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept {
|
|
||||||
td::BigInt256 dest_addr;
|
|
||||||
dest_addr.import_bits(dest_address.addr.as_bitslice());
|
|
||||||
vm::CellBuilder cb;
|
|
||||||
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
|
|
||||||
.store_long(dest_address.bounceable, 1)
|
|
||||||
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
|
|
||||||
.store_long(dest_address.workchain, 8)
|
|
||||||
.store_int256(dest_addr, 256);
|
|
||||||
td::int32 send_mode = 3;
|
|
||||||
if (gramms == -1) {
|
|
||||||
gramms = 0;
|
|
||||||
send_mode += 128;
|
|
||||||
}
|
|
||||||
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
|
|
||||||
cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4);
|
|
||||||
vm::CellString::store(cb, message, 35 * 8).ensure();
|
|
||||||
auto message_inner = cb.finalize();
|
|
||||||
auto message_outer =
|
|
||||||
vm::CellBuilder().store_long(seqno, 32).store_long(send_mode, 8).store_ref(message_inner).finalize();
|
|
||||||
auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok();
|
|
||||||
return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> TestWallet::get_init_code() noexcept {
|
|
||||||
static auto res = [] {
|
|
||||||
auto serialized_code = td::base64_decode(
|
|
||||||
"te6ccgEEAQEAAAAAUwAAov8AIN0gggFMl7qXMO1E0NcLH+Ck8mCBAgDXGCDXCx/tRNDTH9P/"
|
|
||||||
"0VESuvKhIvkBVBBE+RDyovgAAdMfMSDXSpbTB9QC+wDe0aTIyx/L/8ntVA==")
|
|
||||||
.move_as_ok();
|
|
||||||
return vm::std_boc_deserialize(serialized_code).move_as_ok();
|
|
||||||
}();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm::CellHash TestWallet::get_init_code_hash() noexcept {
|
|
||||||
return get_init_code()->get_hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> TestWallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept {
|
|
||||||
return vm::CellBuilder().store_long(0, 32).store_bytes(public_key.as_octet_string()).finalize();
|
|
||||||
}
|
|
||||||
} // namespace tonlib
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vm/cells.h"
|
|
||||||
#include "Ed25519.h"
|
|
||||||
#include "block/block.h"
|
|
||||||
#include "CellString.h"
|
|
||||||
|
|
||||||
namespace tonlib {
|
|
||||||
class TestWallet {
|
|
||||||
public:
|
|
||||||
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
|
|
||||||
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key) noexcept;
|
|
||||||
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept;
|
|
||||||
static td::Ref<vm::Cell> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
|
|
||||||
td::int64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept;
|
|
||||||
|
|
||||||
static td::Ref<vm::Cell> get_init_code() noexcept;
|
|
||||||
static vm::CellHash get_init_code_hash() noexcept;
|
|
||||||
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace tonlib
|
|
File diff suppressed because it is too large
Load diff
|
@ -331,6 +331,7 @@ class TonlibClient : public td::actor::Actor {
|
||||||
|
|
||||||
td::Status do_request(const tonlib_api::smc_getLibraries& request,
|
td::Status do_request(const tonlib_api::smc_getLibraries& request,
|
||||||
td::Promise<object_ptr<tonlib_api::smc_libraryResult>>&& promise);
|
td::Promise<object_ptr<tonlib_api::smc_libraryResult>>&& promise);
|
||||||
|
void get_libraries(ton::BlockIdExt blkid, std::vector<td::Bits256> library_list_, td::Promise<object_ptr<tonlib_api::smc_libraryResult>>&& promise);
|
||||||
|
|
||||||
td::Status do_request(const tonlib_api::smc_getLibrariesExt& request,
|
td::Status do_request(const tonlib_api::smc_getLibrariesExt& request,
|
||||||
td::Promise<object_ptr<tonlib_api::smc_libraryResultExt>>&& promise);
|
td::Promise<object_ptr<tonlib_api::smc_libraryResultExt>>&& promise);
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#include "tonlib/Wallet.h"
|
|
||||||
#include "tonlib/CellString.h"
|
|
||||||
#include "tonlib/GenericAccount.h"
|
|
||||||
#include "tonlib/utils.h"
|
|
||||||
|
|
||||||
#include "vm/boc.h"
|
|
||||||
#include "td/utils/base64.h"
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
namespace tonlib {
|
|
||||||
td::Ref<vm::Cell> Wallet::get_init_state(const td::Ed25519::PublicKey& public_key) noexcept {
|
|
||||||
auto code = get_init_code();
|
|
||||||
auto data = get_init_data(public_key);
|
|
||||||
return GenericAccount::get_init_state(std::move(code), std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> Wallet::get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept {
|
|
||||||
td::uint32 seqno = 0;
|
|
||||||
td::uint32 valid_until = std::numeric_limits<td::uint32>::max();
|
|
||||||
auto signature =
|
|
||||||
private_key
|
|
||||||
.sign(vm::CellBuilder().store_long(seqno, 32).store_long(valid_until, 32).finalize()->get_hash().as_slice())
|
|
||||||
.move_as_ok();
|
|
||||||
return vm::CellBuilder().store_bytes(signature).store_long(seqno, 32).store_long(valid_until, 32).finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> Wallet::make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
|
|
||||||
td::uint32 valid_until, td::int64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept {
|
|
||||||
td::BigInt256 dest_addr;
|
|
||||||
dest_addr.import_bits(dest_address.addr.as_bitslice());
|
|
||||||
vm::CellBuilder cb;
|
|
||||||
cb.append_cellslice(binary_bitstring_to_cellslice("b{01}").move_as_ok())
|
|
||||||
.store_long(dest_address.bounceable, 1)
|
|
||||||
.append_cellslice(binary_bitstring_to_cellslice("b{000100}").move_as_ok())
|
|
||||||
.store_long(dest_address.workchain, 8)
|
|
||||||
.store_int256(dest_addr, 256);
|
|
||||||
td::int32 send_mode = 3;
|
|
||||||
if (gramms == -1) {
|
|
||||||
gramms = 0;
|
|
||||||
send_mode += 128;
|
|
||||||
}
|
|
||||||
block::tlb::t_Grams.store_integer_value(cb, td::BigInt256(gramms));
|
|
||||||
cb.store_zeroes(9 + 64 + 32 + 1 + 1).store_bytes("\0\0\0\0", 4);
|
|
||||||
vm::CellString::store(cb, message, 35 * 8).ensure();
|
|
||||||
auto message_inner = cb.finalize();
|
|
||||||
auto message_outer = vm::CellBuilder()
|
|
||||||
.store_long(seqno, 32)
|
|
||||||
.store_long(valid_until, 32)
|
|
||||||
.store_long(send_mode, 8)
|
|
||||||
.store_ref(message_inner)
|
|
||||||
.finalize();
|
|
||||||
std::string seq_no(4, 0);
|
|
||||||
auto signature = private_key.sign(message_outer->get_hash().as_slice()).move_as_ok();
|
|
||||||
return vm::CellBuilder().store_bytes(signature).append_cellslice(vm::load_cell_slice(message_outer)).finalize();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> Wallet::get_init_code() noexcept {
|
|
||||||
static auto res = [] {
|
|
||||||
auto serialized_code = td::base64_decode(
|
|
||||||
"te6ccgEEAQEAAAAAVwAAqv8AIN0gggFMl7qXMO1E0NcLH+Ck8mCDCNcYINMf0x8B+CO78mPtRNDTH9P/"
|
|
||||||
"0VExuvKhA/kBVBBC+RDyovgAApMg10qW0wfUAvsA6NGkyMsfy//J7VQ=")
|
|
||||||
.move_as_ok();
|
|
||||||
return vm::std_boc_deserialize(serialized_code).move_as_ok();
|
|
||||||
}();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm::CellHash Wallet::get_init_code_hash() noexcept {
|
|
||||||
return get_init_code()->get_hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
td::Ref<vm::Cell> Wallet::get_init_data(const td::Ed25519::PublicKey& public_key) noexcept {
|
|
||||||
return vm::CellBuilder().store_long(0, 32).store_bytes(public_key.as_octet_string()).finalize();
|
|
||||||
}
|
|
||||||
} // namespace tonlib
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
This file is part of TON Blockchain Library.
|
|
||||||
|
|
||||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright 2017-2019 Telegram Systems LLP
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "vm/cells.h"
|
|
||||||
#include "Ed25519.h"
|
|
||||||
#include "block/block.h"
|
|
||||||
#include "CellString.h"
|
|
||||||
|
|
||||||
namespace tonlib {
|
|
||||||
class Wallet {
|
|
||||||
public:
|
|
||||||
static constexpr unsigned max_message_size = vm::CellString::max_bytes;
|
|
||||||
static td::Ref<vm::Cell> get_init_state(const td::Ed25519::PublicKey& public_key) noexcept;
|
|
||||||
static td::Ref<vm::Cell> get_init_message(const td::Ed25519::PrivateKey& private_key) noexcept;
|
|
||||||
static td::Ref<vm::Cell> make_a_gift_message(const td::Ed25519::PrivateKey& private_key, td::uint32 seqno,
|
|
||||||
td::uint32 valid_until, td::int64 gramms, td::Slice message,
|
|
||||||
const block::StdAddress& dest_address) noexcept;
|
|
||||||
|
|
||||||
static td::Ref<vm::Cell> get_init_code() noexcept;
|
|
||||||
static vm::CellHash get_init_code_hash() noexcept;
|
|
||||||
static td::Ref<vm::Cell> get_init_data(const td::Ed25519::PublicKey& public_key) noexcept;
|
|
||||||
};
|
|
||||||
} // namespace tonlib
|
|
|
@ -1427,6 +1427,7 @@ td::Status ValidatorEngine::load_global_config() {
|
||||||
validator_options_.write().set_celldb_compress_depth(celldb_compress_depth_);
|
validator_options_.write().set_celldb_compress_depth(celldb_compress_depth_);
|
||||||
validator_options_.write().set_max_open_archive_files(max_open_archive_files_);
|
validator_options_.write().set_max_open_archive_files(max_open_archive_files_);
|
||||||
validator_options_.write().set_archive_preload_period(archive_preload_period_);
|
validator_options_.write().set_archive_preload_period(archive_preload_period_);
|
||||||
|
validator_options_.write().set_disable_rocksdb_stats(disable_rocksdb_stats_);
|
||||||
|
|
||||||
std::vector<ton::BlockIdExt> h;
|
std::vector<ton::BlockIdExt> h;
|
||||||
for (auto &x : conf.validator_->hardforks_) {
|
for (auto &x : conf.validator_->hardforks_) {
|
||||||
|
@ -4127,6 +4128,9 @@ int main(int argc, char *argv[]) {
|
||||||
p.add_option('\0', "enable-precompiled-smc",
|
p.add_option('\0', "enable-precompiled-smc",
|
||||||
"enable exectuion of precompiled contracts (experimental, disabled by default)",
|
"enable exectuion of precompiled contracts (experimental, disabled by default)",
|
||||||
[]() { block::precompiled::set_precompiled_execution_enabled(true); });
|
[]() { block::precompiled::set_precompiled_execution_enabled(true); });
|
||||||
|
p.add_option('\0', "disable-rocksdb-stats", "disable gathering rocksdb statistics (enabled by default)", [&]() {
|
||||||
|
acts.push_back([&x]() { td::actor::send_closure(x, &ValidatorEngine::set_disable_rocksdb_stats, true); });
|
||||||
|
});
|
||||||
auto S = p.run(argc, argv);
|
auto S = p.run(argc, argv);
|
||||||
if (S.is_error()) {
|
if (S.is_error()) {
|
||||||
LOG(ERROR) << "failed to parse options: " << S.move_as_error();
|
LOG(ERROR) << "failed to parse options: " << S.move_as_error();
|
||||||
|
|
|
@ -220,6 +220,7 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
td::uint32 celldb_compress_depth_ = 0;
|
td::uint32 celldb_compress_depth_ = 0;
|
||||||
size_t max_open_archive_files_ = 0;
|
size_t max_open_archive_files_ = 0;
|
||||||
double archive_preload_period_ = 0.0;
|
double archive_preload_period_ = 0.0;
|
||||||
|
bool disable_rocksdb_stats_ = false;
|
||||||
bool read_config_ = false;
|
bool read_config_ = false;
|
||||||
bool started_keyring_ = false;
|
bool started_keyring_ = false;
|
||||||
bool started_ = false;
|
bool started_ = false;
|
||||||
|
@ -289,6 +290,9 @@ class ValidatorEngine : public td::actor::Actor {
|
||||||
void set_archive_preload_period(double value) {
|
void set_archive_preload_period(double value) {
|
||||||
archive_preload_period_ = value;
|
archive_preload_period_ = value;
|
||||||
}
|
}
|
||||||
|
void set_disable_rocksdb_stats(bool value) {
|
||||||
|
disable_rocksdb_stats_ = value;
|
||||||
|
}
|
||||||
void set_not_all_shards() {
|
void set_not_all_shards() {
|
||||||
not_all_shards_ = true;
|
not_all_shards_ = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,7 +601,7 @@ void ArchiveManager::load_package(PackageId id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
desc.file =
|
desc.file =
|
||||||
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get());
|
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get(), statistics_);
|
||||||
|
|
||||||
m.emplace(id, std::move(desc));
|
m.emplace(id, std::move(desc));
|
||||||
update_permanent_slices();
|
update_permanent_slices();
|
||||||
|
@ -636,7 +636,7 @@ const ArchiveManager::FileDescription *ArchiveManager::add_file_desc(ShardIdFull
|
||||||
td::mkdir(db_root_ + id.path()).ensure();
|
td::mkdir(db_root_ + id.path()).ensure();
|
||||||
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
std::string prefix = PSTRING() << db_root_ << id.path() << id.name();
|
||||||
new_desc.file =
|
new_desc.file =
|
||||||
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get());
|
td::actor::create_actor<ArchiveSlice>("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get(), statistics_);
|
||||||
const FileDescription &desc = f.emplace(id, std::move(new_desc));
|
const FileDescription &desc = f.emplace(id, std::move(new_desc));
|
||||||
if (!id.temp) {
|
if (!id.temp) {
|
||||||
update_desc(f, desc, shard, seqno, ts, lt);
|
update_desc(f, desc, shard, seqno, ts, lt);
|
||||||
|
@ -829,7 +829,10 @@ void ArchiveManager::start_up() {
|
||||||
if (opts_->get_max_open_archive_files() > 0) {
|
if (opts_->get_max_open_archive_files() > 0) {
|
||||||
archive_lru_ = td::actor::create_actor<ArchiveLru>("archive_lru", opts_->get_max_open_archive_files());
|
archive_lru_ = td::actor::create_actor<ArchiveLru>("archive_lru", opts_->get_max_open_archive_files());
|
||||||
}
|
}
|
||||||
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_root_ + "/files/globalindex").move_as_ok());
|
if (!opts_->get_disable_rocksdb_stats()) {
|
||||||
|
statistics_ = td::RocksDb::create_statistics();
|
||||||
|
}
|
||||||
|
index_ = std::make_shared<td::RocksDb>(td::RocksDb::open(db_root_ + "/files/globalindex", statistics_).move_as_ok());
|
||||||
std::string value;
|
std::string value;
|
||||||
auto v = index_->get(create_serialize_tl_object<ton_api::db_files_index_key>().as_slice(), value);
|
auto v = index_->get(create_serialize_tl_object<ton_api::db_files_index_key>().as_slice(), value);
|
||||||
v.ensure();
|
v.ensure();
|
||||||
|
@ -903,6 +906,28 @@ void ArchiveManager::start_up() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opts_->get_disable_rocksdb_stats()) {
|
||||||
|
alarm_timestamp() = td::Timestamp::in(60.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveManager::alarm() {
|
||||||
|
alarm_timestamp() = td::Timestamp::in(60.0);
|
||||||
|
auto stats = td::RocksDb::statistics_to_string(statistics_);
|
||||||
|
auto to_file_r = td::FileFd::open(db_root_ + "/db_stats.txt", td::FileFd::Truncate | td::FileFd::Create | td::FileFd::Write, 0644);
|
||||||
|
if (to_file_r.is_error()) {
|
||||||
|
LOG(ERROR) << "Failed to open db_stats.txt: " << to_file_r.move_as_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto to_file = to_file_r.move_as_ok();
|
||||||
|
auto res = to_file.write(stats);
|
||||||
|
to_file.close();
|
||||||
|
if (res.is_error()) {
|
||||||
|
LOG(ERROR) << "Failed to write to db_stats.txt: " << res.move_as_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::RocksDb::reset_statistics(statistics_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchiveManager::run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) {
|
void ArchiveManager::run_gc(UnixTime mc_ts, UnixTime gc_ts, UnixTime archive_ttl) {
|
||||||
|
|
|
@ -70,6 +70,7 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
td::Promise<td::BufferSlice> promise);
|
td::Promise<td::BufferSlice> promise);
|
||||||
|
|
||||||
void start_up() override;
|
void start_up() override;
|
||||||
|
void alarm() override;
|
||||||
|
|
||||||
void commit_transaction();
|
void commit_transaction();
|
||||||
void set_async_mode(bool mode, td::Promise<td::Unit> promise);
|
void set_async_mode(bool mode, td::Promise<td::Unit> promise);
|
||||||
|
@ -173,6 +174,8 @@ class ArchiveManager : public td::actor::Actor {
|
||||||
bool huge_transaction_started_ = false;
|
bool huge_transaction_started_ = false;
|
||||||
td::uint32 huge_transaction_size_ = 0;
|
td::uint32 huge_transaction_size_ = 0;
|
||||||
|
|
||||||
|
std::shared_ptr<rocksdb::Statistics> statistics_;
|
||||||
|
|
||||||
FileMap &get_file_map(const PackageId &p) {
|
FileMap &get_file_map(const PackageId &p) {
|
||||||
return p.key ? key_files_ : p.temp ? temp_files_ : files_;
|
return p.key ? key_files_ : p.temp ? temp_files_ : files_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,7 +465,7 @@ void ArchiveSlice::get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::
|
||||||
void ArchiveSlice::before_query() {
|
void ArchiveSlice::before_query() {
|
||||||
if (status_ == st_closed) {
|
if (status_ == st_closed) {
|
||||||
LOG(DEBUG) << "Opening archive slice " << db_path_;
|
LOG(DEBUG) << "Opening archive slice " << db_path_;
|
||||||
kv_ = std::make_unique<td::RocksDb>(td::RocksDb::open(db_path_).move_as_ok());
|
kv_ = std::make_unique<td::RocksDb>(td::RocksDb::open(db_path_, statistics_).move_as_ok());
|
||||||
std::string value;
|
std::string value;
|
||||||
auto R2 = kv_->get("status", value);
|
auto R2 = kv_->get("status", value);
|
||||||
R2.ensure();
|
R2.ensure();
|
||||||
|
@ -604,14 +604,15 @@ void ArchiveSlice::set_async_mode(bool mode, td::Promise<td::Unit> promise) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
ArchiveSlice::ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
||||||
td::actor::ActorId<ArchiveLru> archive_lru)
|
td::actor::ActorId<ArchiveLru> archive_lru, std::shared_ptr<rocksdb::Statistics> statistics)
|
||||||
: archive_id_(archive_id)
|
: archive_id_(archive_id)
|
||||||
, key_blocks_only_(key_blocks_only)
|
, key_blocks_only_(key_blocks_only)
|
||||||
, temp_(temp)
|
, temp_(temp)
|
||||||
, finalized_(finalized)
|
, finalized_(finalized)
|
||||||
, p_id_(archive_id_, key_blocks_only_, temp_)
|
, p_id_(archive_id_, key_blocks_only_, temp_)
|
||||||
, db_root_(std::move(db_root))
|
, db_root_(std::move(db_root))
|
||||||
, archive_lru_(std::move(archive_lru)) {
|
, archive_lru_(std::move(archive_lru))
|
||||||
|
, statistics_(statistics) {
|
||||||
db_path_ = PSTRING() << db_root_ << p_id_.path() << p_id_.name() << ".index";
|
db_path_ = PSTRING() << db_root_ << p_id_.path() << p_id_.name() << ".index";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
#include "fileref.hpp"
|
#include "fileref.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
namespace rocksdb {
|
||||||
|
class Statistics;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
namespace validator {
|
namespace validator {
|
||||||
|
@ -81,7 +85,7 @@ class ArchiveLru;
|
||||||
class ArchiveSlice : public td::actor::Actor {
|
class ArchiveSlice : public td::actor::Actor {
|
||||||
public:
|
public:
|
||||||
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
ArchiveSlice(td::uint32 archive_id, bool key_blocks_only, bool temp, bool finalized, std::string db_root,
|
||||||
td::actor::ActorId<ArchiveLru> archive_lru);
|
td::actor::ActorId<ArchiveLru> archive_lru, std::shared_ptr<rocksdb::Statistics> statistics = nullptr);
|
||||||
|
|
||||||
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise);
|
void get_archive_id(BlockSeqno masterchain_seqno, td::Promise<td::uint64> promise);
|
||||||
|
|
||||||
|
@ -151,6 +155,7 @@ class ArchiveSlice : public td::actor::Actor {
|
||||||
|
|
||||||
std::string db_root_;
|
std::string db_root_;
|
||||||
td::actor::ActorId<ArchiveLru> archive_lru_;
|
td::actor::ActorId<ArchiveLru> archive_lru_;
|
||||||
|
std::shared_ptr<rocksdb::Statistics> statistics_;
|
||||||
std::unique_ptr<td::KeyValue> kv_;
|
std::unique_ptr<td::KeyValue> kv_;
|
||||||
|
|
||||||
struct PackageInfo {
|
struct PackageInfo {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "rootdb.hpp"
|
#include "rootdb.hpp"
|
||||||
|
|
||||||
#include "td/db/RocksDb.h"
|
#include "td/db/RocksDb.h"
|
||||||
|
#include "td/utils/filesystem.h"
|
||||||
|
|
||||||
#include "ton/ton-tl.hpp"
|
#include "ton/ton-tl.hpp"
|
||||||
#include "ton/ton-io.hpp"
|
#include "ton/ton-io.hpp"
|
||||||
|
@ -83,7 +84,12 @@ void CellDbIn::start_up() {
|
||||||
};
|
};
|
||||||
|
|
||||||
CellDbBase::start_up();
|
CellDbBase::start_up();
|
||||||
cell_db_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_).move_as_ok());
|
if (!opts_->get_disable_rocksdb_stats()) {
|
||||||
|
statistics_ = td::RocksDb::create_statistics();
|
||||||
|
statistics_flush_at_ = td::Timestamp::in(60.0);
|
||||||
|
}
|
||||||
|
cell_db_ = std::make_shared<td::RocksDb>(td::RocksDb::open(path_, statistics_).move_as_ok());
|
||||||
|
|
||||||
|
|
||||||
boc_ = vm::DynamicBagOfCellsDb::create();
|
boc_ = vm::DynamicBagOfCellsDb::create();
|
||||||
boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth());
|
boc_->set_celldb_compress_depth(opts_->get_celldb_compress_depth());
|
||||||
|
@ -155,7 +161,29 @@ void CellDbIn::get_cell_db_reader(td::Promise<std::shared_ptr<vm::CellDbReader>>
|
||||||
promise.set_result(boc_->get_cell_db_reader());
|
promise.set_result(boc_->get_cell_db_reader());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CellDbIn::flush_db_stats() {
|
||||||
|
auto stats = td::RocksDb::statistics_to_string(statistics_);
|
||||||
|
auto to_file_r = td::FileFd::open(path_ + "/db_stats.txt", td::FileFd::Truncate | td::FileFd::Create | td::FileFd::Write, 0644);
|
||||||
|
if (to_file_r.is_error()) {
|
||||||
|
LOG(ERROR) << "Failed to open db_stats.txt: " << to_file_r.move_as_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto to_file = to_file_r.move_as_ok();
|
||||||
|
auto res = to_file.write(stats);
|
||||||
|
to_file.close();
|
||||||
|
if (res.is_error()) {
|
||||||
|
LOG(ERROR) << "Failed to write to db_stats.txt: " << res.move_as_error();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::RocksDb::reset_statistics(statistics_);
|
||||||
|
}
|
||||||
|
|
||||||
void CellDbIn::alarm() {
|
void CellDbIn::alarm() {
|
||||||
|
if (statistics_flush_at_ && statistics_flush_at_.is_in_past()) {
|
||||||
|
statistics_flush_at_ = td::Timestamp::in(60.0);
|
||||||
|
flush_db_stats();
|
||||||
|
}
|
||||||
|
|
||||||
if (migrate_after_ && migrate_after_.is_in_past()) {
|
if (migrate_after_ && migrate_after_.is_in_past()) {
|
||||||
migrate_cells();
|
migrate_cells();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@
|
||||||
#include "auto/tl/ton_api.h"
|
#include "auto/tl/ton_api.h"
|
||||||
#include "validator.h"
|
#include "validator.h"
|
||||||
|
|
||||||
|
namespace rocksdb {
|
||||||
|
class Statistics;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ton {
|
namespace ton {
|
||||||
|
|
||||||
namespace validator {
|
namespace validator {
|
||||||
|
@ -56,6 +60,8 @@ class CellDbIn : public CellDbBase {
|
||||||
|
|
||||||
void migrate_cell(td::Bits256 hash);
|
void migrate_cell(td::Bits256 hash);
|
||||||
|
|
||||||
|
void flush_db_stats();
|
||||||
|
|
||||||
CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path,
|
CellDbIn(td::actor::ActorId<RootDb> root_db, td::actor::ActorId<CellDb> parent, std::string path,
|
||||||
td::Ref<ValidatorManagerOptions> opts);
|
td::Ref<ValidatorManagerOptions> opts);
|
||||||
|
|
||||||
|
@ -103,6 +109,8 @@ class CellDbIn : public CellDbBase {
|
||||||
|
|
||||||
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
std::unique_ptr<vm::DynamicBagOfCellsDb> boc_;
|
||||||
std::shared_ptr<vm::KeyValue> cell_db_;
|
std::shared_ptr<vm::KeyValue> cell_db_;
|
||||||
|
std::shared_ptr<rocksdb::Statistics> statistics_;
|
||||||
|
td::Timestamp statistics_flush_at_ = td::Timestamp::never();
|
||||||
|
|
||||||
std::function<void(const vm::CellLoader::LoadResult&)> on_load_callback_;
|
std::function<void(const vm::CellLoader::LoadResult&)> on_load_callback_;
|
||||||
std::set<td::Bits256> cells_to_migrate_;
|
std::set<td::Bits256> cells_to_migrate_;
|
||||||
|
|
|
@ -110,7 +110,7 @@ class LiteServerCacheImpl : public LiteServerCache {
|
||||||
std::set<td::Bits256> send_message_cache_;
|
std::set<td::Bits256> send_message_cache_;
|
||||||
size_t send_message_error_cnt_ = 0;
|
size_t send_message_error_cnt_ = 0;
|
||||||
|
|
||||||
static const size_t MAX_CACHE_SIZE = 64 << 20;
|
static constexpr size_t MAX_CACHE_SIZE = 64 << 20;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ton::validator
|
} // namespace ton::validator
|
||||||
|
|
|
@ -233,6 +233,9 @@ void LiteQuery::perform() {
|
||||||
[&](lite_api::liteServer_lookupBlock& q) {
|
[&](lite_api::liteServer_lookupBlock& q) {
|
||||||
this->perform_lookupBlock(ton::create_block_id_simple(q.id_), q.mode_, q.lt_, q.utime_);
|
this->perform_lookupBlock(ton::create_block_id_simple(q.id_), q.mode_, q.lt_, q.utime_);
|
||||||
},
|
},
|
||||||
|
[&](lite_api::liteServer_lookupBlockWithProof& q) {
|
||||||
|
this->perform_lookupBlockWithProof(ton::create_block_id_simple(q.id_), ton::create_block_id(q.mc_block_id_), q.mode_, q.lt_, q.utime_);
|
||||||
|
},
|
||||||
[&](lite_api::liteServer_listBlockTransactions& q) {
|
[&](lite_api::liteServer_listBlockTransactions& q) {
|
||||||
this->perform_listBlockTransactions(ton::create_block_id(q.id_), q.mode_, q.count_,
|
this->perform_listBlockTransactions(ton::create_block_id(q.id_), q.mode_, q.count_,
|
||||||
(q.mode_ & 128) ? q.after_->account_ : td::Bits256::zero(),
|
(q.mode_ & 128) ? q.after_->account_ : td::Bits256::zero(),
|
||||||
|
@ -266,6 +269,9 @@ void LiteQuery::perform() {
|
||||||
[&](lite_api::liteServer_getLibraries& q) {
|
[&](lite_api::liteServer_getLibraries& q) {
|
||||||
this->perform_getLibraries(q.library_list_);
|
this->perform_getLibraries(q.library_list_);
|
||||||
},
|
},
|
||||||
|
[&](lite_api::liteServer_getLibrariesWithProof& q) {
|
||||||
|
this->perform_getLibrariesWithProof(ton::create_block_id(q.id_), q.mode_, q.library_list_);
|
||||||
|
},
|
||||||
[&](lite_api::liteServer_getShardBlockProof& q) {
|
[&](lite_api::liteServer_getShardBlockProof& q) {
|
||||||
this->perform_getShardBlockProof(create_block_id(q.id_));
|
this->perform_getShardBlockProof(create_block_id(q.id_));
|
||||||
},
|
},
|
||||||
|
@ -964,6 +970,100 @@ void LiteQuery::continue_getLibraries(Ref<ton::validator::MasterchainState> mc_s
|
||||||
finish_query(std::move(b));
|
finish_query(std::move(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LiteQuery::perform_getLibrariesWithProof(BlockIdExt blkid, int mode, std::vector<td::Bits256> library_list) {
|
||||||
|
LOG(INFO) << "started a getLibrariesWithProof(<list of " << library_list.size() << " parameters>) liteserver query";
|
||||||
|
if (library_list.size() > 16) {
|
||||||
|
LOG(INFO) << "too many libraries requested, returning only first 16";
|
||||||
|
library_list.resize(16);
|
||||||
|
}
|
||||||
|
sort( library_list.begin(), library_list.end() );
|
||||||
|
library_list.erase( unique( library_list.begin(), library_list.end() ), library_list.end() );
|
||||||
|
|
||||||
|
set_continuation([this, library_list, mode]() -> void { continue_getLibrariesWithProof(library_list, mode); });
|
||||||
|
request_mc_block_data_state(blkid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_getLibrariesWithProof(std::vector<td::Bits256> library_list, int mode) {
|
||||||
|
LOG(INFO) << "obtained masterchain block = " << base_blk_id_.to_str();
|
||||||
|
CHECK(mc_state_.not_null());
|
||||||
|
|
||||||
|
Ref<vm::Cell> state_proof, data_proof;
|
||||||
|
if (!make_mc_state_root_proof(state_proof)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::MerkleProofBuilder pb{mc_state_->root_cell()};
|
||||||
|
block::gen::ShardStateUnsplit::Record state;
|
||||||
|
if (!tlb::unpack_cell(pb.root(), state)) {
|
||||||
|
fatal_error("cannot unpack header of shardchain state "s + base_blk_id_.to_str());
|
||||||
|
}
|
||||||
|
auto libraries_dict = vm::Dictionary(state.r1.libraries->prefetch_ref(), 256);
|
||||||
|
|
||||||
|
std::vector<ton::tl_object_ptr<ton::lite_api::liteServer_libraryEntry>> result;
|
||||||
|
std::vector<td::Bits256> result_hashes;
|
||||||
|
for (const auto& hash : library_list) {
|
||||||
|
LOG(INFO) << "looking for library " << hash.to_hex();
|
||||||
|
|
||||||
|
auto csr = libraries_dict.lookup(hash.bits(), 256);
|
||||||
|
if (csr.is_null() || csr->prefetch_ulong(2) != 0 || !csr->have_refs()) { // shared_lib_descr$00 lib:^Cell
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
block::gen::LibDescr::Record libdescr;
|
||||||
|
if (!tlb::csr_unpack(csr, libdescr)) {
|
||||||
|
fatal_error("cannot unpack LibDescr record "s + hash.to_hex());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mode & 1) {
|
||||||
|
// include first 16 publishers in the proof
|
||||||
|
auto publishers_dict = vm::Dictionary{vm::DictNonEmpty(), libdescr.publishers, 256};
|
||||||
|
auto iter = publishers_dict.begin();
|
||||||
|
constexpr int max_publishers = 15; // set to 15 because publishers_dict.begin() counts as the first visit
|
||||||
|
for (int i = 0; i < max_publishers && iter != publishers_dict.end(); ++i, ++iter) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
result_hashes.push_back(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data_proof_boc = pb.extract_proof_boc();
|
||||||
|
if (data_proof_boc.is_error()) {
|
||||||
|
fatal_error(data_proof_boc.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto state_proof_boc = vm::std_boc_serialize(std::move(state_proof));
|
||||||
|
if (state_proof_boc.is_error()) {
|
||||||
|
fatal_error(state_proof_boc.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& hash : result_hashes) {
|
||||||
|
auto csr = libraries_dict.lookup(hash.bits(), 256);
|
||||||
|
block::gen::LibDescr::Record libdescr;
|
||||||
|
if (!tlb::csr_unpack(csr, libdescr)) {
|
||||||
|
fatal_error("cannot unpack LibDescr record "s + hash.to_hex());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!libdescr.lib->get_hash().bits().equals(hash.bits(), 256)) {
|
||||||
|
LOG(ERROR) << "public library hash mismatch: expected " << hash.to_hex() << " , found "
|
||||||
|
<< libdescr.lib->get_hash().to_hex();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
td::BufferSlice libdata;
|
||||||
|
if (!(mode & 2)) {
|
||||||
|
auto data = vm::std_boc_serialize(libdescr.lib);
|
||||||
|
if (data.is_error()) {
|
||||||
|
LOG(WARNING) << "library serialization failed: " << data.move_as_error().to_string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
libdata = data.move_as_ok();
|
||||||
|
}
|
||||||
|
result.push_back(ton::create_tl_object<ton::lite_api::liteServer_libraryEntry>(hash, std::move(libdata)));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_libraryResultWithProof>(ton::create_tl_lite_block_id(base_blk_id_), mode, std::move(result),
|
||||||
|
state_proof_boc.move_as_ok(), data_proof_boc.move_as_ok());
|
||||||
|
finish_query(std::move(b));
|
||||||
|
}
|
||||||
|
|
||||||
void LiteQuery::perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt) {
|
void LiteQuery::perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt) {
|
||||||
LOG(INFO) << "started a getOneTransaction(" << blkid.to_str() << ", " << workchain << ", " << addr.to_hex() << ","
|
LOG(INFO) << "started a getOneTransaction(" << blkid.to_str() << ", " << workchain << ", " << addr.to_hex() << ","
|
||||||
<< lt << ") liteserver query";
|
<< lt << ") liteserver query";
|
||||||
|
@ -1333,8 +1433,8 @@ static td::Ref<vm::Tuple> prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt,
|
||||||
td::make_refint(lt), // trans_lt:Integer
|
td::make_refint(lt), // trans_lt:Integer
|
||||||
std::move(rand_seed_int), // rand_seed:Integer
|
std::move(rand_seed_int), // rand_seed:Integer
|
||||||
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
balance.as_vm_tuple(), // balance_remaining:[Integer (Maybe Cell)]
|
||||||
my_addr, // myself:MsgAddressInt
|
my_addr, // myself:MsgAddressInt
|
||||||
config ? config->get_root_cell() : vm::StackEntry() // global_config:(Maybe Cell) ] = SmartContractInfo;
|
config ? config->get_root_cell() : vm::StackEntry() // global_config:(Maybe Cell) ] = SmartContractInfo;
|
||||||
};
|
};
|
||||||
if (config && config->get_global_version() >= 4) {
|
if (config && config->get_global_version() >= 4) {
|
||||||
tuple.push_back(my_code); // code:Cell
|
tuple.push_back(my_code); // code:Cell
|
||||||
|
@ -1350,6 +1450,9 @@ static td::Ref<vm::Tuple> prepare_vm_c7(ton::UnixTime now, ton::LogicalTime lt,
|
||||||
if (config && config->get_global_version() >= 6) {
|
if (config && config->get_global_version() >= 6) {
|
||||||
tuple.push_back(config->get_unpacked_config_tuple(now)); // unpacked_config_tuple:[...]
|
tuple.push_back(config->get_unpacked_config_tuple(now)); // unpacked_config_tuple:[...]
|
||||||
tuple.push_back(due_payment); // due_payment:Integer
|
tuple.push_back(due_payment); // due_payment:Integer
|
||||||
|
// precomiled_gas_usage:(Maybe Integer)
|
||||||
|
auto precompiled = config->get_precompiled_contracts_config().get_contract(my_code->get_hash().bits());
|
||||||
|
tuple.push_back(precompiled ? td::make_refint(precompiled.value().gas_usage) : vm::StackEntry());
|
||||||
}
|
}
|
||||||
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
|
||||||
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple_ref).to_string();
|
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple_ref).to_string();
|
||||||
|
@ -1430,6 +1533,7 @@ void LiteQuery::finish_runSmcMethod(td::BufferSlice shard_proof, td::BufferSlice
|
||||||
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance, config.get(),
|
auto c7 = prepare_vm_c7(gen_utime, gen_lt, td::make_ref<vm::CellSlice>(acc.addr->clone()), balance, config.get(),
|
||||||
std::move(code), due_payment);
|
std::move(code), due_payment);
|
||||||
vm.set_c7(c7); // tuple with SmartContractInfo
|
vm.set_c7(c7); // tuple with SmartContractInfo
|
||||||
|
vm.set_global_version(config->get_global_version());
|
||||||
// vm.incr_stack_trace(1); // enable stack dump after each step
|
// vm.incr_stack_trace(1); // enable stack dump after each step
|
||||||
LOG(INFO) << "starting VM to run GET-method of smart contract " << acc_workchain_ << ":" << acc_addr_.to_hex();
|
LOG(INFO) << "starting VM to run GET-method of smart contract " << acc_workchain_ << ":" << acc_addr_.to_hex();
|
||||||
// **** RUN VM ****
|
// **** RUN VM ****
|
||||||
|
@ -1849,7 +1953,7 @@ void LiteQuery::continue_getConfigParams(int mode, std::vector<int> param_list)
|
||||||
void LiteQuery::perform_getAllShardsInfo(BlockIdExt blkid) {
|
void LiteQuery::perform_getAllShardsInfo(BlockIdExt blkid) {
|
||||||
LOG(INFO) << "started a getAllShardsInfo(" << blkid.to_str() << ") liteserver query";
|
LOG(INFO) << "started a getAllShardsInfo(" << blkid.to_str() << ") liteserver query";
|
||||||
set_continuation([&]() -> void { continue_getAllShardsInfo(); });
|
set_continuation([&]() -> void { continue_getAllShardsInfo(); });
|
||||||
request_mc_block_data_state(blkid);
|
request_mc_block_data(blkid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LiteQuery::continue_getShardInfo(ShardIdFull shard, bool exact) {
|
void LiteQuery::continue_getShardInfo(ShardIdFull shard, bool exact) {
|
||||||
|
@ -1896,30 +2000,30 @@ void LiteQuery::continue_getShardInfo(ShardIdFull shard, bool exact) {
|
||||||
|
|
||||||
void LiteQuery::continue_getAllShardsInfo() {
|
void LiteQuery::continue_getAllShardsInfo() {
|
||||||
LOG(INFO) << "completing getAllShardsInfo() query";
|
LOG(INFO) << "completing getAllShardsInfo() query";
|
||||||
Ref<vm::Cell> proof1, proof2;
|
vm::MerkleProofBuilder mpb{mc_block_->root_cell()};
|
||||||
if (!make_mc_state_root_proof(proof1)) {
|
block::gen::Block::Record blk;
|
||||||
|
block::gen::BlockExtra::Record extra;
|
||||||
|
block::gen::McBlockExtra::Record mc_extra;
|
||||||
|
if (!tlb::unpack_cell(mpb.root(), blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() ||
|
||||||
|
!tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra)) {
|
||||||
|
fatal_error("cannot unpack header of block "s + mc_block_->block_id().to_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vm::MerkleProofBuilder mpb{mc_state_->root_cell()};
|
vm::Dictionary shards_dict(std::move(mc_extra.shard_hashes), 32);
|
||||||
auto shards_dict = block::ShardConfig::extract_shard_hashes_dict(mpb.root());
|
Ref<vm::Cell> proof;
|
||||||
if (!shards_dict) {
|
if (!mpb.extract_proof_to(proof)) {
|
||||||
fatal_error("cannot extract ShardHashes from last mc state");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!mpb.extract_proof_to(proof2)) {
|
|
||||||
fatal_error("cannot construct Merkle proof for all shards dictionary");
|
fatal_error("cannot construct Merkle proof for all shards dictionary");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
shards_dict = block::ShardConfig::extract_shard_hashes_dict(mc_state_->root_cell());
|
auto proof_boc = vm::std_boc_serialize(std::move(proof));
|
||||||
vm::CellBuilder cb;
|
if (proof_boc.is_error()) {
|
||||||
Ref<vm::Cell> cell;
|
fatal_error(proof_boc.move_as_error());
|
||||||
if (!(std::move(shards_dict)->append_dict_to_bool(cb) && cb.finalize_to(cell))) {
|
|
||||||
fatal_error("cannot store ShardHashes from last mc state into a new cell");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto proof = vm::std_boc_serialize_multi({std::move(proof1), std::move(proof2)});
|
vm::CellBuilder cb;
|
||||||
if (proof.is_error()) {
|
Ref<vm::Cell> cell;
|
||||||
fatal_error(proof.move_as_error());
|
if (!(shards_dict.append_dict_to_bool(cb) && cb.finalize_to(cell))) {
|
||||||
|
fatal_error("cannot store ShardHashes from last mc block into a new cell");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto data = vm::std_boc_serialize(std::move(cell));
|
auto data = vm::std_boc_serialize(std::move(cell));
|
||||||
|
@ -1929,10 +2033,307 @@ void LiteQuery::continue_getAllShardsInfo() {
|
||||||
}
|
}
|
||||||
LOG(INFO) << "getAllShardInfo() query completed";
|
LOG(INFO) << "getAllShardInfo() query completed";
|
||||||
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_allShardsInfo>(
|
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_allShardsInfo>(
|
||||||
ton::create_tl_lite_block_id(base_blk_id_), proof.move_as_ok(), data.move_as_ok());
|
ton::create_tl_lite_block_id(base_blk_id_), proof_boc.move_as_ok(), data.move_as_ok());
|
||||||
finish_query(std::move(b));
|
finish_query(std::move(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LiteQuery::perform_lookupBlockWithProof(BlockId blkid, BlockIdExt mc_blkid, int mode, LogicalTime lt, UnixTime utime) {
|
||||||
|
if (!((1 << (mode & 7)) & 0x16)) {
|
||||||
|
fatal_error("exactly one of mode.0, mode.1 and mode.2 bits must be set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!mc_blkid.is_masterchain_ext()) {
|
||||||
|
fatal_error("masterchain block id must be specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(mode & 1)) {
|
||||||
|
blkid.seqno = 0;
|
||||||
|
}
|
||||||
|
if (!(mode & 2)) {
|
||||||
|
lt = 0;
|
||||||
|
}
|
||||||
|
if (!(mode & 4)) {
|
||||||
|
utime = 0;
|
||||||
|
}
|
||||||
|
mode_ = mode;
|
||||||
|
base_blk_id_ = mc_blkid;
|
||||||
|
LOG(INFO) << "started a lookupBlockWithProof(" << blkid.to_str() << ", " << mc_blkid.to_str() << ", " << mode << ", "
|
||||||
|
<< lt << ", " << utime << ") liteserver query";
|
||||||
|
|
||||||
|
ton::AccountIdPrefixFull pfx{blkid.workchain, blkid.shard};
|
||||||
|
auto P = td::PromiseCreator::lambda(
|
||||||
|
[Self = actor_id(this), mc_blkid, manager = manager_, mode, pfx](td::Result<ConstBlockHandle> res) {
|
||||||
|
if (res.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto handle = res.move_as_ok();
|
||||||
|
if (!handle->inited_masterchain_ref_block()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error("block doesn't have masterchain ref"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (handle->masterchain_ref_block() > mc_blkid.seqno()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, td::Status::Error("specified mc block is older than block's masterchain ref"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG(DEBUG) << "requesting data for block " << handle->id().to_str();
|
||||||
|
td::actor::send_closure_later(manager, &ValidatorManager::get_block_data_from_db, handle,
|
||||||
|
[Self, mc_ref_blkid = handle->masterchain_ref_block(), mc_blkid, pfx, mode](td::Result<Ref<BlockData>> res) {
|
||||||
|
if (res.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
|
} else {
|
||||||
|
td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlockWithProof_getHeaderProof, res.move_as_ok(), pfx, mc_ref_blkid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mode & 2) {
|
||||||
|
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_lt_from_db_for_litequery, pfx, lt, std::move(P));
|
||||||
|
} else if (mode & 4) {
|
||||||
|
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_unix_time_from_db_for_litequery, pfx, utime, std::move(P));
|
||||||
|
} else {
|
||||||
|
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db_for_litequery, pfx, blkid.seqno, std::move(P));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_lookupBlockWithProof_getHeaderProof(Ref<ton::validator::BlockData> block, AccountIdPrefixFull req_prefix, BlockSeqno masterchain_ref_seqno) {
|
||||||
|
blk_id_ = block->block_id();
|
||||||
|
LOG(INFO) << "obtained data for getBlockHeader(" << blk_id_.to_str() << ", " << mode_ << ")";
|
||||||
|
CHECK(block.not_null());
|
||||||
|
auto block_root = block->root_cell();
|
||||||
|
if (block_root.is_null()) {
|
||||||
|
fatal_error("block has no valid root cell");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm::MerkleProofBuilder mpb{block_root};
|
||||||
|
std::vector<BlockIdExt> prev;
|
||||||
|
BlockIdExt mc_blkid;
|
||||||
|
bool after_split;
|
||||||
|
td::Status S = block::unpack_block_prev_blk_try(mpb.root(), blk_id_, prev, mc_blkid, after_split);
|
||||||
|
if (S.is_error()) {
|
||||||
|
fatal_error(std::move(S));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto proof_data = mpb.extract_proof_boc();
|
||||||
|
if (proof_data.is_error()) {
|
||||||
|
fatal_error(proof_data.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lookup_header_proof_ = proof_data.move_as_ok();
|
||||||
|
|
||||||
|
bool include_prev = mode_ & 6;
|
||||||
|
if (include_prev) {
|
||||||
|
BlockIdExt prev_blkid;
|
||||||
|
for (auto& p : prev) {
|
||||||
|
if (ton::shard_contains(p.shard_full(), req_prefix)) {
|
||||||
|
prev_blkid = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK(prev_blkid.is_valid());
|
||||||
|
get_block_handle_checked(prev_blkid, [Self = actor_id(this), masterchain_ref_seqno, manager = manager_](td::Result<ConstBlockHandle> R) mutable {
|
||||||
|
if (R.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(),
|
||||||
|
[Self, masterchain_ref_seqno](td::Result<Ref<BlockData>> res) mutable {
|
||||||
|
if (res.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_gotPrevBlockData, res.move_as_ok(), masterchain_ref_seqno);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
continue_lookupBlockWithProof_gotPrevBlockData(Ref<BlockData>(), masterchain_ref_seqno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_lookupBlockWithProof_gotPrevBlockData(Ref<BlockData> prev_block, BlockSeqno masterchain_ref_seqno) {
|
||||||
|
if (prev_block.not_null()) {
|
||||||
|
CHECK(prev_block.not_null());
|
||||||
|
if (prev_block->root_cell().is_null()) {
|
||||||
|
fatal_error("block has no valid root cell");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vm::MerkleProofBuilder mpb{prev_block->root_cell()};
|
||||||
|
block::gen::Block::Record blk;
|
||||||
|
block::gen::BlockInfo::Record info;
|
||||||
|
if (!(tlb::unpack_cell(mpb.root(), blk) && tlb::unpack_cell(blk.info, info))) {
|
||||||
|
fatal_error(td::Status::Error("cannot unpack prev block header"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto proof_data = mpb.extract_proof_boc();
|
||||||
|
if (proof_data.is_error()) {
|
||||||
|
fatal_error(proof_data.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lookup_prev_header_proof_ = proof_data.move_as_ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blk_id_.is_masterchain()) {
|
||||||
|
ton::AccountIdPrefixFull pfx{ton::masterchainId, ton::shardIdAll};
|
||||||
|
td::actor::send_closure_later(manager_, &ValidatorManager::get_block_by_seqno_from_db, pfx, masterchain_ref_seqno,
|
||||||
|
[manager = manager_, Self = actor_id(this)](td::Result<ConstBlockHandle> R) mutable {
|
||||||
|
if (R.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::actor::send_closure(manager, &ValidatorManager::get_block_data_from_db, R.move_as_ok(),
|
||||||
|
[Self](td::Result<Ref<BlockData>> res) mutable {
|
||||||
|
if (res.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, res.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::continue_lookupBlockWithProof_buildProofLinks, res.move_as_ok(), std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>>());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
base_blk_id_alt_ = blk_id_;
|
||||||
|
td::actor::send_closure(actor_id(this), &LiteQuery::continue_lookupBlockWithProof_getClientMcBlockDataState, std::vector<std::pair<BlockIdExt, Ref<vm::Cell>>>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_lookupBlockWithProof_buildProofLinks(td::Ref<BlockData> cur_block,
|
||||||
|
std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> result) {
|
||||||
|
BlockIdExt cur_id = cur_block->block_id();
|
||||||
|
BlockIdExt prev_id;
|
||||||
|
vm::MerkleProofBuilder mpb{cur_block->root_cell()};
|
||||||
|
if (cur_id.is_masterchain()) {
|
||||||
|
base_blk_id_alt_ = cur_id;
|
||||||
|
block::gen::Block::Record blk;
|
||||||
|
block::gen::BlockExtra::Record extra;
|
||||||
|
block::gen::McBlockExtra::Record mc_extra;
|
||||||
|
if (!tlb::unpack_cell(mpb.root(), blk) || !tlb::unpack_cell(blk.extra, extra) || !extra.custom->have_refs() ||
|
||||||
|
!tlb::unpack_cell(extra.custom->prefetch_ref(), mc_extra)) {
|
||||||
|
fatal_error("cannot unpack header of block "s + cur_id.to_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
block::ShardConfig shards(mc_extra.shard_hashes->prefetch_ref());
|
||||||
|
ShardIdFull shard_id = blk_id_.shard_full();
|
||||||
|
shard_id.shard = (shard_id.shard & ~(1 << (63 - shard_id.pfx_len()))) | 1;
|
||||||
|
Ref<block::McShardHash> shard_hash = shards.get_shard_hash(shard_id, false);
|
||||||
|
if (shard_hash.is_null()) {
|
||||||
|
fatal_error("shard not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev_id = shard_hash->top_block_id();
|
||||||
|
} else {
|
||||||
|
std::vector<BlockIdExt> prev;
|
||||||
|
BlockIdExt mc_blkid;
|
||||||
|
bool after_split;
|
||||||
|
td::Status S = block::unpack_block_prev_blk_try(mpb.root(), cur_id, prev, mc_blkid, after_split);
|
||||||
|
if (S.is_error()) {
|
||||||
|
fatal_error(std::move(S));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool found = false;
|
||||||
|
for (const BlockIdExt& id : prev) {
|
||||||
|
if (shard_intersects(id.shard_full(), blk_id_.shard_full())) {
|
||||||
|
found = true;
|
||||||
|
prev_id = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
fatal_error("failed to find block chain");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto proof = mpb.extract_proof();
|
||||||
|
if (proof.is_error()) {
|
||||||
|
fatal_error(proof.move_as_error_prefix("cannot serialize Merkle proof : "));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result.emplace_back(prev_id, proof.move_as_ok());
|
||||||
|
|
||||||
|
if (prev_id == blk_id_) {
|
||||||
|
CHECK(base_blk_id_alt_.is_masterchain());
|
||||||
|
if (base_blk_id_alt_ != base_blk_id_) {
|
||||||
|
continue_lookupBlockWithProof_getClientMcBlockDataState(std::move(result));
|
||||||
|
} else {
|
||||||
|
continue_lookupBlockWithProof_getMcBlockPrev(std::move(result));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (result.size() == 8) {
|
||||||
|
// Chains of shardblocks between masterchain blocks can't be longer than 8 (see collator.cpp:991)
|
||||||
|
fatal_error("proof chain is too long");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
td::actor::send_closure_later(
|
||||||
|
manager_, &ValidatorManager::get_block_data_from_db_short, prev_id,
|
||||||
|
[Self = actor_id(this), result = std::move(result)](td::Result<Ref<BlockData>> R) mutable {
|
||||||
|
if (R.is_error()) {
|
||||||
|
td::actor::send_closure(Self, &LiteQuery::abort_query, R.move_as_error());
|
||||||
|
} else {
|
||||||
|
td::actor::send_closure_later(Self, &LiteQuery::continue_lookupBlockWithProof_buildProofLinks, R.move_as_ok(),
|
||||||
|
std::move(result));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_lookupBlockWithProof_getClientMcBlockDataState(std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> links) {
|
||||||
|
set_continuation([this, links = std::move(links)]() -> void {
|
||||||
|
continue_lookupBlockWithProof_getMcBlockPrev(std::move(links));
|
||||||
|
});
|
||||||
|
request_mc_block_data_state(base_blk_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LiteQuery::continue_lookupBlockWithProof_getMcBlockPrev(std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> links) {
|
||||||
|
td::BufferSlice mc_state_proof_buf, client_mc_blk_proof_buf;
|
||||||
|
|
||||||
|
if (base_blk_id_alt_ != base_blk_id_) {
|
||||||
|
vm::MerkleProofBuilder mpb{mc_state_->root_cell()};
|
||||||
|
auto prev_blocks_dict = block::get_prev_blocks_dict(mpb.root());
|
||||||
|
if (!prev_blocks_dict) {
|
||||||
|
fatal_error(td::Status::Error("cannot extract prev_blocks from mc state"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!block::check_old_mc_block_id(*prev_blocks_dict, base_blk_id_alt_)) {
|
||||||
|
fatal_error(td::Status::Error("client mc blkid is not in prev_blocks"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto client_mc_blk_proof = mpb.extract_proof_boc();
|
||||||
|
if (client_mc_blk_proof.is_error()) {
|
||||||
|
fatal_error(client_mc_blk_proof.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client_mc_blk_proof_buf = client_mc_blk_proof.move_as_ok();
|
||||||
|
|
||||||
|
Ref<vm::Cell> mc_state_proof;
|
||||||
|
if (!make_mc_state_root_proof(mc_state_proof)) {
|
||||||
|
fatal_error(td::Status::Error("cannot create Merkle proof for mc state"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto mc_state_proof_boc = vm::std_boc_serialize(std::move(mc_state_proof));
|
||||||
|
if (mc_state_proof_boc.is_error()) {
|
||||||
|
fatal_error(mc_state_proof_boc.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mc_state_proof_buf = mc_state_proof_boc.move_as_ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<tl_object_ptr<lite_api::liteServer_shardBlockLink>> links_res;
|
||||||
|
for (auto& p : links) {
|
||||||
|
auto prev_block_proof = vm::std_boc_serialize(std::move(p.second));
|
||||||
|
if (prev_block_proof.is_error()) {
|
||||||
|
fatal_error(prev_block_proof.move_as_error());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
links_res.push_back(
|
||||||
|
create_tl_object<lite_api::liteServer_shardBlockLink>(create_tl_lite_block_id(p.first), prev_block_proof.move_as_ok()));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto b = ton::create_serialize_tl_object<ton::lite_api::liteServer_lookupBlockResult>(ton::create_tl_lite_block_id(blk_id_),
|
||||||
|
mode_, ton::create_tl_lite_block_id(base_blk_id_alt_), std::move(mc_state_proof_buf), std::move(client_mc_blk_proof_buf),
|
||||||
|
std::move(links_res), std::move(lookup_header_proof_), std::move(lookup_prev_header_proof_));
|
||||||
|
finish_query(std::move(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime) {
|
void LiteQuery::perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime) {
|
||||||
if (!((1 << (mode & 7)) & 0x16)) {
|
if (!((1 << (mode & 7)) & 0x16)) {
|
||||||
fatal_error("exactly one of mode.0, mode.1 and mode.2 bits must be set");
|
fatal_error("exactly one of mode.0, mode.1 and mode.2 bits must be set");
|
||||||
|
|
|
@ -69,6 +69,9 @@ class LiteQuery : public td::actor::Actor {
|
||||||
std::unique_ptr<block::BlockProofChain> chain_;
|
std::unique_ptr<block::BlockProofChain> chain_;
|
||||||
Ref<vm::Stack> stack_;
|
Ref<vm::Stack> stack_;
|
||||||
|
|
||||||
|
td::BufferSlice lookup_header_proof_;
|
||||||
|
td::BufferSlice lookup_prev_header_proof_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
default_timeout_msec = 4500, // 4.5 seconds
|
default_timeout_msec = 4500, // 4.5 seconds
|
||||||
|
@ -124,6 +127,8 @@ class LiteQuery : public td::actor::Actor {
|
||||||
UnixTime gen_utime, LogicalTime gen_lt);
|
UnixTime gen_utime, LogicalTime gen_lt);
|
||||||
void perform_getLibraries(std::vector<td::Bits256> library_list);
|
void perform_getLibraries(std::vector<td::Bits256> library_list);
|
||||||
void continue_getLibraries(Ref<MasterchainState> mc_state, BlockIdExt blkid, std::vector<td::Bits256> library_list);
|
void continue_getLibraries(Ref<MasterchainState> mc_state, BlockIdExt blkid, std::vector<td::Bits256> library_list);
|
||||||
|
void perform_getLibrariesWithProof(BlockIdExt blkid, int mode, std::vector<td::Bits256> library_list);
|
||||||
|
void continue_getLibrariesWithProof(std::vector<td::Bits256> library_list, int mode);
|
||||||
void perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt);
|
void perform_getOneTransaction(BlockIdExt blkid, WorkchainId workchain, StdSmcAddress addr, LogicalTime lt);
|
||||||
void continue_getOneTransaction();
|
void continue_getOneTransaction();
|
||||||
void perform_getTransactions(WorkchainId workchain, StdSmcAddress addr, LogicalTime lt, Bits256 hash, unsigned count);
|
void perform_getTransactions(WorkchainId workchain, StdSmcAddress addr, LogicalTime lt, Bits256 hash, unsigned count);
|
||||||
|
@ -138,6 +143,12 @@ class LiteQuery : public td::actor::Actor {
|
||||||
void perform_getConfigParams(BlockIdExt blkid, int mode, std::vector<int> param_list = {});
|
void perform_getConfigParams(BlockIdExt blkid, int mode, std::vector<int> param_list = {});
|
||||||
void continue_getConfigParams(int mode, std::vector<int> param_list);
|
void continue_getConfigParams(int mode, std::vector<int> param_list);
|
||||||
void perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime);
|
void perform_lookupBlock(BlockId blkid, int mode, LogicalTime lt, UnixTime utime);
|
||||||
|
void perform_lookupBlockWithProof(BlockId blkid, BlockIdExt client_mc_blkid, int mode, LogicalTime lt, UnixTime utime);
|
||||||
|
void continue_lookupBlockWithProof_getHeaderProof(Ref<ton::validator::BlockData> block, AccountIdPrefixFull req_prefix, BlockSeqno masterchain_ref_seqno);
|
||||||
|
void continue_lookupBlockWithProof_gotPrevBlockData(Ref<BlockData> prev_block, BlockSeqno masterchain_ref_seqno);
|
||||||
|
void continue_lookupBlockWithProof_buildProofLinks(td::Ref<BlockData> cur_block, std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> result);
|
||||||
|
void continue_lookupBlockWithProof_getClientMcBlockDataState(std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> links);
|
||||||
|
void continue_lookupBlockWithProof_getMcBlockPrev(std::vector<std::pair<BlockIdExt, td::Ref<vm::Cell>>> links);
|
||||||
void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
void perform_listBlockTransactions(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
||||||
void finish_listBlockTransactions(int mode, int count);
|
void finish_listBlockTransactions(int mode, int count);
|
||||||
void perform_listBlockTransactionsExt(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
void perform_listBlockTransactionsExt(BlockIdExt blkid, int mode, int count, Bits256 account, LogicalTime lt);
|
||||||
|
|
|
@ -314,7 +314,8 @@ bool AsyncStateSerializer::need_serialize(BlockHandle handle) {
|
||||||
if (handle->id().id.seqno == 0 || !handle->is_key_block()) {
|
if (handle->id().id.seqno == 0 || !handle->is_key_block()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ValidatorManager::is_persistent_state(handle->unix_time(), last_key_block_ts_);
|
return ValidatorManager::is_persistent_state(handle->unix_time(), last_key_block_ts_) &&
|
||||||
|
ValidatorManager::persistent_state_ttl(handle->unix_time()) > (UnixTime)td::Clocks::system();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace validator
|
} // namespace validator
|
||||||
|
|
|
@ -121,6 +121,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
double get_archive_preload_period() const override {
|
double get_archive_preload_period() const override {
|
||||||
return archive_preload_period_;
|
return archive_preload_period_;
|
||||||
}
|
}
|
||||||
|
bool get_disable_rocksdb_stats() const override {
|
||||||
|
return disable_rocksdb_stats_;
|
||||||
|
}
|
||||||
ValidatorMode validator_mode() const override {
|
ValidatorMode validator_mode() const override {
|
||||||
return validator_mode_;
|
return validator_mode_;
|
||||||
}
|
}
|
||||||
|
@ -186,6 +189,9 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
void set_archive_preload_period(double value) override {
|
void set_archive_preload_period(double value) override {
|
||||||
archive_preload_period_ = value;
|
archive_preload_period_ = value;
|
||||||
}
|
}
|
||||||
|
void set_disable_rocksdb_stats(bool value) override {
|
||||||
|
disable_rocksdb_stats_ = value;
|
||||||
|
}
|
||||||
void set_validator_mode(ValidatorMode value) override {
|
void set_validator_mode(ValidatorMode value) override {
|
||||||
validator_mode_ = value;
|
validator_mode_ = value;
|
||||||
}
|
}
|
||||||
|
@ -232,6 +238,7 @@ struct ValidatorManagerOptionsImpl : public ValidatorManagerOptions {
|
||||||
td::uint32 celldb_compress_depth_{0};
|
td::uint32 celldb_compress_depth_{0};
|
||||||
size_t max_open_archive_files_ = 0;
|
size_t max_open_archive_files_ = 0;
|
||||||
double archive_preload_period_ = 0.0;
|
double archive_preload_period_ = 0.0;
|
||||||
|
bool disable_rocksdb_stats_;
|
||||||
ValidatorMode validator_mode_ = validator_normal;
|
ValidatorMode validator_mode_ = validator_normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
||||||
virtual td::uint32 get_celldb_compress_depth() const = 0;
|
virtual td::uint32 get_celldb_compress_depth() const = 0;
|
||||||
virtual size_t get_max_open_archive_files() const = 0;
|
virtual size_t get_max_open_archive_files() const = 0;
|
||||||
virtual double get_archive_preload_period() const = 0;
|
virtual double get_archive_preload_period() const = 0;
|
||||||
|
virtual bool get_disable_rocksdb_stats() const = 0;
|
||||||
virtual ValidatorMode validator_mode() const = 0;
|
virtual ValidatorMode validator_mode() const = 0;
|
||||||
|
|
||||||
virtual void set_zero_block_id(BlockIdExt block_id) = 0;
|
virtual void set_zero_block_id(BlockIdExt block_id) = 0;
|
||||||
|
@ -106,6 +107,7 @@ struct ValidatorManagerOptions : public td::CntObject {
|
||||||
virtual void set_celldb_compress_depth(td::uint32 value) = 0;
|
virtual void set_celldb_compress_depth(td::uint32 value) = 0;
|
||||||
virtual void set_max_open_archive_files(size_t value) = 0;
|
virtual void set_max_open_archive_files(size_t value) = 0;
|
||||||
virtual void set_archive_preload_period(double value) = 0;
|
virtual void set_archive_preload_period(double value) = 0;
|
||||||
|
virtual void set_disable_rocksdb_stats(bool value) = 0;
|
||||||
virtual void set_validator_mode(ValidatorMode value) = 0;
|
virtual void set_validator_mode(ValidatorMode value) = 0;
|
||||||
|
|
||||||
static td::Ref<ValidatorManagerOptions> create(
|
static td::Ref<ValidatorManagerOptions> create(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue