1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

Compare commits

...

182 commits

Author SHA1 Message Date
EmelyanenkoK
0439613bff
Merge pull request #1543 from ton-blockchain/testnet
Merge developer branch
2025-03-05 17:21:19 +03:00
EmelyanenkoK
cf50b4b5da Update changelogs 2025-03-05 09:51:34 +03:00
EmelyanenkoK
6eeae5d78b
Merge pull request #1545 from ton-blockchain/tolk-v0.9
Tolk v0.9: nullable types `T?`, null safety, control flow, smart casts
2025-03-05 09:30:05 +03:00
neodix42
faf58118a4
Fix failing docker build - arm64 (#1541)
* fix docker github build (Segmentation fault (core dumped) dpkg: error processing package libc-bin (--configure))

* fix docker github build (Segmentation fault (core dumped) dpkg: error processing package libc-bin (--configure))

* update gh qemu actions

* run on ubuntu 24.04

* try driver-opts: image=moby/buildkit:v0.11.0

* split docker images for amd64 and arm64

* Revert "split docker images for amd64 and arm64"

This reverts commit 609617f005.

* clean libc-bin
2025-03-05 09:29:49 +03:00
tolk-vm
f67e9f4b6f
[Tolk] Bump version to v0.9 2025-02-28 16:44:18 +03:00
tolk-vm
ef0328837f
[Tolk] throw interrupts control flow; never type
In FunC (and in Tolk before) throwing an exception is just
calling a built-in function:
> throw 123; // actually, __throw(123)
Since it's a regular function, the compiler was not aware
that execution will stop, and all following code is unreachable.
For instance, `throw` in the end on function needed to be
followed by `return` statement.

Now, `throw` interrupts control flow, all statements after
it are considered unreachable. At IR level, code Ops are
also not produced.

This works because a built-in __throw() now has `never` type.
It can also be applied to custom functions:
> fun alwaysThrow(): never { throw 123; }
The code after alwaysThrow() call will also be unreachable.
2025-02-28 16:44:18 +03:00
tolk-vm
7bcb8b895f
[Tolk] Smart casts and control flow graph
With the introduction of nullable types, we want the
compiler to be smart in cases like
> if (x == null) return;
> // x is int now
or
> if (x == null) x = 0;
> // x is int now

These are called smart casts: when the type of variable
at particular usage might differ from its declaration.

Implementing smart casts is very challenging. They are based
on building control-flow graph and handling every AST vertex
with care. Actually, I represent cfg not a as a "graph with
edges". Instead, it's a "structured DFS" for the AST:
1) at every point of inferring, we have "current flow facts"
2) when we see an `if (...)`, we create two derived contexts
3) after `if`, finalize them at the end and unify
4) if we detect unreachable code, we mark that context
In other words, we get the effect of a CFG but in a more direct
approach. That's enough for AST-level data-flow.

Smart casts work for local variables and tensor/tuple indices.
Compilation errors have been reworked and now are more friendly.
There are also compilation warnings for always true/false
conditions inside if, assert, etc.
2025-02-28 16:44:15 +03:00
tolk-vm
f3e620f48c
[Tolk] Nullable types T? and null safety
This commit introduces nullable types `T?` that are
distinct from non-nullable `T`.
Example: `int?` (int or null) and `int` are different now.
Previously, `null` could be assigned to any primitive type.
Now, it can be assigned only to `T?`.

A non-null assertion operator `!` was also introduced,
similar to `!` in TypeScript and `!!` in Kotlin.

If `int?` still occupies 1 stack slot, `(int,int)?` and
other nullable tensors occupy N+1 slots, the last for
"null precedence". `v == null` actually compares that slot.
Assigning `(int,int)` to `(int,int)?` implicitly creates
a null presence slot. Assigning `null` to `(int,int)?` widens
this null value to 3 slots. This is called "type transitioning".

All stdlib functions prototypes have been updated to reflect
whether they return/accept a nullable or a strict value.

