Commit graph

3869 commits

Author SHA1 Message Date
Evgeniy Stratonikov
ce549e4cb2 core/test: allow to determine system fee automatically
Eventually this will be replaced by `pkg/neotest` invocations but for
now it allows us to remove NNS constants together with the tests.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
79a48a7800 neotest: allow to use 6-node committee
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
bef2a6f7ae neotest: provide both validator and committee
It will become useful for multi-node committee.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
950adb7b89 neotest: support painless multi-signing
Implementing a separate `Signer` interface is beneficial in multiple
ways:
1. Support both single and multiple transaction witnesses.
2. It should be easy to add contract signer this way.

Tests should use accounts created with `NewAccount` so hiding all
details doesn't seem to be an issue.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
1f9fd4a472 neotest: add contract client wrapper
Reduces amount of boilerplate code in tests.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
e3625152c6 core: move NNS test out of core
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:15 +03:00
Evgeniy Stratonikov
233fca0c1e neotest: add contract testing framework
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-11 11:15:14 +03:00
Roman Khimov
6b8e615094
Merge pull request #2234 from nspcc-dev/rpc/params-parsing
rpc: method-specific parameters parsing optimisation
2021-11-10 20:45:44 +03:00
Anna Shaleva
3c13c8b7a5 rpc: refactor GetUint160FromHex helper
We can trim prefix using `strings` library like it is done for uint256.
2021-11-10 14:54:18 +03:00
Anna Shaleva
4072c2fa90 rpc: handlers parameters audit
Make them compatible with C#.
2021-11-10 14:54:09 +03:00
Anna Shaleva
867bb708fc rpc: add cache to basic parameters
Need to cache values of string, bool, int and array because they can be
reused multiple times by RPC handlers. Other values don't need to be
cached.
2021-11-10 14:42:40 +03:00
Anna Shaleva
2fd04fbb35 rpc: allow to pass null parameter to invoke* calls 2021-11-10 14:42:40 +03:00
Anna Shaleva
2e8bbf2a87 rpc: *In parameters marshalling optimisation
Parse request parameters on-demand.
2021-11-10 14:42:08 +03:00
Anna Shaleva
3be2a22af8 rpc: fix Unknown transaction response for gettransactionheight 2021-11-09 16:56:48 +03:00
Anna Shaleva
1a32fcb2dc core: specify method not found call error
It's useful for debugging and external users.
2021-11-08 17:19:00 +03:00
Evgeniy Stratonikov
4ab18d084a rpc/request: add unmarshal benchmark
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-11-01 17:21:04 +03:00
Roman Khimov
1d16016027
Merge pull request #2217 from nspcc-dev/compiler-overload
compiler: allow to overload methods in manifest
2021-11-01 14:49:43 +03:00
Roman Khimov
fe50f6edc7
Merge pull request #2240 from nspcc-dev/fix-panic-in-network
Fix panic on peer disconnect
2021-11-01 12:44:15 +03:00
Roman Khimov
774dee3cd4 network: fix disconnection race between handleConn() and handleIncoming()
handleIncoming() winning the race for p.Disconnect() call might lead to nil
error passed as the reason for peer unregistration.
2021-11-01 12:20:55 +03:00
Roman Khimov
2eeec73770 network: don't panic if there is no reason for disconnect
Although error should always be there, we shouldn't fail like this if it's not:
    | panic: runtime error: invalid memory address or nil pointer dereference
    | [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0xc8884c]
    |
    | goroutine 113 [running]:
    | github.com/nspcc-dev/neo-go/pkg/network.(*Server).run(0xc000150580)
    |         github.com/nspcc-dev/neo-go/pkg/network/server.go:396 +0x7ac
    | github.com/nspcc-dev/neo-go/pkg/network.(*Server).Start(0xc000150580, 0x0)
    |         github.com/nspcc-dev/neo-go/pkg/network/server.go:294 +0x3fb
    | created by github.com/nspcc-dev/neo-go/cli/server.startServer
    |         github.com/nspcc-dev/neo-go/cli/server/server.go:344 +0x56f
2021-11-01 12:19:00 +03:00
Roman Khimov
328f8b7954
Merge pull request #2238 from nspcc-dev/fix-block-queue
network: remove priority queue from block queue
2021-11-01 12:03:45 +03:00
Roman Khimov
8bb1ecb45a network: remove priority queue from block queue
Use circular buffer which is a bit more appropriate. The problem is that
priority queue accepts and stores equal items which wastes memory even in
normal usage scenario, but it's especially dangerous if the node is stuck for
some reason. In this case it'll accept from peers and put into queue the same
blocks again and again leaking memory up to OOM condition.

