Commit graph

2234 commits

Author SHA1 Message Date
Roman Khimov
6be757af3e
Merge pull request #3444 from nspcc-dev/fix-native-init
native: perform initialisation for the set of hardforks
2024-05-17 16:34:00 +03:00
Anna Shaleva
c90f6785b9 native: perform initialisation for the set of hardforks
Close #3433.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-17 15:58:02 +03:00
Anna Shaleva
82a7c1bd9c native: adjust test helper behaviour
Supply the account with expected balance.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-17 12:33:59 +03:00
Anna Shaleva
c43cfae24c native: fix Policy's IsBlocked behaviour
Account is blocked when it's in the Policy's storage, not when it's
missing from the Policy storage. Introduced in
bbbc6805a8.

This bug leads to the fact that during native Neo cache initialization
at the last block in the dBFT epoch, all candidates accounts are
"blocked", and thus, stand-by committee and validators are used in the
subsequent new epoch. Close #3424.

This bug may lead to the consequences described in #3273, but it needs
to be confirmed.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-17 12:33:51 +03:00
Anna Shaleva
647b8c7fb1
Merge pull request #3439 from nspcc-dev/getnativecontracts
state: drop NativeContract, fix #3430
2024-05-17 10:23:45 +03:00
Roman Khimov
0b69901d1e
Merge pull request #3441 from nspcc-dev/boltdb-clone 2024-05-16 19:49:11 +03:00
Roman Khimov
502f024e7c storage: bytes.Clone(nil) == nil
Signed-off-by: Roman Khimov <roman@nspcc.ru>
2024-05-16 19:29:11 +03:00
Roman Khimov
b1bb12df48 state: drop NativeContract, fix #3430
This unifies getnativecontracts RPC API with regular contracts.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
2024-05-16 18:46:46 +03:00
Anna Shaleva
dc8b2f639a dao: do not remove block executable by conflict record stub
It's possible for transaction to include block hash into Conflicts
attribure. If so, then we must not remove block executable record while
cleaning transation's conflict records.

This commit is a direct consequence of
e6ceee0f230a21c87006a9297636be29c0d8ea47. Ref. #3427.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-16 12:13:41 +03:00
Anna Shaleva
2ad4c86712 dao: move conflict record value length to a separate const
Conflicts-related code contains more and more these magic numbers, and
there's no good in it even if all the usages are commented. This
approach produces bugs like #3426.

No functional changes, just a refactoring.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-16 12:13:41 +03:00
Anna Shaleva
9a1075d332 dao: fix transaction application log decoding
Conflict record stub has value of 5 bytes length: 1 byte for
storage.ExecTransaction prefix and 4 bytes for the block index LE. This
scheme was implemented in #3138, and this commit should be a part of
this PR.

Also, transaction.DummyVersion is removed since it's unused anymore.