This commit also contains refactoring from `const FunctionData*`
to `FunctionPtr` and similar.
2025-02-28 16:41:41 +03:00
SpyCheese
44e7e091b2
Use HashSet/HashMap in storage stat (#1540) 2025-02-27 15:41:21 +03:00
SpyCheese
b3b2bd1c3c
New extra currency behavior (#1539) 2025-02-27 15:18:59 +03:00
tolk-vm
1389ff6789
[Tolk] Change order of assignment evaluation, lhs first
In FunC (and in Tolk before), the assignment
> lhs = rhs
evaluation order (at IR level) was "rhs first, lhs second".
In practice, this did not matter, because lhs could only
be a primitive:
> (v1, v2) = getValue()
Left side of assignment actually has no "evaluation".
Since Tolk implemented indexed access, there could be
> getTensor().0 = getValue()
or (in the future)
> getObject().field = getValue()
where evaluation order becomes significant.

Now evaluation order will be to "lhs first, rhs second"
(more expected from user's point of view), which will become
significant when building control flow graph.
2025-02-24 20:11:13 +03:00
Marat
1b70e48327
Add option to build static tonlibjson and emulator (#1527)
* add option to build static tonlibjson and emulator

* do not export cmake project in case of static tonlibjson
2025-02-23 15:01:33 +03:00
EmelyanenkoK
3ff951c225
Merge pull request #1530 from ton-blockchain/node-patch
Node patch
2025-02-21 11:50:15 +03:00
EmelyanenkoK
901467f424
Merge pull request #1529 from ton-blockchain/master
Merge master
2025-02-21 11:27:28 +03:00
SpyCheese
1e8fdc0561
Fix updateInit offset in storage (#1525) 2025-02-21 10:52:23 +03:00
Sild
61b9155d15
dont use instance after std::move (#1528)
Co-authored-by: Dmitrii Korchagin <d.korchagin@ston.fi>
2025-02-21 10:46:33 +03:00
SpyCheese
8a08bf67a2 Experimental flags for speeding up broadcasts 2025-02-20 17:32:24 +03:00
SpyCheese
04f2bc1360 Fix downloading persistent states in WaitBlockState 2025-02-19 12:44:50 +03:00
SpyCheese
aca51a8dae Don't check external messages if out of sync 2025-02-17 10:14:12 +03:00
SpyCheese
9d94e04d20 Add more stats to validator getstats
1) Liteserver queries count
2) Collated/validated blocks count, number of active sessions
3) Persistent state sizes
4) Initial sync progress
2025-02-17 10:13:17 +03:00
SpyCheese
ce6c29941e Get rid of std::cerr logs in collator/validator 2025-02-13 14:25:04 +03:00
EmelyanenkoK
2a68c8610b
Merge pull request #1516 from ton-blockchain/fix-ls-capabilities
Fix get_prev_blocks_info() at LS getConfigParams [does not affect validators]
2025-02-06 11:32:01 +03:00
Marat S
aef538114a Fix get_prev_blocks_info() at LS getConfigParams 2025-02-06 11:29:55 +03:00
EmelyanenkoK
050a984163
Merge pull request #1512 from ton-blockchain/testnet
Merge developer branch
2025-02-04 12:27:03 +03:00
EmelyanenkoK
3c245c6146
Add forgotten highload-v2 to unlock (#1511) 2025-02-03 11:16:44 +03:00
neodix42
c7271d97ae
Add smartcont+lib folders to release (#1508)
* add folders smartcont and lib only to release for having a small download link

* allow usage of patter in file name

* upgrade upload-release-action@v2 to v3

* Revert "upgrade upload-release-action@v2 to v3"

This reverts commit 516126084a.

* use gh cli for upload smartcont_lib

* use gh cli for upload smartcont_lib

* gh requires gh_token

* clean up
2025-02-03 11:16:11 +03:00
EmelyanenkoK
e5feb76b90
Merge pull request #1503 from ton-blockchain/tolk-v0.8
Tolk v0.8: preparation for structures; indexed access `var.0`
2025-02-03 11:15:38 +03:00
tolk-vm
b1c9466df4
Suppress clang warning "ATOMIC_FLAG_INIT marked deprecated" (#1502)
In C++20, macro 'ATOMIC_FLAG_INIT' has been marked as deprecated.
We need still to use it to be able to compile for C++17.
For now, just suppress this warning.
2025-01-27 17:09:21 +03:00
tolk-vm
e9d8f1611b
[Tolk] Bump version to v0.8 2025-01-27 15:30:21 +03:00
tolk-vm
5b44e01455
[Tolk] Allow cell and slice be valid identifiers
They are not keywords anymore.
> var cell = ...;
> var cell: cell = ...;
Motivation: in the future, when structures are implemented, this obviously should be valid:
> struct a { ... }
> var a = ...;
Struct fields will also be allowed to have names int/slice/cell.
2025-01-27 15:30:21 +03:00
tolk-vm
7a1602f591
[Tolk] Support syntax tensorVar.0 and tupleVar.0
It works both for reading and writing:
> var t = (1, 2);
> t.0;      // 1
> t.0 = 5;
> t;        // (5, 2)

It also works for typed/untyped tuples, producing INDEX and SETINDEX.

Global tensors and tuples works. Nesting `t.0.1.2` works. `mutate` works.
Even mixing tuples inside tensors inside a global for writing works.
2025-01-27 15:30:21 +03:00
tolk-vm
565bc59735
[Tolk] Refactor: get rid of split_vars, construct valid LET ops
In FunC (and in Tolk before), tensor vars (actually occupying
several stack slots) were represented as a single var in terms
or IR vars (Ops):
> var a = (1, 2);
> LET (_i) = (_1, _2)

Now, every tensor of N stack slots is represented as N IR vars.
> LET (_i, _j) = (_1, _2)

This will give an ability to control access to parts of a tensor
when implementing `tensorVar.0` syntax.
2025-01-27 15:30:21 +03:00
tolk-vm
989629a832
[Tolk] Compiler built-in __expect_type() for testing purposes
Currently, tolk-tester can test various "output" of the compiler:
pass input and check output, validate fif codegen, etc.
But it can not test compiler internals and AST representation.

I've added an ability to have special functions to check/expose
internal compiler state. The first (and the only now) is:
> __expect_type(some_expr, "<type>");
Such a call has special treatment in a compilation process.
Compilation fails if this expression doesn't have requested type.

It's intended to be used in tests only. Not present in stdlib.
2025-01-27 15:30:21 +03:00
Marat
c720204199
Fix BUILD_SHARED_LIBS issue (#1496) 2025-01-27 14:34:21 +03:00
EmelyanenkoK
294db69227 Fix typos in changelog 2025-01-27 14:33:52 +03:00
EmelyanenkoK
6f1feb43d5 Update Changelogs 2025-01-27 12:58:54 +03:00
SpyCheese
8ffa3dd9dc
Fix printing TLB NatWidth (#1501) 2025-01-27 12:55:00 +03:00
Andrey Tvorozhkov
2a02b54786
Fix advance_ext (#746) 2025-01-27 12:22:00 +03:00
tuminzee
ed88f55a3d
fix broken link (#1497) 2025-01-27 10:35:56 +03:00
EmelyanenkoK
818a254126 Merge branch 'master' into testnet 2025-01-27 10:33:58 +03:00
Marat
99b78f78d7
build fix (#1495) 2025-01-27 10:20:20 +03:00
neodix42
7d9ef6e0bf
Fix wasm artifacts (#1499)
* put back emscripten 3.1.19

* add create-tolk-release.yml

* filter out master branch only
2025-01-27 10:18:51 +03:00
neodix42
59a8cf0ae5
create tolk release github action (#1490)
* add create-tolk-release.yml

* adjust create-tolk-release for old workflows

* use custom tag

* use old names

* use old names
2025-01-26 16:41:17 +03:00
Marat
e7e57f8e6d
add extra currencies support to emulator (#1494) 2025-01-26 16:39:05 +03:00
SpyCheese
da5644e758
Enable VmState::jump_to bugfix in version 9 (#1491) 2025-01-24 17:48:05 +03:00
Ivan Kalinin
0f6cf13d45
fix(vm): fix saving ret on deep jump (#1487) 2025-01-24 17:41:43 +03:00
EmelyanenkoK
fe46f0e238
Merge pull request #1482 from ton-blockchain/tvm-v9
Tvm v9
2025-01-22 11:13:49 +03:00
neodix42
e0605156de
Reworked TON portable artifacts (#1486)
* improve windows builds

* install nasm for openssl compilation on win

* install nasm for openssl compilation on win for github

* add create-state, proxy-liteserver, rldp-http-proxy, http-proxy, adnl-proxy, dht-server, libtonlibjson.so and libemulator.so to docker image

* build new artifacts inside Docker

* add files smartcont/auto/* to docker image

* build arm64 in docker branch build

* improve secp256k1 build

* adding natively portable binaries (all statically linked with libc++, without nixpkgs help) for x86-64 linux

* install missing headers on ubuntu 20.04

* use clang-16 on ubuntu 20.04

* remove gsl for portable artifacts; add -f key to generate-random-id in order to read addr_list from file;

* typo

* decode json

* decode json

* add github workflow for appimages creation

* add missing dependencies

* use libc++ for appimages artifacts

* typo

* appimages wihtout libc++

* appimages with libc++ and some checks

* add appimages to release (for testing)

* add appimages to release (for testing)

* add appimages to release (for testing)

* add appimages to release (for testing) 2

* add appimages to release (for testing) 3

* appimages only on ubuntu 22 with ssl-3 for now

* appimages only on ubuntu 20 with ssl-3 for now

* appimages only on ubuntu 20 with ssl-3 for now

* add export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}" to appimage AppRun

* create release

* appimages without jemalloc

* bind specific libraries to appimages

* add libreadline

* add plain portable libs

* add proper /lib/x86_64-linux-gnu/libreadline.so.8

* app images build with libc

* try to ensure ABI compatibility with older glibc

* try to ensure ABI compatibility with older glibc for shared libraries

* shared lib without libc but with D_GLIBCXX_USE_CXX11_ABI and -static-libgcc -static-libstdc++

* add -fPIC -fcommon

* add /lib/x86_64-linux-gnu/libstdc++.so.6 to static binaries

* add -static-libgcc -static-libstdc++ to libtonlibjson and emulator when PORTABLE=1

* add -static-libgcc -static-libstdc++ to libtonlibjson and emulator when PORTABLE=1

* update emulator portable

* Update CMakeLists.txt

* test portable macos binaries

* do not use -static-libgcc -static-libstdc++ on mac for shared libs

* do not use -static-libgcc -static-libstdc++ on mac for shared libs

* adjust create-release.yml

* minor fixes, typos

* minor fixes

* linux apps double check

* avoid infinite loop when place in system bin dir

* avoid infinite loop when place in system bin dir 2

* test compilation on linux arm64

* test appimages on arm64 linux

* test appimages on arm64 linux 2

* add portable linux arm64 to release

* clean up

* update README.md
2025-01-21 11:27:25 +03:00
SpyCheese
e42b0cba26 Merge branch 'testnet' into tvm-v9 2025-01-20 13:59:59 +03:00
EmelyanenkoK
1b7c46f496
Merge pull request #1477 from ton-blockchain/tolk-v0.7
Tolk v0.7: overhaul compiler internals and the type system; `bool` type
2025-01-20 12:31:03 +03:00
SpyCheese
a224491179
Fix error processing in StaticBagOfCellsDb (#1481) 2025-01-17 15:58:15 +03:00
SpyCheese
2d603f1f47 Adjust overridden gas limit 2025-01-17 12:46:58 +03:00
SpyCheese
77e5a2f4a2 Merge branch 'testnet' into tvm-v9 2025-01-17 12:32:09 +03:00
SpyCheese
d3485e42b9 Temporary increase gas limit for certain accounts 2025-01-17 12:26:53 +03:00
SpyCheese
710514b8f1
Validate Merkle proofs and updates in TLB validate (#1479)
* Validate Merkle proofs and updates in TLB validate

* Fix out-of-bound access in tl_jni_object.cpp
2025-01-16 09:42:05 +03:00
tolk-vm
2997c027a2
[Tolk] Bump version to v0.7
Totally, v0.7 will include:
- AST-level semantic kernel, transform AST to Ops directly
- fully rewritten type system, drop Hindley-Milner
- `bool` type support
2025-01-15 15:38:47 +03:00
tolk-vm
974d76c5f6
[Tolk] bool type (-1/0 int under the hood)
Comparison operators `== / >= /...` return `bool`.
Logical operators `&& ||` return bool.
Constants `true` and `false` have the `bool` type.
Lots of stdlib functions return `bool`, not `int`.

Operator `!x` supports both `int` and `bool`.
Condition of `if` accepts both `int` and `bool`.
Arithmetic operators are restricted to integers.
Logical `&&` and `||` accept both `bool` and `int`.

No arithmetic operations with bools allowed (only bitwise and logical).
2025-01-15 15:38:47 +03:00
tolk-vm
799e2d1265
[Tolk] Rewrite the type system from Hindley-Milner to static typing
FunC's (and Tolk's before this PR) type system is based on Hindley-Milner.
This is a common approach for functional languages, where
types are inferred from usage through unification.
As a result, type declarations are not necessary:
() f(a,b) { return a+b; } // a and b now int, since `+` (int, int)

While this approach works for now, problems arise with the introduction
of new types like bool, where `!x` must handle both int and bool.
It will also become incompatible with int32 and other strict integers.
This will clash with structure methods, struggle with proper generics,
and become entirely impractical for union types.

This PR completely rewrites the type system targeting the future.
1) type of any expression is inferred and never changed
2) this is available because dependent expressions already inferred
3) forall completely removed, generic functions introduced
   (they work like template functions actually, instantiated while inferring)
4) instantiation `<...>` syntax, example: `t.tupleAt<int>(0)`
5) `as` keyword, for example `t.tupleAt(0) as int`
6) methods binding is done along with type inferring, not before
   ("before", as worked previously, was always a wrong approach)
2025-01-15 15:38:43 +03:00
dbaranovstonfi
987c7ca04b
emulator: set libraries when libs is NOT empty (#1449)
Co-authored-by: dbaranov34 <baranov34@gmail.com>
2025-01-15 13:50:18 +03:00
SpyCheese
2ebc6d6a3c
Fix error processing in load_cell (#1467) 2025-01-15 10:45:04 +03:00
SpyCheese
62838571eb
Support extra currencies in reserve action with +2 flag (#1429)
* Support extra currencies in reserve action with +2 flag

* Enable new reserve behavior in version 9
2025-01-15 10:43:33 +03:00
Victor S.
f6fa986b33
Fix *DATASIZE* opcode log msg (#1465)
Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
2025-01-15 10:39:05 +03:00
crStiv
652f4f0141
Update Changelog.md (#1476)
Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
2025-01-15 10:36:46 +03:00
EmelyanenkoK
8b68210db7
Merge pull request #1475 from ton-blockchain/node-patch
Bugfixes in node and tonlib
2025-01-15 10:34:19 +03:00
SpyCheese
87c4b4a5d4 Fix handling small out-of-sync in validate-query 2025-01-13 17:41:50 +03:00
SpyCheese
cae9ccfacf Retry dht query in adnl-peer if peer does not respond for too long 2025-01-13 17:41:10 +03:00
SpyCheese
4ddb14c136 Fix double tilde for crc computation in tlbc 2025-01-13 17:40:16 +03:00
SpyCheese
dc2f0dad81 Add extra currencies to c7 in tonlib runGetMethod 2025-01-13 17:39:56 +03:00
tolk-vm
3540424aa1
[Tolk] AST-based semantic analysis, get rid of Expr
This is a huge refactoring focusing on untangling compiler internals
(previously forked from FunC).
The goal is to convert AST directly to Op (a kind of IR representation),
doing all code analysis at AST level.

Noteable changes:
- AST-based semantic kernel includes: registering global symbols,
  scope handling and resolving local/global identifiers,
  lvalue/rvalue calc and check, implicit return detection,
  mutability analysis, pure/impure validity checks,
  simple constant folding
- values of `const` variables are calculated NOT based on CodeBlob,
  but via a newly-introduced AST-based constant evaluator
- AST vertices are now inherited from expression/statement/other;
  expression vertices have common properties (TypeExpr, lvalue/rvalue)
- symbol table is rewritten completely, SymDef/SymVal no longer exist,
  lexer now doesn't need to register identifiers
- AST vertices have references to symbols, filled at different
  stages of pipeline
- the remaining "FunC legacy part" is almost unchanged besides Expr
  which was fully dropped; AST is converted to Ops (IR) directly
2025-01-13 20:28:44 +07:00
neodix42
46d4e12b4c
extend generate-random-id utility... (#1462)
* improve windows builds

* install nasm for openssl compilation on win

* install nasm for openssl compilation on win for github

* add create-state, proxy-liteserver, rldp-http-proxy, http-proxy, adnl-proxy, dht-server, libtonlibjson.so and libemulator.so to docker image

* build new artifacts inside Docker

* add files smartcont/auto/* to docker image

* build arm64 in docker branch build

* improve secp256k1 build

* extend generate-random-id with -f parameter (to read addr list from a file)
2025-01-07 19:15:51 +03:00
SpyCheese
0fff1bd8c7 Fix loading library cell in contract code 2024-12-18 12:57:21 +03:00
SpyCheese
a01c7e2e75 Add more recent blocks to "previous blocks info" 2024-12-18 12:57:21 +03:00
SpyCheese
f03f6ce7ca Fix check_underflow in some instructions 2024-12-18 12:57:21 +03:00
SpyCheese
ce58805104
Improve readability of validator-engine-console commands (#1426)
1. Add dashes to command names (old names still work for compatibility)
2. Better shard format
3. Allow base64 in some parameters
2024-12-11 14:48:48 +03:00
EmelyanenkoK
ea0dc16163
Merge pull request #1427 from ton-blockchain/testnet
Merge developer branch
2024-12-11 14:43:20 +03:00
neodix42
540d1fb4b7
Improve windows build scripts (#1416)
* improve windows builds

* install nasm for openssl compilation on win

* install nasm for openssl compilation on win for github

* add create-state, proxy-liteserver, rldp-http-proxy, http-proxy, adnl-proxy, dht-server, libtonlibjson.so and libemulator.so to docker image

* build new artifacts inside Docker

* add files smartcont/auto/* to docker image

* build arm64 in docker branch build

* improve secp256k1 build
2024-12-11 14:41:45 +03:00
EmelyanenkoK
d3d050a319 Update changelogs 2024-12-09 10:00:31 +03:00
SpyCheese
7df2ea9f06
Improve async cell loading in DynamicBagOfCellsDb.cpp (#1414) 2024-12-06 11:56:24 +03:00
krigga
fd095403d7
fix: missing _malloc in emulator-emscripten (#1420) 2024-12-06 11:50:50 +03:00
SpyCheese
645d26a1f3
Patch tonlib and validator-engine (#1417)
* Don't enable fast state serializer automatically

* Fix checking masterchain proof in tonlib lookupBlock
2024-12-05 18:50:12 +03:00
SpyCheese
7bc50e63d7
tonNode.getOutMsgQueueProof query in public shard overlays (#1413)
* tonNode.getOutMsgQueueProof query in public shard overlays

* Allow responding to getOutMsgQueueProof requests one at a time only
2024-12-04 14:38:57 +03:00
SpyCheese
9ae88d87e3
Export all keys command in validator-engine-console (#1412)
* Export all keys command in validator-engine-console

* Use OPENSSL_cleanse in Bits256::fill_zero_s
2024-12-03 17:19:12 +03:00
neodix42
4aa6412f9c
Include proxy-liteserver (#1406)
* include into artifacts

* include proxy-liteserver into release artifacts
2024-12-03 10:03:14 +03:00
SpyCheese
ed7ac6312a
Fix UB in query-utils.cpp (#1411) 2024-12-03 10:02:51 +03:00
dependabot[bot]
531b6ceccc
Bump dawidd6/action-download-artifact from 2 to 6 in /.github/workflows (#1400)
Bumps [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) from 2 to 6.
- [Release notes](https://github.com/dawidd6/action-download-artifact/releases)
- [Commits](https://github.com/dawidd6/action-download-artifact/compare/v2...v6)

---
updated-dependencies:
- dependency-name: dawidd6/action-download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 10:02:30 +03:00
SpyCheese
25b4c6794a
TVM instructions: SECP256K1_XONLY_PUBKEY_TWEAK_ADD, SETCONTCTRMANY(X) (#1404)
* TVM instructions: SECP256K1_XONLY_PUBKEY_TWEAK_ADD, SETCONTCTRMANY(X)

* Add tests for xonly_pubkey_tweak_add

* added secp256k1 as submodule, since we need extrakeys feature of secp256k1

* cleanup

* add ton_crypto_core secp256k1 dependency

* adjust Dockerfile, android and wasm builds

* adjust nix build

* test windows build with SECP256K1_ENABLE_MODULE_EXTRAKEYS

* test windows build with SECP256K1_ENABLE_MODULE_EXTRAKEYS

* adjust android build

* adjust emscripten build

* adjust emscripten build

* try macos-13

* emscripten build adjustments

* windows build adjustments

* final corrections

---------

Co-authored-by: neodix <neodix@ton.org>
2024-11-26 16:23:17 +03:00
SpyCheese
954a96a077
Accelerator: partial fullnodes (#1393)
* Accelerator: partial fullnodes

1) Node can monitor a subset of shards
2) New archive slice format (sharded)
3) Validators are still required to have all shards
4) Support partial liteservers in lite-client, blockchain explorer, tonlib
5) Proxy liteserver

* Fix compilation error
2024-11-26 14:46:58 +03:00
neodix42
62444100f5
Add message hash to tonlib response (#1379)
* add msg hash

* regenerate tonlib_api.tlo
2024-11-26 11:23:05 +03:00
SpyCheese
8a41ee8ffb
Generate random privkey in AdnlExtClient (#1398) 2024-11-26 11:22:35 +03:00
SpyCheese
061c82f89c
Send validator telemetry to the private overlay (#1325)
* Send validator telemetry to the private overlay

* Improve rotating neighbours in overlays
2024-11-25 22:37:18 +03:00
SpyCheese
52b010ff34
Fix block limit classification (#1337)
Block size estimation can decrease, so it was possible that soft limit was reached, but the block is not considered overloaded
2024-11-18 09:39:20 +03:00
SpyCheese
413da6cd20
Cached checked certificates in overlays (#1338) 2024-11-18 09:38:32 +03:00
tolk-vm
f00ff75548
[FunC] Make Expr::VarApply always impure (#1381)
Expr::_VarApply is now always impure. It means, that
for `some_var()`, don't make any considerations about runtime value,
it's always called.
2024-11-14 18:32:04 +03:00
tolk-vm
89f136e670
[FunC] Add more tests for try/catch (#1380)
After fixing a bug with c1/c3 registers in #1332,
cover an issue with tests.
2024-11-14 18:31:21 +03:00
neodix42
a904a0a195
remove stripping of artifacts (#1375)
* remove stripping from nix artifacts

* remove stripping from natively compiled binaries

* add missing tolk on mac

* add missing tolk on mac
2024-11-11 16:07:06 +03:00
EmelyanenkoK
3ce6118c3f
Fix try-catch: save c1, c3 to catch continuation (#1332) 2024-11-02 18:23:08 +03:00
EmelyanenkoK
a5f1f7d73e
Merge pull request #1351 from ton-blockchain/master
Merge tolk
2024-11-02 18:22:24 +03:00
EmelyanenkoK
7151ff2627
Merge pull request #1345 from ton-blockchain/tolk-v0.6.0
Tolk Language: next-generation FunC
2024-11-02 18:20:23 +03:00
tolk-vm
d110022731
[Tolk] Implement logical operators && ||
Unary logical NOT was already implemented earlier.
Logical AND OR are expressed via conditional expression:
* a && b  ->  a ? (b != 0) : 0
* a || b  ->  a ? 1 : (b != 0)
They work as expected in any expressions. For instance, having
`cond && f()`, f is called only if cond is true.
For primitive cases, like `a > 0 && b > 0`, Fift code is not optimal,
it could potentially be without IFs.
These are moments of future optimizations. For now, it's more than enough.
2024-11-02 03:44:14 +04:00
tolk-vm
16824fcfe3
[Tolk] Get rid of ton_crypto dependency, embed address parsing
Instead on 'ton_crypto', Tolk now depends on 'ton_crypto_core'.
The only purpose of ton_crypto (in FunC also, btw) is address parsing:
"EQCRDM9...", "0:52b3..." and so on.
Such parsing has been implemented manually exactly the same way.
2024-11-02 03:44:14 +04:00
tolk-vm
d9dba320cc
[Tolk] Get rid of ~tilda with mutate and self methods
This is a very big change.
If FunC has `.methods()` and `~methods()`, Tolk has only dot,
one and only way to call a `.method()`.
A method may mutate an object, or may not.
It's a behavioral and semantic difference from FunC.

- `cs.loadInt(32)` modifies a slice and returns an integer
- `b.storeInt(x, 32)` modifies a builder
- `b = b.storeInt()` also works, since it not only modifies, but returns
- chained methods also work, they return `self`
- everything works exactly as expected, similar to JS
- no runtime overhead, exactly same Fift instructions
- custom methods are created with ease
- tilda `~` does not exist in Tolk at all
2024-11-02 03:44:14 +04:00
tolk-vm
12ff28ac94
[Tolk] Completely rework stdlib: multiple files and renaming
- split stdlib.tolk into multiple files (tolk-stdlib/ folder)
  (the "core" common.tolk is auto-imported, the rest are
  needed to be explicitly imported like "@stdlib/tvm-dicts.tolk")
- all functions were renamed to long and clear names
- new naming is camelCase
2024-11-02 03:44:13 +04:00
tolk-vm
e2edadba92
[Tolk] v0.6 syntax: fun, import, var, types on the right, etc.
Lots of changes, actually. Most noticeable are:
- traditional //comments
- #include -> import
- a rule "import what you use"
- ~ found -> !found (for -1/0)
- null() -> null
- is_null?(v) -> v == null
- throw is a keyword
- catch with swapped arguments
- throw_if, throw_unless -> assert
- do until -> do while
- elseif -> else if
- drop ifnot, elseifnot
- drop rarely used operators

A testing framework also appears here. All tests existed earlier,
but due to significant syntax changes, their history is useless.
2024-11-02 03:44:13 +04:00
tolk-vm
5a3e3595d6
[Tolk] Compilation pipeline, register global symbols in advance
Since I've implemented AST, now I can drop forward declarations.
Instead, I traverse AST of all files and register global symbols
(functions, constants, global vars) as a separate step, in advance.

That's why, while converting AST to Expr/Op, all available symbols are
already registered.
This greatly simplifies "intermediate state" of yet unknown functions
and checking them afterward.

Redeclaration of local variables (inside the same scope)
is now also prohibited.
2024-11-02 01:33:09 +04:00
tolk-vm
80001d1756
[Tolk] Implement AST: intermediate representation of tolk files
Now, the whole .tolk file can be loaded as AST tree and
then converted to Expr/Op.
This gives a great ability to implement AST transformations.
In the future, more and more code analysis will be moved out of legacy to AST-level.
2024-11-02 01:33:08 +04:00
tolk-vm
6c30e5a7eb
[Tolk] Embedded stdlib.tolk, CompilerState, strict includes
Several related changes:
- stdlib.tolk is embedded into a distribution (deb package or tolk-js),
  the user won't have to download it and store as a project file;
  it's an important step to maintain correct language versioning
- stdlib.tolk is auto-included, that's why all its functions are
  available out of the box
- strict includes: you can't use symbol `f` from another file
  unless you've #include'd this file
- drop all C++ global variables holding compilation state,
  merge them into a single struct CompilerState located at
  compiler-state.h; for instance, stdlib filename is also there
2024-11-02 01:33:08 +04:00
tolk-vm
f0e6470d0b
[Tolk] Rewrite lexer, spaces are not mandatory anymore
A new lexer is noticeably faster and memory efficient
(although splitting a file to tokens is negligible in a whole pipeline).

But the purpose of rewriting lexer was not just to speed up,
but to allow writing code without spaces:
`2+2` is now 4, not a valid identifier as earlier.

The variety of symbols allowed in identifier has greatly reduced
and is now similar to other languages.

SrcLocation became 8 bytes on stack everywhere.

Command-line flags were also reworked:
- the input for Tolk compiler is only a single file now, it's parsed, and parsing continues while new #include are resolved
- flags like -A -P and so on are no more needed, actually
2024-11-02 01:33:08 +04:00
tolk-vm
0bcc0b3c12
[Fift] Fix an issue of FunC/Tolk WASM which truncated long fif output
As it turned out, PSTRING() created a buffer of 128K.
If asm_code exceeded this buffer, it was truncated.
I've just dropped PSTRING() from there in favor of std::string.
2024-11-02 01:33:08 +04:00
tolk-vm
ebbab54cda
[Tolk] Tolk v0.5.0 as FunC v0.5.0 could have been like
All changes from PR "FunC v0.5.0":
https://github.com/ton-blockchain/ton/pull/1026

Instead of developing FunC, we decided to fork it.
BTW, the first Tolk release will be v0.6,
a metaphor of FunC v0.5 that missed a chance to occur.
2024-11-02 01:33:08 +04:00
tolk-vm
82648ebd6a
[Tolk] Initial commit of TOLK Language: fork all sources from FunC
The Tolk Language will be positioned as "next-generation FunC".
It's literally a fork of a FunC compiler,
introducing familiar syntax similar to TypeScript,
but leaving all low-level optimizations untouched.

Note, that FunC sources are partially stored
in the parser/ folder (shared with TL/B).
In Tolk, nothing is shared.
Everything from parser/ is copied into tolk/ folder.
2024-11-02 01:33:08 +04:00
EmelyanenkoK
eed3153ace
Merge pull request #1316 from ton-blockchain/testnet
Fix updating neighbors in private overlays (#1314)
2024-10-24 17:20:52 +03:00
SpyCheese
0862cca295
Fix updating neighbors in private overlays (#1314) 2024-10-24 17:12:22 +03:00
EmelyanenkoK
d4de286f1b
Merge pull request #1288 from ton-blockchain/testnet
Merge developer branch
2024-10-22 11:56:12 +03:00
neodix42
f82827e79e
Fix failing tonlib compilation on ubuntu with nixpkgs (#1309)
* force gcc-11+

* install gcc-11+

* fix missing gcc-11 in nix build on ubuntu

* cleanup
2024-10-22 11:55:05 +03:00
EmelyanenkoK
66e81f59cd Add credits to ret2happy 2024-10-22 11:54:07 +03:00
neodix42
8daf5c335a
Improve artifacts' stripping (#1286)
* add ton build on mac-15 gh action

* rename action titles

* fix https://github.com/ton-blockchain/ton/issues/1246

* improve artifacts' stripping

* improve artifacts' stripping

* use strip -xSX on mac on github runner

* use strip -xSX on mac on github runner + sudo
2024-10-19 13:03:10 +03:00
Victor S.
c1ee18c902
Add state-init option to wallet-v3.fif script (#1282) 2024-10-19 12:34:08 +03:00
EmelyanenkoK
96ddbcd674 Update changelog 2024-10-19 12:33:11 +03:00
SpyCheese
603d1d14b9
More precise calculation of expected shard blocks in checkload (#1279)
* More precise calculation of expected shard blocks in checkload

* Fix monte-carlo checkload
2024-10-15 17:59:12 +03:00
SpyCheese
5920f800de
Improve gas consumption in VmState::jump_to (#1276) 2024-10-15 17:43:46 +03:00
Marat
3e806bf46e
Limit RocksDB logs size (#1278)
* fix logging of failed destroy attempts

* limit rocksdb log size
2024-10-15 17:43:09 +03:00
SpyCheese
97398b7db0
Fix null pointer error in validator group (#1271) 2024-10-14 09:42:52 +03:00
neodix42
8f55efbc01
fix openssl3 linking issues in portable binaries (#1247) 2024-10-12 13:22:45 +03:00
SpyCheese
2ce2c8fc49
Count account_dict size in block size estimation (#1261)
* Count account_dict size in block size estimation

* Fix updating account dict estimator
2024-10-12 13:21:47 +03:00
EmelyanenkoK
d04cdfa0dc
Use parallel write to celldb (#1264)
* Parallel write in celldb

* Add TD_PERF_COUNTER to gc_cell and store_cell

* More error handling

* Tests for prepare_commit_async

* Install g++11 for ubuntu 20.04

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-10-11 15:31:59 +03:00
Aleksandr Kirsanov
fd1735f6ec
[FunC] Fix a bug with << operator to zero value (#1262) 2024-10-09 16:03:58 +03:00
SpyCheese
b69214b6af
Validator patch: state download, adnl stats (#1257)
* Persistent state download improvements

1) Don't start over on restart
2) Download shards one at a time to reduce RAM usage
3) More logs

* Remove old peers from adnl stats
2024-10-09 13:55:59 +03:00
EmelyanenkoK
1da94e62ad
Send only first block candidate optimistically (#1260)
* Broadcast only the first block candidate

* Fix sending block broadcast

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-10-09 13:53:46 +03:00
SpyCheese
8364a2425f
Improve overlay stats (#1242) 2024-10-04 12:19:42 +03:00
SpyCheese
f94d1bee0c
Extra currencies (#1122)
* Support extra currencies in tonlib, blockchain-explorer, getAccountPrunned

* Fix dict_combine_with with non-zero mode
2024-10-01 10:22:49 +03:00
SpyCheese
257cd8cd9c
Fix estimating block size, repeat collation on error (#1178)
* Fix extimating block size, repeat collation on error

* Cancel collation when it is non needed
2024-10-01 10:22:15 +03:00
EmelyanenkoK
fc5e71fc15
Merge pull request #1232 from ton-blockchain/master
Merge master
2024-10-01 10:21:27 +03:00
Maksim Kurbatov
921aa29eb5
create complaints for master vals only for masterchain blocks (#1231) 2024-09-30 20:42:06 +03:00
SpyCheese
6755b8314a
Various changes in node (#1230)
* Remove unneeded "wait_neighbours_not_empty"

* Fix "round_started_at" for the first round

* Fix use after move in overlay.cpp

* Move "last gc masterchain state" stat to CellDbIn::prepare_stats

* Fix disabling state serializer
2024-09-30 17:12:38 +03:00
EmelyanenkoK
b78199370e
Merge pull request #1202 from ton-blockchain/tvm-patch
Fix transaction original_balance and VmState::jump_to
2024-09-23 21:10:57 +03:00
birydrad
72020c04c4
celldb in-memory mode, stats for actors, perf counters, minor fix in rldp2 (#1164)
* getactorstats query for validator-engine-console

* celldb in-memory mode (--celldb-in-memory option)

* rldp2: bugfix - do not estimate speed while nothing is sent

* add simple ed25519 benchmark

* fix compilation errors of different platforms and move to c++20

* fix some warnings

* turn on TON_USE_ABSEIL for glibc 2.27 nix build

---------

Co-authored-by: birydrad <>
2024-09-23 17:34:37 +03:00
neodix42
5f51d3d04f
Remove redundant linking dependencies (#1198)
* fixing compilation warning:
ld: warning: ignoring duplicate libraries: '../crypto/libton_block.a', '../crypto/libton_crypto.a'

* update upload-artifact version in TON Static Code Analysis GH action

* remove even more redundant linking dependencies

* remove even more redundant linking dependencies 2
2024-09-23 17:31:01 +03:00
SpyCheese
2cca7fddcc Consume gas in VmState::jump_to 2024-09-23 12:09:16 +03:00
SpyCheese
e04965c400 Fix setting original_balance in transaction.cpp 2024-09-20 15:16:46 +03:00
SpyCheese
b5734d2e30 Get rid of recursion in tvm continuations 2024-09-20 15:16:27 +03:00
neodix42
eea95aeebb
Add tonlib libraries for Android to release (#1169)
* add android tonlib artifacts to release

* change final artifacts access rights
2024-09-13 20:48:38 +03:00
SpyCheese
b304b1c7be
LS getDispatchQueueInfo and getDispatchQueueMessages methods (#1161)
* liteServer.getDispatchQueueInfo query

* Fix getting min/max lt

* LS getDispatchQueueMessages method
2024-09-13 20:47:30 +03:00
EmelyanenkoK
9f203890f4 Merge branch 'SpyCheese-mintless-util' into testnet 2024-09-13 20:44:47 +03:00
SpyCheese
76cda01af9 mintless-proof-generator make_all_proofs 2024-09-13 10:09:03 +03:00
EmelyanenkoK
1a5bbf30f1
mintless-proof-generator (#1166)
Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-09-12 18:02:56 +03:00
SpyCheese
1e5d84a9d8 mintless-proof-generator 2024-09-12 11:50:34 +03:00
EmelyanenkoK
e55c132178
Merge pull request #1157 from SpyCheese/testnet-update
Update testnet with safe features
2024-09-09 19:40:48 +03:00
EmelyanenkoK
1bef6df455
Merge pull request #1156 from ton-blockchain/safe_features
Merge safe features branch
2024-09-09 17:23:31 +03:00
SpyCheese
feff73c4be Merge branch 'safe_features' into testnet-update 2024-09-06 11:48:46 +03:00
SpyCheese
89e1cd9738 Adapt test-adnl to rate limits 2024-09-05 16:08:52 +03:00
SpyCheese
e32a74e9c5
Collator: change deferring behavior when out queue size is big (#1135) 2024-09-05 15:56:07 +03:00
SpyCheese
cb69f307e9
Add "lastgcdmasterchainstate" to validator stats (#1154) 2024-09-05 13:04:57 +03:00
SpyCheese
e35b34de22
Don't deserialize continuations in LS runSmcMethod (#1151) 2024-09-04 11:38:29 +03:00
EmelyanenkoK
b2b79fead1
Ratelimit nochannel ADNL packets (#1147)
* Get ADNL stats in validator console

* Add timestamp to stats

* Limit nochannel adnl packets

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-09-03 13:34:31 +03:00
EmelyanenkoK
e08111159f
Dynamic catchain delays, state serialization improvements (#1140)
* Validator improvements

* Fix cancelling state serialization
* Disable state serializer on all mainnet validators
* Flag --catchain-max-block-delay-slow

* Set default catchain-max-block-delay to 0.4, delay-slow to 1.0

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
2024-08-30 17:00:06 +03:00
EmelyanenkoK
0c21ce2ee4
Merge pull request #1139 from ton-blockchain/stable_testnet
Merge recent updates
2024-08-30 09:30:46 +03:00
neodix42
97c57c3386
add gh action to create docker image with a specified branch. Branch name will be used as image's tag name. (#1133)
Co-authored-by: neodiX <neodix42@ton.org>
2024-08-28 17:59:28 +03:00
SpyCheese
48d94d500a
Allow unlimited catchain.getBlock requests (#1132) 2024-08-28 14:09:22 +03:00
EmelyanenkoK
e9bd482382 Increase moderate misbehavior threshold 2024-08-28 11:18:12 +03:00
SpyCheese
b5fd8fa610 Disable state serializer on masterchain validators (#1129) 2024-08-28 11:18:06 +03:00
SpyCheese
31840a7aa3 Set default state ttl to 86400, set serializer delay to up to 6h (#1125) 2024-08-28 11:17:56 +03:00
neodix42
18305ab2e6 * update links to docker image (#1109)
* include fift and func into Docker image

Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
Co-authored-by: neodiX <neodix42@ton.org>
2024-08-28 11:16:09 +03:00
SpyCheese
9803d004c4 Fix getting creator stats in lite-client (#1115) 2024-08-28 11:15:53 +03:00
SpyCheese
dc26c3be67 Improve validator session stats (#1117)
* Improve validator session stats

* Collator stats: block limits, number of processed external messages
* Collator and validator work time
* Last key block seqno
* Approvers and signers

* End validator session stats
2024-08-28 11:15:23 +03:00
krigga
b70090dae3 Disable testing and fuzzing for openssl when building WASM packages (#1116)
Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
2024-08-28 11:15:17 +03:00
SpyCheese
622dc8676a Limit the number of threads to 127 (#1111) 2024-08-28 11:15:08 +03:00
SpyCheese
a71d413202 Improve dht lookup in overlays (#1104)
Continue dht lookup even if value was found
2024-08-28 11:15:00 +03:00
SpyCheese
6515136061 Improve creating channels in adnl (#1108)
* Improve creating channels in adnl

* Improve handling of cryptographic keys
2024-08-28 11:14:54 +03:00
SpyCheese
f7e189f272 Fix UB in blst aggregate verify (#1107) 2024-08-28 11:14:41 +03:00
EmelyanenkoK
be55da5fde
Increase moderate misbehavior threshold 2024-08-27 18:17:43 +03:00
SpyCheese
6038147afe
Disable state serializer on masterchain validators (#1129) 2024-08-27 18:10:17 +03:00
SpyCheese
16a2ced4d3
Set default state ttl to 86400, set serializer delay to up to 6h (#1125) 2024-08-26 17:53:42 +03:00
SpyCheese
cba92777a4
Fix adding overlay neighbor (#1121) 2024-08-23 13:12:40 +03:00
neodix42
1af2d3776f
* update links to docker image (#1109)
* include fift and func into Docker image

Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
Co-authored-by: neodiX <neodix42@ton.org>
2024-08-23 11:59:40 +03:00
SpyCheese
908415d00b
Accelerator, part 1 (#1119)
This commit contains some parts of https://github.com/ton-blockchain/ton/tree/accelerator
This is auxiliary code that mostly does not change node behavior.

1) Semiprivate overlays and other improvements in overlays code
2) Rename actual_min_split -> monitor_min_split, fix building shard overlays
3) Loading block candidates by block id from DB, fix accept_block after validator restart
4) Cells: ProofStorageStat and changes in CellUsageTree
5) Remove some unused code, other minor changes
2024-08-23 11:46:40 +03:00
SpyCheese
9a10f79fba
Fix getting creator stats in lite-client (#1115) 2024-08-20 19:55:01 +03:00
SpyCheese
9c3dc22b78
Improve validator session stats (#1117)
* Improve validator session stats

* Collator stats: block limits, number of processed external messages
* Collator and validator work time
* Last key block seqno
* Approvers and signers

* End validator session stats
2024-08-20 19:54:16 +03:00
krigga
5bdcb5e2ce
Disable testing and fuzzing for openssl when building WASM packages (#1116)
Co-authored-by: EmelyanenkoK <emelyanenko.kirill@gmail.com>
2024-08-20 19:50:59 +03:00
SpyCheese
06515c3735
Limit the number of threads to 127 (#1111) 2024-08-16 10:23:41 +03:00
SpyCheese
9661676646
Improve dht lookup in overlays (#1104)
Continue dht lookup even if value was found
2024-08-15 15:26:35 +03:00
SpyCheese
77a816e461
Improve creating channels in adnl (#1108)
* Improve creating channels in adnl

* Improve handling of cryptographic keys
2024-08-15 15:25:16 +03:00
SpyCheese
0cff1c88f7
Fix UB in blst aggregate verify (#1107) 2024-08-15 12:53:05 +03:00
696 changed files with 52745 additions and 5209 deletions

View file

@ -1,20 +0,0 @@
FROM ubuntu:20.04
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
RUN apt install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git curl libreadline-dev ccache libmicrohttpd-dev ninja-build libsecp256k1-dev libsodium-dev pkg-config
WORKDIR /
ARG BRANCH
ARG REPO
RUN git clone --recurse-submodules https://github.com/$REPO ton && cd ton && git checkout $BRANCH && git submodule update
WORKDIR /ton
RUN mkdir /ton/build
WORKDIR /ton/build
ENV CC clang
ENV CXX clang++
ENV CCACHE_DISABLE 1
RUN cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= -DCMAKE_CXX_FLAGS="-mavx2" ..
RUN ninja storage-daemon storage-daemon-cli tonlibjson blockchain-explorer fift func validator-engine validator-engine-console create-state generate-random-id create-hardfork dht-server lite-client

View file

@ -1,20 +0,0 @@
FROM ubuntu:22.04
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
RUN apt install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git curl libreadline-dev ccache libmicrohttpd-dev ninja-build libsecp256k1-dev libsodium-dev pkg-config
WORKDIR /
ARG BRANCH
ARG REPO
RUN git clone --recurse-submodules https://github.com/$REPO ton && cd ton && git checkout $BRANCH && git submodule update
WORKDIR /ton
RUN mkdir /ton/build
WORKDIR /ton/build
ENV CC clang
ENV CXX clang++
ENV CCACHE_DISABLE 1
RUN cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= -DCMAKE_CXX_FLAGS="-mavx2" ..
RUN ninja storage-daemon storage-daemon-cli tonlibjson blockchain-explorer fift func validator-engine validator-engine-console create-state generate-random-id create-hardfork dht-server lite-client

View file

@ -1,20 +0,0 @@
FROM ubuntu:20.04
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
RUN apt install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git curl libreadline-dev ccache libmicrohttpd-dev ninja-build libsecp256k1-dev libsodium-dev pkg-config
WORKDIR /
ARG BRANCH
ARG REPO
RUN git clone --recurse-submodules https://github.com/$REPO ton && cd ton && git checkout $BRANCH && git submodule update
WORKDIR /ton
RUN mkdir /ton/build
WORKDIR /ton/build
ENV CC clang
ENV CXX clang++
ENV CCACHE_DISABLE 1
RUN cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= ..
RUN ninja storage-daemon storage-daemon-cli tonlibjson blockchain-explorer fift func validator-engine validator-engine-console create-state generate-random-id dht-server lite-client

View file

@ -1,20 +0,0 @@
FROM ubuntu:22.04
RUN apt update
RUN DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install tzdata
RUN apt install -y build-essential cmake clang openssl libssl-dev zlib1g-dev gperf wget git curl libreadline-dev ccache libmicrohttpd-dev ninja-build libsecp256k1-dev libsodium-dev pkg-config
WORKDIR /
ARG BRANCH
ARG REPO
RUN git clone --recurse-submodules https://github.com/$REPO ton && cd ton && git checkout $BRANCH && git submodule update
WORKDIR /ton
RUN mkdir /ton/build
WORKDIR /ton/build
ENV CC clang
ENV CXX clang++
ENV CCACHE_DISABLE 1
RUN cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DPORTABLE=1 -DTON_ARCH= ..
RUN ninja storage-daemon storage-daemon-cli tonlibjson blockchain-explorer fift func validator-engine validator-engine-console create-state generate-random-id dht-server lite-client

View file

@ -21,6 +21,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/android/build-android-tonlib.sh .
chmod +x build-android-tonlib.sh
./build-android-tonlib.sh -a
@ -28,5 +30,5 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: tonlib-android
name: ton-android-tonlib
path: artifacts

View file

@ -0,0 +1,57 @@
name: Ubuntu TON build (AppImages, arm64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: ubuntu-22.04-arm
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Install system libraries
run: |
sudo apt update
sudo apt install -y build-essential git cmake ninja-build zlib1g-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev
sudo apt remove libgsl-dev
- name: Install clang-16
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16 all
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-ubuntu-appimages.sh .
chmod +x build-ubuntu-appimages.sh
./build-ubuntu-appimages.sh -a
- name: Make AppImages
run: |
cp assembly/appimage/create-appimages.sh .
cp assembly/appimage/AppRun .
cp assembly/appimage/ton.png .
chmod +x create-appimages.sh
./create-appimages.sh aarch64
rm -rf artifacts
- name: Build TON libs
run: |
cp assembly/native/build-ubuntu-portable-libs.sh .
chmod +x build-ubuntu-portable-libs.sh
./build-ubuntu-portable-libs.sh -a
cp ./artifacts/libtonlibjson.so appimages/artifacts/
cp ./artifacts/libemulator.so appimages/artifacts/
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-arm64-linux
path: appimages/artifacts

View file

@ -0,0 +1,43 @@
name: Ubuntu TON build (shared, arm64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04-arm, ubuntu-24.04-arm]
runs-on: ${{ matrix.os }}
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Install system libraries
run: |
sudo apt-get update
sudo apt-get install -y build-essential git cmake ninja-build zlib1g-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev libjemalloc-dev
- if: matrix.os != 'ubuntu-24.04-arm'
name: Install llvm-16
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16 all
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-ubuntu-shared.sh .
chmod +x build-ubuntu-shared.sh
./build-ubuntu-shared.sh -t -a
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-binaries-${{ matrix.os }}
path: artifacts

View file

@ -0,0 +1,63 @@
name: Ubuntu TON build (AppImages, x86-64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Install system libraries
run: |
sudo apt update
sudo apt install -y build-essential git cmake ninja-build zlib1g-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev
sudo apt remove libgsl-dev
- name: Install gcc-11 g++-11
run: |
sudo apt install -y manpages-dev software-properties-common
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update && sudo apt install gcc-11 g++-11
- name: Install clang-16
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16 all
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-ubuntu-appimages.sh .
chmod +x build-ubuntu-appimages.sh
./build-ubuntu-appimages.sh -a
- name: Make AppImages
run: |
cp assembly/appimage/create-appimages.sh .
cp assembly/appimage/AppRun .
cp assembly/appimage/ton.png .
chmod +x create-appimages.sh
./create-appimages.sh x86_64
rm -rf artifacts
- name: Build TON libs
run: |
cp assembly/native/build-ubuntu-portable-libs.sh .
chmod +x build-ubuntu-portable-libs.sh
./build-ubuntu-portable-libs.sh -a
cp ./artifacts/libtonlibjson.so appimages/artifacts/
cp ./artifacts/libemulator.so appimages/artifacts/
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-x86_64-linux
path: appimages/artifacts

View file

@ -21,6 +21,12 @@ jobs:
sudo apt-get update
sudo apt-get install -y build-essential git cmake ninja-build zlib1g-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev libjemalloc-dev
- if: matrix.os == 'ubuntu-20.04'
run: |
sudo apt install -y manpages-dev software-properties-common
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update && sudo apt install gcc-11 g++-11
- if: matrix.os != 'ubuntu-24.04'
run: |
wget https://apt.llvm.org/llvm.sh
@ -29,6 +35,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-ubuntu-shared.sh .
chmod +x build-ubuntu-shared.sh
./build-ubuntu-shared.sh -t -a

View file

@ -0,0 +1,27 @@
name: MacOS-13 TON build (portable, x86-64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-13
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-portable.sh .
chmod +x build-macos-portable.sh
./build-macos-portable.sh -t -a
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-x86_64-macos
path: artifacts

View file

@ -0,0 +1,27 @@
name: MacOS-14 TON build (portable, arm64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-14
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-portable.sh .
chmod +x build-macos-portable.sh
./build-macos-portable.sh -t -a
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-arm64-macos
path: artifacts

View file

@ -0,0 +1,27 @@
name: MacOS-15 TON build (shared, arm64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-15
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -t -a
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-binaries-macos-15
path: artifacts

View file

@ -1,4 +1,4 @@
name: MacOS TON build (shared, arm64)
name: MacOS-14 TON build (shared, arm64)
on: [push,workflow_dispatch,workflow_call]
@ -14,6 +14,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -t -a

View file

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

View file

@ -15,16 +15,37 @@ jobs:
- name: Install system libraries
run: |
sudo apt-get update
sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev
sudo apt-get install -y build-essential git openssl cmake ninja-build zlib1g-dev libssl-dev libsecp256k1-dev libmicrohttpd-dev libsodium-dev liblz4-dev libjemalloc-dev
- name: Build TON WASM artifacts
run: |
git submodule sync --recursive
git submodule update
cp assembly/wasm/fift-func-wasm-build-ubuntu.sh .
chmod +x fift-func-wasm-build-ubuntu.sh
./fift-func-wasm-build-ubuntu.sh -a
- name: Prepare test
run: |
cp assembly/wasm/*.fc .
git clone https://github.com/ton-community/func-js.git
cd func-js
npm install
npm run build
npm link
- name: Test TON WASM artifacts
run: |
base64 -w 0 artifacts/funcfiftlib.wasm > artifacts/funcfiftlib.wasm.js
printf "module.exports = { FuncFiftLibWasm: '" | cat - artifacts/funcfiftlib.wasm.js > temp.txt && mv temp.txt artifacts/funcfiftlib.wasm.js
echo "'}" >> artifacts/funcfiftlib.wasm.js
cp artifacts/funcfiftlib.wasm.js func-js/node_modules/@ton-community/func-js-bin/dist/funcfiftlib.wasm.js
cp artifacts/funcfiftlib.js func-js/node_modules/@ton-community/func-js-bin/dist/funcfiftlib.js
npx func-js stdlib.fc intrinsics.fc --fift ./output.f
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-wasm-binaries
name: ton-wasm
path: artifacts

View file

@ -4,6 +4,9 @@ on: [workflow_dispatch]
permissions: write-all
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
create-release:
runs-on: ubuntu-22.04
@ -11,76 +14,112 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Download Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
- name: Download Linux arm64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-linux.yml
workflow: build-ton-linux-arm64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download and unzip Linux arm64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-arm64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-x86-64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download and unzip Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-linux.yml
workflow: build-ton-linux-x86-64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download Mac x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-macos.yml
workflow: build-ton-macos-13-x86-64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download Mac arm64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-arm64-macos.yml
workflow: build-ton-macos-14-arm64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download and unzip Mac x86-64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-macos.yml
workflow: build-ton-macos-13-x86-64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download and unzip arm64 artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-arm64-macos.yml
workflow: build-ton-macos-14-arm64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download Windows artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-windows.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download and unzip Windows artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-windows.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download WASM artifacts
uses: dawidd6/action-download-artifact@v2
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-wasm-emscripten.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Download Android Tonlib artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-android-tonlib.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Show all artifacts
@ -139,7 +178,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries.zip
file: artifacts/ton-x86-64-windows.zip
asset_name: ton-win-x86-64.zip
tag: ${{ steps.tag.outputs.TAG }}
@ -147,7 +186,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/fift.exe
file: artifacts/ton-x86-64-windows/fift.exe
asset_name: fift.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -155,23 +194,39 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/func.exe
file: artifacts/ton-x86-64-windows/func.exe
asset_name: func.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86-64-windows/tolk.exe
asset_name: tolk.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - lite-client
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/lite-client.exe
file: artifacts/ton-x86-64-windows/lite-client.exe
asset_name: lite-client.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86-64-windows/proxy-liteserver.exe
asset_name: proxy-liteserver.exe
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Windows 2019 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/rldp-http-proxy.exe
file: artifacts/ton-x86-64-windows/rldp-http-proxy.exe
asset_name: rldp-http-proxy.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -179,7 +234,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/http-proxy.exe
file: artifacts/ton-x86-64-windows/http-proxy.exe
asset_name: http-proxy.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -187,7 +242,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/storage-daemon-cli.exe
file: artifacts/ton-x86-64-windows/storage-daemon-cli.exe
asset_name: storage-daemon-cli.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -195,7 +250,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/storage-daemon.exe
file: artifacts/ton-x86-64-windows/storage-daemon.exe
asset_name: storage-daemon.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -203,7 +258,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/tonlibjson.dll
file: artifacts/ton-x86-64-windows/tonlibjson.dll
asset_name: tonlibjson.dll
tag: ${{ steps.tag.outputs.TAG }}
@ -211,7 +266,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/emulator.dll
file: artifacts/ton-x86-64-windows/emulator.dll
asset_name: libemulator.dll
tag: ${{ steps.tag.outputs.TAG }}
@ -219,7 +274,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-win-binaries/tonlib-cli.exe
file: artifacts/ton-x86-64-windows/tonlib-cli.exe
asset_name: tonlib-cli.exe
tag: ${{ steps.tag.outputs.TAG }}
@ -229,7 +284,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries.zip
file: artifacts/ton-x86_64-macos.zip
asset_name: ton-mac-x86-64.zip
tag: ${{ steps.tag.outputs.TAG }}
@ -237,7 +292,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/fift
file: artifacts/ton-x86_64-macos/fift
asset_name: fift-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -245,23 +300,39 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/func
file: artifacts/ton-x86_64-macos/func
asset_name: func-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos/tolk
asset_name: tolk-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - lite-client
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/lite-client
file: artifacts/ton-x86_64-macos/lite-client
asset_name: lite-client-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos/proxy-liteserver
asset_name: proxy-liteserver-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac x86-64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/rldp-http-proxy
file: artifacts/ton-x86_64-macos/rldp-http-proxy
asset_name: rldp-http-proxy-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -269,7 +340,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/http-proxy
file: artifacts/ton-x86_64-macos/http-proxy
asset_name: http-proxy-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -277,7 +348,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/storage-daemon-cli
file: artifacts/ton-x86_64-macos/storage-daemon-cli
asset_name: storage-daemon-cli-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -285,7 +356,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/storage-daemon
file: artifacts/ton-x86_64-macos/storage-daemon
asset_name: storage-daemon-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -293,7 +364,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/libtonlibjson.dylib
file: artifacts/ton-x86_64-macos/libtonlibjson.dylib
asset_name: tonlibjson-mac-x86-64.dylib
tag: ${{ steps.tag.outputs.TAG }}
@ -301,7 +372,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/libemulator.dylib
file: artifacts/ton-x86_64-macos/libemulator.dylib
asset_name: libemulator-mac-x86-64.dylib
tag: ${{ steps.tag.outputs.TAG }}
@ -309,7 +380,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos-binaries/tonlib-cli
file: artifacts/ton-x86_64-macos/tonlib-cli
asset_name: tonlib-cli-mac-x86-64
tag: ${{ steps.tag.outputs.TAG }}
@ -320,7 +391,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries.zip
file: artifacts/ton-arm64-macos.zip
asset_name: ton-mac-arm64.zip
tag: ${{ steps.tag.outputs.TAG }}
@ -328,7 +399,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/fift
file: artifacts/ton-arm64-macos/fift
asset_name: fift-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -336,23 +407,39 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/func
file: artifacts/ton-arm64-macos/func
asset_name: func-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos/tolk
asset_name: tolk-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - lite-client
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/lite-client
file: artifacts/ton-arm64-macos/lite-client
asset_name: lite-client-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos/proxy-liteserver
asset_name: proxy-liteserver-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Mac arm64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/rldp-http-proxy
file: artifacts/ton-arm64-macos/rldp-http-proxy
asset_name: rldp-http-proxy-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -360,7 +447,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/http-proxy
file: artifacts/ton-arm64-macos/http-proxy
asset_name: http-proxy-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -368,7 +455,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/storage-daemon-cli
file: artifacts/ton-arm64-macos/storage-daemon-cli
asset_name: storage-daemon-cli-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -376,7 +463,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/storage-daemon
file: artifacts/ton-arm64-macos/storage-daemon
asset_name: storage-daemon-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -384,7 +471,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/libtonlibjson.dylib
file: artifacts/ton-arm64-macos/libtonlibjson.dylib
asset_name: tonlibjson-mac-arm64.dylib
tag: ${{ steps.tag.outputs.TAG }}
@ -392,7 +479,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/libemulator.dylib
file: artifacts/ton-arm64-macos/libemulator.dylib
asset_name: libemulator-mac-arm64.dylib
tag: ${{ steps.tag.outputs.TAG }}
@ -400,7 +487,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos-binaries/tonlib-cli
file: artifacts/ton-arm64-macos/tonlib-cli
asset_name: tonlib-cli-mac-arm64
tag: ${{ steps.tag.outputs.TAG }}
@ -410,15 +497,23 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries.zip
file: artifacts/ton-x86_64-linux.zip
asset_name: ton-linux-x86_64.zip
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload generic smartcont+lib artifact
run: |
mkdir smartcont_lib
cd smartcont_lib
cp -r ../artifacts/ton-x86_64-linux/{smartcont,lib} .
zip -r smartcont_lib.zip .
gh release upload ${{ steps.tag.outputs.TAG }} smartcont_lib.zip
- name: Upload Linux x86-64 single artifact - fift
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/fift
file: artifacts/ton-x86_64-linux/fift
asset_name: fift-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
@ -426,23 +521,39 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/func
file: artifacts/ton-x86_64-linux/func
asset_name: func-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux/tolk
asset_name: tolk-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - lite-client
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/lite-client
file: artifacts/ton-x86_64-linux/lite-client
asset_name: lite-client-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux/proxy-liteserver
asset_name: proxy-liteserver-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux x86-64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/rldp-http-proxy
file: artifacts/ton-x86_64-linux/rldp-http-proxy
asset_name: rldp-http-proxy-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
@ -450,7 +561,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/http-proxy
file: artifacts/ton-x86_64-linux/http-proxy
asset_name: http-proxy-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
@ -458,7 +569,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/storage-daemon-cli
file: artifacts/ton-x86_64-linux/storage-daemon-cli
asset_name: storage-daemon-cli-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
@ -466,7 +577,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/storage-daemon
file: artifacts/ton-x86_64-linux/storage-daemon
asset_name: storage-daemon-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
@ -474,7 +585,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/libtonlibjson.so
file: artifacts/ton-x86_64-linux/libtonlibjson.so
asset_name: tonlibjson-linux-x86_64.so
tag: ${{ steps.tag.outputs.TAG }}
@ -482,7 +593,7 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/libemulator.so
file: artifacts/ton-x86_64-linux/libemulator.so
asset_name: libemulator-linux-x86_64.so
tag: ${{ steps.tag.outputs.TAG }}
@ -490,14 +601,130 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux-binaries/tonlib-cli
file: artifacts/ton-x86_64-linux/tonlib-cli
asset_name: tonlib-cli-linux-x86_64
tag: ${{ steps.tag.outputs.TAG }}
# linux arm64
- name: Upload Linux arm64 artifacts
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux.zip
asset_name: ton-linux-arm64.zip
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - fift
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/fift
asset_name: fift-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - func
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/func
asset_name: func-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/tolk
asset_name: tolk-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - lite-client
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/lite-client
asset_name: lite-client-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - proxy-liteserver
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/proxy-liteserver
asset_name: proxy-liteserver-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - rldp-http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/rldp-http-proxy
asset_name: rldp-http-proxy-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - http-proxy
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/http-proxy
asset_name: http-proxy-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - storage-daemon-cli
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/storage-daemon-cli
asset_name: storage-daemon-cli-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - storage-daemon
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/storage-daemon
asset_name: storage-daemon-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - tonlibjson
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/libtonlibjson.so
asset_name: tonlibjson-linux-arm64.so
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - libemulator
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/libemulator.so
asset_name: libemulator-linux-arm64.so
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Linux arm64 single artifact - tonlib-cli
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/tonlib-cli
asset_name: tonlib-cli-linux-arm64
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload WASM artifacts
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-wasm-binaries.zip
asset_name: ton-wasm-binaries.zip
file: artifacts/ton-wasm.zip
asset_name: ton-wasm.zip
tag: ${{ steps.tag.outputs.TAG }}
- name: Upload Android Tonlib artifacts
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-android-tonlib.zip
asset_name: ton-android-tonlib.zip
tag: ${{ steps.tag.outputs.TAG }}

View file

@ -0,0 +1,154 @@
name: Create tolk release
on:
workflow_dispatch:
inputs:
tag:
description: 'tolk release and tag name'
required: true
permissions: write-all
jobs:
create-release:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Download and unzip Linux arm64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-arm64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download and unzip Linux x86-64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-linux-x86-64-appimage.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download and unzip Mac x86-64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-macos-13-x86-64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download and unzip arm64 artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-macos-14-arm64-portable.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download and unzip Windows artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: ton-x86-64-windows.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: false
- name: Download WASM artifacts
uses: dawidd6/action-download-artifact@v6
with:
workflow: build-ton-wasm-emscripten.yml
path: artifacts
workflow_conclusion: success
branch: master
skip_unpack: true
- name: Show all artifacts
run: |
tree artifacts
# create release
- name: Get registration token
id: getRegToken
run: |
curl -X POST -H \"Accept: application/vnd.github+json\" -H 'Authorization: token ${{ secrets.GITHUB_TOKEN }}' https://api.github.com/repos/ton-blockchain/ton/actions/runners/registration-token
- name: Create release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ inputs.tag }}
release_name: ${{ inputs.tag }}
draft: false
prerelease: false
# upload
# win
- name: Upload Windows 2019 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86-64-windows/tolk.exe
asset_name: tolk.exe
tag: ${{ inputs.tag }}
# mac x86-64
- name: Upload Mac x86-64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-macos/tolk
asset_name: tolk-mac-x86-64
tag: ${{ inputs.tag }}
# mac arm64
- name: Upload Mac arm64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-macos/tolk
asset_name: tolk-mac-arm64
tag: ${{ inputs.tag }}
# linux x86-64
- name: Upload Linux x86-64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-x86_64-linux/tolk
asset_name: tolk-linux-x86_64
tag: ${{ inputs.tag }}
# linux arm64
- name: Upload Linux arm64 single artifact - tolk
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-arm64-linux/tolk
asset_name: tolk-linux-arm64
tag: ${{ inputs.tag }}
- name: Upload WASM artifacts
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: artifacts/ton-wasm.zip
asset_name: ton-wasm.zip
tag: ${{ inputs.tag }}

View file

@ -0,0 +1,61 @@
name: Docker Ubuntu 22.04 branch image
on:
workflow_dispatch:
push:
branches-ignore:
- master
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-22.04
steps:
- name: Check out repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.5.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.10.0
with:
driver-opts: image=moby/buildkit:v0.11.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and export to Docker
uses: docker/build-push-action@v6
with:
load: true
context: ./
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
- name: Test
run: |
docker run --rm -e "TEST=1" ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
- name: Get tag as branch name
id: tag
run: |
echo "TAG=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT
- name: Build and push
id: docker_build
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
push: true
context: ./
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.TAG }}

View file

@ -20,10 +20,10 @@ jobs:
submodules: 'recursive'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v3.5.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v3.10.0
- name: Login to GitHub Container Registry
uses: docker/login-action@v3

View file

@ -1,37 +0,0 @@
name: MacOS TON build (portable, arm64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-14
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- uses: cachix/install-nix-action@v23
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Build TON
run: |
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh -t
- name: Simple binaries test
run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V
artifacts/lite-client -V
artifacts/fift -V
artifacts/func -V
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-arm64-macos-binaries
path: artifacts

View file

@ -20,7 +20,7 @@ jobs:
generate report: true
- name: Upload report
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@master
with:
name: ton-ccpcheck-report
path: output

View file

@ -1,41 +0,0 @@
name: Ubuntu TON build (portable, x86-64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- run: |
sudo apt update
sudo apt install -y apt-utils
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- uses: cachix/install-nix-action@v23
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Build TON
run: |
cp assembly/nix/build-linux-x86-64-nix.sh .
chmod +x build-linux-x86-64-nix.sh
./build-linux-x86-64-nix.sh -t
- name: Simple binaries test
run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V
artifacts/lite-client -V
artifacts/fift -V
artifacts/func -V
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-x86_64-linux-binaries
path: artifacts

View file

@ -1,37 +0,0 @@
name: MacOS TON build (portable, x86-64)
on: [push,workflow_dispatch,workflow_call]
jobs:
build:
runs-on: macos-12
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- uses: cachix/install-nix-action@v23
with:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Build TON
run: |
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh -t
- name: Simple binaries test
run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V
artifacts/lite-client -V
artifacts/fift -V
artifacts/func -V
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-x86_64-macos-binaries
path: artifacts

View file

@ -23,6 +23,8 @@ jobs:
- name: Build TON
run: |
git submodule sync --recursive
git submodule update
copy assembly\native\build-windows-github-2019.bat .
copy assembly\native\build-windows-2019.bat .
build-windows-github-2019.bat Enterprise
@ -30,5 +32,5 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: ton-win-binaries
name: ton-x86-64-windows
path: artifacts

3
.gitignore vendored
View file

@ -13,11 +13,12 @@ test/regression-tests.cache/
**/*build*/
.idea
.vscode
.DS_Store
dev/
zlib/
libsodium/
libmicrohttpd-0.9.77-w32-bin/
readline-5.0-1-lib/
secp256k1/
openssl-3.1.4/
libsodium-1.0.18-stable-msvc.zip
libmicrohttpd-0.9.77-w32-bin.zip

4
.gitmodules vendored
View file

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

View file

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

View file

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

View file

@ -127,10 +127,16 @@ elseif (WIN32)
endif()
string(APPEND _PLATFORM_PATH "/$$CONFIG$$")
message(STATUS "MSVC_VERSION ${MSVC_VERSION}")
if (MSVC_VERSION LESS 1900)
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60")
else()
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50")
if (MSVC_VERSION EQUAL 1941)
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 51")
else()
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50")
endif()
endif()
string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}")

View file

@ -79,11 +79,12 @@ else()
set(HAVE_SSE42 FALSE)
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_EXTENSIONS FALSE)
#BEGIN internal
option(BUILD_SHARED_LIBS "Use \"ON\" to build shared libraries instead of static where it's not specified (not recommended)" OFF)
option(USE_EMSCRIPTEN "Use \"ON\" for config building wasm." OFF)
option(TON_ONLY_TONLIB "Use \"ON\" to build only tonlib." OFF)
if (USE_EMSCRIPTEN)
@ -183,6 +184,7 @@ message("Add ton")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
include(BuildBLST)
include(BuildSECP256K1)
# Configure CCache if available
find_program(CCACHE_FOUND ccache)
@ -237,6 +239,11 @@ if (TON_USE_JEMALLOC)
find_package(jemalloc REQUIRED)
endif()
if (NIX)
find_package(Secp256k1 REQUIRED)
endif()
set(MEMPROF "" CACHE STRING "Use one of \"ON\", \"FAST\" or \"SAFE\" to enable memory profiling. \
Works under macOS and Linux when compiled using glibc. \
In FAST mode stack is unwinded only using frame pointers, which may fail. \
@ -333,6 +340,10 @@ add_cxx_compiler_flag("-Wno-sign-conversion")
add_cxx_compiler_flag("-Qunused-arguments")
add_cxx_compiler_flag("-Wno-unused-private-field")
add_cxx_compiler_flag("-Wno-redundant-move")
#add_cxx_compiler_flag("-Wno-unused-function")
#add_cxx_compiler_flag("-Wno-unused-variable")
#add_cxx_compiler_flag("-Wno-shorten-64-to-32")
#add_cxx_compiler_flag("-Werror")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/include/c++/v1")
@ -409,6 +420,7 @@ add_subdirectory(adnl)
add_subdirectory(crypto)
add_subdirectory(lite-client)
add_subdirectory(emulator)
add_subdirectory(tolk)
#BEGIN tonlib
add_subdirectory(tonlib)
@ -484,10 +496,10 @@ target_link_libraries(test-net PRIVATE tdnet tdutils ${CMAKE_THREAD_LIBS_INIT})
#BEGIN tonlib
add_executable(test-tonlib ${TONLIB_ONLINE_TEST_SOURCE})
target_link_libraries(test-tonlib tdutils tdactor adnllite tl_api ton_crypto ton_block tl_tonlib_api tonlib)
target_link_libraries(test-tonlib tdactor adnllite tl_api ton_crypto tl_tonlib_api tonlib)
add_executable(test-tonlib-offline test/test-td-main.cpp ${TONLIB_OFFLINE_TEST_SOURCE})
target_link_libraries(test-tonlib-offline tdutils tdactor adnllite tl_api ton_crypto ton_block fift-lib tl_tonlib_api tonlib)
target_link_libraries(test-tonlib-offline tdactor adnllite tl_api ton_crypto fift-lib tl_tonlib_api tonlib)
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(test-tonlib-offline gen_fif)
@ -529,6 +541,8 @@ target_link_libraries(test-rldp2 adnl adnltest dht rldp2 tl_api)
add_executable(test-validator-session-state test/test-validator-session-state.cpp)
target_link_libraries(test-validator-session-state adnl dht rldp validatorsession tl_api)
add_executable(test-overlay test/test-overlay.cpp)
target_link_libraries(test-overlay overlay tdutils tdactor adnl adnltest tl_api dht )
add_executable(test-catchain test/test-catchain.cpp)
target_link_libraries(test-catchain overlay tdutils tdactor adnl adnltest rldp tl_api dht
catchain )
@ -620,6 +634,30 @@ if (NOT NIX)
endif()
endif()
# Tolk tests
if (NOT NIX)
if (MSVC)
set(PYTHON_VER "python")
else()
set(PYTHON_VER "python3")
endif()
add_test(
NAME test-tolk
COMMAND ${PYTHON_VER} tolk-tester.py tests/
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tolk-tester)
if (WIN32)
set_property(TEST test-tolk PROPERTY ENVIRONMENT
"TOLK_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/tolk/tolk.exe"
"FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/fift.exe"
"FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/")
else()
set_property(TEST test-tolk PROPERTY ENVIRONMENT
"TOLK_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/tolk/tolk"
"FIFT_EXECUTABLE=${CMAKE_CURRENT_BINARY_DIR}/crypto/fift"
"FIFTPATH=${CMAKE_CURRENT_SOURCE_DIR}/crypto/fift/lib/")
endif()
endif()
#BEGIN internal
if (NOT TON_ONLY_TONLIB)
add_test(test-adnl test-adnl)

View file

@ -1,7 +1,64 @@
## 2025.03 Update
1. New extracurrency behavior introduced, check [GlobalVersions.md](./doc/GlobalVersions.md#version-10)
2. Optmization of validation process, in particular CellStorageStat.
3. Flag for speeding up broadcasts in various overlays.
4. Fixes for static builds for emulator and tonlibjson
5. Improving getstats output: adds
* Liteserver queries count
* Collated/validated blocks count, number of active sessions
* Persistent state sizes
* Initial sync progress
6. Fixes in logging, TON Storage, external message checking, persistent state downloading, UB in tonlib
Besides the work of the core team, this update is based on the efforts of @Sild from StonFi(UB in tonlib).
## 2025.02 Update
1. Series of improvement/fixes for `Config8.version >= 9`, check [GlobalVersions.md](./doc/GlobalVersions.md)
2. Fix for better discovery of updated nodes' (validators') IPs: retry dht queries
3. Series of improvements for extra currency adoption: fixed c7 in rungetmethod, reserve modes
4. TVM: Fix processing continuation control data on deep jump
5. A few fixes of tl-b schemes: crc computation, incorrect tag for merkle proofs, advance_ext, NatWidth print
6. Emulator improvements: fix setting libraries, extracurrency support
7. Increase of gas limit for unlocking highload-v2 wallets locked in the beginning of 2024
8. Validator console improvement: dashed names, better shard formats
Besides the work of the core team, this update is based on the efforts of @dbaranovstonfi from StonFi(libraries in emulator), @Rexagon (ret on deep jumps), @tvorogme from DTon (`advance_ext`), Nan from Zellic (`stk_und` and JNI)
## 2024.12 Update
1. FunC 0.4.6: Fix in try/catch handling, fixing pure flag for functions stored in variables
2. Merging parts of Accelerator: support of specific shard monitoring, archive/liteserver slice format, support for partial liteservers, proxy liteserver, on-demand neighbour queue loading
3. Fix of asynchronous cell loading
4. Various improvements: caching certificates checks, better block overloading detection, `_malloc` in emulator
5. Introduction of telemetry in overlays
6. Use non-null local-id for tonlib-LS interaction - mitigates MitM attack.
7. Adding `SECP256K1_XONLY_PUBKEY_TWEAK_ADD`, `SETCONTCTRMANY` instructions to TVM (activated by `Config8.version >= 9`)
8. Private keys export via validator-engine-console - required for better backups
9. Fix proof checking in tonlib, `hash` in `raw.Message` in tonlib_api
Besides the work of the core team, this update is based on the efforts of OtterSec and LayerZero (FunC), tg:@throwunless (FunC), Aviv Frenkel and Dima Kogan from Fordefi (LS MitM), @hacker-volodya (Tonlib), OKX team (async cell loading), @krigga (emulator)
## 2024.10 Update
1. Parallel write to celldb: substantial improvement of sync and GC speed, especially with slow disks.
2. Decreased network traffic: only first block candidate is sent optimistically.
3. Improved channel creation and dht lookups, introduction of semi-private overlays
4. New LS dispatch queue related methods and improvement security
5. Fixing recursion in TVM continuations
6. Improved stats for actors, validator sessions, perf counters, overlays, adnl, rocksdb
7. Migration to C++20
8. Improved block size estimates: account for depth in various structures
9. Fix bug with `<<` optimization in FunC
10. Minor changes of TVM which will be activated by `Config8.version >= 9`
11. Multiple minor improvements
Besides the work of the core team, this update is based on the efforts of @krigga (emulator), Arayz @ TonBit (LS security, TVM recursion), @ret2happy (UB in BLST).
## 2024.08 Update
1. Introduction of dispatch queues, message envelopes with transaction chain metadata, and explicitly stored msg_queue size, which will be activated by `Config8.version >= 8` and new `Config8.capabilities` bits: `capStoreOutMsgQueueSize`, `capMsgMetadata`, `capDeferMessages`.
2. A number of changes to transcation executor which will activated for `Config8.version >= 8`:
2. A number of changes to transaction executor which will activated for `Config8.version >= 8`:
- Check mode on invalid `action_send_msg`. Ignore action if `IGNORE_ERROR` (+2) bit is set, bounce if `BOUNCE_ON_FAIL` (+16) bit is set.
- Slightly change random seed generation to fix mix of `addr_rewrite` and `addr`.
- Fill in `skipped_actions` for both invalid and valid messages with `IGNORE_ERROR` mode that can't be sent.
@ -73,7 +130,7 @@ Besides the work of the core team, this update is based on the efforts of @akifo
* Fix error in proof generation for blocks after merge
* Fix most of `block is not applied` issues related to sending too recent block in Proofs
* LS now check external messages till `accept_message` (`set_gas`).
3. Improvements in DHT work and storage, CellDb, config.json ammendment, peer misbehavior detection, validator session stats collection, emulator.
3. Improvements in DHT work and storage, CellDb, config.json amendment, peer misbehavior detection, validator session stats collection, emulator.
4. Change in CTOS and XLOAD behavior activated through setting `version >= 5` in `ConfigParam 8;`:
* Loading "nested libraries" (i.e. a library cell that points to another library cell) throws an exception.
* Loading a library consumes gas for cell load only once (for the library cell), not twice (both for the library cell and the cell in the library).
@ -84,7 +141,7 @@ Besides the work of the Core team, this update is based on the efforts of @XaBbl
## 2023.12 Update
1. Optimized message queue handling, now queue cleaning speed doesn't depend on total queue size
* Cleaning delivered messages using lt augmentation instead of random search / consequtive walk
* Cleaning delivered messages using lt augmentation instead of random search / consecutive walk
* Keeping root cell of queue message in memory until outdated (caching)
2. Changes to block collation/validation limits
3. Stop accepting new external message if message queue is overloaded
@ -176,7 +233,7 @@ Besides the work of the core team, this update is based on the efforts of @vtama
Besides the work of the core team, this update is based on the efforts of @tvorogme (debug improvements), @AlexeyFSL (WASM builds) and third-party security auditors.
## 2022.08 Update
* Blockchain state serialization now works via separate db-handler which simplfies memory clearing after serialization
* Blockchain state serialization now works via separate db-handler which simplifies memory clearing after serialization
* CellDB now works asynchronously which substantially increase database access throughput
* Abseil-cpp and crc32 updated: solve issues with compilation on recent OS distributives
* Fixed a series of UBs and issues for exotic endianness hosts

View file

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

View file

@ -47,9 +47,9 @@ Main TON monorepo, which includes the code of the node/validator, lite-client, t
__The Open Network (TON)__ is a fast, secure, scalable blockchain focused on handling _millions of transactions per second_ (TPS) with the goal of reaching hundreds of millions of blockchain users.
- To learn more about different aspects of TON blockchain and its underlying ecosystem check [documentation](https://ton.org/docs)
- To run node, validator or lite-server check [Participate section](https://ton.org/docs/participate/nodes/run-node)
- To develop decentralised apps check [Tutorials](https://ton.org/docs/develop/smart-contracts/), [FunC docs](https://ton.org/docs/develop/func/overview) and [DApp tutorials](https://ton.org/docs/develop/dapps/)
- To develop decentralised apps check [Tutorials](https://docs.ton.org/v3/guidelines/smart-contracts/guidelines), [FunC docs](https://ton.org/docs/develop/func/overview) and [DApp tutorials](https://docs.ton.org/v3/guidelines/dapps/overview)
- To work on TON check [wallets](https://ton.app/wallets), [explorers](https://ton.app/explorers), [DEXes](https://ton.app/dex) and [utilities](https://ton.app/utilities)
- To interact with TON check [APIs](https://ton.org/docs/develop/dapps/apis/)
- To interact with TON check [APIs](https://docs.ton.org/v3/guidelines/dapps/apis-sdks/overview)
## Updates flow
@ -71,7 +71,7 @@ Usually, the response to your pull request will indicate which section it falls
## Build TON blockchain
### Ubuntu 20.4, 22.04 (x86-64, aarch64)
### Ubuntu 20.4, 22.04, 24.04 (x86-64, aarch64)
Install additional system libraries
```bash
sudo apt-get update
@ -141,18 +141,10 @@ Compile TON tonlib library
./build-android-tonlib.sh
```
### Build TON portable binaries with Nix package manager
You need to install Nix first.
```bash
sh <(curl -L https://nixos.org/nix/install) --daemon
```
Then compile TON with Nix by executing below command from the root folder:
```bash
cp -r assembly/nix/* .
export NIX_PATH=nixpkgs=https://github.com/nixOS/nixpkgs/archive/23.05.tar.gz
nix-build linux-x86-64-static.nix
```
More examples for other platforms can be found under `assembly/nix`.
### TON portable binaries
Linux portable binaries are wrapped into AppImages, at the same time MacOS portable binaries are statically linked executables.
Linux and MacOS binaries are available for both x86-64 and arm64 architectures.
## Running tests

View file

@ -88,17 +88,15 @@ target_link_libraries(adnl PUBLIC tdactor ton_crypto tl_api tdnet tddb keys keyr
add_executable(adnl-proxy ${ADNL_PROXY_SOURCE})
target_include_directories(adnl-proxy PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(adnl-proxy PUBLIC tdactor ton_crypto tl_api tdnet common
tl-utils git)
target_link_libraries(adnl-proxy PUBLIC tdactor ton_crypto tl_api tdnet common tl-utils git)
add_executable(adnl-pong adnl-pong.cpp)
target_include_directories(adnl-pong PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(adnl-pong PUBLIC tdactor ton_crypto tl_api tdnet common
tl-utils adnl dht git)
target_link_libraries(adnl-pong PUBLIC tdactor ton_crypto tl_api tdnet common tl-utils adnl dht git)
add_library(adnltest STATIC ${ADNL_TEST_SOURCE})
target_include_directories(adnltest PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(adnltest PUBLIC adnl )
target_link_libraries(adnltest PUBLIC adnl)
install(TARGETS adnl-proxy RUNTIME DESTINATION bin)
endif()

View file

@ -112,16 +112,16 @@ void AdnlChannelImpl::send_message(td::uint32 priority, td::actor::ActorId<AdnlN
}
void AdnlChannelImpl::receive(td::IPAddress addr, td::BufferSlice data) {
auto P = td::PromiseCreator::lambda(
[peer = peer_pair_, channel_id = channel_in_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
if (R.is_error()) {
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
} else {
auto packet = R.move_as_ok();
packet.set_remote_addr(addr);
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, std::move(packet));
}
});
auto P = td::PromiseCreator::lambda([peer = peer_pair_, channel_id = channel_in_id_, addr, id = print_id(),
size = data.size()](td::Result<AdnlPacket> R) {
if (R.is_error()) {
VLOG(ADNL_WARNING) << id << ": dropping IN message: can not decrypt: " << R.move_as_error();
} else {
auto packet = R.move_as_ok();
packet.set_remote_addr(addr);
td::actor::send_closure(peer, &AdnlPeerPair::receive_packet_from_channel, channel_id, std::move(packet), size);
}
});
decrypt(std::move(data), std::move(P));
}

View file

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

View file

@ -41,20 +41,34 @@ AdnlAddressList AdnlLocalId::get_addr_list() const {
}
void AdnlLocalId::receive(td::IPAddress addr, td::BufferSlice data) {
auto P = td::PromiseCreator::lambda(
[peer_table = peer_table_, dst = short_id_, addr, id = print_id()](td::Result<AdnlPacket> R) {
if (R.is_error()) {
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
} else {
auto packet = R.move_as_ok();
packet.set_remote_addr(addr);
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, std::move(packet));
}
});
InboundRateLimiter& rate_limiter = inbound_rate_limiter_[addr];
if (!rate_limiter.rate_limiter.take()) {
VLOG(ADNL_NOTICE) << this << ": dropping IN message: rate limit exceeded";
add_dropped_packet_stats(addr);
return;
}
++rate_limiter.currently_decrypting_packets;
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), peer_table = peer_table_, dst = short_id_, addr,
id = print_id(), size = data.size()](td::Result<AdnlPacket> R) {
td::actor::send_closure(SelfId, &AdnlLocalId::decrypt_packet_done, addr);
if (R.is_error()) {
VLOG(ADNL_WARNING) << id << ": dropping IN message: cannot decrypt: " << R.move_as_error();
} else {
auto packet = R.move_as_ok();
packet.set_remote_addr(addr);
td::actor::send_closure(peer_table, &AdnlPeerTable::receive_decrypted_packet, dst, std::move(packet), size);
}
});
decrypt(std::move(data), std::move(P));
}
void AdnlLocalId::decrypt_packet_done(td::IPAddress addr) {
auto it = inbound_rate_limiter_.find(addr);
CHECK(it != inbound_rate_limiter_.end());
--it->second.currently_decrypting_packets;
add_decrypted_packet_stats(addr);
}
void AdnlLocalId::deliver(AdnlNodeIdShort src, td::BufferSlice data) {
auto s = std::move(data);
for (auto &cb : cb_) {
@ -292,6 +306,72 @@ void AdnlLocalId::update_packet(AdnlPacket packet, bool update_id, bool sign, td
}
}
void AdnlLocalId::get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats_localId>> promise) {
auto stats = create_tl_object<ton_api::adnl_stats_localId>();
stats->short_id_ = short_id_.bits256_value();
for (auto &[ip, x] : inbound_rate_limiter_) {
if (x.currently_decrypting_packets != 0) {
stats->current_decrypt_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", x.currently_decrypting_packets));
}
}
prepare_packet_stats();
stats->packets_recent_ = packet_stats_prev_.tl();
stats->packets_total_ = packet_stats_total_.tl(all);
stats->packets_total_->ts_start_ = (double)Adnl::adnl_start_time();
stats->packets_total_->ts_end_ = td::Clocks::system();
promise.set_result(std::move(stats));
}
void AdnlLocalId::add_decrypted_packet_stats(td::IPAddress addr) {
prepare_packet_stats();
packet_stats_cur_.decrypted_packets[addr].inc();
packet_stats_total_.decrypted_packets[addr].inc();
}
void AdnlLocalId::add_dropped_packet_stats(td::IPAddress addr) {
prepare_packet_stats();
packet_stats_cur_.dropped_packets[addr].inc();
packet_stats_total_.dropped_packets[addr].inc();
}
void AdnlLocalId::prepare_packet_stats() {
double now = td::Clocks::system();
if (now >= packet_stats_cur_.ts_end) {
packet_stats_prev_ = std::move(packet_stats_cur_);
packet_stats_cur_ = {};
auto now_int = (int)td::Clocks::system();
packet_stats_cur_.ts_start = (double)(now_int / 60 * 60);
packet_stats_cur_.ts_end = packet_stats_cur_.ts_start + 60.0;
if (packet_stats_prev_.ts_end < now - 60.0) {
packet_stats_prev_ = {};
packet_stats_prev_.ts_end = packet_stats_cur_.ts_start;
packet_stats_prev_.ts_start = packet_stats_prev_.ts_end - 60.0;
}
}
}
tl_object_ptr<ton_api::adnl_stats_localIdPackets> AdnlLocalId::PacketStats::tl(bool all) const {
double threshold = all ? -1.0 : td::Clocks::system() - 600.0;
auto obj = create_tl_object<ton_api::adnl_stats_localIdPackets>();
obj->ts_start_ = ts_start;
obj->ts_end_ = ts_end;
for (const auto &[ip, packets] : decrypted_packets) {
if (packets.last_packet_ts >= threshold) {
obj->decrypted_packets_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets.packets));
}
}
for (const auto &[ip, packets] : dropped_packets) {
if (packets.last_packet_ts >= threshold) {
obj->dropped_packets_.push_back(create_tl_object<ton_api::adnl_stats_ipPackets>(
ip.is_valid() ? PSTRING() << ip.get_ip_str() << ":" << ip.get_port() : "", packets.packets));
}
}
return obj;
}
} // namespace adnl
} // namespace ton

View file

@ -55,6 +55,7 @@ class AdnlLocalId : public td::actor::Actor {
void deliver(AdnlNodeIdShort src, td::BufferSlice data);
void deliver_query(AdnlNodeIdShort src, td::BufferSlice data, td::Promise<td::BufferSlice> promise);
void receive(td::IPAddress addr, td::BufferSlice data);
void decrypt_packet_done(td::IPAddress addr);
void subscribe(std::string prefix, std::unique_ptr<AdnlPeerTable::Callback> callback);
void unsubscribe(std::string prefix);
@ -77,6 +78,8 @@ class AdnlLocalId : public td::actor::Actor {
void update_packet(AdnlPacket packet, bool update_id, bool sign, td::int32 update_addr_list_if,
td::int32 update_priority_addr_list_if, td::Promise<AdnlPacket> promise);
void get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats_localId>> promise);
td::uint32 get_mode() {
return mode_;
}
@ -101,6 +104,32 @@ class AdnlLocalId : public td::actor::Actor {
td::uint32 mode_;
struct InboundRateLimiter {
RateLimiter rate_limiter = RateLimiter(75, 0.33);
td::uint64 currently_decrypting_packets = 0;
};
std::map<td::IPAddress, InboundRateLimiter> inbound_rate_limiter_;
struct PacketStats {
double ts_start = 0.0, ts_end = 0.0;
struct Counter {
td::uint64 packets = 0;
double last_packet_ts = 0.0;
void inc() {
++packets;
last_packet_ts = td::Clocks::system();
}
};
std::map<td::IPAddress, Counter> decrypted_packets;
std::map<td::IPAddress, Counter> dropped_packets;
tl_object_ptr<ton_api::adnl_stats_localIdPackets> tl(bool all = true) const;
} packet_stats_cur_, packet_stats_prev_, packet_stats_total_;
void add_decrypted_packet_stats(td::IPAddress addr);
void add_dropped_packet_stats(td::IPAddress addr);
void prepare_packet_stats();
void publish_address_list();
};

View file

@ -84,7 +84,7 @@ void AdnlPeerTableImpl::receive_packet(td::IPAddress addr, AdnlCategoryMask cat_
<< " (len=" << (data.size() + 32) << ")";
}
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) {
void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet, td::uint64 serialized_size) {
packet.run_basic_checks().ensure();
if (!packet.inited_from_short()) {
@ -119,7 +119,7 @@ void AdnlPeerTableImpl::receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket
return;
}
td::actor::send_closure(it->second, &AdnlPeer::receive_packet, dst, it2->second.mode, it2->second.local_id.get(),
std::move(packet));
std::move(packet), serialized_size);
}
void AdnlPeerTableImpl::add_peer(AdnlNodeIdShort local_id, AdnlNodeIdFull id, AdnlAddressList addr_list) {
@ -385,6 +385,88 @@ void AdnlPeerTableImpl::get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_
td::actor::send_closure(it->second, &AdnlPeer::get_conn_ip_str, l_id, std::move(promise));
}
void AdnlPeerTableImpl::get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) {
class Cb : public td::actor::Actor {
public:
explicit Cb(td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) : promise_(std::move(promise)) {
}
void got_local_id_stats(tl_object_ptr<ton_api::adnl_stats_localId> local_id) {
auto &local_id_stats = local_id_stats_[local_id->short_id_];
if (local_id_stats) {
local_id->peers_ = std::move(local_id_stats->peers_);
}
local_id_stats = std::move(local_id);
dec_pending();
}
void got_peer_stats(std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>> peer_pairs) {
for (auto &peer_pair : peer_pairs) {
auto &local_id_stats = local_id_stats_[peer_pair->local_id_];
if (local_id_stats == nullptr) {
local_id_stats = create_tl_object<ton_api::adnl_stats_localId>();
local_id_stats->short_id_ = peer_pair->local_id_;
}
local_id_stats->peers_.push_back(std::move(peer_pair));
}
dec_pending();
}
void inc_pending() {
++pending_;
}
void dec_pending() {
CHECK(pending_ > 0);
--pending_;
if (pending_ == 0) {
auto stats = create_tl_object<ton_api::adnl_stats>();
stats->timestamp_ = td::Clocks::system();
for (auto &[id, local_id_stats] : local_id_stats_) {
stats->local_ids_.push_back(std::move(local_id_stats));
}
promise_.set_result(std::move(stats));
stop();
}
}
private:
td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise_;
size_t pending_ = 1;
std::map<td::Bits256, tl_object_ptr<ton_api::adnl_stats_localId>> local_id_stats_;
};
auto callback = td::actor::create_actor<Cb>("adnlstats", std::move(promise)).release();
for (auto &[id, local_id] : local_ids_) {
td::actor::send_closure(callback, &Cb::inc_pending);
td::actor::send_closure(local_id.local_id, &AdnlLocalId::get_stats, all,
[id = id, callback](td::Result<tl_object_ptr<ton_api::adnl_stats_localId>> R) {
if (R.is_error()) {
VLOG(ADNL_NOTICE)
<< "failed to get stats for local id " << id << " : " << R.move_as_error();
td::actor::send_closure(callback, &Cb::dec_pending);
} else {
td::actor::send_closure(callback, &Cb::got_local_id_stats, R.move_as_ok());
}
});
}
for (auto &[id, peer] : peers_) {
td::actor::send_closure(callback, &Cb::inc_pending);
td::actor::send_closure(
peer, &AdnlPeer::get_stats, all,
[id = id, callback](td::Result<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> R) {
if (R.is_error()) {
VLOG(ADNL_NOTICE) << "failed to get stats for peer " << id << " : " << R.move_as_error();
td::actor::send_closure(callback, &Cb::dec_pending);
} else {
td::actor::send_closure(callback, &Cb::got_peer_stats, R.move_as_ok());
}
});
}
td::actor::send_closure(callback, &Cb::dec_pending);
}
} // namespace adnl
} // namespace ton

View file

@ -90,7 +90,7 @@ class AdnlPeerTable : public Adnl {
virtual void answer_query(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlQueryId query_id, td::BufferSlice data) = 0;
virtual void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) = 0;
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet) = 0;
virtual void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket packet, td::uint64 serialized_size) = 0;
virtual void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) = 0;
virtual void register_channel(AdnlChannelIdShort id, AdnlNodeIdShort local_id,

View file

@ -44,7 +44,7 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
void add_static_nodes_from_config(AdnlNodesList nodes) override;
void receive_packet(td::IPAddress addr, AdnlCategoryMask cat_mask, td::BufferSlice data) override;
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data) override;
void receive_decrypted_packet(AdnlNodeIdShort dst, AdnlPacket data, td::uint64 serialized_size) override;
void send_message_in(AdnlNodeIdShort src, AdnlNodeIdShort dst, AdnlMessage message, td::uint32 flags) override;
void send_message(AdnlNodeIdShort src, AdnlNodeIdShort dst, td::BufferSlice data) override {
send_message_ex(src, dst, std::move(data), 0);
@ -108,6 +108,8 @@ class AdnlPeerTableImpl : public AdnlPeerTable {
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) override;
void get_conn_ip_str(AdnlNodeIdShort l_id, AdnlNodeIdShort p_id, td::Promise<td::string> promise) override;
void get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) override;
struct PrintId {};
PrintId print_id() const {
return PrintId{};

View file

@ -26,6 +26,7 @@
#include "td/utils/base64.h"
#include "td/utils/Random.h"
#include "auto/tl/ton_api.h"
#include "td/utils/overloaded.h"
namespace ton {
@ -50,9 +51,13 @@ void AdnlPeerPairImpl::start_up() {
}
void AdnlPeerPairImpl::alarm() {
if (next_dht_query_at_ && next_dht_query_at_.is_in_past()) {
next_dht_query_at_ = td::Timestamp::never();
discover();
if (!disable_dht_query_) {
disable_dht_query_ = true;
if (next_dht_query_at_ && next_dht_query_at_.is_in_past()) {
next_dht_query_at_ = td::Timestamp::never();
discover();
}
alarm_timestamp().relax(next_dht_query_at_);
}
if (next_db_update_at_ && next_db_update_at_.is_in_past()) {
if (received_from_db_ && received_from_static_nodes_ && !peer_id_.empty()) {
@ -68,11 +73,8 @@ void AdnlPeerPairImpl::alarm() {
}
if (retry_send_at_ && retry_send_at_.is_in_past()) {
retry_send_at_ = td::Timestamp::never();
auto messages = std::move(pending_messages_);
pending_messages_.clear();
send_messages_in(std::move(messages), false);
send_messages_from_queue();
}
alarm_timestamp().relax(next_dht_query_at_);
alarm_timestamp().relax(next_db_update_at_);
alarm_timestamp().relax(retry_send_at_);
}
@ -117,6 +119,7 @@ void AdnlPeerPairImpl::discover() {
void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
last_received_packet_ = td::Timestamp::now();
try_reinit_at_ = td::Timestamp::never();
drop_addr_list_at_ = td::Timestamp::never();
request_reverse_ping_after_ = td::Timestamp::in(15.0);
auto d = Adnl::adnl_start_time();
if (packet.dst_reinit_date() > d) {
@ -207,18 +210,24 @@ void AdnlPeerPairImpl::receive_packet_checked(AdnlPacket packet) {
}
}
void AdnlPeerPairImpl::receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) {
void AdnlPeerPairImpl::receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet,
td::uint64 serialized_size) {
add_packet_stats(serialized_size, /* in = */ true, /* channel = */ true);
if (id != channel_in_id_) {
VLOG(ADNL_NOTICE) << this << ": dropping IN message: outdated channel id" << id;
return;
}
if (channel_inited_) {
if (channel_inited_ && !channel_ready_) {
channel_ready_ = true;
if (!out_messages_queue_.empty()) {
td::actor::send_closure(actor_id(this), &AdnlPeerPairImpl::send_messages_from_queue);
}
}
receive_packet_checked(std::move(packet));
}
void AdnlPeerPairImpl::receive_packet(AdnlPacket packet) {
void AdnlPeerPairImpl::receive_packet(AdnlPacket packet, td::uint64 serialized_size) {
add_packet_stats(serialized_size, /* in = */ true, /* channel = */ false);
packet.run_basic_checks().ensure();
if (!encryptor_) {
@ -239,128 +248,132 @@ void AdnlPeerPairImpl::deliver_message(AdnlMessage message) {
message.visit([&](const auto &obj) { this->process_message(obj); });
}
void AdnlPeerPairImpl::send_messages_in(std::vector<OutboundAdnlMessage> messages, bool allow_postpone) {
for (td::int32 idx = 0; idx < 2; idx++) {
std::vector<OutboundAdnlMessage> not_sent;
void AdnlPeerPairImpl::send_messages_from_queue() {
while (!out_messages_queue_.empty() && out_messages_queue_.front().second.is_in_past()) {
out_messages_queue_total_size_ -= out_messages_queue_.front().first.size();
add_expired_msg_stats(out_messages_queue_.front().first.size());
out_messages_queue_.pop();
VLOG(ADNL_NOTICE) << this << ": dropping OUT message: message in queue expired";
}
if (out_messages_queue_.empty()) {
return;
}
auto connR = get_conn(idx == 1);
if (connR.is_error()) {
if (!allow_postpone) {
VLOG(ADNL_NOTICE) << this << ": dropping OUT messages: cannot get conn: " << connR.move_as_error();
return;
}
VLOG(ADNL_INFO) << this << ": delaying OUT messages: cannot get conn: " << connR.move_as_error();
if (!retry_send_at_) {
retry_send_at_.relax(td::Timestamp::in(10.0));
alarm_timestamp().relax(retry_send_at_);
}
for (auto &m : messages) {
pending_messages_.push_back(std::move(m));
}
auto connR = get_conn();
if (connR.is_error()) {
disable_dht_query_ = false;
retry_send_at_.relax(td::Timestamp::in(message_in_queue_ttl_ - 1.0));
alarm_timestamp().relax(retry_send_at_);
VLOG(ADNL_INFO) << this << ": delaying OUT messages: cannot get conn: " << connR.move_as_error();
return;
}
disable_dht_query_ = true;
auto C = connR.move_as_ok();
auto conn = std::move(C.first);
bool is_direct = C.second;
bool first = !skip_init_packet_;
while (!out_messages_queue_.empty()) {
bool try_reinit = try_reinit_at_ && try_reinit_at_.is_in_past();
bool via_channel = channel_ready_ && !try_reinit;
if (!via_channel && !nochannel_rate_limiter_.take()) {
alarm_timestamp().relax(retry_send_at_ = nochannel_rate_limiter_.ready_at());
return;
}
auto C = connR.move_as_ok();
bool is_direct = C.second;
auto conn = std::move(C.first);
if (idx == 1) {
CHECK(is_direct);
if (try_reinit) {
try_reinit_at_ = td::Timestamp::in(td::Random::fast(0.5, 1.5));
}
respond_with_nop_after_ = td::Timestamp::in(td::Random::fast(1.0, 2.0));
size_t s = (via_channel ? channel_packet_header_max_size() : packet_header_max_size());
if (first) {
s += 2 * addr_list_max_size();
}
size_t ptr = 0;
bool first = true;
do {
bool try_reinit = try_reinit_at_ && try_reinit_at_.is_in_past();
bool via_channel = channel_ready_ && !try_reinit;
size_t s = (via_channel ? channel_packet_header_max_size() : packet_header_max_size());
if (first) {
s += 2 * addr_list_max_size();
}
AdnlPacket packet;
packet.set_seqno(++out_seqno_);
packet.set_confirm_seqno(in_seqno_);
AdnlPacket packet;
packet.set_seqno(++out_seqno_);
packet.set_confirm_seqno(in_seqno_);
if (first) {
if (!channel_inited_) {
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
s += M.size();
packet.add_message(std::move(M));
} else if (!channel_ready_) {
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
s += M.size();
packet.add_message(std::move(M));
}
if (first) {
if (!channel_inited_) {
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
s += M.size();
packet.add_message(std::move(M));
} else if (!channel_ready_) {
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
s += M.size();
packet.add_message(std::move(M));
}
}
if (!addr_list_.empty()) {
packet.set_received_addr_list_version(addr_list_.version());
}
if (!priority_addr_list_.empty()) {
packet.set_received_priority_addr_list_version(priority_addr_list_.version());
}
if (!addr_list_.empty()) {
packet.set_received_addr_list_version(addr_list_.version());
}
if (!priority_addr_list_.empty()) {
packet.set_received_priority_addr_list_version(priority_addr_list_.version());
}
while (ptr < messages.size()) {
auto &M = messages[ptr];
if (!is_direct && (M.flags() & Adnl::SendFlags::direct_only)) {
not_sent.push_back(std::move(M));
continue;
}
CHECK(M.size() <= get_mtu());
skip_init_packet_ = true;
while (!out_messages_queue_.empty()) {
auto &M = out_messages_queue_.front().first;
if (!is_direct && (M.flags() & Adnl::SendFlags::direct_only)) {
out_messages_queue_total_size_ -= M.size();
out_messages_queue_.pop();
continue;
}
CHECK(M.size() <= get_mtu());
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
s += M.size();
out_messages_queue_total_size_ -= M.size();
packet.add_message(M.release());
out_messages_queue_.pop();
skip_init_packet_ = false;
} else {
break;
}
}
if (!via_channel) {
packet.set_reinit_date(Adnl::adnl_start_time(), reinit_date_);
packet.set_source(local_id_);
}
if (!first) {
if (!channel_inited_) {
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
s += M.size();
packet.add_message(M.release());
ptr++;
} else {
break;
packet.add_message(std::move(M));
}
} else if (!channel_ready_) {
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
s += M.size();
packet.add_message(std::move(M));
}
}
if (!via_channel) {
packet.set_reinit_date(Adnl::adnl_start_time(), reinit_date_);
packet.set_source(local_id_);
}
if (!first) {
if (!channel_inited_) {
auto M = adnlmessage::AdnlMessageCreateChannel{channel_pub_, channel_pk_date_};
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
s += M.size();
packet.add_message(std::move(M));
}
} else if (!channel_ready_) {
auto M = adnlmessage::AdnlMessageConfirmChannel{channel_pub_, peer_channel_pub_, channel_pk_date_};
if (s + M.size() <= AdnlNetworkManager::get_mtu()) {
s += M.size();
packet.add_message(std::move(M));
}
}
}
packet.run_basic_checks().ensure();
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), conn, id = print_id(),
via_channel](td::Result<AdnlPacket> res) {
if (res.is_error()) {
LOG(ERROR) << id << ": dropping OUT message: error while creating packet: " << res.move_as_error();
} else {
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_packet_continue, res.move_as_ok(), conn, via_channel);
}
});
td::actor::send_closure(local_actor_, &AdnlLocalId::update_packet, std::move(packet),
(!channel_ready_ && ack_seqno_ == 0 && in_seqno_ == 0) || try_reinit, !via_channel,
(first || s + addr_list_max_size() <= AdnlNetworkManager::get_mtu())
? (try_reinit ? 0 : peer_recv_addr_list_version_)
: 0x7fffffff,
(first || s + 2 * addr_list_max_size() <= AdnlNetworkManager::get_mtu())
? peer_recv_priority_addr_list_version_
: 0x7fffffff,
std::move(P));
first = false;
} while (ptr < messages.size());
messages = std::move(not_sent);
if (!messages.size()) {
break;
}
packet.run_basic_checks().ensure();
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), conn, id = print_id(),
via_channel](td::Result<AdnlPacket> res) {
if (res.is_error()) {
LOG(ERROR) << id << ": dropping OUT message: error while creating packet: " << res.move_as_error();
} else {
td::actor::send_closure(SelfId, &AdnlPeerPairImpl::send_packet_continue, res.move_as_ok(), conn, via_channel);
}
});
td::actor::send_closure(local_actor_, &AdnlLocalId::update_packet, std::move(packet),
(!channel_ready_ && ack_seqno_ == 0 && in_seqno_ == 0) || try_reinit, !via_channel,
(first || s + addr_list_max_size() <= AdnlNetworkManager::get_mtu())
? (try_reinit ? 0 : peer_recv_addr_list_version_)
: 0x7fffffff,
(first || s + 2 * addr_list_max_size() <= AdnlNetworkManager::get_mtu())
? peer_recv_priority_addr_list_version_
: 0x7fffffff,
std::move(P));
first = false;
}
}
@ -391,7 +404,11 @@ void AdnlPeerPairImpl::send_messages(std::vector<OutboundAdnlMessage> messages)
}
}
}
send_messages_in(std::move(new_vec), true);
for (auto &m : new_vec) {
out_messages_queue_total_size_ += m.size();
out_messages_queue_.emplace(std::move(m), td::Timestamp::in(message_in_queue_ttl_));
}
send_messages_from_queue();
}
void AdnlPeerPairImpl::send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn,
@ -399,10 +416,14 @@ void AdnlPeerPairImpl::send_packet_continue(AdnlPacket packet, td::actor::ActorI
if (!try_reinit_at_ && last_received_packet_ < td::Timestamp::in(-5.0)) {
try_reinit_at_ = td::Timestamp::in(10.0);
}
if (!drop_addr_list_at_ && last_received_packet_ < td::Timestamp::in(-60.0 * 9.0)) {
drop_addr_list_at_ = td::Timestamp::in(60.0);
}
packet.run_basic_checks().ensure();
auto B = serialize_tl_object(packet.tl(), true);
if (via_channel) {
if (channel_ready_) {
add_packet_stats(B.size(), /* in = */ false, /* channel = */ true);
td::actor::send_closure(channel_, &AdnlChannel::send_message, priority_, conn, std::move(B));
} else {
VLOG(ADNL_WARNING) << this << ": dropping OUT message [" << local_id_ << "->" << peer_id_short_
@ -430,6 +451,7 @@ void AdnlPeerPairImpl::send_packet_continue(AdnlPacket packet, td::actor::ActorI
S.remove_prefix(32);
S.copy_from(X.as_slice());
add_packet_stats(B.size(), /* in = */ false, /* channel = */ false);
td::actor::send_closure(conn, &AdnlNetworkConnection::send, local_id_, peer_id_short_, priority_, std::move(enc));
}
@ -504,12 +526,6 @@ void AdnlPeerPairImpl::create_channel(pubkeys::Ed25519 pub, td::uint32 date) {
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageCreateChannel &message) {
create_channel(message.key(), message.date());
if (respond_to_channel_create_after_.is_in_past()) {
respond_to_channel_create_after_ = td::Timestamp::in(td::Random::fast(1.0, 2.0));
std::vector<OutboundAdnlMessage> messages;
messages.emplace_back(adnlmessage::AdnlMessageNop{}, 0);
send_messages(std::move(messages));
}
}
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageConfirmChannel &message) {
@ -522,10 +538,14 @@ void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageConfirmChan
VLOG(ADNL_NOTICE) << this << ": received adnl.message.confirmChannel with old key";
return;
}
channel_ready_ = true;
if (!channel_ready_) {
channel_ready_ = true;
send_messages_from_queue();
}
}
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageCustom &message) {
respond_with_nop();
td::actor::send_closure(local_actor_, &AdnlLocalId::deliver, peer_id_short_, message.data());
}
@ -538,6 +558,7 @@ void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageReinit &mes
}
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageQuery &message) {
respond_with_nop();
auto P = td::PromiseCreator::lambda([SelfId = actor_id(this), query_id = message.query_id(),
flags = static_cast<td::uint32>(0)](td::Result<td::BufferSlice> R) {
if (R.is_error()) {
@ -556,6 +577,7 @@ void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageQuery &mess
}
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageAnswer &message) {
respond_with_nop();
auto Q = out_queries_.find(message.query_id());
if (Q == out_queries_.end()) {
@ -573,6 +595,7 @@ void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessageAnswer &mes
}
void AdnlPeerPairImpl::process_message(const adnlmessage::AdnlMessagePart &message) {
respond_with_nop();
auto size = message.total_size();
if (size > huge_packet_max_size()) {
VLOG(ADNL_WARNING) << this << ": dropping too big huge message: size=" << size;
@ -635,6 +658,14 @@ void AdnlPeerPairImpl::delete_query(AdnlQueryId id) {
}
}
void AdnlPeerPairImpl::respond_with_nop() {
if (respond_with_nop_after_.is_in_past()) {
std::vector<OutboundAdnlMessage> messages;
messages.emplace_back(adnlmessage::AdnlMessageNop{}, 0);
send_messages(std::move(messages));
}
}
void AdnlPeerPairImpl::reinit(td::int32 date) {
if (reinit_date_ == 0) {
reinit_date_ = date;
@ -664,7 +695,17 @@ void AdnlPeerPairImpl::reinit(td::int32 date) {
}
}
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> AdnlPeerPairImpl::get_conn(bool direct_only) {
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> AdnlPeerPairImpl::get_conn() {
if (drop_addr_list_at_ && drop_addr_list_at_.is_in_past()) {
drop_addr_list_at_ = td::Timestamp::never();
priority_addr_list_ = AdnlAddressList{};
priority_conns_.clear();
addr_list_ = AdnlAddressList{};
conns_.clear();
has_reverse_addr_ = false;
return td::Status::Error(ErrorCode::notready, "no active connections");
}
if (!priority_addr_list_.empty() && priority_addr_list_.expire_at() < td::Clocks::system()) {
priority_addr_list_ = AdnlAddressList{};
priority_conns_.clear();
@ -682,14 +723,18 @@ td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> AdnlPeerP
}
}
for (auto &conn : priority_conns_) {
if (conn.ready() && (!direct_only || conn.is_direct())) {
return std::make_pair(conn.conn.get(), conn.is_direct());
for (int direct_only = 1; direct_only >= 0; --direct_only) {
for (auto &conn : priority_conns_) {
if (conn.ready() && (!direct_only || conn.is_direct())) {
return std::make_pair(conn.conn.get(), conn.is_direct());
}
}
}
for (auto &conn : conns_) {
if (conn.ready() && (!direct_only || conn.is_direct())) {
return std::make_pair(conn.conn.get(), conn.is_direct());
for (int direct_only = 1; direct_only >= 0; --direct_only) {
for (auto &conn : conns_) {
if (conn.ready() && (!direct_only || conn.is_direct())) {
return std::make_pair(conn.conn.get(), conn.is_direct());
}
}
}
return td::Status::Error(ErrorCode::notready, "no active connections");
@ -777,6 +822,55 @@ void AdnlPeerPairImpl::get_conn_ip_str(td::Promise<td::string> promise) {
promise.set_value("undefined");
}
void AdnlPeerPairImpl::get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats_peerPair>> promise) {
if (!all) {
double threshold = td::Clocks::system() - 600.0;
if (last_in_packet_ts_ < threshold && last_out_packet_ts_ < threshold) {
promise.set_value(nullptr);
return;
}
}
auto stats = create_tl_object<ton_api::adnl_stats_peerPair>();
stats->local_id_ = local_id_.bits256_value();
stats->peer_id_ = peer_id_short_.bits256_value();
for (const AdnlAddress &addr : addr_list_.addrs()) {
ton_api::downcast_call(*addr->tl(), td::overloaded(
[&](const ton_api::adnl_address_udp &obj) {
stats->ip_str_ = PSTRING() << td::IPAddress::ipv4_to_str(obj.ip_) << ":"
<< obj.port_;
},
[&](const auto &) {}));
if (!stats->ip_str_.empty()) {
break;
}
}
prepare_packet_stats();
stats->last_in_packet_ts_ = last_in_packet_ts_;
stats->last_out_packet_ts_ = last_out_packet_ts_;
stats->packets_total_ = packet_stats_total_.tl();
stats->packets_total_->ts_start_ = started_ts_;
stats->packets_total_->ts_end_ = td::Clocks::system();
stats->packets_recent_ = packet_stats_prev_.tl();
if (channel_ready_) {
stats->channel_status_ = 2;
} else if (channel_inited_) {
stats->channel_status_ = 1;
} else {
stats->channel_status_ = 0;
}
stats->try_reinit_at_ = (try_reinit_at_ ? try_reinit_at_.at_unix() : 0.0);
stats->connection_ready_ =
std::any_of(conns_.begin(), conns_.end(), [](const Conn &conn) { return conn.ready(); }) ||
std::any_of(priority_conns_.begin(), priority_conns_.end(), [](const Conn &conn) { return conn.ready(); });
stats->out_queue_messages_ = out_messages_queue_.size();
stats->out_queue_bytes_ = out_messages_queue_total_size_;
promise.set_result(std::move(stats));
}
void AdnlPeerImpl::update_id(AdnlNodeIdFull id) {
CHECK(id.compute_short_id() == peer_id_short_);
if (!peer_id_.empty()) {
@ -800,10 +894,8 @@ void AdnlPeerPairImpl::Conn::create_conn(td::actor::ActorId<AdnlPeerPairImpl> pe
void AdnlPeerPairImpl::conn_change_state(AdnlConnectionIdShort id, bool ready) {
if (ready) {
if (pending_messages_.size() > 0) {
auto messages = std::move(pending_messages_);
pending_messages_.clear();
send_messages_in(std::move(messages), true);
if (out_messages_queue_.empty()) {
send_messages_from_queue();
}
}
}
@ -825,7 +917,7 @@ td::actor::ActorOwn<AdnlPeer> AdnlPeer::create(td::actor::ActorId<AdnlNetworkMan
}
void AdnlPeerImpl::receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::actor::ActorId<AdnlLocalId> dst_actor,
AdnlPacket packet) {
AdnlPacket packet, td::uint64 serialized_size) {
if (packet.inited_from()) {
update_id(packet.from());
}
@ -843,7 +935,7 @@ void AdnlPeerImpl::receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::
}
}
td::actor::send_closure(it->second.get(), &AdnlPeerPair::receive_packet, std::move(packet));
td::actor::send_closure(it->second.get(), &AdnlPeerPair::receive_packet, std::move(packet), serialized_size);
}
void AdnlPeerImpl::send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
@ -923,6 +1015,58 @@ void AdnlPeerImpl::update_addr_list(AdnlNodeIdShort local_id, td::uint32 local_m
td::actor::send_closure(it->second, &AdnlPeerPair::update_addr_list, std::move(addr_list));
}
void AdnlPeerImpl::get_stats(bool all, td::Promise<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> promise) {
class Cb : public td::actor::Actor {
public:
explicit Cb(td::Promise<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> promise)
: promise_(std::move(promise)) {
}
void got_peer_pair_stats(tl_object_ptr<ton_api::adnl_stats_peerPair> peer_pair) {
if (peer_pair) {
result_.push_back(std::move(peer_pair));
}
dec_pending();
}
void inc_pending() {
++pending_;
}
void dec_pending() {
CHECK(pending_ > 0);
--pending_;
if (pending_ == 0) {
promise_.set_result(std::move(result_));
stop();
}
}
private:
td::Promise<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> promise_;
size_t pending_ = 1;
std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>> result_;
};
auto callback = td::actor::create_actor<Cb>("adnlpeerstats", std::move(promise)).release();
for (auto &[local_id, peer_pair] : peer_pairs_) {
td::actor::send_closure(callback, &Cb::inc_pending);
td::actor::send_closure(peer_pair, &AdnlPeerPair::get_stats, all,
[local_id = local_id, peer_id = peer_id_short_,
callback](td::Result<tl_object_ptr<ton_api::adnl_stats_peerPair>> R) {
if (R.is_error()) {
VLOG(ADNL_NOTICE) << "failed to get stats for peer pair " << peer_id << "->" << local_id
<< " : " << R.move_as_error();
td::actor::send_closure(callback, &Cb::dec_pending);
} else {
td::actor::send_closure(callback, &Cb::got_peer_pair_stats, R.move_as_ok());
}
});
}
td::actor::send_closure(callback, &Cb::dec_pending);
}
void AdnlPeerPairImpl::got_data_from_db(td::Result<AdnlDbItem> R) {
received_from_db_ = false;
if (R.is_error()) {
@ -1006,6 +1150,66 @@ void AdnlPeerPairImpl::request_reverse_ping_result(td::Result<td::Unit> R) {
}
}
void AdnlPeerPairImpl::add_packet_stats(td::uint64 bytes, bool in, bool channel) {
prepare_packet_stats();
auto add_stats = [&](PacketStats &stats) {
if (in) {
++stats.in_packets;
stats.in_bytes += bytes;
if (channel) {
++stats.in_packets_channel;
stats.in_bytes_channel += bytes;
}
} else {
++stats.out_packets;
stats.out_bytes += bytes;
if (channel) {
++stats.out_packets_channel;
stats.out_bytes_channel += bytes;
}
}
};
add_stats(packet_stats_cur_);
add_stats(packet_stats_total_);
if (in) {
last_in_packet_ts_ = td::Clocks::system();
} else {
last_out_packet_ts_ = td::Clocks::system();
}
}
void AdnlPeerPairImpl::add_expired_msg_stats(td::uint64 bytes) {
prepare_packet_stats();
auto add_stats = [&](PacketStats &stats) {
++stats.out_expired_messages;
stats.out_expired_bytes += bytes;
};
add_stats(packet_stats_cur_);
add_stats(packet_stats_total_);
}
void AdnlPeerPairImpl::prepare_packet_stats() {
double now = td::Clocks::system();
if (now >= packet_stats_cur_.ts_end) {
packet_stats_prev_ = std::move(packet_stats_cur_);
packet_stats_cur_ = {};
auto now_int = (int)now;
packet_stats_cur_.ts_start = (double)(now_int / 60 * 60);
packet_stats_cur_.ts_end = packet_stats_cur_.ts_start + 60.0;
if (packet_stats_prev_.ts_end < now - 60.0) {
packet_stats_prev_ = {};
packet_stats_prev_.ts_end = packet_stats_cur_.ts_start;
packet_stats_prev_.ts_start = packet_stats_prev_.ts_end - 60.0;
}
}
}
tl_object_ptr<ton_api::adnl_stats_packets> AdnlPeerPairImpl::PacketStats::tl() const {
return create_tl_object<ton_api::adnl_stats_packets>(ts_start, ts_end, in_packets, in_bytes, in_packets_channel,
in_bytes_channel, out_packets, out_bytes, out_packets_channel,
out_bytes_channel, out_expired_messages, out_expired_bytes);
}
} // namespace adnl
} // namespace ton

View file

@ -39,9 +39,9 @@ class AdnlPeer;
class AdnlPeerPair : public td::actor::Actor {
public:
virtual void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) = 0;
virtual void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet, td::uint64 serialized_size) = 0;
virtual void receive_packet_checked(AdnlPacket packet) = 0;
virtual void receive_packet(AdnlPacket packet) = 0;
virtual void receive_packet(AdnlPacket packet, td::uint64 serialized_size) = 0;
virtual void send_messages(std::vector<OutboundAdnlMessage> message) = 0;
inline void send_message(OutboundAdnlMessage message) {
@ -59,6 +59,7 @@ class AdnlPeerPair : public td::actor::Actor {
virtual void update_peer_id(AdnlNodeIdFull id) = 0;
virtual void update_addr_list(AdnlAddressList addr_list) = 0;
virtual void get_conn_ip_str(td::Promise<td::string> promise) = 0;
virtual void get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats_peerPair>> promise) = 0;
static td::actor::ActorOwn<AdnlPeerPair> create(td::actor::ActorId<AdnlNetworkManager> network_manager,
td::actor::ActorId<AdnlPeerTable> peer_table, td::uint32 local_mode,
@ -71,7 +72,7 @@ class AdnlPeerPair : public td::actor::Actor {
class AdnlPeer : public td::actor::Actor {
public:
virtual void receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::actor::ActorId<AdnlLocalId> dst_actor,
AdnlPacket message) = 0;
AdnlPacket message, td::uint64 serialized_size) = 0;
virtual void send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
std::vector<OutboundAdnlMessage> messages) = 0;
virtual void send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
@ -100,6 +101,7 @@ class AdnlPeer : public td::actor::Actor {
td::actor::ActorId<AdnlLocalId> local_actor, AdnlAddressList addr_list) = 0;
virtual void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) = 0;
virtual void get_conn_ip_str(AdnlNodeIdShort l_id, td::Promise<td::string> promise) = 0;
virtual void get_stats(bool all, td::Promise<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> promise) = 0;
};
} // namespace adnl

View file

@ -20,6 +20,7 @@
#include <vector>
#include <map>
#include <queue>
#include "adnl-peer.h"
#include "adnl-peer-table.h"
@ -66,12 +67,12 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
void discover();
void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet) override;
void receive_packet_from_channel(AdnlChannelIdShort id, AdnlPacket packet, td::uint64 serialized_size) override;
void receive_packet_checked(AdnlPacket packet) override;
void receive_packet(AdnlPacket packet) override;
void receive_packet(AdnlPacket packet, td::uint64 serialized_size) override;
void deliver_message(AdnlMessage message);
void send_messages_in(std::vector<OutboundAdnlMessage> messages, bool allow_postpone);
void send_messages_from_queue();
void send_messages(std::vector<OutboundAdnlMessage> messages) override;
void send_packet_continue(AdnlPacket packet, td::actor::ActorId<AdnlNetworkConnection> conn, bool via_channel);
void send_query(std::string name, td::Promise<td::BufferSlice> promise, td::Timestamp timeout, td::BufferSlice data,
@ -89,6 +90,7 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
void update_peer_id(AdnlNodeIdFull id) override;
void get_conn_ip_str(td::Promise<td::string> promise) override;
void get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats_peerPair>> promise) override;
void got_data_from_db(td::Result<AdnlDbItem> R);
void got_data_from_static_nodes(td::Result<AdnlNode> R);
@ -122,8 +124,9 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
}
private:
void respond_with_nop();
void reinit(td::int32 date);
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> get_conn(bool direct_only);
td::Result<std::pair<td::actor::ActorId<AdnlNetworkConnection>, bool>> get_conn();
void create_channel(pubkeys::Ed25519 pub, td::uint32 date);
bool received_packet(td::uint64 seqno) const {
@ -182,11 +185,11 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
Conn() {
}
bool ready() {
bool ready() const {
return !conn.empty() && conn.get_actor_unsafe().is_active();
}
bool is_direct() {
bool is_direct() const {
return addr->is_public();
}
@ -194,7 +197,14 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
td::actor::ActorId<Adnl> adnl);
};
std::vector<OutboundAdnlMessage> pending_messages_;
// Messages waiting for connection or for nochannel rate limiter
std::queue<std::pair<OutboundAdnlMessage, td::Timestamp>> out_messages_queue_;
td::uint64 out_messages_queue_total_size_ = 0;
RateLimiter nochannel_rate_limiter_ = RateLimiter(50, 0.5); // max 50, period = 0.5s
td::Timestamp retry_send_at_ = td::Timestamp::never();
bool disable_dht_query_ = false;
bool skip_init_packet_ = false;
double message_in_queue_ttl_ = 10.0;
td::actor::ActorId<AdnlNetworkManager> network_manager_;
td::actor::ActorId<AdnlPeerTable> peer_table_;
@ -214,7 +224,7 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
pubkeys::Ed25519 channel_pub_;
td::int32 channel_pk_date_;
td::actor::ActorOwn<AdnlChannel> channel_;
td::Timestamp respond_to_channel_create_after_;
td::Timestamp respond_with_nop_after_;
td::uint64 in_seqno_ = 0;
td::uint64 out_seqno_ = 0;
@ -253,20 +263,34 @@ class AdnlPeerPairImpl : public AdnlPeerPair {
td::Timestamp next_dht_query_at_ = td::Timestamp::never();
td::Timestamp next_db_update_at_ = td::Timestamp::never();
td::Timestamp retry_send_at_ = td::Timestamp::never();
td::Timestamp last_received_packet_ = td::Timestamp::never();
td::Timestamp try_reinit_at_ = td::Timestamp::never();
td::Timestamp drop_addr_list_at_ = td::Timestamp::never();
bool has_reverse_addr_ = false;
td::Timestamp request_reverse_ping_after_ = td::Timestamp::now();
bool request_reverse_ping_active_ = false;
struct PacketStats {
double ts_start = 0.0, ts_end = 0.0;
td::uint64 in_packets = 0, in_bytes = 0, in_packets_channel = 0, in_bytes_channel = 0;
td::uint64 out_packets = 0, out_bytes = 0, out_packets_channel = 0, out_bytes_channel = 0;
td::uint64 out_expired_messages = 0, out_expired_bytes = 0;
tl_object_ptr<ton_api::adnl_stats_packets> tl() const;
} packet_stats_cur_, packet_stats_prev_, packet_stats_total_;
double last_in_packet_ts_ = 0.0, last_out_packet_ts_ = 0.0;
double started_ts_ = td::Clocks::system();
void add_packet_stats(td::uint64 bytes, bool in, bool channel);
void add_expired_msg_stats(td::uint64 bytes);
void prepare_packet_stats();
};
class AdnlPeerImpl : public AdnlPeer {
public:
void receive_packet(AdnlNodeIdShort dst, td::uint32 dst_mode, td::actor::ActorId<AdnlLocalId> dst_actor,
AdnlPacket packet) override;
AdnlPacket packet, td::uint64 serialized_size) override;
void send_messages(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor,
std::vector<OutboundAdnlMessage> messages) override;
void send_query(AdnlNodeIdShort src, td::uint32 src_mode, td::actor::ActorId<AdnlLocalId> src_actor, std::string name,
@ -279,6 +303,7 @@ class AdnlPeerImpl : public AdnlPeer {
AdnlAddressList addr_list) override;
void update_dht_node(td::actor::ActorId<dht::Dht> dht_node) override;
void get_conn_ip_str(AdnlNodeIdShort l_id, td::Promise<td::string> promise) override;
void get_stats(bool all, td::Promise<std::vector<tl_object_ptr<ton_api::adnl_stats_peerPair>>> promise) override;
//void check_signature(td::BufferSlice data, td::BufferSlice signature, td::Promise<td::Unit> promise) override;
AdnlPeerImpl(td::actor::ActorId<AdnlNetworkManager> network_manager, td::actor::ActorId<AdnlPeerTable> peer_table,

View file

@ -25,7 +25,7 @@ namespace ton {
namespace adnl {
void AdnlQuery::alarm() {
set_error(td::Status::Error(ErrorCode::timeout, "adnl query timeout"));
set_error(td::Status::Error(ErrorCode::timeout, PSTRING() << "timeout for adnl query " << name_));
}
void AdnlQuery::result(td::BufferSlice data) {
promise_.set_value(std::move(data));

View file

@ -121,6 +121,8 @@ class Adnl : public AdnlSenderInterface {
virtual void create_tunnel(AdnlNodeIdShort dst, td::uint32 size,
td::Promise<std::pair<td::actor::ActorOwn<AdnlTunnel>, AdnlAddress>> promise) = 0;
virtual void get_stats(bool all, td::Promise<tl_object_ptr<ton_api::adnl_stats>> promise) = 0;
static td::actor::ActorOwn<Adnl> create(std::string db, td::actor::ActorId<keyring::Keyring> keyring);
static std::string int_to_bytestring(td::int32 id) {

View file

@ -40,6 +40,40 @@ inline bool adnl_node_is_older(AdnlNode &a, AdnlNode &b) {
return a.addr_list().version() < b.addr_list().version();
}
class RateLimiter {
public:
explicit RateLimiter(td::uint32 capacity, double period) : capacity_(capacity), period_(period), remaining_(capacity) {
}
bool take() {
while (remaining_ < capacity_ && increment_at_.is_in_past()) {
++remaining_;
increment_at_ += period_;
}
if (remaining_) {
--remaining_;
if (increment_at_.is_in_past()) {
increment_at_ = td::Timestamp::in(period_);
}
return true;
}
return false;
}
td::Timestamp ready_at() const {
if (remaining_) {
return td::Timestamp::now();
}
return increment_at_;
}
private:
td::uint32 capacity_;
double period_;
td::uint32 remaining_;
td::Timestamp increment_at_ = td::Timestamp::never();
};
} // namespace adnl
} // namespace ton

View file

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

3
assembly/appimage/AppRun Normal file
View file

@ -0,0 +1,3 @@
#!/bin/sh
export LD_LIBRARY_PATH="${APPDIR}/usr/lib:${LD_LIBRARY_PATH}"
exec "$(dirname $0)"/usr/bin/app "$@"

View file

@ -0,0 +1,50 @@
#!/bin/bash
if [ ! -d "artifacts" ]; then
echo "No artifacts found."
exit 2
fi
# x86_64 or aarch64
ARCH=$1
rm -rf appimages
mkdir -p appimages/artifacts
wget -nc https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-$ARCH.AppImage
chmod +x ./appimagetool-$ARCH.AppImage
cd appimages
for file in ../artifacts/*; do
if [[ -f "$file" && "$file" != *.so ]]; then
appName=$(basename "$file")
echo $appName
# prepare AppDir
mkdir -p $appName.AppDir/usr/{bin,lib}
cp ../AppRun $appName.AppDir/AppRun
sed -i "s/app/$appName/g" $appName.AppDir/AppRun
chmod +x ./$appName.AppDir/AppRun
printf '[Desktop Entry]\nName='$appName'\nExec='$appName'\nIcon='$appName'\nType=Application\nCategories=Utility;\n' > $appName.AppDir/$appName.desktop
cp ../ton.png $appName.AppDir/$appName.png
cp $file $appName.AppDir/usr/bin/
cp ../build/openssl_3/libcrypto.so.3 \
/lib/$ARCH-linux-gnu/libatomic.so.1 \
/lib/$ARCH-linux-gnu/libsodium.so.23 \
/lib/$ARCH-linux-gnu/libz.so.1 \
/lib/$ARCH-linux-gnu/liblz4.so.1 \
/lib/$ARCH-linux-gnu/libmicrohttpd.so.12 \
/lib/$ARCH-linux-gnu/libreadline.so.8 \
/lib/$ARCH-linux-gnu/libstdc++.so.6 \
$appName.AppDir/usr/lib/
chmod +x ./$appName.AppDir/usr/bin/$appName
# create AppImage
./../appimagetool-$ARCH.AppImage -l $appName.AppDir
mv $appName-$ARCH.AppImage artifacts/$appName
fi
done
ls -larth artifacts
cp -r ../artifacts/{smartcont,lib} artifacts/
pwd
ls -larth artifacts

BIN
assembly/appimage/ton.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -1,237 +0,0 @@
pipeline {
agent none
stages {
stage('Run Builds') {
parallel {
stage('Ubuntu 20.04 x86-64 (shared)') {
agent {
label 'Ubuntu_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/native/build-ubuntu-shared.sh .
chmod +x build-ubuntu-shared.sh
./build-ubuntu-shared.sh -a
'''
sh '''
cd artifacts
zip -9r ton-x86_64-linux-shared ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-x86_64-linux-shared.zip'
}
}
}
stage('Ubuntu 20.04 x86-64 (portable)') {
agent {
label 'Ubuntu_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/nix/build-linux-x86-64-nix.sh .
chmod +x build-linux-x86-64-nix.sh
./build-linux-x86-64-nix.sh
'''
sh '''
cd artifacts
zip -9r ton-x86-64-linux-portable ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-x86-64-linux-portable.zip'
}
}
}
stage('Ubuntu 20.04 aarch64 (shared)') {
agent {
label 'Ubuntu_arm64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/native/build-ubuntu-shared.sh .
chmod +x build-ubuntu-shared.sh
./build-ubuntu-shared.sh -a
'''
sh '''
cd artifacts
zip -9r ton-arm64-linux-shared ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-arm64-linux-shared.zip'
}
}
}
stage('Ubuntu 20.04 aarch64 (portable)') {
agent {
label 'Ubuntu_arm64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/nix/build-linux-arm64-nix.sh .
chmod +x build-linux-arm64-nix.sh
./build-linux-arm64-nix.sh
'''
sh '''
cd artifacts
zip -9r ton-arm64-linux-portable ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-arm64-linux-portable.zip'
}
}
}
stage('macOS 12.7 x86-64 (shared)') {
agent {
label 'macOS_12.7_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -a
'''
sh '''
cd artifacts
zip -9r ton-x86-64-macos-shared ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-x86-64-macos-shared.zip'
}
}
}
stage('macOS 12.7 x86-64 (portable)') {
agent {
label 'macOS_12.7_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh
'''
sh '''
cd artifacts
zip -9r ton-x86-64-macos-portable ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-x86-64-macos-portable.zip'
}
}
}
stage('macOS 12.6 aarch64 (shared)') {
agent {
label 'macOS_12.6-arm64-m1'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -a
'''
sh '''
cd artifacts
zip -9r ton-arm64-macos-m1-shared ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-arm64-macos-m1-shared.zip'
}
}
}
stage('macOS 12.6 aarch64 (portable)') {
agent {
label 'macOS_12.6-arm64-m1'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/nix/build-macos-nix.sh .
chmod +x build-macos-nix.sh
./build-macos-nix.sh
'''
sh '''
cd artifacts
zip -9r ton-arm64-macos-portable ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-arm64-macos-portable.zip'
}
}
}
stage('macOS 13.2 aarch64 (shared)') {
agent {
label 'macOS_13.2-arm64-m2'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/native/build-macos-shared.sh .
chmod +x build-macos-shared.sh
./build-macos-shared.sh -a
'''
sh '''
cd artifacts
zip -9r ton-arm64-macos-m2-shared ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-arm64-macos-m2-shared.zip'
}
}
}
stage('Windows Server 2022 x86-64') {
agent {
label 'Windows_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
bat '''
copy assembly\\native\\build-windows.bat .
build-windows.bat
'''
bat '''
cd artifacts
zip -9r ton-x86-64-windows ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-x86-64-windows.zip'
}
}
}
stage('Android Tonlib') {
agent {
label 'Ubuntu_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/android/build-android-tonlib.sh .
chmod +x build-android-tonlib.sh
./build-android-tonlib.sh -a
'''
sh '''
cd artifacts/tonlib-android-jni
zip -9r ton-android-tonlib ./*
'''
archiveArtifacts artifacts: 'artifacts/tonlib-android-jni/ton-android-tonlib.zip'
}
}
}
stage('WASM fift func emulator') {
agent {
label 'Ubuntu_x86-64'
}
steps {
timeout(time: 180, unit: 'MINUTES') {
sh '''
cp assembly/wasm/fift-func-wasm-build-ubuntu.sh .
chmod +x fift-func-wasm-build-ubuntu.sh
./fift-func-wasm-build-ubuntu.sh -a
'''
sh '''
cd artifacts
zip -9r ton-wasm-binaries ./*
'''
archiveArtifacts artifacts: 'artifacts/ton-wasm-binaries.zip'
}
}
}
}
}
}
}

View file

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

View file

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

View file

@ -0,0 +1,109 @@
#/bin/bash
with_tests=false
with_artifacts=false
while getopts 'ta' flag; do
case "${flag}" in
t) with_tests=true ;;
a) with_artifacts=true ;;
*) break
;;
esac
done
if [ ! -d "build" ]; then
mkdir build
cd build
else
cd build
rm -rf .ninja* CMakeCache.txt
fi
export CC=$(which clang-16)
export CXX=$(which clang++-16)
export CCACHE_DISABLE=1
if [ ! -d "openssl_3" ]; then
git clone https://github.com/openssl/openssl openssl_3
cd openssl_3
opensslPath=`pwd`
git checkout openssl-3.1.4
./config
make build_libs -j12
test $? -eq 0 || { echo "Can't compile openssl_3"; exit 1; }
cd ..
else
opensslPath=$(pwd)/openssl_3
echo "Using compiled openssl_3"
fi
cmake -GNinja .. \
-DCMAKE_BUILD_TYPE=Release \
-DPORTABLE=1 \
-DOPENSSL_ROOT_DIR=$opensslPath \
-DOPENSSL_INCLUDE_DIR=$opensslPath/include \
-DOPENSSL_CRYPTO_LIBRARY=$opensslPath/libcrypto.so
test $? -eq 0 || { echo "Can't configure ton"; exit 1; }
if [ "$with_tests" = true ]; then
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator test-ed25519 test-ed25519-crypto test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
# simple binaries' test
./storage/storage-daemon/storage-daemon -V || exit 1
./validator-engine/validator-engine -V || exit 1
./lite-client/lite-client -V || exit 1
./crypto/fift -V || exit 1
echo validator-engine
ldd ./validator-engine/validator-engine || exit 1
ldd ./validator-engine-console/validator-engine-console || exit 1
ldd ./crypto/fift || exit 1
echo blockchain-explorer
ldd ./blockchain-explorer/blockchain-explorer || exit 1
echo libtonlibjson.so
ldd ./tonlib/libtonlibjson.so.0.5 || exit 1
echo libemulator.so
ldd ./emulator/libemulator.so || exit 1
cd ..
if [ "$with_artifacts" = true ]; then
rm -rf artifacts
mkdir artifacts
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/tolk/tolk build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/utils/proxy-liteserver \
build/tonlib/libtonlibjson.so build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy \
build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine \
build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy build/emulator/libemulator.so \
artifacts
test $? -eq 0 || { echo "Can't copy final binaries"; exit 1; }
cp -R crypto/smartcont artifacts
cp -R crypto/fift/lib artifacts
chmod -R +x artifacts/*
fi
if [ "$with_tests" = true ]; then
cd build
# ctest --output-on-failure -E "test-catchain|test-actors|test-smartcont|test-adnl|test-validator-session-state|test-dht|test-rldp"
ctest --output-on-failure --timeout 1800
fi

View file

@ -0,0 +1,132 @@
#/bin/bash
#sudo apt-get update
#sudo apt-get install -y build-essential git cmake ninja-build automake libtool texinfo autoconf libc++-dev libc++abi-dev
with_artifacts=false
while getopts 'ta' flag; do
case "${flag}" in
a) with_artifacts=true ;;
*) break
;;
esac
done
if [ ! -d "build" ]; then
mkdir build
cd build
else
cd build
rm -rf .ninja* CMakeCache.txt
fi
export CC=$(which clang)
export CXX=$(which clang++)
export CCACHE_DISABLE=1
if [ ! -d "lz4" ]; then
git clone https://github.com/lz4/lz4.git
cd lz4
lz4Path=`pwd`
git checkout v1.9.4
CFLAGS="-fPIC" make -j12
test $? -eq 0 || { echo "Can't compile lz4"; exit 1; }
cd ..
# ./lib/liblz4.a
# ./lib
else
lz4Path=$(pwd)/lz4
echo "Using compiled lz4"
fi
if [ ! -d "libsodium" ]; then
export LIBSODIUM_FULL_BUILD=1
git clone https://github.com/jedisct1/libsodium.git
cd libsodium
sodiumPath=`pwd`
git checkout 1.0.18
./autogen.sh
./configure --with-pic --enable-static
make -j12
test $? -eq 0 || { echo "Can't compile libsodium"; exit 1; }
cd ..
else
sodiumPath=$(pwd)/libsodium
echo "Using compiled libsodium"
fi
if [ ! -d "openssl_3" ]; then
git clone https://github.com/openssl/openssl openssl_3
cd openssl_3
opensslPath=`pwd`
git checkout openssl-3.1.4
./config
make build_libs -j12
test $? -eq 0 || { echo "Can't compile openssl_3"; exit 1; }
cd ..
else
opensslPath=$(pwd)/openssl_3
echo "Using compiled openssl_3"
fi
if [ ! -d "zlib" ]; then
git clone https://github.com/madler/zlib.git
cd zlib
zlibPath=`pwd`
./configure --static
make -j12
test $? -eq 0 || { echo "Can't compile zlib"; exit 1; }
cd ..
else
zlibPath=$(pwd)/zlib
echo "Using compiled zlib"
fi
if [ ! -d "libmicrohttpd" ]; then
git clone https://git.gnunet.org/libmicrohttpd.git
cd libmicrohttpd
libmicrohttpdPath=`pwd`
./autogen.sh
./configure --enable-static --disable-tests --disable-benchmark --disable-shared --disable-https --with-pic
make -j12
test $? -eq 0 || { echo "Can't compile libmicrohttpd"; exit 1; }
cd ..
else
libmicrohttpdPath=$(pwd)/libmicrohttpd
echo "Using compiled libmicrohttpd"
fi
cmake -GNinja .. \
-DPORTABLE=1 \
-DCMAKE_BUILD_TYPE=Release \
-DOPENSSL_FOUND=1 \
-DOPENSSL_INCLUDE_DIR=$opensslPath/include \
-DOPENSSL_CRYPTO_LIBRARY=$opensslPath/libcrypto.a \
-DZLIB_FOUND=1 \
-DZLIB_INCLUDE_DIR=$zlibPath \
-DZLIB_LIBRARIES=$zlibPath/libz.a \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \
-DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \
-DMHD_FOUND=1 \
-DMHD_INCLUDE_DIR=$libmicrohttpdPath/src/include \
-DMHD_LIBRARY=$libmicrohttpdPath/src/microhttpd/.libs/libmicrohttpd.a \
-DLZ4_FOUND=1 \
-DLZ4_INCLUDE_DIRS=$lz4Path/lib \
-DLZ4_LIBRARIES=$lz4Path/lib/liblz4.a
test $? -eq 0 || { echo "Can't configure ton"; exit 1; }
ninja tonlibjson emulator
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
cd ..
mkdir artifacts
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/tonlib/libtonlibjson.so \
build/emulator/libemulator.so \
artifacts

View file

@ -1,7 +1,7 @@
#/bin/bash
#sudo apt-get update
#sudo apt-get install -y build-essential git cmake ninja-build automake libtool texinfo autoconf
#sudo apt-get install -y build-essential git cmake ninja-build automake libtool texinfo autoconf libc++-dev libc++abi-dev
with_tests=false
with_artifacts=false
@ -24,8 +24,8 @@ else
rm -rf .ninja* CMakeCache.txt
fi
export CC=$(which clang-16)
export CXX=$(which clang++-16)
export CC=$(which clang)
export CXX=$(which clang++)
export CCACHE_DISABLE=1
if [ ! -d "lz4" ]; then
@ -33,7 +33,7 @@ git clone https://github.com/lz4/lz4.git
cd lz4
lz4Path=`pwd`
git checkout v1.9.4
make -j12
CFLAGS="-fPIC" make -j12
test $? -eq 0 || { echo "Can't compile lz4"; exit 1; }
cd ..
# ./lib/liblz4.a
@ -43,23 +43,6 @@ else
echo "Using compiled lz4"
fi
if [ ! -d "secp256k1" ]; then
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
secp256k1Path=`pwd`
git checkout v0.3.2
./autogen.sh
./configure --enable-module-recovery --enable-static --disable-tests --disable-benchmark --with-pic
make -j12
test $? -eq 0 || { echo "Can't compile secp256k1"; exit 1; }
cd ..
# ./.libs/libsecp256k1.a
# ./include
else
secp256k1Path=$(pwd)/secp256k1
echo "Using compiled secp256k1"
fi
if [ ! -d "libsodium" ]; then
export LIBSODIUM_FULL_BUILD=1
git clone https://github.com/jedisct1/libsodium.git
@ -81,7 +64,7 @@ if [ ! -d "openssl_3" ]; then
cd openssl_3
opensslPath=`pwd`
git checkout openssl-3.1.4
./config -static
./config
make build_libs -j12
test $? -eq 0 || { echo "Can't compile openssl_3"; exit 1; }
cd ..
@ -126,9 +109,6 @@ cmake -GNinja .. \
-DZLIB_FOUND=1 \
-DZLIB_INCLUDE_DIR=$zlibPath \
-DZLIB_LIBRARIES=$zlibPath/libz.a \
-DSECP256K1_FOUND=1 \
-DSECP256K1_INCLUDE_DIR=$secp256k1Path/include \
-DSECP256K1_LIBRARY=$secp256k1Path/.libs/libsecp256k1.a \
-DSODIUM_FOUND=1 \
-DSODIUM_INCLUDE_DIR=$sodiumPath/src/libsodium/include \
-DSODIUM_LIBRARY_RELEASE=$sodiumPath/src/libsodium/.libs/libsodium.a \
@ -144,44 +124,22 @@ cmake -GNinja .. \
test $? -eq 0 || { echo "Can't configure ton"; exit 1; }
if [ "$with_tests" = true ]; then
ninja storage-daemon storage-daemon-cli fift func tonlib tonlibjson tonlib-cli \
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator test-ed25519 test-ed25519-crypto test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli fift func tonlib tonlibjson tonlib-cli \
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator
adnl-proxy create-state emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -g storage/storage-daemon/storage-daemon \
storage/storage-daemon/storage-daemon-cli \
blockchain-explorer/blockchain-explorer \
crypto/fift \
crypto/tlbc \
crypto/func \
crypto/create-state \
validator-engine-console/validator-engine-console \
tonlib/tonlib-cli \
tonlib/libtonlibjson.so.0.5 \
http/http-proxy \
rldp-http-proxy/rldp-http-proxy \
dht-server/dht-server \
lite-client/lite-client \
validator-engine/validator-engine \
utils/generate-random-id \
utils/json2tlo \
adnl/adnl-proxy \
emulator/libemulator.*
test $? -eq 0 || { echo "Can't strip final binaries"; exit 1; }
# simple binaries' test
./storage/storage-daemon/storage-daemon -V || exit 1
./validator-engine/validator-engine -V || exit 1
@ -193,20 +151,18 @@ cd ..
if [ "$with_artifacts" = true ]; then
rm -rf artifacts
mkdir artifacts
cp crypto/fift/lib artifacts/
cp -R crypto/smartcont/ artifacts/
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/tolk/tolk build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/utils/proxy-liteserver \
build/tonlib/libtonlibjson.so build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy \
build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine \
build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy build/emulator/libemulator.so \
artifacts
test $? -eq 0 || { echo "Can't copy final binaries"; exit 1; }
chmod +x artifacts/*
cp -R crypto/smartcont artifacts
cp -R crypto/fift/lib artifacts
chmod -R +x artifacts/*
fi
if [ "$with_tests" = true ]; then

View file

@ -52,44 +52,22 @@ cmake -GNinja -DTON_USE_JEMALLOC=ON .. \
test $? -eq 0 || { echo "Can't configure ton"; exit 1; }
if [ "$with_tests" = true ]; then
ninja storage-daemon storage-daemon-cli fift func tonlib tonlibjson tonlib-cli \
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator test-ed25519 test-ed25519-crypto test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
ninja storage-daemon storage-daemon-cli fift func tonlib tonlibjson tonlib-cli \
ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-cli \
validator-engine lite-client pow-miner validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy \
adnl-proxy create-state emulator
adnl-proxy create-state emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
fi
strip -g storage/storage-daemon/storage-daemon \
storage/storage-daemon/storage-daemon-cli \
blockchain-explorer/blockchain-explorer \
crypto/fift \
crypto/tlbc \
crypto/func \
crypto/create-state \
validator-engine-console/validator-engine-console \
tonlib/tonlib-cli \
tonlib/libtonlibjson.so.0.5 \
http/http-proxy \
rldp-http-proxy/rldp-http-proxy \
dht-server/dht-server \
lite-client/lite-client \
validator-engine/validator-engine \
utils/generate-random-id \
utils/json2tlo \
adnl/adnl-proxy \
emulator/libemulator.*
test $? -eq 0 || { echo "Can't strip final binaries"; exit 1; }
# simple binaries' test
./storage/storage-daemon/storage-daemon -V || exit 1
./validator-engine/validator-engine -V || exit 1
@ -105,16 +83,16 @@ if [ "$with_artifacts" = true ]; then
mkdir artifacts
mv build/tonlib/libtonlibjson.so.0.5 build/tonlib/libtonlibjson.so
cp build/storage/storage-daemon/storage-daemon build/storage/storage-daemon/storage-daemon-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli \
build/crypto/fift build/crypto/tlbc build/crypto/func build/tolk/tolk build/crypto/create-state build/blockchain-explorer/blockchain-explorer \
build/validator-engine-console/validator-engine-console build/tonlib/tonlib-cli build/utils/proxy-liteserver \
build/tonlib/libtonlibjson.so build/http/http-proxy build/rldp-http-proxy/rldp-http-proxy \
build/dht-server/dht-server build/lite-client/lite-client build/validator-engine/validator-engine \
build/utils/generate-random-id build/utils/json2tlo build/adnl/adnl-proxy build/emulator/libemulator.so \
artifacts
test $? -eq 0 || { echo "Can't copy final binaries"; exit 1; }
chmod +x artifacts/*
cp -R crypto/smartcont artifacts
cp -R crypto/fift/lib artifacts
chmod -R +x artifacts/*
fi
if [ "$with_tests" = true ]; then

View file

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

View file

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

View file

@ -35,3 +35,4 @@ cp ./result/lib/libtonlibjson.so.0.5 artifacts/libtonlibjson.so
cp ./result/lib/libemulator.so artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts

View file

@ -35,3 +35,4 @@ cp ./result/lib/libtonlibjson.so.0.5 artifacts/libtonlibjson.so
cp ./result/lib/libemulator.so artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts

View file

@ -35,3 +35,4 @@ cp ./result/lib/libtonlibjson.dylib artifacts/
cp ./result/lib/libemulator.dylib artifacts/
cp ./result/lib/fift/* artifacts/lib/
cp -r ./result/share/ton/smartcont artifacts/
chmod -R +x artifacts

View file

@ -42,10 +42,13 @@ pkgs.llvmPackages_16.stdenv.mkDerivation {
];
dontAddStaticConfigureFlags = false;
doCheck = false;
doInstallCheck = false;
cmakeFlags = [
"-DTON_USE_ABSEIL=OFF"
"-DTON_USE_ABSEIL=ON"
"-DNIX=ON"
"-DTON_ONLY_TONLIB=ON"
];
LDFLAGS = [

View file

@ -58,10 +58,13 @@ stdenv227.mkDerivation {
];
dontAddStaticConfigureFlags = false;
doCheck = false;
doInstallCheck = false;
cmakeFlags = [
"-DTON_USE_ABSEIL=OFF"
"-DTON_USE_ABSEIL=ON"
"-DNIX=ON"
"-DTON_ONLY_TONLIB=ON"
];
LDFLAGS = [

View file

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

View file

@ -0,0 +1,61 @@
#pragma allow-post-modification;
#pragma compute-asm-ltr;
(slice, slice) __tact_load_address(slice cs) inline {
slice raw = cs~load_msg_addr();
return (cs, raw);
}
slice __gen_slice1 () asm """
B{b5ee9c72410101010005000006abcdefe1e98884} B>boc <s PUSHSLICE
""";
slice __gen_slice_slice_eb58904b617945cdf4f33042169c462cd36cf1772a2229f06171fd899e920b7f() asm """
B{b5ee9c724101010100030000011025086565} B>boc <s PUSHSLICE
""";
slice __gen_slice3 () asm """
B{b5ee9c724101010100030000017888c37a8e} B>boc <s PUSHSLICE
""";
slice __gen_slice_slice_6694a4a61b0dc7c7d5f63bbd394449f6921de7b2ad9cb() asm """
B{b5ee9c724101010100820000ffabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdab} B>boc <s PUSHSLICE
""";
slice __gen_slice_slice_80b26bab85f37e2bde3795993cdf7402cd42e68eff6187e8388083ce6cfe7c92() asm """
B{b5ee9c724101010100030000018a0adc2f9c} B>boc <s PUSHSLICE
""";
(slice,((slice, cell, int, int, slice, slice, int, int, int, int, slice, slice, slice, slice, slice, slice, slice, slice, slice, slice, slice))) IntrinsicsTester_load(slice sc_0) inline {
var v'c = sc_0~__tact_load_address();
var v'd = sc_0~load_ref();
var v'e = sc_0~load_int(257);
var v'f = sc_0~load_int(257);
slice sc_1 = sc_0~load_ref().begin_parse();
var v'g = sc_1~load_ref().begin_parse();
var v'h = sc_1~load_ref().begin_parse();
var v'i = sc_1~load_int(257);
var v'j = sc_1~load_int(257);
var v'k = sc_1~load_int(257);
slice sc_2 = sc_1~load_ref().begin_parse();
var v'l = sc_2~load_int(257);
var v'm = sc_2~load_ref().begin_parse();
var v'n = sc_2~load_ref().begin_parse();
var v'o = sc_2~load_ref().begin_parse();
slice sc_3 = sc_2~load_ref().begin_parse();
var v'p = sc_3~load_ref().begin_parse();
var v'q = sc_3~load_ref().begin_parse();
var v'r = sc_3~load_ref().begin_parse();
slice sc_4 = sc_3~load_ref().begin_parse();
var v's = sc_4~load_ref().begin_parse();
var v't = sc_4~load_ref().begin_parse();
var v'u = sc_4~load_ref().begin_parse();
slice sc_5 = sc_4~load_ref().begin_parse();
var v'w = sc_5~load_ref().begin_parse();
var v'v = sc_5~load_ref().begin_parse();
return (sc_0, (v'c, v'd, v'e, v'f, v'g, v'h, v'i, v'j, v'k, v'l, v'm, v'n, v'o, v'p, v'q, v'r, v's, v't, v'u, v'w, v'v));
}
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure { }

681
assembly/wasm/stdlib.fc Normal file
View file

@ -0,0 +1,681 @@
;; Standard library for funC
;;
{-
This file is part of TON FunC Standard Library.
FunC Standard 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.
FunC Standard 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.
-}
{-
# Tuple manipulation primitives
The names and the types are mostly self-explaining.
See [polymorhism with forall](https://ton.org/docs/#/func/functions?id=polymorphism-with-forall)
for more info on the polymorphic functions.
Note that currently values of atomic type `tuple` can't be cast to composite tuple type (e.g. `[int, cell]`)
and vise versa.
-}
{-
# Lisp-style lists
Lists can be represented as nested 2-elements tuples.
Empty list is conventionally represented as TVM `null` value (it can be obtained by calling [null()]).
For example, tuple `(1, (2, (3, null)))` represents list `[1, 2, 3]`. Elements of a list can be of different types.
-}
;;; Adds an element to the beginning of lisp-style list.
forall X -> tuple cons(X head, tuple tail) asm "CONS";
;;; Extracts the head and the tail of lisp-style list.
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
;;; Extracts the tail and the head of lisp-style list.
forall X -> (tuple, X) list_next(tuple list) asm(-> 1 0) "UNCONS";
;;; Returns the head of lisp-style list.
forall X -> X car(tuple list) asm "CAR";
;;; Returns the tail of lisp-style list.
tuple cdr(tuple list) asm "CDR";
;;; Creates tuple with zero elements.
tuple empty_tuple() asm "NIL";
;;; Appends a value `x` to a `Tuple t = (x1, ..., xn)`, but only if the resulting `Tuple t' = (x1, ..., xn, x)`
;;; is of length at most 255. Otherwise throws a type check exception.
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
;;; Creates a tuple of length one with given argument as element.
forall X -> [X] single(X x) asm "SINGLE";
;;; Unpacks a tuple of length one
forall X -> X unsingle([X] t) asm "UNSINGLE";
;;; Creates a tuple of length two with given arguments as elements.
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
;;; Unpacks a tuple of length two
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
;;; Creates a tuple of length three with given arguments as elements.
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
;;; Unpacks a tuple of length three
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
;;; Creates a tuple of length four with given arguments as elements.
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
;;; Unpacks a tuple of length four
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
;;; Returns the first element of a tuple (with unknown element types).
forall X -> X first(tuple t) asm "FIRST";
;;; Returns the second element of a tuple (with unknown element types).
forall X -> X second(tuple t) asm "SECOND";
;;; Returns the third element of a tuple (with unknown element types).
forall X -> X third(tuple t) asm "THIRD";
;;; Returns the fourth element of a tuple (with unknown element types).
forall X -> X fourth(tuple t) asm "3 INDEX";
;;; Returns the first element of a pair tuple.
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
;;; Returns the second element of a pair tuple.
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
;;; Returns the first element of a triple tuple.
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
;;; Returns the second element of a triple tuple.
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
;;; Returns the third element of a triple tuple.
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
;;; Push null element (casted to given type)
;;; By the TVM type `Null` FunC represents absence of a value of some atomic type.
;;; So `null` can actually have any atomic type.
forall X -> X null() asm "PUSHNULL";
;;; Moves a variable [x] to the top of the stack
forall X -> (X, ()) ~impure_touch(X x) impure asm "NOP";
;;; Returns the current Unix time as an Integer
int now() asm "NOW";
;;; Returns the internal address of the current smart contract as a Slice with a `MsgAddressInt`.
;;; If necessary, it can be parsed further using primitives such as [parse_std_addr].
slice my_address() asm "MYADDR";
;;; Returns the balance of the smart contract as a tuple consisting of an int
;;; (balance in nanotoncoins) and a `cell`
;;; (a dictionary with 32-bit keys representing the balance of "extra currencies")
;;; at the start of Computation Phase.
;;; Note that RAW primitives such as [send_raw_message] do not update this field.
[int, cell] get_balance() asm "BALANCE";
;;; Returns the logical time of the current transaction.
int cur_lt() asm "LTIME";
;;; Returns the starting logical time of the current block.
int block_lt() asm "BLOCKLT";
;;; Computes the representation hash of a `cell` [c] and returns it as a 256-bit unsigned integer `x`.
;;; Useful for signing and checking signatures of arbitrary entities represented by a tree of cells.
int cell_hash(cell c) asm "HASHCU";
;;; Computes the hash of a `slice s` and returns it as a 256-bit unsigned integer `x`.
;;; The result is the same as if an ordinary cell containing only data and references from `s` had been created
;;; and its hash computed by [cell_hash].
int slice_hash(slice s) asm "HASHSU";
;;; Computes sha256 of the data bits of `slice` [s]. If the bit length of `s` is not divisible by eight,
;;; throws a cell underflow exception. The hash value is returned as a 256-bit unsigned integer `x`.
int string_hash(slice s) asm "SHA256U";
{-
# Signature checks
-}
;;; Checks the Ed25519-`signature` of a `hash` (a 256-bit unsigned integer, usually computed as the hash of some data)
;;; using [public_key] (also represented by a 256-bit unsigned integer).
;;; The signature must contain at least 512 data bits; only the first 512 bits are used.
;;; The result is `1` if the signature is valid, `0` otherwise.
;;; Note that `CHKSIGNU` creates a 256-bit slice with the hash and calls `CHKSIGNS`.
;;; That is, if [hash] is computed as the hash of some data, these data are hashed twice,
;;; the second hashing occurring inside `CHKSIGNS`.
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
;;; Checks whether [signature] is a valid Ed25519-signature of the data portion of `slice data` using `public_key`,
;;; similarly to [check_signature].
;;; If the bit length of [data] is not divisible by eight, throws a cell underflow exception.
;;; The verification of Ed25519 signatures is the standard one,
;;; with sha256 used to reduce [data] to the 256-bit number that is actually signed.
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
{---
# Computation of boc size
The primitives below may be useful for computing storage fees of user-provided data.
-}
;;; Returns `(x, y, z, -1)` or `(null, null, null, 0)`.
;;; Recursively computes the count of distinct cells `x`, data bits `y`, and cell references `z`
;;; in the DAG rooted at `cell` [c], effectively returning the total storage used by this DAG taking into account
;;; the identification of equal cells.
;;; The values of `x`, `y`, and `z` are computed by a depth-first traversal of this DAG,
;;; with a hash table of visited cell hashes used to prevent visits of already-visited cells.
;;; The total count of visited cells `x` cannot exceed non-negative [max_cells];
;;; otherwise the computation is aborted before visiting the `(max_cells + 1)`-st cell and
;;; a zero flag is returned to indicate failure. If [c] is `null`, returns `x = y = z = 0`.
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
;;; Similar to [compute_data_size?], but accepting a `slice` [s] instead of a `cell`.
;;; The returned value of `x` does not take into account the cell that contains the `slice` [s] itself;
;;; however, the data bits and the cell references of [s] are accounted for in `y` and `z`.
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
;;; A non-quiet version of [compute_data_size?] that throws a cell overflow exception (`8`) on failure.
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
;;; A non-quiet version of [slice_compute_data_size?] that throws a cell overflow exception (8) on failure.
(int, int, int, int) slice_compute_data_size?(cell c, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
;;; Throws an exception with exit_code excno if cond is not 0 (commented since implemented in compilator)
;; () throw_if(int excno, int cond) impure asm "THROWARGIF";
{--
# Debug primitives
Only works for local TVM execution with debug level verbosity
-}
;;; Dumps the stack (at most the top 255 values) and shows the total stack depth.
() dump_stack() impure asm "DUMPSTK";
{-
# Persistent storage save and load
-}
;;; Returns the persistent contract storage cell. It can be parsed or modified with slice and builder primitives later.
cell get_data() asm "c4 PUSH";
;;; Sets `cell` [c] as persistent contract data. You can update persistent contract storage with this primitive.
() set_data(cell c) impure asm "c4 POP";
{-
# Continuation primitives
-}
;;; Usually `c3` has a continuation initialized by the whole code of the contract. It is used for function calls.
;;; The primitive returns the current value of `c3`.
cont get_c3() impure asm "c3 PUSH";
;;; Updates the current value of `c3`. Usually, it is used for updating smart contract code in run-time.
;;; Note that after execution of this primitive the current code
;;; (and the stack of recursive function calls) won't change,
;;; but any other function call will use a function from the new code.
() set_c3(cont c) impure asm "c3 POP";
;;; Transforms a `slice` [s] into a simple ordinary continuation `c`, with `c.code = s` and an empty stack and savelist.
cont bless(slice s) impure asm "BLESS";
{---
# Gas related primitives
-}
;;; Sets current gas limit `gl` to its maximal allowed value `gm`, and resets the gas credit `gc` to zero,
;;; decreasing the value of `gr` by `gc` in the process.
;;; In other words, the current smart contract agrees to buy some gas to finish the current transaction.
;;; This action is required to process external messages, which bring no value (hence no gas) with themselves.
;;;
;;; For more details check [accept_message effects](https://ton.org/docs/#/smart-contracts/accept).
() accept_message() impure asm "ACCEPT";
;;; Sets current gas limit `gl` to the minimum of limit and `gm`, and resets the gas credit `gc` to zero.
;;; If the gas consumed so far (including the present instruction) exceeds the resulting value of `gl`,
;;; an (unhandled) out of gas exception is thrown before setting new gas limits.
;;; Notice that [set_gas_limit] with an argument `limit ≥ 2^63 1` is equivalent to [accept_message].
() set_gas_limit(int limit) impure asm "SETGASLIMIT";
;;; Commits the current state of registers `c4` (“persistent data”) and `c5` (“actions”)
;;; so that the current execution is considered “successful” with the saved values even if an exception
;;; in Computation Phase is thrown later.
() commit() impure asm "COMMIT";
;;; Not implemented
;;; Computes the amount of gas that can be bought for `amount` nanoTONs,
;;; and sets `gl` accordingly in the same way as [set_gas_limit].
;;() buy_gas(int amount) impure asm "BUYGAS";
;;; Computes the minimum of two integers [x] and [y].
int min(int x, int y) asm "MIN";
;;; Computes the maximum of two integers [x] and [y].
int max(int x, int y) asm "MAX";
;;; Sorts two integers.
(int, int) minmax(int x, int y) asm "MINMAX";
;;; Computes the absolute value of an integer [x].
int abs(int x) asm "ABS";
{-
# Slice primitives
It is said that a primitive _loads_ some data,
if it returns the data and the remainder of the slice
(so it can also be used as [modifying method](https://ton.org/docs/#/func/statements?id=modifying-methods)).
It is said that a primitive _preloads_ some data, if it returns only the data
(it can be used as [non-modifying method](https://ton.org/docs/#/func/statements?id=non-modifying-methods)).
Unless otherwise stated, loading and preloading primitives read the data from a prefix of the slice.
-}
;;; Converts a `cell` [c] into a `slice`. Notice that [c] must be either an ordinary cell,
;;; or an exotic cell (see [TVM.pdf](https://ton-blockchain.github.io/docs/tvm.pdf), 3.1.2)
;;; which is automatically loaded to yield an ordinary cell `c'`, converted into a `slice` afterwards.
slice begin_parse(cell c) asm "CTOS";
;;; Checks if [s] is empty. If not, throws an exception.
() end_parse(slice s) impure asm "ENDS";
;;; Loads the first reference from the slice.
(slice, cell) load_ref(slice s) asm(-> 1 0) "LDREF";
;;; Preloads the first reference from the slice.
cell preload_ref(slice s) asm "PLDREF";
{- Functions below are commented because are implemented on compilator level for optimisation -}
;;; Loads a signed [len]-bit integer from a slice [s].
;; (slice, int) ~load_int(slice s, int len) asm(s len -> 1 0) "LDIX";
;;; Loads an unsigned [len]-bit integer from a slice [s].
;; (slice, int) ~load_uint(slice s, int len) asm( -> 1 0) "LDUX";
;;; Preloads a signed [len]-bit integer from a slice [s].
;; int preload_int(slice s, int len) asm "PLDIX";
;;; Preloads an unsigned [len]-bit integer from a slice [s].
;; int preload_uint(slice s, int len) asm "PLDUX";
;;; Loads the first `0 ≤ len ≤ 1023` bits from slice [s] into a separate `slice s''`.
;; (slice, slice) load_bits(slice s, int len) asm(s len -> 1 0) "LDSLICEX";
;;; Preloads the first `0 ≤ len ≤ 1023` bits from slice [s] into a separate `slice s''`.
;; slice preload_bits(slice s, int len) asm "PLDSLICEX";
;;; Loads serialized amount of TonCoins (any unsigned integer up to `2^120 - 1`).
(slice, int) load_grams(slice s) asm(-> 1 0) "LDGRAMS";
(slice, int) load_coins(slice s) asm(-> 1 0) "LDVARUINT16";
(slice, int) load_varint16(slice s) asm(-> 1 0) "LDVARINT16";
(slice, int) load_varint32(slice s) asm(-> 1 0) "LDVARINT32";
(slice, int) load_varuint16(slice s) asm(-> 1 0) "LDVARUINT16";
(slice, int) load_varuint32(slice s) asm(-> 1 0) "LDVARUINT32";
;;; Returns all but the first `0 ≤ len ≤ 1023` bits of `slice` [s].
slice skip_bits(slice s, int len) asm "SDSKIPFIRST";
(slice, ()) ~skip_bits(slice s, int len) asm "SDSKIPFIRST";
;;; Returns the first `0 ≤ len ≤ 1023` bits of `slice` [s].
slice first_bits(slice s, int len) asm "SDCUTFIRST";
;;; Returns all but the last `0 ≤ len ≤ 1023` bits of `slice` [s].
slice skip_last_bits(slice s, int len) asm "SDSKIPLAST";
(slice, ()) ~skip_last_bits(slice s, int len) asm "SDSKIPLAST";
;;; Returns the last `0 ≤ len ≤ 1023` bits of `slice` [s].
slice slice_last(slice s, int len) asm "SDCUTLAST";
;;; Loads a dictionary `D` (HashMapE) from `slice` [s].
;;; (returns `null` if `nothing` constructor is used).
(slice, cell) load_dict(slice s) asm(-> 1 0) "LDDICT";
;;; Preloads a dictionary `D` from `slice` [s].
cell preload_dict(slice s) asm "PLDDICT";
;;; Loads a dictionary as [load_dict], but returns only the remainder of the slice.
slice skip_dict(slice s) asm "SKIPDICT";
(slice, ()) ~skip_dict(slice s) asm "SKIPDICT";
;;; Loads (Maybe ^Cell) from `slice` [s].
;;; In other words loads 1 bit and if it is true
;;; loads first ref and return it with slice remainder
;;; otherwise returns `null` and slice remainder
(slice, cell) load_maybe_ref(slice s) asm(-> 1 0) "LDOPTREF";
;;; Preloads (Maybe ^Cell) from `slice` [s].
cell preload_maybe_ref(slice s) asm "PLDOPTREF";
;;; Returns the depth of `cell` [c].
;;; If [c] has no references, then return `0`;
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [c].
;;; If [c] is a `null` instead of a cell, returns zero.
int cell_depth(cell c) asm "CDEPTH";
{-
# Slice size primitives
-}
;;; Returns the number of references in `slice` [s].
int slice_refs(slice s) asm "SREFS";
;;; Returns the number of data bits in `slice` [s].
int slice_bits(slice s) asm "SBITS";
;;; Returns both the number of data bits and the number of references in `slice` [s].
(int, int) slice_bits_refs(slice s) asm "SBITREFS";
;;; Checks whether a `slice` [s] is empty (i.e., contains no bits of data and no cell references).
int slice_empty?(slice s) asm "SEMPTY";
;;; Checks whether `slice` [s] has no bits of data.
int slice_data_empty?(slice s) asm "SDEMPTY";
;;; Checks whether `slice` [s] has no references.
int slice_refs_empty?(slice s) asm "SREMPTY";
;;; Returns the depth of `slice` [s].
;;; If [s] has no references, then returns `0`;
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [s].
int slice_depth(slice s) asm "SDEPTH";
{-
# Builder size primitives
-}
;;; Returns the number of cell references already stored in `builder` [b]
int builder_refs(builder b) asm "BREFS";
;;; Returns the number of data bits already stored in `builder` [b].
int builder_bits(builder b) asm "BBITS";
;;; Returns the depth of `builder` [b].
;;; If no cell references are stored in [b], then returns 0;
;;; otherwise the returned value is one plus the maximum of depths of cells referred to from [b].
int builder_depth(builder b) asm "BDEPTH";
{-
# Builder primitives
It is said that a primitive _stores_ a value `x` into a builder `b`
if it returns a modified version of the builder `b'` with the value `x` stored at the end of it.
It can be used as [non-modifying method](https://ton.org/docs/#/func/statements?id=non-modifying-methods).
All the primitives below first check whether there is enough space in the `builder`,
and only then check the range of the value being serialized.
-}
;;; Creates a new empty `builder`.
builder begin_cell() asm "NEWC";
;;; Converts a `builder` into an ordinary `cell`.
cell end_cell(builder b) asm "ENDC";
;;; Stores a reference to `cell` [c] into `builder` [b].
builder store_ref(builder b, cell c) asm(c b) "STREF";
;;; Stores an unsigned [len]-bit integer `x` into `b` for `0 ≤ len ≤ 256`.
;; builder store_uint(builder b, int x, int len) asm(x b len) "STUX";
;;; Stores a signed [len]-bit integer `x` into `b` for` 0 ≤ len ≤ 257`.
;; builder store_int(builder b, int x, int len) asm(x b len) "STIX";
;;; Stores `slice` [s] into `builder` [b]
builder store_slice(builder b, slice s) asm "STSLICER";
;;; Stores (serializes) an integer [x] in the range `0..2^120 1` into `builder` [b].
;;; The serialization of [x] consists of a 4-bit unsigned big-endian integer `l`,
;;; which is the smallest integer `l ≥ 0`, such that `x < 2^8l`,
;;; followed by an `8l`-bit unsigned big-endian representation of [x].
;;; If [x] does not belong to the supported range, a range check exception is thrown.
;;;
;;; Store amounts of TonCoins to the builder as VarUInteger 16
builder store_grams(builder b, int x) asm "STGRAMS";
builder store_coins(builder b, int x) asm "STVARUINT16";
builder store_varint16(builder b, int x) asm "STVARINT16";
builder store_varint32(builder b, int x) asm "STVARINT32";
builder store_varuint16(builder b, int x) asm "STVARUINT16";
builder store_varuint32(builder b, int x) asm "STVARUINT32";
;;; Stores dictionary `D` represented by `cell` [c] or `null` into `builder` [b].
;;; In other words, stores a `1`-bit and a reference to [c] if [c] is not `null` and `0`-bit otherwise.
builder store_dict(builder b, cell c) asm(c b) "STDICT";
;;; Stores (Maybe ^Cell) to builder:
;;; if cell is null store 1 zero bit
;;; otherwise store 1 true bit and ref to cell
builder store_maybe_ref(builder b, cell c) asm(c b) "STOPTREF";
{-
# Address manipulation primitives
The address manipulation primitives listed below serialize and deserialize values according to the following TL-B scheme:
```TL-B
addr_none$00 = MsgAddressExt;
addr_extern$01 len:(## 8) external_address:(bits len)
= MsgAddressExt;
anycast_info$_ depth:(#<= 30) { depth >= 1 }
rewrite_pfx:(bits depth) = Anycast;
addr_std$10 anycast:(Maybe Anycast)
workchain_id:int8 address:bits256 = MsgAddressInt;
addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9)
workchain_id:int32 address:(bits addr_len) = MsgAddressInt;
_ _:MsgAddressInt = MsgAddress;
_ _:MsgAddressExt = MsgAddress;
int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
src:MsgAddress dest:MsgAddressInt
value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt
created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed;
```
A deserialized `MsgAddress` is represented by a tuple `t` as follows:
- `addr_none` is represented by `t = (0)`,
i.e., a tuple containing exactly one integer equal to zero.
- `addr_extern` is represented by `t = (1, s)`,
where slice `s` contains the field `external_address`. In other words, `
t` is a pair (a tuple consisting of two entries), containing an integer equal to one and slice `s`.
- `addr_std` is represented by `t = (2, u, x, s)`,
where `u` is either a `null` (if `anycast` is absent) or a slice `s'` containing `rewrite_pfx` (if anycast is present).
Next, integer `x` is the `workchain_id`, and slice `s` contains the address.
- `addr_var` is represented by `t = (3, u, x, s)`,
where `u`, `x`, and `s` have the same meaning as for `addr_std`.
-}
;;; Loads from slice [s] the only prefix that is a valid `MsgAddress`,
;;; and returns both this prefix `s'` and the remainder `s''` of [s] as slices.
(slice, slice) load_msg_addr(slice s) asm(-> 1 0) "LDMSGADDR";
;;; Decomposes slice [s] containing a valid `MsgAddress` into a `tuple t` with separate fields of this `MsgAddress`.
;;; If [s] is not a valid `MsgAddress`, a cell deserialization exception is thrown.
tuple parse_addr(slice s) asm "PARSEMSGADDR";
;;; Parses slice [s] containing a valid `MsgAddressInt` (usually a `msg_addr_std`),
;;; applies rewriting from the anycast (if present) to the same-length prefix of the address,
;;; and returns both the workchain and the 256-bit address as integers.
;;; If the address is not 256-bit, or if [s] is not a valid serialization of `MsgAddressInt`,
;;; throws a cell deserialization exception.
(int, int) parse_std_addr(slice s) asm "REWRITESTDADDR";
;;; A variant of [parse_std_addr] that returns the (rewritten) address as a slice [s],
;;; even if it is not exactly 256 bit long (represented by a `msg_addr_var`).
(int, slice) parse_var_addr(slice s) asm "REWRITEVARADDR";
{-
# Dictionary primitives
-}
;;; Sets the value associated with [key_len]-bit key signed index in dictionary [dict] to [value] (cell),
;;; and returns the resulting dictionary.
cell idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
(cell, ()) ~idict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETREF";
;;; Sets the value associated with [key_len]-bit key unsigned index in dictionary [dict] to [value] (cell),
;;; and returns the resulting dictionary.
cell udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
(cell, ()) ~udict_set_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETREF";
cell idict_get_ref(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETOPTREF";
(cell, int) idict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGETREF" "NULLSWAPIFNOT";
(cell, int) udict_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGETREF" "NULLSWAPIFNOT";
(cell, cell) idict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTISETGETOPTREF";
(cell, cell) udict_set_get_ref(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUSETGETOPTREF";
(cell, int) idict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDEL";
(cell, int) udict_delete?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDEL";
(slice, int) idict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIGET" "NULLSWAPIFNOT";
(slice, int) udict_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUGET" "NULLSWAPIFNOT";
(cell, slice, int) idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
(cell, slice, int) udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
(cell, (slice, int)) ~idict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGET" "NULLSWAPIFNOT";
(cell, (slice, int)) ~udict_delete_get?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGET" "NULLSWAPIFNOT";
(cell, cell, int) idict_delete_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGETREF" "NULLSWAPIFNOT";
(cell, cell, int) udict_delete_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGETREF" "NULLSWAPIFNOT";
(cell, (cell, int)) ~idict_delete_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTIDELGETREF" "NULLSWAPIFNOT";
(cell, (cell, int)) ~udict_delete_get_ref?(cell dict, int key_len, int index) asm(index dict key_len) "DICTUDELGETREF" "NULLSWAPIFNOT";
cell udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
(cell, ()) ~udict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUSET";
cell idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
(cell, ()) ~idict_set(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTISET";
cell dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
(cell, ()) ~dict_set(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTSET";
(cell, int) udict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUADD";
(cell, int) udict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACE";
(cell, int) udict_replace_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUREPLACEREF";
(cell, slice, int) udict_replaceget?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACEGET" "NULLSWAPIFNOT";
(cell, cell, int) udict_replaceget_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUREPLACEGETREF" "NULLSWAPIFNOT";
(cell, (slice, int)) ~udict_replaceget?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTUREPLACEGET" "NULLSWAPIFNOT";
(cell, (cell, int)) ~udict_replaceget_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTUREPLACEGETREF" "NULLSWAPIFNOT";
(cell, int) idict_add?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIADD";
(cell, int) idict_replace?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACE";
(cell, int) idict_replace_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTIREPLACEREF";
(cell, slice, int) idict_replaceget?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACEGET" "NULLSWAPIFNOT";
(cell, cell, int) idict_replaceget_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTIREPLACEGETREF" "NULLSWAPIFNOT";
(cell, (slice, int)) ~idict_replaceget?(cell dict, int key_len, int index, slice value) asm(value index dict key_len) "DICTIREPLACEGET" "NULLSWAPIFNOT";
(cell, (cell, int)) ~idict_replaceget_ref?(cell dict, int key_len, int index, cell value) asm(value index dict key_len) "DICTIREPLACEGETREF" "NULLSWAPIFNOT";
cell udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
(cell, ()) ~udict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUSETB";
cell idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
(cell, ()) ~idict_set_builder(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTISETB";
cell dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
(cell, ()) ~dict_set_builder(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTSETB";
(cell, int) dict_replace_builder?(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTREPLACEB";
(cell, builder, int) dict_replaceget_builder?(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTREPLACEGETB" "NULLSWAPIFNOT";
(cell, slice, int) dict_replaceget?(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTREPLACEGET" "NULLSWAPIFNOT";
(cell, (builder, int)) ~dict_replaceget_builder?(cell dict, int key_len, slice index, builder value) asm(value index dict key_len) "DICTREPLACEGETB" "NULLSWAPIFNOT";
(cell, (slice, int)) ~dict_replaceget?(cell dict, int key_len, slice index, slice value) asm(value index dict key_len) "DICTREPLACEGET" "NULLSWAPIFNOT";
(cell, int) udict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUADDB";
(cell, int) udict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEB";
(cell, builder, int) udict_replaceget_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEGETB" "NULLSWAPIFNOT";
(cell, (builder, int)) ~udict_replaceget_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTUREPLACEGETB" "NULLSWAPIFNOT";
(cell, int) idict_add_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIADDB";
(cell, int) idict_replace_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEB";
(cell, builder, int) idict_replaceget_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEGETB" "NULLSWAPIFNOT";
(cell, (builder, int)) ~idict_replaceget_builder?(cell dict, int key_len, int index, builder value) asm(value index dict key_len) "DICTIREPLACEGETB" "NULLSWAPIFNOT";
(cell, int, slice, int) udict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
(cell, (int, slice, int)) ~udict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMIN" "NULLSWAPIFNOT2";
(cell, int, slice, int) idict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
(cell, (int, slice, int)) ~idict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMIN" "NULLSWAPIFNOT2";
(cell, slice, slice, int) dict_delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
(cell, (slice, slice, int)) ~dict::delete_get_min(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMIN" "NULLSWAPIFNOT2";
(cell, int, slice, int) udict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
(cell, (int, slice, int)) ~udict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTUREMMAX" "NULLSWAPIFNOT2";
(cell, int, slice, int) idict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
(cell, (int, slice, int)) ~idict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTIREMMAX" "NULLSWAPIFNOT2";
(cell, slice, slice, int) dict_delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
(cell, (slice, slice, int)) ~dict::delete_get_max(cell dict, int key_len) asm(-> 0 2 1 3) "DICTREMMAX" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMIN" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAX" "NULLSWAPIFNOT2";
(int, cell, int) udict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMINREF" "NULLSWAPIFNOT2";
(int, cell, int) udict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTUMAXREF" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_min?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMIN" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_max?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAX" "NULLSWAPIFNOT2";
(int, cell, int) idict_get_min_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMINREF" "NULLSWAPIFNOT2";
(int, cell, int) idict_get_max_ref?(cell dict, int key_len) asm (-> 1 0 2) "DICTIMAXREF" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXT" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETNEXTEQ" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREV" "NULLSWAPIFNOT2";
(int, slice, int) udict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTUGETPREVEQ" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_next?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXT" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_nexteq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETNEXTEQ" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_prev?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREV" "NULLSWAPIFNOT2";
(int, slice, int) idict_get_preveq?(cell dict, int key_len, int pivot) asm(pivot dict key_len -> 1 0 2) "DICTIGETPREVEQ" "NULLSWAPIFNOT2";
;;; Creates an empty dictionary, which is actually a null value. Equivalent to PUSHNULL
cell new_dict() asm "NEWDICT";
;;; Checks whether a dictionary is empty. Equivalent to cell_null?.
int dict_empty?(cell c) asm "DICTEMPTY";
{- Prefix dictionary primitives -}
(slice, slice, slice, int) pfxdict_get?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTGETQ" "NULLSWAPIFNOT2";
(cell, int) pfxdict_set?(cell dict, int key_len, slice key, slice value) asm(value key dict key_len) "PFXDICTSET";
(cell, int) pfxdict_delete?(cell dict, int key_len, slice key) asm(key dict key_len) "PFXDICTDEL";
;;; Returns the value of the global configuration parameter with integer index `i` as a `cell` or `null` value.
cell config_param(int x) asm "CONFIGOPTPARAM";
;;; Checks whether c is a null. Note, that FunC also has polymorphic null? built-in.
int cell_null?(cell c) asm "ISNULL";
;;; Creates an output action which would reserve exactly amount nanotoncoins (if mode = 0), at most amount nanotoncoins (if mode = 2), or all but amount nanotoncoins (if mode = 1 or mode = 3), from the remaining balance of the account. It is roughly equivalent to creating an outbound message carrying amount nanotoncoins (or b amount nanotoncoins, where b is the remaining balance) to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. Bit +2 in mode means that the external action does not fail if the specified amount cannot be reserved; instead, all remaining balance is reserved. Bit +8 in mode means `amount <- -amount` before performing any further actions. Bit +4 in mode means that amount is increased by the original balance of the current account (before the compute phase), including all extra currencies, before performing any other checks and actions. Currently, amount must be a non-negative integer, and mode must be in the range 0..15.
() raw_reserve(int amount, int mode) impure asm "RAWRESERVE";
;;; Similar to raw_reserve, but also accepts a dictionary extra_amount (represented by a cell or null) with extra currencies. In this way currencies other than TonCoin can be reserved.
() raw_reserve_extra(int amount, cell extra_amount, int mode) impure asm "RAWRESERVEX";
;;; Sends a raw message contained in msg, which should contain a correctly serialized object Message X, with the only exception that the source address is allowed to have dummy value addr_none (to be automatically replaced with the current smart contract address), and ihr_fee, fwd_fee, created_lt and created_at fields can have arbitrary values (to be rewritten with correct values during the action phase of the current transaction). Integer parameter mode contains the flags. Currently mode = 0 is used for ordinary messages; mode = 128 is used for messages that are to carry all the remaining balance of the current smart contract (instead of the value originally indicated in the message); mode = 64 is used for messages that carry all the remaining value of the inbound message in addition to the value initially indicated in the new message (if bit 0 is not set, the gas fees are deducted from this amount); mode' = mode + 1 means that the sender wants to pay transfer fees separately; mode' = mode + 2 means that any errors arising while processing this message during the action phase should be ignored. Finally, mode' = mode + 32 means that the current account must be destroyed if its resulting balance is zero. This flag is usually employed together with +128.
() send_raw_message(cell msg, int mode) impure asm "SENDRAWMSG";
;;; Creates an output action that would change this smart contract code to that given by cell new_code. Notice that this change will take effect only after the successful termination of the current run of the smart contract
() set_code(cell new_code) impure asm "SETCODE";
;;; Generates a new pseudo-random unsigned 256-bit integer x. The algorithm is as follows: if r is the old value of the random seed, considered as a 32-byte array (by constructing the big-endian representation of an unsigned 256-bit integer), then its sha512(r) is computed; the first 32 bytes of this hash are stored as the new value r' of the random seed, and the remaining 32 bytes are returned as the next random value x.
int random() impure asm "RANDU256";
;;; Generates a new pseudo-random integer z in the range 0..range1 (or range..1, if range < 0). More precisely, an unsigned random value x is generated as in random; then z := x * range / 2^256 is computed.
int rand(int range) impure asm "RAND";
;;; Returns the current random seed as an unsigned 256-bit Integer.
int get_seed() impure asm "RANDSEED";
;;; Sets the random seed to unsigned 256-bit seed.
() set_seed(int x) impure asm "SETRAND";
;;; Mixes unsigned 256-bit integer x into the random seed r by setting the random seed to sha256 of the concatenation of two 32-byte strings: the first with the big-endian representation of the old seed r, and the second with the big-endian representation of x.
() randomize(int x) impure asm "ADDRAND";
;;; Equivalent to randomize(cur_lt());.
() randomize_lt() impure asm "LTIME" "ADDRAND";
;;; Checks whether the data parts of two slices coinside
int equal_slices_bits(slice a, slice b) asm "SDEQ";
;;; Checks whether b is a null. Note, that FunC also has polymorphic null? built-in.
int builder_null?(builder b) asm "ISNULL";
;;; Concatenates two builders
builder store_builder(builder to, builder from) asm "STBR";
;; CUSTOM:
;; TVM UPGRADE 2023-07 https://docs.ton.org/learn/tvm-instructions/tvm-upgrade-2023-07
;; In mainnet since 20 Dec 2023 https://t.me/tonblockchain/226
;;; Retrieves code of smart-contract from c7
cell my_code() asm "MYCODE";

View file

@ -16,26 +16,27 @@ add_executable(blockchain-explorer ${BLOCHAIN_EXPLORER_SOURCE})
if (NIX)
if (MHD_FOUND)
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR})
target_link_libraries(blockchain-explorer tdutils tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARY})
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(MHD libmicrohttpd)
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR} ${MHD_STATIC_INCLUDE_DIRS})
target_link_libraries(blockchain-explorer tdutils tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block ${MHD_LIBRARIES} ${MHD_STATIC_LIBRARIES})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARIES} ${MHD_STATIC_LIBRARIES})
endif()
else()
if (MHD_FOUND)
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR})
target_link_libraries(blockchain-explorer tdutils tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARY})
else()
find_package(MHD)
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR})
target_link_libraries(blockchain-explorer tdutils tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARY})
endif()
endif()
target_include_directories(blockchain-explorer PUBLIC ${MHD_INCLUDE_DIR})
target_link_libraries(blockchain-explorer tdutils tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ton_block ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer tdactor adnllite tl_lite_api tl-lite-utils ton_crypto ${MHD_LIBRARY})
target_link_libraries(blockchain-explorer lite-client-common)
install(TARGETS blockchain-explorer RUNTIME DESTINATION bin)

View file

@ -122,9 +122,8 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
abort("cannot unpack internal message");
return *this;
}
td::RefInt256 value;
td::Ref<vm::Cell> extra;
if (!block::unpack_CurrencyCollection(info.value, value, extra)) {
block::CurrencyCollection currency_collection;
if (!currency_collection.unpack(info.value)) {
abort("cannot unpack message value");
return *this;
}
@ -133,7 +132,7 @@ HttpAnswer& HttpAnswer::operator<<(MessageCell msg) {
<< "<tr><th>destination</th><td>" << AddressCell{info.dest} << "</td></tr>\n"
<< "<tr><th>lt</th><td>" << info.created_lt << "</td></tr>\n"
<< "<tr><th>time</th><td>" << info.created_at << " (" << time_to_human(info.created_at) << ")</td></tr>\n"
<< "<tr><th>value</th><td>" << value << "</td></tr>\n";
<< "<tr><th>value</th><td>" << currency_collection.to_str()<< "</td></tr>\n";
break;
}
default:
@ -365,6 +364,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
ton::LogicalTime last_trans_lt = 0;
ton::Bits256 last_trans_hash;
last_trans_hash.set_zero();
block::CurrencyCollection balance = block::CurrencyCollection::zero();
try {
auto state_root = vm::MerkleProof::virtualize(acc_c.q_roots[1], 1);
if (state_root.is_null()) {
@ -397,6 +397,20 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
}
last_trans_hash = acc_info.last_trans_hash;
last_trans_lt = acc_info.last_trans_lt;
block::gen::Account::Record_account acc;
block::gen::AccountStorage::Record storage_rec;
if (!tlb::unpack_cell(acc_c.root, acc)) {
abort("cannot unpack Account");
return *this;
}
if (!tlb::csr_unpack(acc.storage, storage_rec)) {
abort("cannot unpack AccountStorage");
return *this;
}
if (!balance.unpack(storage_rec.balance)) {
abort("cannot unpack account balance");
return *this;
}
} else if (acc_c.root.not_null()) {
abort(PSTRING() << "account state proof shows that account state for " << acc_c.addr.workchain << ":"
<< acc_c.addr.addr.to_hex() << " must be empty, but it is not");
@ -434,6 +448,7 @@ HttpAnswer& HttpAnswer::operator<<(AccountCell acc_c) {
*this << "<tr><th>workchain</th><td>" << acc_c.addr.workchain << "</td></tr>";
*this << "<tr><th>account hex</th><td>" << acc_c.addr.addr.to_hex() << "</td></tr>";
*this << "<tr><th>account</th><td>" << acc_c.addr.rserialize(true) << "</td></tr>";
*this << "<tr><th>balance</th><td>" << balance.to_str() << "</td></tr>";
if (last_trans_lt > 0) {
*this << "<tr><th>last transaction</th><td>"
<< "<a href=\"" << TransactionLink{acc_c.addr, last_trans_lt, last_trans_hash} << "\">lt=" << last_trans_lt

View file

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

View file

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

View file

@ -34,6 +34,5 @@ target_include_directories(overlay PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/..
${OPENSSL_INCLUDE_DIR}
)
target_link_libraries(catchain PRIVATE tdutils tdactor adnl tl_api dht tdfec
overlay)
target_link_libraries(catchain PRIVATE tdutils tdactor adnl tl_api dht tdfec overlay)

View file

@ -61,7 +61,7 @@ class CatChainReceiverSource {
virtual td::BufferSlice fork_proof() const = 0;
virtual bool fork_is_found() const = 0;
// One block can be sent to one node only a limited number of times to prevent DoS
// One block can be sent to one node in catchain.getDifference only a limited number of times to prevent DoS
virtual bool allow_send_block(CatChainBlockHash hash) = 0;
static td::Result<std::unique_ptr<CatChainReceiverSource>> create(CatChainReceiver *chain, PublicKey pub_key,

View file

@ -27,6 +27,8 @@
#include "catchain-receiver.hpp"
#include "td/utils/ThreadSafeCounter.h"
namespace ton {
namespace catchain {
@ -368,6 +370,12 @@ void CatChainReceiverImpl::add_block(td::BufferSlice payload, std::vector<CatCha
}
int height = prev->height_ + 1;
auto max_block_height = get_max_block_height(opts_, sources_.size());
if (td::narrow_cast<td::uint64>(height) > max_block_height) {
VLOG(CATCHAIN_WARNING) << this << ": cannot create block: max height exceeded (" << max_block_height << ")";
active_send_ = false;
return;
}
auto block_data = create_tl_object<ton_api::catchain_block_data>(std::move(prev), std::move(deps_arr));
auto block = create_tl_object<ton_api::catchain_block>(incarnation_, local_idx_, height, std::move(block_data),
td::BufferSlice());
@ -518,10 +526,12 @@ void CatChainReceiverImpl::start_up() {
for (td::uint32 i = 0; i < get_sources_cnt(); i++) {
root_keys.emplace(get_source(i)->get_hash(), OVERLAY_MAX_ALLOWED_PACKET_SIZE);
}
td::actor::send_closure(overlay_manager_, &overlay::Overlays::create_private_overlay,
overlay::OverlayOptions overlay_options;
overlay_options.broadcast_speed_multiplier_ = opts_.broadcast_speed_multiplier;
td::actor::send_closure(overlay_manager_, &overlay::Overlays::create_private_overlay_ex,
get_source(local_idx_)->get_adnl_id(), overlay_full_id_.clone(), std::move(ids),
make_callback(), overlay::OverlayPrivacyRules{0, 0, std::move(root_keys)},
R"({ "type": "catchain" })");
R"({ "type": "catchain" })", std::move(overlay_options));
CHECK(root_block_);
@ -679,6 +689,7 @@ void CatChainReceiverImpl::receive_query_from_overlay(adnl::AdnlNodeIdShort src,
promise.set_error(td::Status::Error(ErrorCode::notready, "db not read"));
return;
}
TD_PERF_COUNTER(catchain_query_process);
td::PerfWarningTimer t{"catchain query process", 0.05};
auto F = fetch_tl_object<ton_api::Function>(data.clone(), true);
if (F.is_error()) {
@ -697,12 +708,8 @@ void CatChainReceiverImpl::process_query(adnl::AdnlNodeIdShort src, ton_api::cat
} else {
CatChainReceiverSource *S = get_source_by_adnl_id(src);
CHECK(S != nullptr);
if (S->allow_send_block(it->second->get_hash())) {
promise.set_value(serialize_tl_object(create_tl_object<ton_api::catchain_blockResult>(it->second->export_tl()),
true, it->second->get_payload().as_slice()));
} else {
promise.set_error(td::Status::Error("block was requested too many times"));
}
promise.set_value(serialize_tl_object(create_tl_object<ton_api::catchain_blockResult>(it->second->export_tl()),
true, it->second->get_payload().as_slice()));
}
}

View file

@ -96,6 +96,7 @@ class CatChain : public td::actor::Actor {
virtual void send_query_via(const PublicKeyHash &dst, std::string name, td::Promise<td::BufferSlice> promise,
td::Timestamp timeout, td::BufferSlice query, td::uint64 max_answer_size,
td::actor::ActorId<adnl::AdnlSenderInterface> via) = 0;
virtual void get_source_heights(td::Promise<std::vector<CatChainBlockHeight>> promise) = 0;
virtual void destroy() = 0;
static td::actor::ActorOwn<CatChain> create(std::unique_ptr<Callback> callback, const CatChainOptions &opts,

View file

@ -115,6 +115,15 @@ class CatChainImpl : public CatChain {
td::actor::send_closure(receiver_, &CatChainReceiverInterface::send_custom_query_data_via, dst, name,
std::move(promise), timeout, std::move(query), max_answer_size, via);
}
void get_source_heights(td::Promise<std::vector<CatChainBlockHeight>> promise) override {
std::vector<CatChainBlockHeight> heights(top_source_blocks_.size(), 0);
for (size_t i = 0; i < top_source_blocks_.size(); ++i) {
if (top_source_blocks_[i]) {
heights[i] = top_source_blocks_[i]->height();
}
}
promise.set_result(std::move(heights));
}
void destroy() override;
CatChainImpl(std::unique_ptr<Callback> callback, const CatChainOptions &opts,
td::actor::ActorId<keyring::Keyring> keyring, td::actor::ActorId<adnl::Adnl> adnl,

View file

@ -49,4 +49,29 @@ template <typename T>
void delay_action(T promise, td::Timestamp timeout) {
DelayedAction<T>::create(std::move(promise), timeout);
}
template <typename PromiseT, typename ValueT>
class AsyncApply : public td::actor::Actor {
public:
AsyncApply(PromiseT promise, ValueT value) : promise_(std::move(promise)), value_(std::move(value)){
}
void start_up() override {
promise_(std::move(value_));
stop();
}
static void create(td::Slice name, PromiseT promise, ValueT value ) {
td::actor::create_actor<AsyncApply>(PSLICE() << "async:" << name, std::move(promise), std::move(value)).release();
}
private:
PromiseT promise_;
ValueT value_;
};
template <class PromiseT, class ValueT>
void async_apply(td::Slice name, PromiseT &&promise, ValueT &&value) {
AsyncApply<PromiseT, ValueT>::create(name, std::forward<PromiseT>(promise), std::forward<ValueT>(value));
}
} // namespace ton

View file

@ -19,6 +19,6 @@
namespace ton {
// See doc/GlobalVersions.md
const int SUPPORTED_VERSION = 8;
constexpr int SUPPORTED_VERSION = 10;
}

View file

@ -10,8 +10,7 @@ set(CREATE_HARDFORK_SOURCE
)
add_executable(create-hardfork ${CREATE_HARDFORK_SOURCE})
target_link_libraries(create-hardfork overlay tdutils tdactor adnl tl_api dht
rldp catchain validatorsession full-node validator-hardfork ton_validator
target_link_libraries(create-hardfork overlay tdutils tdactor adnl tl_api dht rldp catchain validatorsession full-node validator-hardfork ton_validator
validator-hardfork fift-lib memprof git ${JEMALLOC_LIBRARIES})
install(TARGETS create-hardfork RUNTIME DESTINATION bin)

View file

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

View file

@ -151,6 +151,7 @@ set(TON_DB_SOURCE
vm/db/CellHashTable.h
vm/db/CellStorage.h
vm/db/TonDb.h
vm/db/InMemoryBagOfCellsDb.cpp
)
set(FIFT_SOURCE
@ -300,9 +301,8 @@ endif()
target_include_directories(ton_crypto_core SYSTEM PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
add_library(ton_crypto STATIC ${TON_CRYPTO_SOURCE})
target_include_directories(ton_crypto PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(ton_crypto PUBLIC ${OPENSSL_CRYPTO_LIBRARY} tdutils tddb_utils ton_crypto_core ton_block)
target_include_directories(ton_crypto PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(ton_crypto PUBLIC ${OPENSSL_CRYPTO_LIBRARY} ton_crypto_core ton_block)
if (USE_EMSCRIPTEN)
target_link_options(ton_crypto PRIVATE -fexceptions)
target_compile_options(ton_crypto PRIVATE -fexceptions)
@ -318,20 +318,20 @@ endif()
target_include_directories(ton_crypto SYSTEM PUBLIC $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
add_dependencies(ton_crypto blst)
add_dependencies(ton_crypto_core secp256k1)
target_include_directories(ton_crypto PRIVATE ${BLST_INCLUDE_DIR})
target_link_libraries(ton_crypto PRIVATE ${BLST_LIB})
if (NOT USE_EMSCRIPTEN)
find_package(Secp256k1 REQUIRED)
endif()
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
if (MSVC)
find_package(Sodium REQUIRED)
target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY})
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY})
elseif (ANDROID OR EMSCRIPTEN)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
elseif (EMSCRIPTEN)
target_link_libraries(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_LIBRARY}>)
target_link_libraries(ton_crypto PUBLIC $<BUILD_INTERFACE:${SECP256K1_LIBRARY}>)
else()
if (NOT SODIUM_FOUND)
@ -340,7 +340,7 @@ else()
message(STATUS "Using Sodium ${SODIUM_LIBRARY_RELEASE}")
endif()
target_compile_definitions(ton_crypto PUBLIC SODIUM_STATIC)
target_include_directories(ton_crypto_core PUBLIC $<BUILD_INTERFACE:${SECP256K1_INCLUDE_DIR}>)
target_link_libraries(ton_crypto_core PUBLIC ${SECP256K1_LIBRARY})
target_link_libraries(ton_crypto PUBLIC ${SECP256K1_LIBRARY})
endif()
@ -358,7 +358,7 @@ target_link_libraries(test-ed25519-crypto PUBLIC ton_crypto)
add_library(fift-lib STATIC ${FIFT_SOURCE})
target_include_directories(fift-lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(fift-lib PUBLIC ton_crypto tdutils ton_block)
target_link_libraries(fift-lib PUBLIC ton_crypto)
if (USE_EMSCRIPTEN)
target_link_options(fift-lib PRIVATE -fexceptions)
@ -379,7 +379,7 @@ target_link_libraries(src_parser PUBLIC ton_crypto_core)
add_library(ton_block STATIC ${BLOCK_SOURCE})
target_include_directories(ton_block PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/block> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(ton_block PUBLIC ton_crypto tdutils tdactor tl_api)
target_link_libraries(ton_block PUBLIC ton_crypto_core tdactor tl_api)
if (USE_EMSCRIPTEN)
target_link_options(ton_block PRIVATE -fexceptions)
target_compile_options(ton_block PRIVATE -fexceptions)
@ -387,7 +387,7 @@ endif()
add_executable(func func/func-main.cpp ${FUNC_LIB_SOURCE})
target_include_directories(func PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(func PUBLIC ton_crypto src_parser git ton_block)
target_link_libraries(func PUBLIC ton_crypto src_parser git)
if (WINGETOPT_FOUND)
target_link_libraries_system(func wingetopt)
endif()
@ -416,23 +416,31 @@ endif()
add_executable(tlbc tl/tlbc.cpp)
target_include_directories(tlbc PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(tlbc PUBLIC ton_crypto_core src_parser)
target_link_libraries(tlbc PUBLIC src_parser)
if (WINGETOPT_FOUND)
target_link_libraries_system(tlbc wingetopt)
endif()
add_library(pow-miner-lib util/Miner.cpp util/Miner.h)
target_include_directories(pow-miner-lib PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(pow-miner-lib PUBLIC ton_crypto ton_block)
target_link_libraries(pow-miner-lib PUBLIC ton_crypto)
add_executable(pow-miner util/pow-miner.cpp)
target_link_libraries(pow-miner PRIVATE ton_crypto ton_block pow-miner-lib git)
target_link_libraries(pow-miner PRIVATE ton_crypto pow-miner-lib git)
if (WINGETOPT_FOUND)
target_link_libraries_system(fift wingetopt)
target_link_libraries_system(pow-miner wingetopt)
endif()
add_executable(mintless-proof-generator util/mintless-proof-generator.cpp)
target_link_libraries(mintless-proof-generator PRIVATE ton_crypto git ${JEMALLOC_LIBRARIES})
if (JEMALLOC_FOUND)
target_include_directories(mintless-proof-generator PRIVATE ${JEMALLOC_INCLUDE_DIR})
target_compile_definitions(mintless-proof-generator PRIVATE -DTON_USE_JEMALLOC=1)
endif()
set(TURN_OFF_LSAN cd .)
if (TON_USE_ASAN AND NOT WIN32)
set(TURN_OFF_LSAN export LSAN_OPTIONS=detect_leaks=0)
@ -531,12 +539,12 @@ add_executable(create-state block/create-state.cpp)
target_include_directories(create-state PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
if (INTERNAL_COMPILE)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib git)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib tonlib git)
else()
if (TONLIB_COMPILE)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block tonlib git)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib tonlib git)
else()
target_link_libraries(create-state PUBLIC ton_crypto fift-lib ton_block git)
target_link_libraries(create-state PUBLIC ton_crypto fift-lib git)
endif()
endif()
if (WINGETOPT_FOUND)
@ -546,7 +554,7 @@ endif()
add_executable(dump-block block/dump-block.cpp)
target_include_directories(dump-block PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(dump-block PUBLIC ton_crypto fift-lib ton_block git)
target_link_libraries(dump-block PUBLIC ton_crypto fift-lib git)
if (WINGETOPT_FOUND)
target_link_libraries_system(dump-block wingetopt)
endif()
@ -554,7 +562,7 @@ endif()
add_executable(adjust-block block/adjust-block.cpp)
target_include_directories(adjust-block PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(adjust-block PUBLIC ton_crypto fift-lib ton_block git)
target_link_libraries(adjust-block PUBLIC ton_crypto fift-lib git)
if (WINGETOPT_FOUND)
target_link_libraries_system(dump-block wingetopt)
target_link_libraries_system(adjust-block wingetopt)
@ -563,7 +571,7 @@ endif()
add_executable(test-weight-distr block/test-weight-distr.cpp)
target_include_directories(test-weight-distr PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>)
target_link_libraries(test-weight-distr PUBLIC ton_crypto fift-lib ton_block git)
target_link_libraries(test-weight-distr PUBLIC ton_crypto fift-lib git)
if (WINGETOPT_FOUND)
target_link_libraries_system(test-weight-distr wingetopt)
endif()

View file

@ -360,7 +360,6 @@ MsgProcessedUptoCollection::MsgProcessedUptoCollection(ton::ShardIdFull _owner,
z.shard = key.get_uint(64);
z.mc_seqno = (unsigned)((key + 64).get_uint(32));
z.last_inmsg_lt = value.write().fetch_ulong(64);
// std::cerr << "ProcessedUpto shard " << std::hex << z.shard << std::dec << std::endl;
return value.write().fetch_bits_to(z.last_inmsg_hash) && z.shard && ton::shard_contains(owner.shard, z.shard);
});
}
@ -660,6 +659,12 @@ bool EnqueuedMsgDescr::check_key(td::ConstBitPtr key) const {
hash_ == key + 96;
}
bool ImportedMsgQueueLimits::deserialize(vm::CellSlice& cs) {
return cs.fetch_ulong(8) == 0xd3 // imported_msg_queue_limits#d3
&& cs.fetch_uint_to(32, max_bytes) // max_bytes:#
&& cs.fetch_uint_to(32, max_msgs); // max_msgs:#
}
bool ParamLimits::deserialize(vm::CellSlice& cs) {
return cs.fetch_ulong(8) == 0xc3 // param_limits#c3
&& cs.fetch_uint_to(32, limits_[0]) // underload:uint32
@ -719,8 +724,8 @@ td::uint64 BlockLimitStatus::estimate_block_size(const vm::NewCellStorageStat::S
if (extra) {
sum += *extra;
}
return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + accounts * 200 +
transactions * 200 + (extra ? 200 : 0) + extra_out_msgs * 300 + public_library_diff * 700;
return 2000 + (sum.bits >> 3) + sum.cells * 12 + sum.internal_refs * 3 + sum.external_refs * 40 + transactions * 200 +
(extra ? 200 : 0) + extra_out_msgs * 300 + public_library_diff * 700;
}
int BlockLimitStatus::classify() const {
@ -856,8 +861,10 @@ td::Status ShardState::unpack_out_msg_queue_info(Ref<vm::Cell> out_msg_queue_inf
out_msg_queue_ =
std::make_unique<vm::AugmentedDictionary>(std::move(qinfo.out_queue), 352, block::tlb::aug_OutMsgQueue);
if (verbosity >= 3 * 1) {
LOG(DEBUG) << "unpacking ProcessedUpto of our previous block " << id_.to_str();
block::gen::t_ProcessedInfo.print(std::cerr, qinfo.proc_info);
FLOG(DEBUG) {
sb << "unpacking ProcessedUpto of our previous block " << id_.to_str();
block::gen::t_ProcessedInfo.print(sb, qinfo.proc_info);
};
}
if (!block::gen::t_ProcessedInfo.validate_csr(1024, qinfo.proc_info)) {
return td::Status::Error(
@ -1313,6 +1320,65 @@ CurrencyCollection CurrencyCollection::operator-(td::RefInt256 other_grams) cons
}
}
bool CurrencyCollection::clamp(const CurrencyCollection& other) {
if (!is_valid() || !other.is_valid()) {
return invalidate();
}
grams = std::min(grams, other.grams);
vm::Dictionary dict1{extra, 32}, dict2(other.extra, 32);
bool ok = dict1.check_for_each([&](td::Ref<vm::CellSlice> cs1, td::ConstBitPtr key, int n) {
CHECK(n == 32);
td::Ref<vm::CellSlice> cs2 = dict2.lookup(key, 32);
td::RefInt256 val1 = tlb::t_VarUIntegerPos_32.as_integer(cs1);
if (val1.is_null()) {
return false;
}
td::RefInt256 val2 = cs2.is_null() ? td::zero_refint() : tlb::t_VarUIntegerPos_32.as_integer(cs2);
if (val2.is_null()) {
return false;
}
if (val1 > val2) {
if (val2->sgn() == 0) {
dict1.lookup_delete(key, 32);
} else {
dict1.set(key, 32, cs2);
}
}
return true;
});
extra = dict1.get_root_cell();
return ok || invalidate();
}
bool CurrencyCollection::check_extra_currency_limit(td::uint32 max_currencies) const {
td::uint32 count = 0;
return vm::Dictionary{extra, 32}.check_for_each([&](td::Ref<vm::CellSlice>, td::ConstBitPtr, int) {
++count;
return count <= max_currencies;
});
}
bool CurrencyCollection::remove_zero_extra_currencies(Ref<vm::Cell>& root, td::uint32 max_currencies) {
td::uint32 count = 0;
vm::Dictionary dict{root, 32};
int res = dict.filter([&](const vm::CellSlice& cs, td::ConstBitPtr, int) -> int {
++count;
if (count > max_currencies) {
return -1;
}
td::RefInt256 val = tlb::t_VarUInteger_32.as_integer(cs);
if (val.is_null()) {
return -1;
}
return val->sgn() > 0;
});
if (res < 0) {
return false;
}
root = dict.get_root_cell();
return true;
}
bool CurrencyCollection::operator==(const CurrencyCollection& other) const {
return is_valid() && other.is_valid() && !td::cmp(grams, other.grams) &&
(extra.not_null() == other.extra.not_null()) &&

View file

@ -216,6 +216,16 @@ static inline std::ostream& operator<<(std::ostream& os, const MsgProcessedUptoC
return proc_coll.print(os);
}
struct ImportedMsgQueueLimits {
// Default values
td::uint32 max_bytes = 1 << 16;
td::uint32 max_msgs = 30;
bool deserialize(vm::CellSlice& cs);
ImportedMsgQueueLimits operator*(td::uint32 x) const {
return {max_bytes * x, max_msgs * x};
}
};
struct ParamLimits {
enum { limits_cnt = 4 };
enum { cl_underload = 0, cl_normal = 1, cl_soft = 2, cl_medium = 3, cl_hard = 4 };
@ -239,6 +249,12 @@ struct ParamLimits {
bool deserialize(vm::CellSlice& cs);
int classify(td::uint64 value) const;
bool fits(unsigned cls, td::uint64 value) const;
void multiply_by(double x) {
CHECK(x > 0.0);
for (td::uint32& y : limits_) {
y = (td::uint32)std::min<double>(y * x, 1e9);
}
}
private:
std::array<td::uint32, limits_cnt> limits_;
@ -374,6 +390,9 @@ struct CurrencyCollection {
CurrencyCollection operator-(const CurrencyCollection& other) const;
CurrencyCollection operator-(CurrencyCollection&& other) const;
CurrencyCollection operator-(td::RefInt256 other_grams) const;
bool clamp(const CurrencyCollection& other);
bool check_extra_currency_limit(td::uint32 max_currencies) const;
static bool remove_zero_extra_currencies(Ref<vm::Cell>& root, td::uint32 max_currencies);
bool store(vm::CellBuilder& cb) const;
bool store_or_zero(vm::CellBuilder& cb) const;
bool fetch(vm::CellSlice& cs);

View file

@ -296,7 +296,7 @@ transaction$0111 account_addr:bits256 lt:uint64
total_fees:CurrencyCollection state_update:^(HASH_UPDATE Account)
description:^TransactionDescr = Transaction;
!merkle_update#02 {X:Type} old_hash:bits256 new_hash:bits256
!merkle_update#04 {X:Type} old_hash:bits256 new_hash:bits256 old_depth:uint16 new_depth:uint16
old:^X new:^X = MERKLE_UPDATE X;
update_hashes#72 {X:Type} old_hash:bits256 new_hash:bits256
= HASH_UPDATE X;
@ -666,15 +666,15 @@ wc_split_merge_timings#0
//workchain#a5 enabled_since:uint32 min_split:(## 8) max_split:(## 8)
// { min_split <= max_split } { max_split <= 60 }
workchain#a6 enabled_since:uint32 actual_min_split:(## 8)
min_split:(## 8) max_split:(## 8) { actual_min_split <= min_split }
workchain#a6 enabled_since:uint32 monitor_min_split:(## 8)
min_split:(## 8) max_split:(## 8) { monitor_min_split <= min_split }
basic:(## 1) active:Bool accept_msgs:Bool flags:(## 13) { flags = 0 }
zerostate_root_hash:bits256 zerostate_file_hash:bits256
version:uint32 format:(WorkchainFormat basic)
= WorkchainDescr;
workchain_v2#a7 enabled_since:uint32 actual_min_split:(## 8)
min_split:(## 8) max_split:(## 8) { actual_min_split <= min_split }
workchain_v2#a7 enabled_since:uint32 monitor_min_split:(## 8)
min_split:(## 8) max_split:(## 8) { monitor_min_split <= min_split }
basic:(## 1) active:Bool accept_msgs:Bool flags:(## 13) { flags = 0 }
zerostate_root_hash:bits256 zerostate_file_hash:bits256
version:uint32 format:(WorkchainFormat basic)
@ -801,7 +801,7 @@ size_limits_config#01 max_msg_bits:uint32 max_msg_cells:uint32 max_library_cells
max_ext_msg_size:uint32 max_ext_msg_depth:uint16 = SizeLimitsConfig;
size_limits_config_v2#02 max_msg_bits:uint32 max_msg_cells:uint32 max_library_cells:uint32 max_vm_data_depth:uint16
max_ext_msg_size:uint32 max_ext_msg_depth:uint16 max_acc_state_cells:uint32 max_acc_state_bits:uint32
max_acc_public_libraries:uint32 defer_out_queue_size_limit:uint32 = SizeLimitsConfig;
max_acc_public_libraries:uint32 defer_out_queue_size_limit:uint32 max_msg_extra_currencies:uint32 = SizeLimitsConfig;
_ SizeLimitsConfig = ConfigParam 43;
// key is [ wc:int32 addr:uint256 ]
@ -818,7 +818,7 @@ _ OracleBridgeParams = ConfigParam 72; // Binance Smart Chain bridge
_ OracleBridgeParams = ConfigParam 73; // Polygon bridge
// Note that chains in which bridge, minter and jetton-wallet operate are fixated
jetton_bridge_prices#_ bridge_burn_fee:Coins bridge_mint_fee:Coins
jetton_bridge_prices#_ bridge_burn_fee:Coins bridge_mint_fee:Coins
wallet_min_tons_for_storage:Coins
wallet_gas_consumption:Coins
minter_min_tons_for_storage:Coins

View file

@ -426,7 +426,7 @@ bool store_validator_list_hash(vm::CellBuilder& cb) {
LOG_CHECK(vset) << "unpacked validator set is empty";
auto ccvc = block::Config::unpack_catchain_validators_config(config_dict.lookup_ref(td::BitArray<32>{28}));
ton::ShardIdFull shard{ton::masterchainId};
auto nodes = block::Config::do_compute_validator_set(ccvc, shard, *vset, now, 0);
auto nodes = block::Config::do_compute_validator_set(ccvc, shard, *vset, 0);
LOG_CHECK(!nodes.empty()) << "validator node list in unpacked validator set is empty";
auto vset_hash = block::compute_validator_set_hash(0, shard, std::move(nodes));
LOG(DEBUG) << "initial validator set hash is " << vset_hash;

View file

@ -163,8 +163,11 @@ td::Status ConfigInfo::unpack() {
}
gen::McStateExtra::Record extra_info;
if (!tlb::unpack_cell(state_extra_root_, extra_info)) {
vm::load_cell_slice(state_extra_root_).print_rec(std::cerr);
block::gen::t_McStateExtra.print_ref(std::cerr, state_extra_root_);
FLOG(WARNING) {
sb << "state extra information is invalid: ";
vm::load_cell_slice(state_extra_root_).print_rec(sb);
block::gen::t_McStateExtra.print_ref(sb, state_extra_root_);
};
return td::Status::Error("state extra information is invalid");
}
gen::ValidatorInfo::Record validator_info;
@ -320,7 +323,7 @@ ton::ValidatorSessionConfig Config::get_consensus_config() const {
c.max_block_size = r.max_block_bytes;
c.max_collated_data_size = r.max_collated_bytes;
};
auto set_v2 = [&] (auto& r) {
auto set_v2 = [&](auto& r) {
set_v1(r);
c.new_catchain_ids = r.new_catchain_ids;
};
@ -1067,7 +1070,6 @@ Ref<McShardHash> ShardConfig::get_shard_hash(ton::ShardIdFull id, bool exact) co
ton::ShardIdFull true_id;
vm::CellSlice cs;
if (get_shard_hash_raw(cs, id, true_id, exact)) {
// block::gen::t_ShardDescr.print(std::cerr, vm::CellSlice{cs});
return McShardHash::unpack(cs, true_id);
} else {
return {};
@ -1637,8 +1639,10 @@ bool ShardConfig::set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value) {
if (!gen::t_BinTree_ShardDescr.validate_ref(1024, value)) {
LOG(ERROR) << "attempting to store an invalid (BinTree ShardDescr) at shard configuration position "
<< shard.to_str();
gen::t_BinTree_ShardDescr.print_ref(std::cerr, value);
vm::load_cell_slice(value).print_rec(std::cerr);
FLOG(WARNING) {
gen::t_BinTree_ShardDescr.print_ref(sb, value);
vm::load_cell_slice(value).print_rec(sb);
};
return false;
}
auto root = shard_hashes_dict_->lookup_ref(td::BitArray<32>{shard.workchain});
@ -1746,7 +1750,7 @@ ton::CatchainSeqno ConfigInfo::get_shard_cc_seqno(ton::ShardIdFull shard) const
std::vector<ton::ValidatorDescr> Config::compute_validator_set(ton::ShardIdFull shard, const block::ValidatorSet& vset,
ton::UnixTime time, ton::CatchainSeqno cc_seqno) const {
return do_compute_validator_set(get_catchain_validators_config(), shard, vset, time, cc_seqno);
return do_compute_validator_set(get_catchain_validators_config(), shard, vset, cc_seqno);
}
std::vector<ton::ValidatorDescr> Config::compute_validator_set(ton::ShardIdFull shard, ton::UnixTime time,
@ -1773,7 +1777,7 @@ std::vector<ton::ValidatorDescr> ConfigInfo::compute_validator_set_cc(ton::Shard
if (cc_seqno_delta) {
cc_seqno = *cc_seqno_delta += cc_seqno;
}
return do_compute_validator_set(get_catchain_validators_config(), shard, vset, time, cc_seqno);
return do_compute_validator_set(get_catchain_validators_config(), shard, vset, cc_seqno);
}
std::vector<ton::ValidatorDescr> ConfigInfo::compute_validator_set_cc(ton::ShardIdFull shard, ton::UnixTime time,
@ -1856,9 +1860,8 @@ int ValidatorSet::lookup_public_key(td::ConstBitPtr pubkey) const {
return -1;
}
std::vector<ton::ValidatorDescr> Config::do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard,
const block::ValidatorSet& vset, ton::UnixTime time,
std::vector<ton::ValidatorDescr> Config::do_compute_validator_set(const CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard, const ValidatorSet& vset,
ton::CatchainSeqno cc_seqno) {
// LOG(DEBUG) << "in Config::do_compute_validator_set() for " << shard.to_str() << " ; cc_seqno=" << cc_seqno;
std::vector<ton::ValidatorDescr> nodes;
@ -1940,7 +1943,7 @@ td::Result<SizeLimitsConfig> Config::get_size_limits_config() const {
td::Result<SizeLimitsConfig> Config::do_get_size_limits_config(td::Ref<vm::CellSlice> cs) {
SizeLimitsConfig limits;
if (cs.is_null()) {
return limits; // default values
return limits; // default values
}
auto unpack_v1 = [&](auto& rec) {
limits.max_msg_bits = rec.max_msg_bits;
@ -1957,6 +1960,7 @@ td::Result<SizeLimitsConfig> Config::do_get_size_limits_config(td::Ref<vm::CellS
limits.max_acc_state_cells = rec.max_acc_state_cells;
limits.max_acc_public_libraries = rec.max_acc_public_libraries;
limits.defer_out_queue_size_limit = rec.defer_out_queue_size_limit;
limits.max_msg_extra_currencies = rec.max_msg_extra_currencies;
};
gen::SizeLimitsConfig::Record_size_limits_config rec_v1;
gen::SizeLimitsConfig::Record_size_limits_config_v2 rec_v2;
@ -2075,7 +2079,7 @@ bool WorkchainInfo::unpack(ton::WorkchainId wc, vm::CellSlice& cs) {
}
auto unpack_v1 = [this](auto& info) {
enabled_since = info.enabled_since;
actual_min_split = info.actual_min_split;
monitor_min_split = info.monitor_min_split;
min_split = info.min_split;
max_split = info.max_split;
basic = info.basic;
@ -2293,39 +2297,55 @@ Ref<vm::Cell> ConfigInfo::lookup_library(td::ConstBitPtr root_hash) const {
td::Result<Ref<vm::Tuple>> ConfigInfo::get_prev_blocks_info() const {
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
// [ last_mc_blocks:[BlockId...]
// prev_key_block:BlockId ] : PrevBlocksInfo
// prev_key_block:BlockId
// last_mc_blocks_100[BlockId...] ] : PrevBlocksInfo
auto block_id_to_tuple = [](const ton::BlockIdExt& block_id) -> vm::Ref<vm::Tuple> {
td::RefInt256 shard = td::make_refint(block_id.id.shard);
if (shard->sgn() < 0) {
shard &= ((td::make_refint(1) << 64) - 1);
}
return vm::make_tuple_ref(
td::make_refint(block_id.id.workchain),
std::move(shard),
td::make_refint(block_id.id.seqno),
td::bits_to_refint(block_id.root_hash.bits(), 256),
td::bits_to_refint(block_id.file_hash.bits(), 256));
return vm::make_tuple_ref(td::make_refint(block_id.id.workchain), std::move(shard),
td::make_refint(block_id.id.seqno), td::bits_to_refint(block_id.root_hash.bits(), 256),
td::bits_to_refint(block_id.file_hash.bits(), 256));
};
std::vector<vm::StackEntry> last_mc_blocks;
std::vector<vm::StackEntry> tuple;
std::vector<vm::StackEntry> last_mc_blocks;
last_mc_blocks.push_back(block_id_to_tuple(block_id));
for (ton::BlockSeqno seqno = block_id.id.seqno; seqno > 0 && last_mc_blocks.size() < 16; ) {
for (ton::BlockSeqno seqno = block_id.id.seqno; seqno > 0 && last_mc_blocks.size() < 16;) {
--seqno;
ton::BlockIdExt block_id;
if (!get_old_mc_block_id(seqno, block_id)) {
ton::BlockIdExt id;
if (!get_old_mc_block_id(seqno, id)) {
return td::Status::Error("cannot fetch old mc block");
}
last_mc_blocks.push_back(block_id_to_tuple(block_id));
last_mc_blocks.push_back(block_id_to_tuple(id));
}
tuple.push_back(td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks)));
ton::BlockIdExt last_key_block;
ton::LogicalTime last_key_block_lt;
if (!get_last_key_block(last_key_block, last_key_block_lt)) {
return td::Status::Error("cannot fetch last key block");
}
return vm::make_tuple_ref(
td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks)),
block_id_to_tuple(last_key_block));
tuple.push_back(block_id_to_tuple(last_key_block));
if (get_global_version() >= 9) {
std::vector<vm::StackEntry> last_mc_blocks_100;
for (ton::BlockSeqno seqno = block_id.id.seqno / 100 * 100; last_mc_blocks_100.size() < 16;) {
ton::BlockIdExt id;
if (!get_old_mc_block_id(seqno, id)) {
return td::Status::Error("cannot fetch old mc block");
}
last_mc_blocks_100.push_back(block_id_to_tuple(id));
if (seqno < 100) {
break;
}
seqno -= 100;
}
tuple.push_back(td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(last_mc_blocks_100)));
}
return td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
}
td::optional<PrecompiledContractsConfig::Contract> PrecompiledContractsConfig::get_contract(

View file

@ -197,6 +197,7 @@ struct McShardHash : public McShardHashI {
: blk_(blk), start_lt_(start_lt), end_lt_(end_lt) {
}
McShardHash(const McShardHash&) = default;
McShardHash& operator=(const McShardHash&) = default;
bool is_valid() const {
return blk_.is_valid();
}
@ -396,6 +397,7 @@ struct SizeLimitsConfig {
td::uint32 max_acc_state_bits = (1 << 16) * 1023;
td::uint32 max_acc_public_libraries = 256;
td::uint32 defer_out_queue_size_limit = 256;
td::uint32 max_msg_extra_currencies = 2;
};
struct CatchainValidatorsConfig {
@ -414,7 +416,7 @@ struct CatchainValidatorsConfig {
struct WorkchainInfo : public td::CntObject {
ton::WorkchainId workchain{ton::workchainInvalid};
ton::UnixTime enabled_since;
td::uint32 actual_min_split;
td::uint32 monitor_min_split;
td::uint32 min_split, max_split;
bool basic;
bool active;
@ -455,10 +457,11 @@ class ShardConfig {
ShardConfig() = default;
ShardConfig(const ShardConfig& other);
ShardConfig(ShardConfig&& other) = default;
ShardConfig(Ref<vm::Cell> shard_hashes, Ref<McShardHash> mc_shard_hash = {})
explicit ShardConfig(Ref<vm::Cell> shard_hashes, Ref<McShardHash> mc_shard_hash = {})
: shard_hashes_(std::move(shard_hashes)), mc_shard_hash_(std::move(mc_shard_hash)) {
init();
}
ShardConfig& operator=(ShardConfig&& other) = default;
bool is_valid() const {
return valid_;
}
@ -545,7 +548,10 @@ class Config {
};
public:
enum { needValidatorSet = 16, needSpecialSmc = 32, needWorkchainInfo = 256, needCapabilities = 512 };
static constexpr int needValidatorSet = 16;
static constexpr int needSpecialSmc = 32;
static constexpr int needWorkchainInfo = 256;
static constexpr int needCapabilities = 512;
int mode{0};
ton::BlockIdExt block_id;
@ -655,9 +661,8 @@ class Config {
BurningConfig get_burning_config() const;
td::Ref<vm::Tuple> get_unpacked_config_tuple(ton::UnixTime now) const;
PrecompiledContractsConfig get_precompiled_contracts_config() const;
static std::vector<ton::ValidatorDescr> do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard,
const block::ValidatorSet& vset, ton::UnixTime time,
static std::vector<ton::ValidatorDescr> do_compute_validator_set(const CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard, const ValidatorSet& vset,
ton::CatchainSeqno cc_seqno);
static td::Result<std::unique_ptr<Config>> unpack_config(Ref<vm::Cell> config_root,
@ -682,14 +687,12 @@ class Config {
class ConfigInfo : public Config, public ShardConfig {
public:
enum {
needStateRoot = 1,
needLibraries = 2,
needStateExtraRoot = 4,
needShardHashes = 8,
needAccountsRoot = 64,
needPrevBlocks = 128
};
static constexpr int needStateRoot = 1;
static constexpr int needLibraries = 2;
static constexpr int needStateExtraRoot = 4;
static constexpr int needShardHashes = 8;
static constexpr int needAccountsRoot = 64;
static constexpr int needPrevBlocks = 128;
ton::BlockSeqno vert_seqno{~0U};
int global_id_{0};
ton::UnixTime utime{0};

View file

@ -138,7 +138,6 @@ bool OutputQueueMerger::add_root(int src, Ref<vm::Cell> outmsg_root) {
if (outmsg_root.is_null()) {
return true;
}
//block::gen::HashmapAug{352, block::gen::t_EnqueuedMsg, block::gen::t_uint64}.print_ref(std::cerr, outmsg_root);
auto kv = std::make_unique<MsgKeyValue>(src, std::move(outmsg_root));
if (kv->replace_by_prefix(common_pfx.cbits(), common_pfx_len)) {
heap.push_back(std::move(kv));

View file

@ -446,8 +446,10 @@ bool Account::unpack(Ref<vm::CellSlice> shard_account, ton::UnixTime now, bool s
return false;
}
if (verbosity > 2) {
shard_account->print_rec(std::cerr, 2);
block::gen::t_ShardAccount.print(std::cerr, *shard_account);
FLOG(INFO) {
shard_account->print_rec(sb, 2);
block::gen::t_ShardAccount.print(sb, shard_account);
};
}
block::gen::ShardAccount::Record acc_info;
if (!(block::tlb::t_ShardAccount.validate_csr(shard_account) && tlb::unpack_exact(shard_account.write(), acc_info))) {
@ -737,9 +739,11 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
return false;
}
if (verbosity > 2) {
fprintf(stderr, "unpacking inbound message for a new transaction: ");
block::gen::t_Message_Any.print_ref(std::cerr, in_msg);
load_cell_slice(in_msg).print_rec(std::cerr);
FLOG(INFO) {
sb << "unpacking inbound message for a new transaction: ";
block::gen::t_Message_Any.print_ref(sb, in_msg);
load_cell_slice(in_msg).print_rec(sb);
};
}
auto cs = vm::load_cell_slice(in_msg);
int tag = block::gen::t_CommonMsgInfo.get_tag(cs);
@ -1145,31 +1149,66 @@ td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const {
namespace transaction {
/**
* Checks if it is required to increase gas_limit (from GasLimitsPrices config) to special_gas_limit * 2
* from masterchain GasLimitsPrices config for the transaction.
* Checks if it is required to increase gas_limit (from GasLimitsPrices config) for the transaction
*
* In January 2024 a highload wallet of @wallet Telegram bot in mainnet was stuck because current gas limit (1M) is
* not enough to clean up old queires, thus locking funds inside.
* See comment in crypto/smartcont/highload-wallet-v2-code.fc for details on why this happened.
* Account address: EQD_v9j1rlsuHHw2FIhcsCFFSD367ldfDdCKcsNmNpIRzUlu
* It was proposed to validators to increase gas limit for this account for a limited amount of time (until 2024-02-29).
* It was proposed to validators to increase gas limit for this account to 70M for a limited amount
* of time (until 2024-02-29).
* It is activated by setting global version to 5 in ConfigParam 8.
* This config change also activates new behavior for special accounts in masterchain.
*
* In August 2024 it was decided to unlock other old highload wallets that got into the same situation.
* See https://t.me/tondev_news/129
* It is activated by setting global version to 9.
*
* @param cfg The compute phase configuration.
* @param now The Unix time of the transaction.
* @param account The account of the transaction.
*
* @returns True if gas_limit override is required, false otherwise
* @returns Overridden gas limit or empty td::optional
*/
static bool override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now, const Account& account) {
if (!cfg.special_gas_full) {
return false;
static td::optional<td::uint64> override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now,
const Account& account) {
struct OverridenGasLimit {
td::uint64 new_limit;
int from_version;
ton::UnixTime until;
};
static std::map<std::pair<ton::WorkchainId, ton::StdSmcAddress>, OverridenGasLimit> accounts = []() {
auto parse_addr = [](const char* s) -> std::pair<ton::WorkchainId, ton::StdSmcAddress> {
auto r_addr = StdAddress::parse(td::Slice(s));
r_addr.ensure();
return {r_addr.ok().workchain, r_addr.ok().addr};
};
std::map<std::pair<ton::WorkchainId, ton::StdSmcAddress>, OverridenGasLimit> accounts;
// Increase limit for EQD_v9j1rlsuHHw2FIhcsCFFSD367ldfDdCKcsNmNpIRzUlu until 2024-02-29 00:00:00 UTC
accounts[parse_addr("0:FFBFD8F5AE5B2E1C7C3614885CB02145483DFAEE575F0DD08A72C366369211CD")] = {
.new_limit = 70'000'000, .from_version = 5, .until = 1709164800};
// Increase limit for multiple accounts (https://t.me/tondev_news/129) until 2025-03-01 00:00:00 UTC
accounts[parse_addr("UQBeSl-dumOHieZ3DJkNKVkjeso7wZ0VpzR4LCbLGTQ8xr57")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQC3VcQ-43klww9UfimR58TBjBzk7GPupXQ3CNuthoNp-uTR")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQBhwBb8jvokGvfreHRRoeVxI237PrOJgyrsAhLA-4rBC_H5")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQCkoRp4OE-SFUoMEnYfL3vF43T3AzNfW8jyTC4yzk8cJqMS")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("UQBN5ICras79U8FYEm71ws34n-ZNIQ0LRNpckOUsIV3OebnC")] = {
.new_limit = 70'000'000, .from_version = 9, .until = 1740787200};
accounts[parse_addr("EQBDanbCeUqI4_v-xrnAN0_I2wRvEIaLg1Qg2ZN5c6Zl1KOh")] = {
.new_limit = 225'000'000, .from_version = 9, .until = 1740787200};
return accounts;
}();
auto it = accounts.find({account.workchain, account.addr});
if (it == accounts.end() || cfg.global_version < it->second.from_version || now >= it->second.until) {
return {};
}
ton::UnixTime until = 1709164800; // 2024-02-29 00:00:00 UTC
ton::WorkchainId wc = 0;
const char* addr_hex = "FFBFD8F5AE5B2E1C7C3614885CB02145483DFAEE575F0DD08A72C366369211CD";
return now < until && account.workchain == wc && account.addr.to_hex() == addr_hex;
return it->second.new_limit;
}
/**
@ -1183,10 +1222,12 @@ static bool override_gas_limit(const ComputePhaseConfig& cfg, ton::UnixTime now,
* @returns The amount of gas.
*/
td::uint64 Transaction::gas_bought_for(const ComputePhaseConfig& cfg, td::RefInt256 nanograms) {
if (override_gas_limit(cfg, now, account)) {
if (auto new_limit = override_gas_limit(cfg, now, account)) {
gas_limit_overridden = true;
// Same as ComputePhaseConfig::gas_bought for, but with other gas_limit and max_gas_threshold
auto gas_limit = cfg.mc_gas_prices.special_gas_limit * 2;
auto gas_limit = new_limit.value();
LOG(INFO) << "overridding gas limit for account " << account.workchain << ":" << account.addr.to_hex() << " to "
<< gas_limit;
auto max_gas_threshold =
compute_max_gas_threshold(cfg.gas_price256, gas_limit, cfg.flat_gas_limit, cfg.flat_gas_price);
if (nanograms.is_null() || sgn(nanograms) < 0) {
@ -1336,7 +1377,8 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
// See crypto/block/mc-config.cpp#2223 (get_prev_blocks_info)
// [ wc:Integer shard:Integer seqno:Integer root_hash:Integer file_hash:Integer] = BlockId;
// [ last_mc_blocks:[BlockId...]
// prev_key_block:BlockId ] : PrevBlocksInfo
// prev_key_block:BlockId
// last_mc_blocks_100:[BlockId...] ] : PrevBlocksInfo
// The only context where PrevBlocksInfo (13 parameter of c7) is null is inside emulator
// where it need to be set via transaction_emulator_set_prev_blocks_info (see emulator/emulator-extern.cpp)
// Inside validator, collator and liteserver checking external message contexts
@ -1512,11 +1554,13 @@ bool Transaction::run_precompiled_contract(const ComputePhaseConfig& cfg, precom
cp.actions = impl.get_c5();
int out_act_num = output_actions_count(cp.actions);
if (verbosity > 2) {
std::cerr << "new smart contract data: ";
bool can_be_special = true;
load_cell_slice_special(cp.new_data, can_be_special).print_rec(std::cerr);
std::cerr << "output actions: ";
block::gen::OutList{out_act_num}.print_ref(std::cerr, cp.actions);
FLOG(INFO) {
sb << "new smart contract data: ";
bool can_be_special = true;
load_cell_slice_special(cp.new_data, can_be_special).print_rec(sb);
sb << "output actions: ";
block::gen::OutList{out_act_num}.print_ref(sb, cp.actions);
};
}
}
cp.mode = 0;
@ -1555,7 +1599,14 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
// ...
compute_phase = std::make_unique<ComputePhase>();
ComputePhase& cp = *(compute_phase.get());
original_balance -= total_fees;
if (cfg.global_version >= 9) {
original_balance = balance;
if (msg_balance_remaining.is_valid()) {
original_balance -= msg_balance_remaining;
}
} else {
original_balance -= total_fees;
}
if (td::sgn(balance.grams) <= 0) {
// no gas
cp.skip_reason = ComputePhase::sk_no_gas;
@ -1574,7 +1625,6 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
if (in_msg_state.not_null()) {
LOG(DEBUG) << "HASH(in_msg_state) = " << in_msg_state->get_hash().bits().to_hex(256)
<< ", account_state_hash = " << account.state_hash.to_hex();
// vm::load_cell_slice(in_msg_state).print_rec(std::cerr);
} else {
LOG(DEBUG) << "in_msg_state is null";
}
@ -1684,9 +1734,8 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
}
}
}
vm::VmState vm{new_code, std::move(stack), gas, 1, new_data, vm_log, compute_vm_libraries(cfg)};
vm::VmState vm{new_code, cfg.global_version, std::move(stack), gas, 1, new_data, vm_log, compute_vm_libraries(cfg)};
vm.set_max_data_depth(cfg.max_vm_data_depth);
vm.set_global_version(cfg.global_version);
vm.set_c7(prepare_vm_c7(cfg)); // tuple with SmartContractInfo
vm.set_chksig_always_succeed(cfg.ignore_chksig);
vm.set_stop_on_accept_message(cfg.stop_on_accept_message);
@ -1731,11 +1780,13 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
cp.actions = vm.get_committed_state().c5; // c5 -> action list
int out_act_num = output_actions_count(cp.actions);
if (verbosity > 2) {
std::cerr << "new smart contract data: ";
bool can_be_special = true;
load_cell_slice_special(cp.new_data, can_be_special).print_rec(std::cerr);
std::cerr << "output actions: ";
block::gen::OutList{out_act_num}.print_ref(std::cerr, cp.actions);
FLOG(INFO) {
sb << "new smart contract data: ";
bool can_be_special = true;
load_cell_slice_special(cp.new_data, can_be_special).print_rec(sb);
sb << "output actions: ";
block::gen::OutList{out_act_num}.print_ref(sb, cp.actions);
};
}
}
cp.mode = 0;
@ -1949,9 +2000,9 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
ap.remaining_balance += ap.reserved_balance;
CHECK(ap.remaining_balance.is_valid());
if (ap.acc_delete_req) {
CHECK(ap.remaining_balance.is_zero());
CHECK(cfg.extra_currency_v2 ? ap.remaining_balance.grams->sgn() == 0 : ap.remaining_balance.is_zero());
ap.acc_status_change = ActionPhase::acst_deleted;
acc_status = Account::acc_deleted;
acc_status = (ap.remaining_balance.is_zero() ? Account::acc_deleted : Account::acc_uninit);
was_deleted = true;
}
ap.success = true;
@ -2421,6 +2472,20 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
LOG(DEBUG) << "invalid destination address in a proposed outbound message";
return check_skip_invalid(36); // invalid destination address
}
if (cfg.extra_currency_v2) {
CurrencyCollection value;
if (!value.unpack(info.value)) {
LOG(DEBUG) << "invalid value:ExtraCurrencies in a proposed outbound message";
return check_skip_invalid(37); // invalid value:CurrencyCollection
}
if (!CurrencyCollection::remove_zero_extra_currencies(value.extra, cfg.size_limits.max_msg_extra_currencies)) {
LOG(DEBUG) << "invalid value:ExtraCurrencies in a proposed outbound message: too many currencies (max "
<< cfg.size_limits.max_msg_extra_currencies << ")";
// Dict should be valid, since it was checked in t_OutListNode.validate_ref, so error here means limit exceeded
return check_skip_invalid(41); // invalid value:CurrencyCollection : too many extra currencies
}
info.value = value.pack();
}
// fetch message pricing info
const MsgPrices& msg_prices = cfg.fetch_msg_prices(to_mc || account.is_masterchain());
@ -2473,7 +2538,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
};
add_used_storage(msg.init, 3); // message init
add_used_storage(msg.body, 3); // message body (the root cell itself is not counted)
if (!ext_msg) {
if (!ext_msg && !cfg.extra_currency_v2) {
add_used_storage(info.value->prefetch_ref(), 0);
}
auto collect_fine = [&] {
@ -2544,11 +2609,19 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
if (act_rec.mode & 0x80) {
// attach all remaining balance to this message
req = ap.remaining_balance;
if (cfg.extra_currency_v2) {
req.grams = ap.remaining_balance.grams;
} else {
req = ap.remaining_balance;
}
act_rec.mode &= ~1; // pay fees from attached value
} else if (act_rec.mode & 0x40) {
// attach all remaining balance of the inbound message (in addition to the original value)
req += msg_balance_remaining;
if (cfg.extra_currency_v2) {
req.grams += msg_balance_remaining.grams;
} else {
req += msg_balance_remaining;
}
if (!(act_rec.mode & 1)) {
req -= ap.action_fine;
if (compute_phase) {
@ -2588,6 +2661,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
return check_skip_invalid(37); // not enough grams
}
if (cfg.extra_currency_v2 && !req.check_extra_currency_limit(cfg.size_limits.max_msg_extra_currencies)) {
LOG(DEBUG) << "too many extra currencies in the message : max " << cfg.size_limits.max_msg_extra_currencies;
return check_skip_invalid(41); // to many extra currencies
}
Ref<vm::Cell> new_extra;
if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) {
@ -2629,7 +2707,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
// clear msg_balance_remaining if it has been used
if (act_rec.mode & 0xc0) {
msg_balance_remaining.set_zero();
if (cfg.extra_currency_v2) {
msg_balance_remaining.grams = td::zero_refint();
} else {
msg_balance_remaining.set_zero();
}
}
// update balance
@ -2681,14 +2763,18 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
}
if (!block::gen::t_Message_Any.validate_ref(new_msg)) {
LOG(ERROR) << "generated outbound message is not a valid (Message Any) according to automated check";
block::gen::t_Message_Any.print_ref(std::cerr, new_msg);
vm::load_cell_slice(new_msg).print_rec(std::cerr);
FLOG(INFO) {
block::gen::t_Message_Any.print_ref(sb, new_msg);
vm::load_cell_slice(new_msg).print_rec(sb);
};
collect_fine();
return -1;
}
if (verbosity > 2) {
std::cerr << "converted outbound message: ";
block::gen::t_Message_Any.print_ref(std::cerr, new_msg);
FLOG(INFO) {
sb << "converted outbound message: ";
block::gen::t_Message_Any.print_ref(sb, new_msg);
};
}
ap.msgs_created++;
@ -2699,8 +2785,13 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
ap.total_fwd_fees += fees_total;
if ((act_rec.mode & 0xa0) == 0xa0) {
CHECK(ap.remaining_balance.is_zero());
ap.acc_delete_req = ap.reserved_balance.is_zero();
if (cfg.extra_currency_v2) {
CHECK(ap.remaining_balance.grams->sgn() == 0);
ap.acc_delete_req = ap.reserved_balance.grams->sgn() == 0;
} else {
CHECK(ap.remaining_balance.is_zero());
ap.acc_delete_req = ap.reserved_balance.is_zero();
}
}
ap.tot_msg_bits += sstat.bits + new_msg_bits;
@ -2753,22 +2844,25 @@ int Transaction::try_action_reserve_currency(vm::CellSlice& cs, ActionPhase& ap,
LOG(DEBUG) << "cannot reserve a negative amount: " << reserve.to_str();
return -1;
}
if (reserve.grams > ap.remaining_balance.grams) {
if (mode & 2) {
reserve.grams = ap.remaining_balance.grams;
if (mode & 2) {
if (cfg.reserve_extra_enabled) {
if (!reserve.clamp(ap.remaining_balance)) {
LOG(DEBUG) << "failed to clamp reserve amount" << mode;
return -1;
}
} else {
LOG(DEBUG) << "cannot reserve " << reserve.grams << " nanograms : only " << ap.remaining_balance.grams
<< " available";
return 37; // not enough grams
reserve.grams = std::min(reserve.grams, ap.remaining_balance.grams);
}
}
if (reserve.grams > ap.remaining_balance.grams) {
LOG(DEBUG) << "cannot reserve " << reserve.grams << " nanograms : only " << ap.remaining_balance.grams
<< " available";
return 37; // not enough grams
}
if (!block::sub_extra_currency(ap.remaining_balance.extra, reserve.extra, newc.extra)) {
LOG(DEBUG) << "not enough extra currency to reserve: " << block::CurrencyCollection{0, reserve.extra}.to_str()
<< " required, only " << block::CurrencyCollection{0, ap.remaining_balance.extra}.to_str()
<< " available";
if (mode & 2) {
// TODO: process (mode & 2) correctly by setting res_extra := inf (reserve.extra, ap.remaining_balance.extra)
}
return 38; // not enough (extra) funds
}
newc.grams = ap.remaining_balance.grams - reserve.grams;
@ -2860,22 +2954,26 @@ td::Status Transaction::check_state_limits(const SizeLimitsConfig& size_limits,
vm::CellStorageStat storage_stat;
storage_stat.limit_cells = size_limits.max_acc_state_cells;
storage_stat.limit_bits = size_limits.max_acc_state_bits;
td::Timer timer;
auto add_used_storage = [&](const td::Ref<vm::Cell>& cell) -> td::Status {
if (cell.not_null()) {
TRY_RESULT(res, storage_stat.add_used_storage(cell));
if (res.max_merkle_depth > max_allowed_merkle_depth) {
return td::Status::Error("too big merkle depth");
{
TD_PERF_COUNTER(transaction_storage_stat_a);
td::Timer timer;
auto add_used_storage = [&](const td::Ref<vm::Cell>& cell) -> td::Status {
if (cell.not_null()) {
TRY_RESULT(res, storage_stat.add_used_storage(cell));
if (res.max_merkle_depth > max_allowed_merkle_depth) {
return td::Status::Error("too big merkle depth");
}
}
return td::Status::OK();
};
TRY_STATUS(add_used_storage(new_code));
TRY_STATUS(add_used_storage(new_data));
TRY_STATUS(add_used_storage(new_library));
if (timer.elapsed() > 0.1) {
LOG(INFO) << "Compute used storage took " << timer.elapsed() << "s";
}
return td::Status::OK();
};
TRY_STATUS(add_used_storage(new_code));
TRY_STATUS(add_used_storage(new_data));
TRY_STATUS(add_used_storage(new_library));
if (timer.elapsed() > 0.1) {
LOG(INFO) << "Compute used storage took " << timer.elapsed() << "s";
}
if (acc_status == Account::acc_active) {
storage_stat.clear_limit();
} else {
@ -2964,7 +3062,8 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
bp.fwd_fees -= bp.fwd_fees_collected;
total_fees += td::make_refint(bp.fwd_fees_collected);
// serialize outbound message
info.created_lt = end_lt++;
info.created_lt = start_lt + 1 + out_msgs.size();
end_lt++;
info.created_at = now;
vm::CellBuilder cb;
CHECK(cb.store_long_bool(5, 4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
@ -2994,8 +3093,10 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
}
CHECK(cb.finalize_to(bp.out_msg));
if (verbosity > 2) {
LOG(INFO) << "generated bounced message: ";
block::gen::t_Message_Any.print_ref(std::cerr, bp.out_msg);
FLOG(INFO) {
sb << "generated bounced message: ";
block::gen::t_Message_Any.print_ref(sb, bp.out_msg);
};
}
out_msgs.push_back(bp.out_msg);
bp.ok = true;
@ -3043,6 +3144,7 @@ bool Account::store_acc_status(vm::CellBuilder& cb, int acc_status) const {
* Tries to update the storage statistics based on the old storage statistics and old account state without fully recomputing it.
*
* It succeeds if only root cell of AccountStorage is changed.
* old_cs and new_cell are AccountStorage without extra currencies (if global_version >= 10).
*
* @param old_stat The old storage statistics.
* @param old_cs The old AccountStorage.
@ -3076,13 +3178,48 @@ static td::optional<vm::CellStorageStat> try_update_storage_stat(const vm::CellS
return new_stat;
}
/**
* Removes extra currencies dict from AccountStorage.
*
* This is used for computing account storage stats.
*
* @param storage_cs AccountStorage as CellSlice.
*
* @returns AccountStorage without extra currencies as Cell.
*/
static td::Ref<vm::Cell> storage_without_extra_currencies(td::Ref<vm::CellSlice> storage_cs) {
block::gen::AccountStorage::Record rec;
if (!block::gen::csr_unpack(storage_cs, rec)) {
LOG(ERROR) << "failed to unpack AccountStorage";
return {};
}
if (rec.balance->size_refs() > 0) {
block::gen::CurrencyCollection::Record balance;
if (!block::gen::csr_unpack(rec.balance, balance)) {
LOG(ERROR) << "failed to unpack AccountStorage";
return {};
}
balance.other = vm::CellBuilder{}.store_zeroes(1).as_cellslice_ref();
if (!block::gen::csr_pack(rec.balance, balance)) {
LOG(ERROR) << "failed to pack AccountStorage";
return {};
}
}
td::Ref<vm::Cell> cell;
if (!block::gen::pack_cell(cell, rec)) {
LOG(ERROR) << "failed to pack AccountStorage";
return {};
}
return cell;
}
namespace transaction {
/**
* Computes the new state of the account.
*
* @returns True if the state computation is successful, false otherwise.
*/
bool Transaction::compute_state() {
bool Transaction::compute_state(const SerializeConfig& cfg) {
if (new_total_state.not_null()) {
return true;
}
@ -3116,11 +3253,13 @@ bool Transaction::compute_state() {
auto frozen_state = cb2.finalize();
frozen_hash = frozen_state->get_hash().bits();
if (verbosity >= 3 * 1) { // !!!DEBUG!!!
std::cerr << "freezing state of smart contract: ";
block::gen::t_StateInit.print_ref(std::cerr, frozen_state);
CHECK(block::gen::t_StateInit.validate_ref(frozen_state));
CHECK(block::tlb::t_StateInit.validate_ref(frozen_state));
std::cerr << "with hash " << frozen_hash.to_hex() << std::endl;
FLOG(INFO) {
sb << "freezing state of smart contract: ";
block::gen::t_StateInit.print_ref(sb, frozen_state);
CHECK(block::gen::t_StateInit.validate_ref(frozen_state));
CHECK(block::tlb::t_StateInit.validate_ref(frozen_state));
sb << "with hash " << frozen_hash.to_hex();
};
}
}
new_code.clear();
@ -3152,12 +3291,27 @@ bool Transaction::compute_state() {
new_inner_state.clear();
}
vm::CellStorageStat& stats = new_storage_stat;
auto new_stats = try_update_storage_stat(account.storage_stat, account.storage, storage);
td::Ref<vm::CellSlice> old_storage_for_stat = account.storage;
td::Ref<vm::Cell> new_storage_for_stat = storage;
if (cfg.extra_currency_v2) {
new_storage_for_stat = storage_without_extra_currencies(new_storage);
if (new_storage_for_stat.is_null()) {
return false;
}
if (old_storage_for_stat.not_null()) {
old_storage_for_stat = vm::load_cell_slice_ref(storage_without_extra_currencies(old_storage_for_stat));
if (old_storage_for_stat.is_null()) {
return false;
}
}
}
auto new_stats = try_update_storage_stat(account.storage_stat, old_storage_for_stat, storage);
if (new_stats) {
stats = new_stats.unwrap();
} else {
TD_PERF_COUNTER(transaction_storage_stat_b);
td::Timer timer;
stats.add_used_storage(Ref<vm::Cell>(storage)).ensure();
stats.add_used_storage(new_storage_for_stat).ensure();
if (timer.elapsed() > 0.1) {
LOG(INFO) << "Compute used storage took " << timer.elapsed() << "s";
}
@ -3177,8 +3331,10 @@ bool Transaction::compute_state() {
CHECK(cb.append_data_cell_bool(std::move(storage)));
new_total_state = cb.finalize();
if (verbosity > 2) {
std::cerr << "new account state: ";
block::gen::t_Account.print_ref(std::cerr, new_total_state);
FLOG(INFO) {
sb << "new account state: ";
block::gen::t_Account.print_ref(sb, new_total_state);
};
}
CHECK(block::tlb::t_Account.validate_ref(new_total_state));
return true;
@ -3191,11 +3347,11 @@ bool Transaction::compute_state() {
*
* @returns True if the serialization is successful, False otherwise.
*/
bool Transaction::serialize() {
bool Transaction::serialize(const SerializeConfig& cfg) {
if (root.not_null()) {
return true;
}
if (!compute_state()) {
if (!compute_state(cfg)) {
return false;
}
vm::Dictionary dict{15};
@ -3270,22 +3426,28 @@ bool Transaction::serialize() {
return false;
}
if (verbosity >= 3 * 1) {
std::cerr << "new transaction: ";
block::gen::t_Transaction.print_ref(std::cerr, root);
vm::load_cell_slice(root).print_rec(std::cerr);
FLOG(INFO) {
sb << "new transaction: ";
block::gen::t_Transaction.print_ref(sb, root);
vm::load_cell_slice(root).print_rec(sb);
};
}
if (!block::gen::t_Transaction.validate_ref(4096, root)) {
LOG(ERROR) << "newly-generated transaction failed to pass automated validation:";
vm::load_cell_slice(root).print_rec(std::cerr);
block::gen::t_Transaction.print_ref(std::cerr, root);
FLOG(INFO) {
vm::load_cell_slice(root).print_rec(sb);
block::gen::t_Transaction.print_ref(sb, root);
};
root.clear();
return false;
}
if (!block::tlb::t_Transaction.validate_ref(4096, root)) {
LOG(ERROR) << "newly-generated transaction failed to pass hand-written validation:";
vm::load_cell_slice(root).print_rec(std::cerr);
block::gen::t_Transaction.print_ref(std::cerr, root);
FLOG(INFO) {
vm::load_cell_slice(root).print_rec(sb);
block::gen::t_Transaction.print_ref(sb, root);
};
root.clear();
return false;
}
@ -3655,6 +3817,7 @@ bool Account::libraries_changed() const {
* @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`.
* @param compute_phase_cfg Pointer to store the compute phase configuration.
* @param action_phase_cfg Pointer to store the action phase configuration.
* @param serialize_cfg Pointer to store the serialize phase configuration.
* @param masterchain_create_fee Pointer to store the masterchain create fee.
* @param basechain_create_fee Pointer to store the basechain create fee.
* @param wc The workchain ID.
@ -3663,15 +3826,15 @@ bool Account::libraries_changed() const {
td::Status FetchConfigParams::fetch_config_params(
const block::ConfigInfo& config, Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg,
ActionPhaseConfig* action_phase_cfg, td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now) {
ActionPhaseConfig* action_phase_cfg, SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now) {
auto prev_blocks_info = config.get_prev_blocks_info();
if (prev_blocks_info.is_error()) {
return prev_blocks_info.move_as_error_prefix(
td::Status::Error(-668, "cannot fetch prev blocks info from masterchain configuration: "));
}
return fetch_config_params(config, prev_blocks_info.move_as_ok(), old_mparams, storage_prices, storage_phase_cfg,
rand_seed, compute_phase_cfg, action_phase_cfg, masterchain_create_fee,
rand_seed, compute_phase_cfg, action_phase_cfg, serialize_cfg, masterchain_create_fee,
basechain_create_fee, wc, now);
}
@ -3686,6 +3849,7 @@ td::Status FetchConfigParams::fetch_config_params(
* @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`.
* @param compute_phase_cfg Pointer to store the compute phase configuration.
* @param action_phase_cfg Pointer to store the action phase configuration.
* @param serialize_cfg Pointer to store the serialize phase configuration.
* @param masterchain_create_fee Pointer to store the masterchain create fee.
* @param basechain_create_fee Pointer to store the basechain create fee.
* @param wc The workchain ID.
@ -3695,8 +3859,8 @@ td::Status FetchConfigParams::fetch_config_params(
const block::Config& config, td::Ref<vm::Tuple> prev_blocks_info, Ref<vm::Cell>* old_mparams,
std::vector<block::StoragePrices>* storage_prices, StoragePhaseConfig* storage_phase_cfg,
td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee, ton::WorkchainId wc,
ton::UnixTime now) {
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now) {
*old_mparams = config.get_config_param(9);
{
auto res = config.get_storage_prices();
@ -3766,7 +3930,12 @@ td::Status FetchConfigParams::fetch_config_params(
action_phase_cfg->bounce_on_fail_enabled = config.get_global_version() >= 4;
action_phase_cfg->message_skip_enabled = config.get_global_version() >= 8;
action_phase_cfg->disable_custom_fess = config.get_global_version() >= 8;
action_phase_cfg->reserve_extra_enabled = config.get_global_version() >= 9;
action_phase_cfg->mc_blackhole_addr = config.get_burning_config().blackhole_addr;
action_phase_cfg->extra_currency_v2 = config.get_global_version() >= 10;
}
{
serialize_cfg->extra_currency_v2 = config.get_global_version() >= 10;
}
{
// fetch block_grams_created

View file

@ -169,12 +169,18 @@ struct ActionPhaseConfig {
bool bounce_on_fail_enabled{false};
bool message_skip_enabled{false};
bool disable_custom_fess{false};
bool reserve_extra_enabled{false};
bool extra_currency_v2{false};
td::optional<td::Bits256> mc_blackhole_addr;
const MsgPrices& fetch_msg_prices(bool is_masterchain) const {
return is_masterchain ? fwd_mc : fwd_std;
}
};
struct SerializeConfig {
bool extra_currency_v2{false};
};
struct CreditPhase {
td::RefInt256 due_fees_collected;
block::CurrencyCollection credit;
@ -388,8 +394,8 @@ struct Transaction {
bool prepare_action_phase(const ActionPhaseConfig& cfg);
td::Status check_state_limits(const SizeLimitsConfig& size_limits, bool update_storage_stat = true);
bool prepare_bounce_phase(const ActionPhaseConfig& cfg);
bool compute_state();
bool serialize();
bool compute_state(const SerializeConfig& cfg);
bool serialize(const SerializeConfig& cfg);
td::uint64 gas_used() const {
return compute_phase ? compute_phase->gas_used : 0;
}
@ -427,14 +433,14 @@ struct FetchConfigParams {
std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now);
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now);
static td::Status fetch_config_params(const block::Config& config, Ref<vm::Tuple> prev_blocks_info,
Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now);
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now);
};
} // namespace block

View file

@ -2294,11 +2294,11 @@ std::string AnyIntView<Tr>::to_dec_string_destroy_any() {
stack.push_back(divmod_short_any(Tr::max_pow10));
} while (sgn());
char slice[word_bits * 97879 / 325147 + 2];
std::sprintf(slice, "%lld", stack.back());
std::snprintf(slice, sizeof(slice), "%lld", stack.back());
s += slice;
stack.pop_back();
while (stack.size()) {
std::sprintf(slice, "%018lld", stack.back());
std::snprintf(slice, sizeof(slice), "%018lld", stack.back());
s += slice;
stack.pop_back();
}

View file

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

View file

@ -29,6 +29,7 @@ Ref<CntObject> CntObject::clone() const {
namespace detail {
struct SafeDeleter {
public:
thread_local static td::int64 delete_count;
void retire(const CntObject *ptr) {
if (is_active_) {
to_delete_.push_back(ptr);
@ -39,9 +40,11 @@ struct SafeDeleter {
is_active_ = false;
};
delete ptr;
delete_count++;
while (!to_delete_.empty()) {
auto *ptr = to_delete_.back();
to_delete_.pop_back();
delete_count++;
delete ptr;
}
}
@ -50,6 +53,7 @@ struct SafeDeleter {
std::vector<const CntObject *> to_delete_;
bool is_active_{false};
};
thread_local td::int64 SafeDeleter::delete_count{0};
TD_THREAD_LOCAL SafeDeleter *deleter;
void safe_delete(const CntObject *ptr) {
@ -57,4 +61,7 @@ void safe_delete(const CntObject *ptr) {
deleter->retire(ptr);
}
} // namespace detail
int64 ref_get_delete_count() {
return detail::SafeDeleter::delete_count;
}
} // namespace td

View file

@ -472,5 +472,6 @@ template <class T>
void swap(Ref<T>& r1, Ref<T>& r2) {
r1.swap(r2);
}
int64 ref_get_delete_count();
} // namespace td

View file

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

View file

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

View file

@ -1015,6 +1015,10 @@ x{EDC} dup @Defop(c) SAVEBOTH @Defop(c) SAVEBOTHCTR
x{EDE0} @Defop PUSHCTRX
x{EDE1} @Defop POPCTRX
x{EDE2} @Defop SETCONTCTRX
x{EDE3} @Defop(8u) SETCONTCTRMANY
x{EDE3} @Defop(8u) SETCONTMANY
x{EDE4} @Defop SETCONTCTRMANYX
x{EDE4} @Defop SETCONTMANYX
x{EDF0} dup @Defop BOOLAND @Defop COMPOS
x{EDF1} dup @Defop BOOLOR @Defop COMPOSALT
x{EDF2} @Defop COMPOSBOTH
@ -1308,6 +1312,7 @@ x{F832} @Defop CONFIGPARAM
x{F833} @Defop CONFIGOPTPARAM
x{F83400} @Defop PREVMCBLOCKS
x{F83401} @Defop PREVKEYBLOCK
x{F83402} @Defop PREVMCBLOCKS_100
x{F835} @Defop GLOBALID
x{F836} @Defop GETGASFEE
x{F837} @Defop GETSTORAGEFEE
@ -1354,6 +1359,7 @@ x{F90704} @Defop HASHEXTAR_KECCAK512
x{F910} @Defop CHKSIGNU
x{F911} @Defop CHKSIGNS
x{F912} @Defop ECRECOVER
x{F913} @Defop SECP256K1_XONLY_PUBKEY_TWEAK_ADD
x{F914} @Defop P256_CHKSIGNU
x{F915} @Defop P256_CHKSIGNS
@ -1589,6 +1595,9 @@ forget @proclist forget @proccnt
{ }END> b> } : }END>c
{ }END>c <s } : }END>s
// This is the way how FunC assigns method_id for reserved functions.
// Note, that Tolk entrypoints have other names (`onInternalMessage`, etc.),
// but method_id is assigned not by Fift, but by Tolk code generation.
0 constant recv_internal
-1 constant recv_external
-2 constant run_ticktock

View file

@ -114,7 +114,7 @@ class MemoryFileLoader : public fift::FileLoader {
std::map<std::string, std::string, std::less<>> files_;
};
td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_preamble = true, bool need_asm = true,
td::Result<fift::SourceLookup> create_source_lookup(std::string&& main, bool need_preamble = true, bool need_asm = true,
bool need_ton_util = true, bool need_lisp = true,
bool need_w3_code = true, bool need_fift_ext = true,
bool need_disasm = true, std::string dir = "") {
@ -189,7 +189,7 @@ td::Result<fift::SourceLookup> run_fift(fift::SourceLookup source_lookup, std::o
} // namespace
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args, std::string fift_dir) {
std::stringstream ss;
TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, true, true, true, true, fift_dir));
TRY_RESULT(source_lookup, create_source_lookup(std::move(source), true, true, true, true, true, true, true, fift_dir));
TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args)));
FiftOutput res;
res.source_lookup = std::move(source_lookup);
@ -207,19 +207,43 @@ td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std:
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir, bool need_preamble,
bool need_asm, bool need_ton_util, bool need_lisp,
bool need_w3_code) {
return create_source_lookup(main, need_preamble, need_asm, need_ton_util, need_lisp, need_w3_code, false, false,
return create_source_lookup(std::move(main), need_preamble, need_asm, need_ton_util, need_lisp, need_w3_code, false, false,
fift_dir);
}
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) {
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code) {
std::stringstream ss;
TRY_RESULT(source_lookup,
create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n"
<< (is_raw ? "}>c" : "") << " boc>B \"res\" B>file",
true, true, true, false, false, false, false, fift_dir));
std::string sb;
sb.reserve(asm_code.size() + 100);
sb.append("\"Asm.fif\" include\n <{\n");
sb.append(asm_code.data(), asm_code.size());
sb.append("\n}>c boc>B \"res\" B>file");
TRY_RESULT(source_lookup, create_source_lookup(std::move(sb), true, true, true, false, false, false, false));
TRY_RESULT(res, run_fift(std::move(source_lookup), &ss));
TRY_RESULT(boc, res.read_file("res"));
return vm::std_boc_deserialize(std::move(boc.data));
}
td::Result<CompiledProgramOutput> compile_asm_program(std::string&& program_code, const std::string& fift_dir) {
std::string main_fif;
main_fif.reserve(program_code.size() + 100);
main_fif.append(program_code.data(), program_code.size());
main_fif.append(R"( dup hashB B>X $>B "hex" B>file)"); // write codeHashHex to a file
main_fif.append(R"( boc>B B>base64 $>B "boc" B>file)"); // write codeBoc64 to a file
std::stringstream fift_output_stream;
TRY_RESULT(source_lookup, create_source_lookup(std::move(main_fif), true, true, false, false, false, false, false, fift_dir));
TRY_RESULT(res, run_fift(std::move(source_lookup), &fift_output_stream));
TRY_RESULT(boc, res.read_file("boc"));
TRY_RESULT(hex, res.read_file("hex"));
return CompiledProgramOutput{
std::move(program_code),
std::move(boc.data),
std::move(hex.data),
};
}
} // namespace fift

View file

@ -26,11 +26,21 @@ struct FiftOutput {
SourceLookup source_lookup;
std::string output;
};
// given a valid Fift code PROGRAM{ ... }END>c, compile_asm_program() returns this output
// now it's used primarily for wasm output (see tolk-js, for example)
struct CompiledProgramOutput {
std::string fiftCode;
std::string codeBoc64;
std::string codeHashHex;
};
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir = "",
bool need_preamble = true, bool need_asm = true,
bool need_ton_util = true, bool need_lisp = true,
bool need_w3_code = true);
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args = {}, std::string fift_dir = "");
td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std::string> args);
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true);
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code);
td::Result<CompiledProgramOutput> compile_asm_program(std::string&& program_code, const std::string& fift_dir);
} // namespace fift

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