Notice that queue length calculation might be wrong in case circular buffer
wraps, but it's not very likely to happen (usually blocks not coming from the
queue are added by consensus and it's not very fast in doing so).
2021-11-01 11:49:01 +03:00
Evgeniy Stratonikov
7758378d28 compiler: allow to overload methods in manifest
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-29 20:15:21 +03:00
Evgeniy Stratonikov
51127b8918 vmcli: convert base64 string to address in parse
In application logs hashes are serialized as base64 so it is useful
to convert them back to address via `util convert`.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-29 14:55:10 +03:00
Roman Khimov
67eac3a27f
Merge pull request #2196 from nspcc-dev/drop-badger-and-redis
Drop Badger and Redis
2021-10-28 16:08:49 +03:00
AnnaShaleva
3fed7b8eec core: handle empty MPT batch properly
It's OK to have it.
2021-10-27 18:44:39 +03:00
Roman Khimov
1144a03486 storage: drop RedisDB, close #2130 2021-10-27 17:32:25 +03:00
Roman Khimov
fb4b87bb96 storage: drop BadgerDB support, close #2130 2021-10-27 17:31:55 +03:00
Roman Khimov
fdf80dbdc5
Merge pull request #2225 from nspcc-dev/notary/allow-to-combine-witnesses
notary: allow to combine signers of different types
2021-10-26 17:54:07 +03:00
AnnaShaleva
2d196b3f35 rpc: refactor calculatenetworkfee handler
Use (Blockchainer).VerifyWitness() to calculate network fee for
contract-based witnesses.
2021-10-25 19:07:25 +03:00
Anna Shaleva
807fa4a720 services: allow non-empty inv scripts for contract-based notary witness 2021-10-25 17:23:29 +03:00
Evgeniy Stratonikov
4fe188a60d compiler: check correctness of emitted bytecode
The error here indicates a bug in compiler implementation.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-25 13:55:55 +03:00
Evgeniy Stratonikov
a885f84cad compiler: fail if some functions are missing
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-25 13:55:55 +03:00
Evgeniy Stratonikov
8a0429036b compiler: set type information during traversal, fix #2231
Set all necessary context before file traversal, not only import
maps. Also, we can skip restoring import maps because all our code is
processed via `For*` iterators which set necessary context.
We can also refactor this a bit to have all context in one place,
this will be done in #2086.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-25 13:55:55 +03:00
Anna Shaleva
75d7891ca1 services: add ability to combine notary signers
Notes for witnesses:
* [N sig + M multisig + K contract] combination is possible where N, M, K >=0.
* Each verification script should be properly filled in.
* Each invocation script should either be empty or contain exactly one
signature.
2021-10-25 12:22:13 +03:00
Evgeniy Stratonikov
b91de50e65 compiler: remove convert.To* from the list of builtins
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-23 16:16:03 +03:00
Evgeniy Stratonikov
a92bf281c1 compiler: remove custom logic for util builtins
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-23 16:12:47 +03:00
Roman Khimov
6fe8f4565d
Merge pull request #2228 from nspcc-dev/additional-interop
Constants and ABORT in interops
2021-10-22 21:45:57 +03:00
Anna Shaleva
fcc7f7349d services: refactor the logic of notary signatures counting
Maintain the number of signatures left to collect instead of maintaining
the number of already collected signatures and overall number of
signatures.
2021-10-22 17:06:46 +03:00
Roman Khimov
36295357d8 interop: add Abort() function to ABORT things
Related to #2227.
2021-10-22 14:50:51 +03:00
Anna Shaleva
693c376d21 vm: wait more for a test prog execution ending 2021-10-22 12:14:37 +03:00
Roman Khimov
e230040c2e interop: add canonical type lengths as constants
Contracts need them anyway.
2021-10-22 10:56:58 +03:00
Roman Khimov
d551439654
Merge pull request #2193 from nspcc-dev/optimize-find
core: optimise (*MemCachedStorage).Seek
2021-10-21 21:20:33 +03:00
Anna Shaleva
3450371910 core: split (*MemCachedStore) Seek and SeekAsync methods
Use SeekAsync for System.Storage.Find and Seek for the rest of cases.
2021-10-21 10:05:12 +03:00
Anna Shaleva
dcda7bec63 core: squash PS-seeking and merging routines in (*MemCachedStore).Seek
We don't need a separate routine to merge seek results.
2021-10-21 10:05:12 +03:00
Anna Shaleva
c88720bf45 core: remove memstore routine from (*MemCachedStore).SeekAsync
It adds unnecessary overhead to computations.
2021-10-21 10:05:12 +03:00
Anna Shaleva
dfe2c667e1 core: do not hold the lock while seeking over persistent store 2021-10-21 10:05:12 +03:00
Anna Shaleva
07cbe4d253 core: add finalizer functions to interop context
These functions are aimed to free the resources occupied by storage
iterator by the end of script execution or whenever Finilize is called.
2021-10-21 10:05:12 +03:00
Anna Shaleva
0a4f45c9b0 core: add ability to free storage.Iterator resources 2021-10-21 10:05:12 +03:00
Anna Shaleva
89ee2e7720 core: refactor storage.Find and storage.Iterator to work with channel
Add SeekAsync methods in order to fetch matching storage items
on demand. Refactor storage.Find and storage.Iterator wrt these changes.
2021-10-21 10:05:12 +03:00
Anna Shaleva
f2ac07a3c0 core: do not copy key/value results got from MemCachedStore.Seek
They are already copied inside the MemCachedStore.Seek, so that
persistent storage  can't change them anymore.
2021-10-21 10:05:12 +03:00
Anna Shaleva
72726d46d3 core: refactor callers of MemCachedStore.Seek
MemCachedStore.Seek now sorts results, so its callers may omit sorting.
2021-10-21 10:05:12 +03:00
Anna Shaleva
7ba88e98e2 core: optimize (*MemCachedStore).Seek operation
Real persistent storage guarantees that result of Seek is sorted
by keys. The idea of optimisation is to merge two sorted seek
results into one (memStore+persistentStore), so that
(*MemCachedStore).Seek will return sorted list. The only thing
that remains is to sort items got from (*MemoryStore).Seek.
2021-10-21 10:05:12 +03:00
Anna Shaleva
191cc45032 core: sort items in MemoryStore.Seek
MemoryStore is used in a MemCachedStore as a persistent layer in tests.
Further commits suppose that persistent storage returns sorted values
from Seek, so sort the result of MemoryStore.Seek.

Benchmark results for 10000 matching items in MemoryStore compared to
master:
name          old time/op    new time/op    delta
MemorySeek-8     712µs ± 0%    3850µs ± 0%   +440.52%  (p=0.000 n=8+8)

name          old alloc/op   new alloc/op   delta
MemorySeek-8     160kB ± 0%    2724kB ± 0%  +1602.61%  (p=0.000 n=10+8)