Close #3426. The reason of `failed to locate application log: EOF` error
during genesis AER request is in the following: genesis executable was
overwritten by conflict record stub produced by transaction
0x289c235dcdab8be7426d05f0fbb5e86c619f81481ea136493fa95deee5dbb7cc (ref.
 #3427). As a consequence, an attempt to decode transaction AER was
initited, but conflict record scheme was changed in #3138.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-16 12:13:41 +03:00
Anna Shaleva
58a086ea91 core: allow transaction to conflict with block
Transaction
0x289c235dcdab8be7426d05f0fbb5e86c619f81481ea136493fa95deee5dbb7cc is
already on mainnet at block 5272006 and we can't do anything with it.
This transaction has genesis block hash in Conflicts attribute. It leads
to the following consequences:
1. Genesis block executable record is overwritten by conflict record
   stub. Genesis block can't be retrieved anymore. This bug is described
   in #3427.
2. Somehow this transaction has passed verification on NeoGo CN without
   any warnings:
```
Apr 24 16:12:30 kangra neo-go[2453907]: 2024-04-24T16:12:30.865+0300        INFO        initializing dbft        {"height": 5272006, "view": 0, "index": 6, "role": "Backup"}
Apr 24 16:12:31 kangra neo-go[2453907]: 2024-04-24T16:12:31.245+0300        INFO        persisted to disk        {"blocks": 1, "keys": 37, "headerHeight": 5272005, "blockHeight": 5272005, "took": "14.548903ms"}
Apr 24 16:12:34 kangra neo-go[2453907]: 2024-04-24T16:12:34.977+0300        ERROR        can't add SV-signed state root        {"error": "stateroot mismatch at block 5272005: 9d5f95784f26c862d6f889f213aad1e3330611880c02330e88db8802c750aa46 vs d25304d518645df725014897d13bbf023919928e79074abcea48f31cf9f32a25"}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.820+0300        INFO        received PrepareRequest        {"validator": 5, "tx": 1}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.821+0300        INFO        sending PrepareResponse        {"height": 5272006, "view": 0}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.827+0300        INFO        received PrepareResponse        {"validator": 4}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.830+0300        INFO        received PrepareResponse        {"validator": 3}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.875+0300        INFO        received PrepareResponse        {"validator": 2}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.878+0300        INFO        sending Commit        {"height": 5272006, "view": 0}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.879+0300        INFO        received Commit        {"validator": 4}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.881+0300        INFO        received PrepareResponse        {"validator": 0}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.881+0300        INFO        received Commit        {"validator": 3}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.906+0300        INFO        received Commit        {"validator": 0}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.907+0300        INFO        received PrepareResponse        {"validator": 1}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.915+0300        INFO        received Commit        {"validator": 1}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.915+0300        INFO        approving block        {"height": 5272006, "hash": "6b111519537343ce579d04ccad71c43318b12c680d0f374dfcd466aa22643fb6", "tx_count": 1, "merkle": "ccb7dbe5ee5da93f4936a11e48819f616ce8b5fbf0056d42e78babcd5d239c28", "prev": "12ad6cc5d0cd357b9fc9fb0c1a016ba8014d3cdd5a96818598e6a40a1a4a2a21"}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.917+0300        WARN        contract invocation failed        {"tx": "289c235dcdab8be7426d05f0fbb5e86c619f81481ea136493fa95deee5dbb7cc", "block": 5272006, "error": "at instruction 86 (ASSERT): ASSERT failed"}
Apr 24 16:12:45 kangra neo-go[2453907]: 2024-04-24T16:12:45.950+0300        INFO        initializing dbft        {"height": 5272007, "view": 0, "index": 6, "role": "Primary"}
Apr 24 16:12:46 kangra neo-go[2453907]: 2024-04-24T16:12:46.256+0300        INFO        persisted to disk        {"blocks": 1, "keys": 67, "headerHeight": 5272006, "blockHeight": 5272006, "took": "16.576594ms"}
```
   And thus, we must treat this transaction as valid for this behaviour
   to be reproducable.

This commit contains two fixes:
1. Do not overwrite block executable records by conflict record stubs.
   If some transaction conflicts with block, then just skip the conflict
   record stub for this attribute since it's impossible to create
   transaction with the same hash.
2. Do not fail verification for those transactions that have Conflicts
   attribute with block hash inside. This one is controversial, but we
   have to adjust this code to treat already accepted transaction as
   valid.

Close #3427.

The transaction itself:
```
{
   "id" : 1,
   "jsonrpc" : "2.0",
   "result" : {
      "attributes" : [
         {
            "height" : 0,
            "type" : "NotValidBefore"
         },
         {
            "hash" : "0x1f4d1defa46faa5e7b9b8d3f79a06bec777d7c26c4aa5f6f5899a291daa87c15",
            "type" : "Conflicts"
         }
      ],
      "blockhash" : "0xb63f6422aa66d4fc4d370f0d682cb11833c471adcc049d57ce4373531915116b",
      "blocktime" : 1713964365700,
      "confirmations" : 108335,
      "hash" : "0x289c235dcdab8be7426d05f0fbb5e86c619f81481ea136493fa95deee5dbb7cc",
      "netfee" : "237904",
      "nonce" : 0,
      "script" : "CxAMFIPvkoyXujYCRmgq9qEfMJQ4wNveDBSD75KMl7o2AkZoKvahHzCUOMDb3hTAHwwIdHJhbnNmZXIMFPVj6kC8KD1NDgXEjqMFs/Kgc0DvQWJ9W1I5",
      "sender" : "NbcGB1tBEGM5MfhNbDAimvpJKzvVjLQ3jW",
      "signers" : [
         {
            "account" : "0x649ca095e38a790d6c15ff78e0c6175099b428ac",
            "scopes" : "None"
         },
         {
            "account" : "0xdedbc03894301fa1f62a68460236ba978c92ef83",
            "scopes" : "None"
         }
      ],
      "size" : 412,
      "sysfee" : "997778",
      "validuntilblock" : 5277629,
      "version" : 0,
      "vmstate" : "FAULT",
      "witnesses" : [
         {
            "invocation" : "DECw8XNuyRg5vPeHxisQXlZ7VYNDxxK4xEm8zwpPyWJSSu+JaRKQxdrlPkXxXj34wc4ZSrZvKICGgPFE0ZHXhLPo",
            "verification" : "DCEC+PI2tRSlp0wGwnjRuQdWdI0tBXNS7SlzSBBHFsaKUsdBVuezJw=="
         },
         {
            "invocation" : "DEAxwi97t+rg9RsccOUzdJTJK7idbR7uUqQp0/0/ob9FbuW/tFius3/FOi82PDZtwdhk7s7KiNM/pU7vZLsgIbM0",
            "verification" : "DCEDbInkzF5llzmgljE4HSMvtrNgPaz73XO5wgVJXLHNLXRBVuezJw=="
         }
      ]
   }
}
```

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-16 12:13:41 +03:00
Anna Shaleva
59c98c4d09 core: always warn if accepted transaction fails verification
These warnings must be monitored by developers since it might be a sign
of behaviour difference between Go and C# nodes.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-16 12:13:40 +03:00
Anna Shaleva
0aecddea10 native: autogenerate nativehashes package
Ref.
https://github.com/nspcc-dev/neo-go/pull/3402#discussion_r1577879141.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-14 09:39:53 +03:00
Anna Shaleva
6e0926e59f native: adjust NamedCurveHash values
Use 122 and 123 respectively for Secp256k1Keccak256 and
Secp256r1Keccak256, ref.
https://github.com/neo-project/neo/pull/3209#issuecomment-2095798056.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 10:10:56 +03:00
Anna Shaleva
988440949b native: reduce callflag scope for Koblitz verification scripts
callflag.All is too wide.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Roman Khimov
701ea8d5f3 native: use ABORT in Koblitz multisig
Make the script a bit shorter. ABORTMSG would cost a bit more.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Roman Khimov
3d1e33a502 native: make multisig koblitz easier to parse
1. Make prologue be exactly the same as regular CheckMultisig.
2. But instead of "SYSCALL System.Crypto.CheckMultisig" do INITSLOT and K check.
3. This makes all of the code from INITSLOT below be independent of N/M, so
   one can parse the script beginning in the same way CheckMultisig is parsed and
   then just compare the rest of it with some known-good blob.
4. The script becomes a tiny bit larger now, but properties above are too good.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Anna Shaleva
5053a073f9 rpcsrv: test calculatenetworkfee with custom Koblitz-based witness
Value calculated by calculatenetworkfee is enough to pass the real
tx verification. However, network fee may be decreased, so calculations
are not quite accurate. Need to investigate, why.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Anna Shaleva
71aa32406d native: add test for multisignature Koblitz witness verification
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Anna Shaleva
3acb132e9a native: add preferable method to TestCryptoLib_KoblitzVerificationScript
It's based on the constant-length network magic, ref.
https://github.com/nspcc-dev/neo-go/pull/3425#discussion_r1582068061.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:42 +03:00
Anna Shaleva
34eef47a18 native: extend CryptoLib's verifyWithECDsa with hasher parameter
Replace native CryptoLib's verifyWithECDsa `curve` parameter by
`curveHash` parameter which is a enum over supported pairs of named
curves and hash functions.

Even though this change is a compatible extension of the protocol, it
changes the genesis state due to parameter renaming. But we're going to
resync chain in 3.7 release anyway, so it's not a big deal.

Also, we need to check mainnet and testnet compatibility in case if
anyone has ever called verifyWithECDsa with 24 or 25 `curve` value.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:33:41 +03:00
Anna Shaleva
7995229f6b native: add test for custom Koblitz witness verification script
Every single thing is already implemented in the protocol for Koblitz
verification scripts.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-05-13 09:27:42 +03:00
Roman Khimov
b21db99747
Merge pull request #3402 from nspcc-dev/native-upd
native: implement HF-based update
2024-05-10 11:53:55 +03:00
Ekaterina Pavlova
956fd08adb *: add Copy() to transaction.Transaction and payload.P2PNotaryRequest
Add a method that makes a deep copy of all fields and resets size/hash
caches.

Close #3288

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-04-28 00:59:15 +05:30
Ekaterina Pavlova
df2a56908b core: move transaction Attribute value to a designated interface
Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-04-26 21:40:23 +05:30
Anna Shaleva
9b8d579bce core: add unit tests for HF-based native contracts update
A part of #3213.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
36e128516b core: add nativenames.All list
It's useful to keep the ordered set of native contract names.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
4ca2686583 core: distinguish empty Hardforks map from nil
Ensure that Blockchain constructor is able to distinguish empty
Hardforks map (no hardforks should be enabled) from nil hardforks map
(the default value should be used in this case, i.e. all hardforks
should be active from genesis).

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
235f4398c6 native: make Oracle service handle native Oracle updates
A part of #3213.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
ec6fc54bc6 *: use nativehashes package where possible
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
2d3d52e3d0 native: add nativehashes package
Similar to nativenames, instantiate once and then reuse everywhere.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
82993dab2b core: extend error message for contract state check
It will give us a clue on what's wrong with contract states if something
unexpected happen.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
5c75ee13d0 config, native: introduce Cockatrice hard-fork
With all associated native API changes ported from
https://github.com/neo-project/neo/pull/2925 and
https://github.com/neo-project/neo/pull/3154.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
3a2e301267 native: make HF-specific MD cache less lazy
Initialize all necessary HF-specific contract descriptors once during
contract construction.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
d74dc368e0 core: unexport generic native contract methods and events
External users should use HF-specific methods and events.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:54 +03:00
Anna Shaleva
73c742a466 native: emit Deploy/Update notifications on native deploy/update
Ported as a part of https://github.com/neo-project/neo/pull/2942.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:26:53 +03:00
Anna Shaleva
d62fad1268 native: implement HF-based update
A part of #3213.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-04-25 13:16:42 +03:00
Ekaterina Pavlova
fcbfc3b807 native: adjust error message for ExecFeeFactor and StoragePrice
Close #3311

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-04-09 01:51:03 +03:00
Anna Shaleva
627a0abb57
Merge pull request #3371 from nspcc-dev/upd-dbft
consensus: integrate dBFT pre-0.2.0
2024-03-25 19:54:05 +03:00
Anna Shaleva
3e6dfff503 consensus: fetch dbft pre-0.2.0 version
Try out updated dBFT interface.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-03-25 19:21:50 +03:00
Anna Shaleva
85a2a9a989 *: improve error text for System.Crypto.CheckMultisig handling
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-03-25 19:16:21 +03:00
Ekaterina Pavlova
1840c057bd interop: add keccak256 implementation
Port neo-project/neo#2925.

Close #3295

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-03-22 17:15:43 +03:00
Ekaterina Pavlova
e0328cc1f8 native: add getCommitteeAddress method
Port neo-project/neo#3154.

Close #3334

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-03-22 16:46:59 +03:00
Ekaterina Pavlova
270515de6a native: add committee change events
Port neo-project/neo#3158.

Close #3326

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-03-19 23:00:06 +03:00
Anna Shaleva
a6f52a7180 core: prohibit reentry to Notary withdraw
If we're withdrawing funds to contract that has onNEP17Payment method,
then it may call Notary's withdraw one more time, but the account's
state is not yet updated by this moment.

The problem is similar to https://github.com/neo-project/neo/pull/2734.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-03-18 17:08:32 +03:00
Ekaterina Pavlova
0e6fbadfd5 native: clear LastGasPerVote when voting for NULL
Port neo-project/neo#3173.

Close #3345

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
2024-03-15 10:51:32 +03:00
Roman Khimov
d65b1fd66d *: use v2 LRU, fix #3322
Signed-off-by: Roman Khimov <roman@nspcc.ru>
2024-03-05 18:39:17 +03:00
Anna Shaleva
8162e9033d *: replace slice.Copy with bytes.Clone
And refactor some code a bit, don't use bytes.Clone where type-specific
helpers may be used instead.

Close #2907.

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-03-05 13:54:10 +03:00
Anna Shaleva
b030c331b0 core: copy SC storage iterator prefix while returning values
It's a bug since Prefix is shared between all iterator items and
appending is not enough. If prefix has enough capacity, then new slice
won't be created and the previous item's prefix will be changed.

This commit fixes the following test failure caused by moving from
bytes.Clone to slice.Copy:
```
 --- FAIL: TestComlileAndInvokeFunction/test_Storage.Find (0.02s)
        --- FAIL: TestComlileAndInvokeFunction/test_Storage.Find/keys_only (0.01s)
            contract_test.go:866:
                	Error Trace:	/home/anna/Documents/GitProjects/nspcc-dev/neo-go/cli/smartcontract/contract_test.go:866
                	Error:      	Not equal:
                	            	expected: []stackitem.Item{(*stackitem.ByteArray)(0xc000a1cdf8), (*stackitem.ByteArray)(0xc000a1ce10)}
                	            	actual  : []stackitem.Item{(*stackitem.ByteArray)(0xc000a1cdb0), (*stackitem.ByteArray)(0xc000a1cdc8)}

                	            	Diff:
                	            	--- Expected
                	            	+++ Actual
                	            	@@ -2,3 +2,3 @@
                	            	  (*stackitem.ByteArray)((len=8) {
                	            	-  00000000  66 69 6e 64 6b 65 79 31                           |findkey1|
                	            	+  00000000  66 69 6e 64 6b 65 79 32                           |findkey2|
                	            	  }),
                	Test:       	TestComlileAndInvokeFunction/test_Storage.Find/keys_only
        --- FAIL: TestComlileAndInvokeFunction/test_Storage.Find/both (0.01s)
            contract_test.go:881:
                	Error Trace:	/home/anna/Documents/GitProjects/nspcc-dev/neo-go/cli/smartcontract/contract_test.go:881
                	Error:      	Not equal:
                	            	expected: []stackitem.Item{(*stackitem.ByteArray)(0xc000515920), (*stackitem.ByteArray)(0xc000515938)}
                	            	actual  : []stackitem.Item{(*stackitem.ByteArray)(0xc000515848), (*stackitem.ByteArray)(0xc000515860)}

                	            	Diff:
                	            	--- Expected
                	            	+++ Actual
                	            	@@ -2,3 +2,3 @@
                	            	  (*stackitem.ByteArray)((len=8) {
                	            	-  00000000  66 69 6e 64 6b 65 79 31                           |findkey1|
                	            	+  00000000  66 69 6e 64 6b 65 79 32                           |findkey2|
                	            	  }),
                	Test:       	TestComlileAndInvokeFunction/test_Storage.Find/both
```

Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
2024-03-05 13:54:10 +03:00