name          old allocs/op  new allocs/op  delta
MemorySeek-8     10.0k ± 0%     10.0k ± 0%     +0.24%  (p=0.000 n=10+10)

For details on implementation efficiency see the
https://github.com/nspcc-dev/neo-go/pull/2193#discussion_r722993358.
2021-10-21 10:05:12 +03:00
Anna Shaleva
d8210c0137 core: add benchmarks for iterator.Next, MemCached.Seek, Mem.Seek 2021-10-21 10:05:12 +03:00
Anna Shaleva
8d8071f97e core: distinguish storage.KeyValue and storage.KeyValueExists
We need Exists field for storage batch related code; other cases may go
without Exists, so add new KeyValue structure and refactor related code.
2021-10-21 10:05:12 +03:00
Roman Khimov
b44f9eefb0 rpc: correctly handle RPC invocations with no arguments, fix #2219
In N3 no arguments passed should be treated as empty arguments array not as
missing array of arguments, because the array must be present even for
functions that accept no parameters.
2021-10-16 21:28:43 +03:00
Anna Shaleva
002b5a2c3c core: add Trie.Find compatibility test 2021-10-15 10:28:08 +03:00
Anna Shaleva
55fb221bbb rpc: make getproof work with destroyed contracts
Now it's able to get proof for destroyed contract if the contract wasn't
destroyed before the requested stateroot's height.
2021-10-15 07:06:25 +03:00
Evgeniy Stratonikov
0bc81aecf4 compiler: do not emit code for unused imported functions
Our current algorithm marks function as used if it is called
at least ones, even if the callee function is itself unused.
This commit implements more clever traversal to collect usage
information more precisely.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-13 15:56:07 +03:00
Roman Khimov
2bec43511d
Merge pull request #2207 from nspcc-dev/rpc/gethistoricalstate
rpc: implement `getstate` and `findstates` RPC methods
2021-10-13 15:27:51 +03:00
Anna Shaleva
495aba4174 core: try to collapse traversed Billet part on errStop 2021-10-13 14:47:59 +03:00
Anna Shaleva
360bb220b0 rpc: remove unnecessary base64 encoding
It's default encoding for []byte.
2021-10-13 14:47:59 +03:00
Anna Shaleva
892eadf86d core: mandate passing from as a subprefix for (*Trie).Find
However, we need to distinguish empty subprefix and nil subprefix (no
start specified) to match the C# behaviour.
2021-10-13 14:47:41 +03:00
Anna Shaleva
8e7c76827b core: optimise (*Billet).Traverse and (*Trie).Find
(*Billet).Traverse changes:
1. Get rid of the `offset` argument. We can cut `from` and pass just the
part that remains. This implies that node with path matching `from` will
also be included in the result, so additional check needs to be added to
the callback function.
2. Pass `path` and `from` without search prefix. Append prefix to the
result inside the callback.
3. Remove duplicating code.

(*Trie).Find changes:
1. Properly prepare `from` argument for traversing function. It closly
depends on the `path` argument.
2021-10-13 13:52:33 +03:00
Anna Shaleva
43ac4e1517 rpc: implement findstates RPC handler 2021-10-13 11:41:05 +03:00
Anna Shaleva
7da394fd3f core: check MPT node is not requested twice by StateSync module
This check prevents infinite loop if something goes wrong with MPT nodes
restore process.
2021-10-12 14:08:56 +03:00
Roman Khimov
e2c4b6d393
Merge pull request #2209 from nspcc-dev/vm-exceptions
Catch out-of-bounds exceptions in VM
2021-10-12 09:30:49 +03:00
Roman Khimov
38ba6d735e
Merge pull request #2212 from nspcc-dev/fix-nep17-paging
rpc: use uint64 for timestamp boundaries in GetNEP17Transfers
2021-10-11 17:42:59 +03:00
Anna Shaleva
6eb3cad6d5 rpc: use uint64 for timestamp boundaries in GetNEP17Transfers
Block's timestamp is in milliseconds, so it overflows uint32.
2021-10-11 17:34:05 +03:00
Evgeniy Stratonikov
5c470a6e3d vm: catch out-of-bounds exceptions, fix #2208
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-11 17:28:00 +03:00
Evgeniy Stratonikov
435463e620 vm: allow big string keys in PICKITEM
Because `MaxKeySize` is bigger than integer size, we fail on integer
cast while retreiving items from map. SETITEM is not affected.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-11 17:14:28 +03:00
Anna Shaleva
01143da621 rpc: add getstate RPC handler 2021-10-11 16:43:44 +03:00
Evgeniy Stratonikov
8d562cef99 compiler: allow to use multiple underscores in func arguments
It should still be present in the argument array in VM so just don't
save them in the map.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-09 13:23:11 +03:00
Roman Khimov
fb31a81fd2
Merge pull request #2206 from nspcc-dev/compiler-safe-methods
compiler: check that safe methods exist
2021-10-07 14:53:37 +03:00
Roman Khimov
5ff475383b
Merge pull request #2200 from nspcc-dev/optimize-headers
network: request headers in parallel
2021-10-07 14:51:38 +03:00
Anna Shaleva
c8120a139d core: add MaxKeyLength restrictions to MPT's operations 2021-10-06 16:37:23 +03:00
Evgeniy Stratonikov
cb5b075e7d wallet: do not store file handle
Close immediately after read/write. This can be a bit slower but
we store everything in memory anyway and code size is smaller.
`wallet.Close()` method is now a no-op.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-06 15:29:52 +03:00
Evgeniy Stratonikov
4dd3a0d503 network: request headers in parallel, fix #2158
Do this similarly to how blocks are requested.
See also 4aa1a37.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-06 15:25:54 +03:00
Evgeniy Stratonikov
0c01d89827 compiler: check that safe methods exist
If a method is missing from the manifest, it is most likely a typo
or regression after refactoring. There is no "turn-off" flag
for this error because we can do this precisely.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-06 15:18:58 +03:00
Evgeniy Stratonikov
7b6203d0d4 wallet: allow to open in read-only mode, fix #2182
If wallet was opened via `NewWalletFromFile`, open it as read-only first
and re-open for write if needed.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-10-05 16:25:50 +03:00
Roman Khimov
b4e24bef14
Merge pull request #2202 from nspcc-dev/validatorscount
rpc: add validatorscount to getversion response
2021-09-29 11:55:59 +03:00
Roman Khimov
5a2b77238c rpc: add validatorscount to getversion response
See neo-project/neo-modules#642.
2021-09-28 10:10:26 +03:00
Evgeniy Stratonikov
45976a4111 rpc/response: beautify error message
If `Error.Cause` is nil, omit ugly `%s!<nil>`.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-28 09:57:42 +03:00
Evgeniy Stratonikov
e6aa9b76ee mempool: reword ErrConflict message, fix #2197
Make it more user-friendly.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-28 09:57:42 +03:00
fyrchik
cfeaeb0f07
Merge pull request #2194 from nspcc-dev/fix-config-types
config: fix duration parameter types
2021-09-27 10:20:15 +03:00
Evgeniy Stratonikov
7fa6c8dcf6 config: fix duration parameter types
These parameters denote seconds and are thus unitless integers, not
durations.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-25 13:13:51 +03:00
Anna Shaleva
5c97e0dcf2 rpc: move NotaryRequestEvent to the subscriptions pkg
It is used for subscriptions only, so move it to the subscriptions pkg.
2021-09-24 17:42:59 +03:00
Anna Shaleva
b3ea7504cb subscriptions: add container hash to notification event
External users make use of it. Close #2190.
2021-09-24 17:42:02 +03:00
Roman Khimov
42a9d3d7b8 nef: add Source field
Follow neo-project/neo#2605.
2021-09-24 00:19:37 +03:00
Roman Khimov
c009356b73 core: simplify component flushing in storeBlock
Instead of flushing everything to `cache` and then to `bc.dao`, wrap `bc.dao`
directly for block/tx data and AERs and then flush to it. Block/transactions
are usually processed more quickly than other components, so they easily end
up in `cache` where they directly affect Seek performance for any executing
transaction.

Simple as it is this change improves voter NEO transfer benchmark with 1000
accounts by more than 25%, from ~18500 TPS to ~23500 TPS. It doesn't affect
much other cases.
2021-09-22 17:15:12 +03:00
Roman Khimov
b66bc33cf9 native: short-circuit successive GAS distributions
GAS can only be distributed once in a block for particular address, so it
makes little sense trying to calculate it again and again. This fixes
neo-bench for NEO voter, because without it we get ~2500 TPS for
single-address test and with it it jumps 13-fold to normal values like
~33500.
2021-09-22 17:13:55 +03:00
Anna Shaleva
06d3c21e3f core: remove unused interopnames 2021-09-21 16:43:09 +03:00
Roman Khimov
4743d5aacf
Merge pull request #2181 from nspcc-dev/states-diff_testnet_289026
core: fix NEO balance state handler
2021-09-21 15:39:37 +03:00
Anna Shaleva
c113d682bd core: fix NEO balance state handler
We need to store NEO balance's LastUpdateHeight before GAS mint,
because mint can call onNEP17Payment and onNEP17Payment can call NEO
transfer which also calls GAS mint. Storing balance height allows to
avoid recursion.
2021-09-20 19:23:35 +03:00
Roman Khimov
56dd7b7364
Merge pull request #2177 from nspcc-dev/fix-lint
Replace golint with revive
2021-09-15 17:59:04 +03:00
Roman Khimov
68af14100c
Merge pull request #2174 from nspcc-dev/states-diff_testnet_284177
smartcontract: escape non-ascii characters for manifest.Extra SI
2021-09-15 15:07:25 +03:00
Anna Shaleva
dfc0b25cfe gomod: use nspcc-dev's fork of go-ordered-json
Escape non-ASCII characters while JSON encoding.
2021-09-15 15:01:01 +03:00
Roman Khimov
1480e29548
Merge pull request #2178 from nspcc-dev/fix-oracle-unsupported-code
transaction: fix ContentTypeNotSupported oracle code processing
2021-09-14 18:01:40 +03:00
Roman Khimov
24a3cce1ca
Merge pull request #2169 from nspcc-dev/states-diff_mainnet_131795
core: allow transfer 0 GAS/NEO with zero balance
2021-09-14 17:30:41 +03:00
Roman Khimov
8a440a4016 transaction: fix ContentTypeNotSupported oracle code processing
Fix testnet block 311487 block processing and synchronization errors:
  2021-09-14T15:18:53.611+0300    WARN    peer disconnected       {"addr": "20.198.226.132:20333", "reason": "invalid oracle response code", "peerCount": 10}

Fix 8e9302f40b.
2021-09-14 15:18:38 +03:00
Evgeniy Stratonikov
176b61e317 *: fix linter issues
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-14 14:39:39 +03:00
Evgeniy Stratonikov
918d7e65bf smartcontract: unmarhal null values properly
First we unmarshal `null` to `[]byte`, then we marshal it to the empty
string.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-14 13:28:01 +03:00
Roman Khimov
5209fe1e09
Merge pull request #2173 from nspcc-dev/fix-race
network: fix race in StateSync module tests
2021-09-14 11:57:21 +03:00
Roman Khimov
621478296c
Merge pull request #2161 from nspcc-dev/rpc-get-version
rpc: return protocol parameters in `getversion`, fix #2160
2021-09-13 19:10:43 +03:00
Anna Shaleva
6357af0bb0 network: fix race in TestHandleGetMPTData
Init server config before server start. Fixes the following data race:

```
WARNING: DATA RACE
Write at 0x00c00032ef20 by goroutine 26:
  github.com/nspcc-dev/neo-go/pkg/network.TestHandleGetMPTData.func2()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:755 +0x10a
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1193 +0x202

Previous read at 0x00c00032ef20 by goroutine 24:
  github.com/nspcc-dev/neo-go/internal/fakechain.(*FakeChain).GetConfig()
      /go/src/github.com/nspcc-dev/neo-go/internal/fakechain/fakechain.go:167 +0x6f
  github.com/nspcc-dev/neo-go/pkg/network.(*Server).initStaleMemPools()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server.go:1433 +0x89
  github.com/nspcc-dev/neo-go/pkg/network.(*Server).Start()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server.go:284 +0x288
  github.com/nspcc-dev/neo-go/pkg/network.startWithChannel.func1()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:91 +0x44

Goroutine 26 (running) created at:
  testing.(*T).Run()
      /usr/local/go/src/testing/testing.go:1238 +0x5d7
  github.com/nspcc-dev/neo-go/pkg/network.TestHandleGetMPTData()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:752 +0x8c
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1193 +0x202

Goroutine 24 (running) created at:
  github.com/nspcc-dev/neo-go/pkg/network.startWithChannel()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:90 +0x78
  github.com/nspcc-dev/neo-go/pkg/network.startTestServer()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:384 +0xbd
  github.com/nspcc-dev/neo-go/pkg/network.TestHandleGetMPTData.func2()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:753 +0x55
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1193 +0x202
```
2021-09-13 11:45:48 +03:00
Anna Shaleva
29ef076f4b network: fix race in TestTryInitStateSync
Register peers properly. Fixes the following data race:
```
Read at 0x00c001184ac8 by goroutine 116:
  github.com/nspcc-dev/neo-go/pkg/network.(*localPeer).EnqueueHPPacket()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/helper_test.go:127 +0x1f2
  github.com/nspcc-dev/neo-go/pkg/network.(*localPeer).EnqueuePacket()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/helper_test.go:114 +0xac
  github.com/nspcc-dev/neo-go/pkg/network.(*localPeer).EnqueueMessage()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/helper_test.go:111 +0xc1
  github.com/nspcc-dev/neo-go/pkg/network.(*localPeer).SendPing()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/helper_test.go:159 +0x88
  github.com/nspcc-dev/neo-go/pkg/network.(*Server).runProto()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server.go:446 +0x409

Previous write at 0x00c001184ac8 by goroutine 102:
  github.com/nspcc-dev/neo-go/pkg/network.newLocalPeer()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/helper_test.go:83 +0x476
  github.com/nspcc-dev/neo-go/pkg/network.TestTryInitStateSync.func3()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:1064 +0x40f
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1123 +0x202

Goroutine 116 (running) created at:
  github.com/nspcc-dev/neo-go/pkg/network.(*Server).run()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server.go:358 +0x69
  github.com/nspcc-dev/neo-go/pkg/network.(*Server).Start()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server.go:292 +0x488
  github.com/nspcc-dev/neo-go/pkg/network.startWithChannel.func1()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:91 +0x44

Goroutine 102 (running) created at:
  testing.(*T).Run()
      /usr/local/go/src/testing/testing.go:1168 +0x5bb
  github.com/nspcc-dev/neo-go/pkg/network.TestTryInitStateSync()
      /go/src/github.com/nspcc-dev/neo-go/pkg/network/server_test.go:1056 +0xbb
  testing.tRunner()
      /usr/local/go/src/testing/testing.go:1123 +0x202
```
2021-09-13 11:45:48 +03:00
Evgeniy Stratonikov
8a3e05096b *: gofmt -s
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-10 21:49:11 +03:00
Evgeniy Stratonikov
c465b18cb2 rpc: return protocol parameters in getversion, fix #2160
`StateRootInHeader` is duplicated similarly to `Network`.
It will be removed in future as it is surely a protocol parameter.

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-10 21:45:59 +03:00
Roman Khimov
63e00ac128
Merge pull request #2166 from nspcc-dev/fix-nns-compat
Fix NNS compatibility
2021-09-10 18:10:17 +03:00
Anna Shaleva
7fc57c9d58 core: allow transfer 0 GAS/NEO with zero balance
This commit fixes states diff at 131795 block of mainnet.

Transaction:
```
NEO-GO-VM > loadbase64 DAAQDBSPsxdYh6cITC3gUKI4oWmYxJs49gwUj7MXWIenCEwt4FCiOKFpmMSbOPYUwB8MCHRyYW5zZmVyDBT1Y+pAvCg9TQ4FxI6jBbPyoHNA70FifVtSOQwAEQwUj7MXWIenCEwt4FCiOKFpmMSbOPYMFL1Mb4Fqp6gHiEwzM6xSc8fLS+RpFMAfDAh0cmFuc2ZlcgwU9WPqQLwoPU0OBcSOowWz8qBzQO9BYn1bUjk=
READY: loaded 176 instructions
NEO-GO-VM 0 > ops
INDEX    OPCODE       PARAMETER
0        PUSHDATA1     ("")                                       <<
2        PUSH0
3        PUSHDATA1    8fb3175887a7084c2de050a238a16998c49b38f6
25       PUSHDATA1    8fb3175887a7084c2de050a238a16998c49b38f6
47       PUSH4
48       PACK
49       PUSH15
50       PUSHDATA1    7472616e73666572 ("transfer")
60       PUSHDATA1    f563ea40bc283d4d0e05c48ea305b3f2a07340ef    // NEO token
82       SYSCALL      System.Contract.Call (627d5b52)
87       ASSERT
88       PUSHDATA1     ("")
90       PUSH1
91       PUSHDATA1    8fb3175887a7084c2de050a238a16998c49b38f6
113      PUSHDATA1    bd4c6f816aa7a807884c3333ac5273c7cb4be469
135      PUSH4
136      PACK
137      PUSH15
138      PUSHDATA1    7472616e73666572 ("transfer")
148      PUSHDATA1    f563ea40bc283d4d0e05c48ea305b3f2a07340ef    // NEO token
170      SYSCALL      System.Contract.Call (627d5b52)
175      ASSERT

```

Go's applog:
```
{
   "id" : 1,
   "result" : {
      "txid" : "0x97d2ccb01467b22c73a2cb95f7af298f3a5bd8c849d7044371898b8efecdaabd",
      "executions" : [
         {
            "exception" : "at instruction 87 (ASSERT): ASSERT failed",
            "stack" : [],
            "gasconsumed" : "4988995",
            "notifications" : [],
            "trigger" : "Application",
            "vmstate" : "FAULT"
         }
      ]
   },
   "jsonrpc" : "2.0"
}
```

C#'s applog:
```
{
   "jsonrpc" : "2.0",
   "result" : {
      "executions" : [
         {
            "stack" : [],
            "notifications" : [
               {
                  "contract" : "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5",
                  "state" : {
                     "type" : "Array",
                     "value" : [
                        {
                           "type" : "ByteString",
                           "value" : "j7MXWIenCEwt4FCiOKFpmMSbOPY="
                        },
                        {
                           "type" : "ByteString",
                           "value" : "j7MXWIenCEwt4FCiOKFpmMSbOPY="
                        },
                        {
                           "value" : "0",
                           "type" : "Integer"
                        }
                     ]
                  },
                  "eventname" : "Transfer"
               },
               {
                  "contract" : "0xd2a4cff31913016155e38e474a2c06d08be276cf",
                  "state" : {
                     "value" : [
                        {
                           "type" : "Any"
                        },
                        {
                           "type" : "ByteString",
                           "value" : "vUxvgWqnqAeITDMzrFJzx8tL5Gk="
                        },
                        {
                           "value" : "2490",
                           "type" : "Integer"
                        }
                     ],
                     "type" : "Array"
                  },
                  "eventname" : "Transfer"
               },
               {
                  "contract" : "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5",
                  "state" : {
                     "value" : [
                        {
                           "value" : "vUxvgWqnqAeITDMzrFJzx8tL5Gk=",
                           "type" : "ByteString"
                        },
                        {
                           "value" : "j7MXWIenCEwt4FCiOKFpmMSbOPY=",
                           "type" : "ByteString"
                        },
                        {
                           "value" : "1",
                           "type" : "Integer"
                        }
                     ],
                     "type" : "Array"
                  },
                  "eventname" : "Transfer"
               }
            ],
            "vmstate" : "HALT",
            "gasconsumed" : "9977990",
            "trigger" : "Application",
            "exception" : null
         }
      ],
      "txid" : "0x97d2ccb01467b22c73a2cb95f7af298f3a5bd8c849d7044371898b8efecdaabd"
   },
   "id" : 1
}

```
2021-09-10 17:18:09 +03:00
Roman Khimov
aaccf748ac nft-nd-nns: add getAllRecords method
See neo-project/non-native-contracts#5.
2021-09-10 16:30:45 +03:00
Roman Khimov
c4637514d4
Merge pull request #2165 from nspcc-dev/rpc/audit
rpc: request handlers audit
2021-09-10 13:16:40 +03:00
Anna Shaleva
b989fdb462 rpc: fill transaction witnesses during invokescript handling 2021-09-10 11:38:59 +03:00
Anna Shaleva
61fd7bd6ba core: avoid nil values during natives manifest marshalling 2021-09-10 11:38:59 +03:00
Anna Shaleva
61faf28738 rpc: avoid null unverified transactions in getrawmempool response 2021-09-10 11:38:59 +03:00
Anna Shaleva
ed9cdfe667 rpc: use core Header for getblockheader response
Nonce and Primary fields were missing from response.
2021-09-09 18:47:22 +03:00
Anna Shaleva
db13362e86 core: marshal Block.Nonce in upper-case hex 2021-09-09 15:52:51 +03:00
Anna Shaleva
3b04b6d238 vm: refactor stack dump commands 2021-09-09 13:45:10 +03:00
Anna Shaleva
6da458365d vm CLI: allow to dump slots 2021-09-09 13:45:10 +03:00
Roman Khimov
b502c5f148
Merge pull request #2162 from nspcc-dev/docs/update
docs: minor documentation updates and adjustments
2021-09-09 12:38:20 +03:00
Anna Shaleva
2f23d83a49 interop: adjust documentation 2021-09-08 17:53:09 +03:00
Anna Shaleva
df8141ff7d rpc: adjust client documentation 2021-09-08 17:53:09 +03:00
Anna Shaleva
913e3878c5 vm CLI: check whether VM is ready before jumping to the instruction
It allows to avoid panic:
```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0xdab469]

goroutine 1 [running]:
github.com/nspcc-dev/neo-go/pkg/vm.(*VM).Jump(...)
	github.com/nspcc-dev/neo-go/pkg/vm/vm.go:1506
github.com/nspcc-dev/neo-go/pkg/vm/cli.handleRun(0xc0005988f0)
	github.com/nspcc-dev/neo-go/pkg/vm/cli/cli.go:413 +0x2e9
github.com/abiosoft/ishell/v2.(*Shell).handleCommand(0xc0004320f0, {0xc00032c7c0, 0xc0002a3920, 0x0})
	github.com/abiosoft/ishell/v2@v2.0.2/ishell.go:279 +0x143
github.com/abiosoft/ishell/v2.handleInput(0xc0004320f0, {0xc00032c7c0, 0x3, 0x4})
	github.com/abiosoft/ishell/v2@v2.0.2/ishell.go:233 +0x31
github.com/abiosoft/ishell/v2.(*Shell).run(0xc0004320f0)
	github.com/abiosoft/ishell/v2@v2.0.2/ishell.go:212 +0x30f
github.com/abiosoft/ishell/v2.(*Shell).Run(0xc0004320f0)
	github.com/abiosoft/ishell/v2@v2.0.2/ishell.go:112 +0x28
github.com/nspcc-dev/neo-go/pkg/vm/cli.(*VMCLI).Run(0xc000224030)
	github.com/nspcc-dev/neo-go/pkg/vm/cli/cli.go:538 +0x39
github.com/nspcc-dev/neo-go/cli/vm.startVMPrompt(0xc0001f46e0)
	github.com/nspcc-dev/neo-go/cli/vm/vm.go:28 +0xb4
github.com/urfave/cli.HandleAction({0xe65fa0, 0x1161c68}, 0x2)
	github.com/urfave/cli@v1.22.5/app.go:524 +0xa8
github.com/urfave/cli.Command.Run({{0xfed435, 0x2}, {0x0, 0x0}, {0x0, 0x0, 0x0}, {0x100576d, 0x19}, {0x0, ...}, ...}, ...)
	github.com/urfave/cli@v1.22.5/command.go:173 +0x652
github.com/urfave/cli.(*App).Run(0xc0001016c0, {0xc0000c6000, 0x2, 0x2})
	github.com/urfave/cli@v1.22.5/app.go:277 +0x705
main.main()
	./main.go:19 +0x33
```
2021-09-08 17:53:09 +03:00
Anna Shaleva
cbc75afd4d docs: refactor documentation
CLI:
* Typos are fixed
* Documentation on NEP-11 tokens is added
* NeoGo node configuration is moved to a separate file

Compiler:
* Typos and indentations are fixed
* Ops dump example is updated

Consensus:
* Typos are fixed
* Links are fixed

Notifications:
* Minor adjustments

RPC:
* `getversion` response is updated
* `getunclamedgas` comment is removed (not valid since
https://github.com/neo-project/neo-modules/pull/243)

VM:
* Update help message
* `load*` command adjustments
* `astack` command removal
2021-09-08 17:52:46 +03:00
Anna Shaleva
0fa48691f7 network: do not duplicate MPT nodes in GetMPTNodes response
Also tests are added.
2021-09-08 14:25:54 +03:00
Anna Shaleva
51c8c0d82b core: add tests for StateSync module 2021-09-07 19:43:27 +03:00
Anna Shaleva
0aedfd0038 core: fix bug in MPT pool during Update
We need to copy the result of `TryGet` method, otherwice the slice can
be modified inside `Add` or `Update` methods, which leads to
inconsistent MPT pool state.
2021-09-07 19:43:27 +03:00
Anna Shaleva
36808b8904 core: clone MPT node while restoring it multiple times
We need this to avoid collapse collisions. Example of such collapse
described in
https://github.com/nspcc-dev/neo-go/pull/2019#discussion_r689629704.
2021-09-07 19:43:27 +03:00
Anna Shaleva
5cd78c31af core: allow to recover after state jump interruption
We need several stages to manage state jump process in order not to mess
up old and new contract storage items and to be sure about genesis state data
are properly removed from the storage. Other operations do not require
separate stage and can be performed each time `jumpToStateInternal` is
called.
2021-09-07 19:43:27 +03:00
Anna Shaleva
5cda24b3af core: initialize headers before current block 2021-09-07 19:43:27 +03:00
Anna Shaleva
0e0b55350a core: convert (*Blockchain).JumpToState to a callback
We don't need this method to be exposed, the only its user is the
StateSync module. At the same time StateSync module manages its state by
itself which guarantees that (*Blockchain).jumpToState will be called
with proper StateSync stage.
2021-09-07 19:43:27 +03:00
Anna Shaleva
6381173293 core: store statesync-related storage items under temp prefix
State jump should be an atomic operation, we can't modify contract
storage items state on-the-fly. Thus, store fresh items under temp
prefix and replase the outdated ones after state sync is completed.
Related
https://github.com/nspcc-dev/neo-go/pull/2019#discussion_r693350460.
2021-09-07 19:43:27 +03:00
Anna Shaleva
51f405471e core: remove outdated blocks/txs/AERs/MPT nodes during state sync
Before state sync process can be started, outdated MPT nodes
should be removed from storage. After state sync is completed,
outdated blocks/transactions/AERs should also be removed.
2021-09-07 19:43:27 +03:00
Anna Shaleva
a276a85b72 core: unify code of state sync module initialization 2021-09-07 19:43:27 +03:00
Anna Shaleva
3b7807e897 network: request unknown MPT nodes
In this commit:

1. Request unknown MPT nodes from peers. Note, that StateSync module itself
shouldn't be responsible for nodes requests, that's a server duty.
2. Do not request the same node twice, check if it is in storage
already. If so, then the only thing remaining is to update refcounter.
2021-09-07 19:43:27 +03:00
Anna Shaleva
6a04880b49 core: collapse completed parts of Billet
Some kind of marker is needed to check whether node has been collapsed
or not. So introduce (HashNode).Collapsed
2021-09-07 19:43:27 +03:00
Anna Shaleva
74f1848d19 core: adjust LastUpdatedBlock calculation for NEP17 balances
...wrt P2PStateExchange setting.
2021-09-07 19:43:27 +03:00
Anna Shaleva
d67ff30704 core: implement statesync module
And support GetMPTData and MPTData P2P commands.
2021-09-07 19:43:27 +03:00
Anna Shaleva
a22b1caa3e core: implement MPT Billet structure for MPT restore
MPT restore process is much simpler then regular MPT maintaining: trie
has a fixed structure, we don't need to remove or rebuild MPT nodes. The
only thing we should do is to replace Hash nodes to their unhashed
counterparts and increment refcount. It's better not to touch the
regular MPT code and create a separate structure for this.
2021-09-07 19:43:27 +03:00
Roman Khimov
c9e62769a6
Merge pull request #2143 from nspcc-dev/mpt/add_empty_values
core: allow empty MPT Leaf values
2021-09-07 09:18:48 +03:00
Anna Shaleva
c95f2079d5 core: adjust comments on behaviour defferences for MPT TestCompatibility
C# node does not return empty proof enymore in case if path is bad. C#
node also throws an exception on bad Put.

Our node does not return an error on delete if the key is empty.
2021-09-03 13:46:52 +03:00
Anna Shaleva
f721384ead core: allow empty MPT Leaf values
Allow it for (*Trie).Put. And distinguish empty value and nil value for
(*Trie).PutBatch, because batch is already capable of handling both nil
and empty value. For (*Trie).PutBatch putting nil value means deletion,
while putting empty value means just putting LeafNode with an empty
value.
2021-09-03 13:46:48 +03:00
Evgeniy Stratonikov
7371593bdc native/policy: disallow blocking native contracts
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-03 11:11:06 +03:00
Evgeniy Stratonikov
9d34547118 rpc/client: add MaxConnsPerHost option, fix #2149
Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
2021-09-02 11:26:17 +03:00
Roman Khimov
b07347e602 core: reuse PushItem for interops
Probably less critical here, but still let's push things faster.
2021-08-30 23:43:58 +03:00
Roman Khimov
a3892aa662 vm: don't use PushVal when item type is known
PushVal is very convenient, but type switch is somewhat expensive.

name                    old time/op    new time/op    delta
ScriptFibonacci-8          736µs ± 1%     602µs ± 1%  -18.21%  (p=0.000 n=9+10)
ScriptNestedRefCount-8    1.08ms ± 2%    0.96ms ± 1%  -11.13%  (p=0.000 n=10+10)
ScriptPushPop/4-8         1.48µs ± 3%    1.35µs ± 2%   -9.14%  (p=0.000 n=10+9)
ScriptPushPop/16-8        3.59µs ± 1%    3.38µs ± 1%   -6.01%  (p=0.000 n=10+10)
ScriptPushPop/128-8       23.7µs ± 1%    22.6µs ± 1%   -4.39%  (p=0.000 n=10+8)
ScriptPushPop/1024-8       176µs ± 2%     167µs ± 3%   -5.24%  (p=0.000 n=9+10)

name                    old alloc/op   new alloc/op   delta
ScriptFibonacci-8          123kB ± 0%     114kB ± 0%   -6.88%  (p=0.000 n=10+9)
ScriptNestedRefCount-8     266kB ± 0%     241kB ± 0%   -9.23%  (p=0.000 n=8+10)
ScriptPushPop/4-8           160B ± 0%      160B ± 0%     ~     (all equal)
ScriptPushPop/16-8          640B ± 0%      640B ± 0%     ~     (all equal)
ScriptPushPop/128-8       8.70kB ± 0%    8.70kB ± 0%     ~     (all equal)
ScriptPushPop/1024-8      73.2kB ± 0%    73.2kB ± 0%     ~     (all equal)

name                    old allocs/op  new allocs/op  delta
ScriptFibonacci-8          3.53k ± 0%     3.17k ± 0%   -9.98%  (p=0.000 n=10+10)
ScriptNestedRefCount-8     11.8k ± 0%     10.7k ± 0%   -8.70%  (p=0.000 n=10+10)
ScriptPushPop/4-8           8.00 ± 0%      8.00 ± 0%     ~     (all equal)
ScriptPushPop/16-8          32.0 ± 0%      32.0 ± 0%     ~     (all equal)
ScriptPushPop/128-8          259 ± 0%       259 ± 0%     ~     (all equal)
ScriptPushPop/1024-8       2.05k ± 0%     2.05k ± 0%     ~     (all equal)
2021-08-30 23:43:58 +03:00
Roman Khimov
bc31c97c32 vm: simplify access to context, don't call Context() twice
Avoid going through Value(), avoid doing type casts twice for every
instruction.

name                    old time/op    new time/op    delta
ScriptFibonacci-8          793µs ± 3%     736µs ± 1%  -7.18%  (p=0.000 n=10+9)
ScriptNestedRefCount-8    1.09ms ± 1%    1.08ms ± 2%  -0.96%  (p=0.035 n=10+10)
ScriptPushPop/4-8         1.51µs ± 3%    1.48µs ± 3%    ~     (p=0.072 n=10+10)
ScriptPushPop/16-8        3.76µs ± 1%    3.59µs ± 1%  -4.56%  (p=0.000 n=10+10)
ScriptPushPop/128-8       25.0µs ± 1%    23.7µs ± 1%  -5.28%  (p=0.000 n=10+10)
ScriptPushPop/1024-8       184µs ± 1%     176µs ± 2%  -4.22%  (p=0.000 n=9+9)
2021-08-30 23:43:58 +03:00
Roman Khimov
e09a0f3969 vm: don't allocate for break points in NewContext
They're rarely used and when they're used they're appended to.
2021-08-29 13:15:12 +03:00
Roman Khimov
7b9558d756
Merge pull request #2142 from nspcc-dev/fix-customgroups-witness-scope
runtime: fix CustomGroups witness
2021-08-26 18:13:08 +03:00