Compare commits

...

98 commits

Author SHA1 Message Date
ceac1c8709
[#1594] dev: Remove unused parameter 'FROSTFS_MORPH_INACTIVITY_TIMEOUT'
Some checks failed
Tests and linters / Run gofumpt (pull_request) Successful in 30s
DCO action / DCO (pull_request) Successful in 39s
Vulncheck / Vulncheck (pull_request) Successful in 54s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m24s
Build / Build Components (pull_request) Successful in 1m29s
Tests and linters / Staticcheck (pull_request) Successful in 1m58s
Tests and linters / Tests with -race (pull_request) Successful in 2m39s
Tests and linters / Lint (pull_request) Successful in 2m47s
Tests and linters / Tests (pull_request) Successful in 2m58s
Tests and linters / gopls check (pull_request) Successful in 3m16s
Vulncheck / Vulncheck (push) Successful in 1m1s
Pre-commit hooks / Pre-commit (push) Successful in 1m27s
Tests and linters / Run gofumpt (push) Successful in 2m8s
Tests and linters / Tests (push) Successful in 2m17s
Tests and linters / gopls check (push) Successful in 2m16s
Tests and linters / Staticcheck (push) Successful in 2m20s
Tests and linters / Lint (push) Successful in 3m41s
Tests and linters / Tests with -race (push) Successful in 3m58s
Build / Build Components (push) Failing after 14m36s
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2025-01-09 20:52:24 +03:00
f7e75b13b0 [#1506] ape_manager: Await tx persist before returning response
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 28s
Vulncheck / Vulncheck (push) Successful in 57s
Build / Build Components (push) Successful in 1m42s
Pre-commit hooks / Pre-commit (push) Successful in 1m40s
Tests and linters / Staticcheck (push) Successful in 2m4s
Tests and linters / Tests with -race (push) Successful in 2m31s
Tests and linters / Tests (push) Successful in 2m44s
Tests and linters / Lint (push) Successful in 2m51s
Tests and linters / gopls check (push) Successful in 3m30s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 12:04:21 +00:00
198aaebc94 [#1506] morph: Simplify WaitTxHalt() signature
Avoid dependency on `morph/client` package because of `InvokeRes`.
Make signature resemble `WaitAny()` method of `waiter.Waiter` from neo-go.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 12:04:21 +00:00
85af6bcd5c [#1506] ape: Use contract reader in ListMorphRuleChains()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 12:04:21 +00:00
8a658de0b2 [#1506] ape: Do not create cosigners slice on each contract invocation
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 12:04:21 +00:00
3900b92927
Revert "[#1492] metabase: Ensure Unmarshal() is called on a cloned slice"
Some checks failed
DCO action / DCO (pull_request) Successful in 42s
Tests and linters / Run gofumpt (pull_request) Successful in 44s
Vulncheck / Vulncheck (pull_request) Successful in 1m20s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m38s
Build / Build Components (pull_request) Successful in 1m55s
Tests and linters / Tests (pull_request) Successful in 2m32s
Tests and linters / Staticcheck (pull_request) Successful in 2m36s
Tests and linters / gopls check (pull_request) Successful in 2m51s
Tests and linters / Lint (pull_request) Successful in 3m5s
Tests and linters / Tests with -race (pull_request) Successful in 3m57s
Build / Build Components (push) Has been cancelled
Pre-commit hooks / Pre-commit (push) Has been cancelled
Tests and linters / Lint (push) Has been cancelled
Tests and linters / Tests (push) Has been cancelled
Tests and linters / Tests with -race (push) Has been cancelled
Tests and linters / Staticcheck (push) Has been cancelled
Tests and linters / gopls check (push) Has been cancelled
Tests and linters / Run gofumpt (push) Has been cancelled
Vulncheck / Vulncheck (push) Has been cancelled
This reverts commit 8ed7a676d5.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 14:34:20 +03:00
5ccb3394b4
[#1592] go.mod: Update sdk-go
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 14:34:16 +03:00
dc410fca90 [#1590] adm: Accept many accounts in proxy-* commands
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 38s
Vulncheck / Vulncheck (push) Successful in 1m9s
Pre-commit hooks / Pre-commit (push) Successful in 1m27s
Tests and linters / Tests (push) Successful in 2m1s
Tests and linters / Staticcheck (push) Successful in 2m19s
Tests and linters / Tests with -race (push) Successful in 2m43s
Tests and linters / gopls check (push) Successful in 2m50s
Tests and linters / Lint (push) Successful in 3m9s
Build / Build Components (push) Successful in 1m25s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 07:51:54 +00:00
cddcd73f04 [#1590] adm: Make --account flag required in proxy-* commands
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2025-01-09 07:51:54 +00:00
d7fcc5ce30 [#1586] objsvc: Allow to send search response in multiple messages
All checks were successful
Pre-commit hooks / Pre-commit (push) Successful in 1m18s
Vulncheck / Vulncheck (push) Successful in 1m16s
Build / Build Components (push) Successful in 1m41s
Tests and linters / gopls check (push) Successful in 2m17s
Tests and linters / Run gofumpt (push) Successful in 2m31s
Tests and linters / Lint (push) Successful in 3m9s
Tests and linters / Staticcheck (push) Successful in 3m9s
Tests and linters / Tests (push) Successful in 3m24s
Tests and linters / Tests with -race (push) Successful in 3m32s
Previously, `ln` was only set once, so search has really worked for
small number of objects.

Fix panic:
```
panic: runtime error: slice bounds out of range [:43690] with capacity 21238
goroutine 6859775 [running]:
git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object.(*searchStreamMsgSizeCtrl).Send(0xc001eec8d0, 0xc005734000)
        git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/transport_splitter.go:173 +0x1f0
git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/v2.(*streamWriter).WriteIDs(0xc000520320, {0xc00eb1a000, 0x4fd9c, 0x7fd6475a9a68?})
        git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/v2/streamer.go:28 +0x155
git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*uniqueIDWriter).WriteIDs(0xc001386420, {0xc00eb1a000?, 0xc0013ea9c0?, 0x113eef3?})
        git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/util.go:62 +0x202
git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*execCtx).writeIDList(0xc00011aa38?, {0xc00eb1a000?, 0xc001eec9f0?, 0xc0008f4380?})
        git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/exec.go:68 +0x91
git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*execCtx).executeLocal(0xc0008f4380, {0x176c538, 0xc001eec9f0})
        git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/local.go:18 +0x16b
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-28 12:29:22 +00:00
c0221d76e6 [#1577] node/container: Fix typo
All checks were successful
DCO action / DCO (pull_request) Successful in 44s
Pre-commit hooks / Pre-commit (pull_request) Successful in 1m52s
Vulncheck / Vulncheck (pull_request) Successful in 1m31s
Tests and linters / Run gofumpt (pull_request) Successful in 1m37s
Build / Build Components (pull_request) Successful in 1m54s
Tests and linters / gopls check (pull_request) Successful in 2m30s
Tests and linters / Staticcheck (pull_request) Successful in 2m21s
Tests and linters / Tests (pull_request) Successful in 2m32s
Tests and linters / Lint (pull_request) Successful in 3m4s
Tests and linters / Tests with -race (pull_request) Successful in 4m17s
Tests and linters / Run gofumpt (push) Successful in 1m25s
Vulncheck / Vulncheck (push) Successful in 1m35s
Pre-commit hooks / Pre-commit (push) Successful in 1m53s
Build / Build Components (push) Successful in 1m56s
Tests and linters / Tests (push) Successful in 2m6s
Tests and linters / Staticcheck (push) Successful in 2m15s
Tests and linters / gopls check (push) Successful in 2m30s
Tests and linters / Tests with -race (push) Successful in 2m44s
Tests and linters / Lint (push) Successful in 3m1s
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-28 12:05:01 +03:00
242f0095d0 [#1577] container: Reduce iterations through container list
* Separated iteration through container ids from `ContainersOf()`
  so that it could be reused.
* When listing containers we used to iterate through the
  the whole list of containers twice: first when reading from
  a contract, then when sending them. Now we can send batches
  of containers when reading from the contract.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-27 15:30:26 +03:00
6fe34d266a [#1577] morph: Fix typo
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-27 14:03:19 +03:00
fa08bfa553
[#1583] metabase/test: Update TestLisObjectsWithCursor
All checks were successful
DCO action / DCO (pull_request) Successful in 4m37s
Vulncheck / Vulncheck (pull_request) Successful in 5m1s
Tests and linters / Run gofumpt (pull_request) Successful in 5m36s
Build / Build Components (pull_request) Successful in 6m3s
Pre-commit hooks / Pre-commit (pull_request) Successful in 6m0s
Tests and linters / Staticcheck (pull_request) Successful in 6m29s
Tests and linters / gopls check (pull_request) Successful in 6m41s
Tests and linters / Tests with -race (pull_request) Successful in 6m56s
Tests and linters / Tests (pull_request) Successful in 7m5s
Tests and linters / Lint (pull_request) Successful in 7m13s
Vulncheck / Vulncheck (push) Successful in 5m9s
Tests and linters / Run gofumpt (push) Successful in 5m18s
Pre-commit hooks / Pre-commit (push) Successful in 5m37s
Build / Build Components (push) Successful in 6m6s
Tests and linters / Staticcheck (push) Successful in 6m30s
Tests and linters / gopls check (push) Successful in 6m33s
Tests and linters / Tests (push) Successful in 7m6s
Tests and linters / Tests with -race (push) Successful in 7m7s
Tests and linters / Lint (push) Successful in 7m26s
Update this test following recent changes to ensure
that `(*DB).ListWithCursor` skips expired objects.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-26 14:39:50 +03:00
0da998ef50
[#1583] metabase: Skip expired objects in ListWithCursor
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-26 14:39:49 +03:00
e44782473a [#1512] object: Fix writePart for EC-container
All checks were successful
Vulncheck / Vulncheck (push) Successful in 4m58s
Tests and linters / Run gofumpt (push) Successful in 5m9s
Pre-commit hooks / Pre-commit (push) Successful in 6m11s
Tests and linters / Staticcheck (push) Successful in 6m14s
Build / Build Components (push) Successful in 6m33s
Tests and linters / gopls check (push) Successful in 6m41s
Tests and linters / Tests (push) Successful in 6m50s
Tests and linters / Tests with -race (push) Successful in 6m54s
Tests and linters / Lint (push) Successful in 7m16s
* Immediatly return after `ObjectAlreadyRemoved` error.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-26 11:27:55 +00:00
9cd1bcef06 [#1512] object: Make raw PutSingle check status within response
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-26 11:27:55 +00:00
ca0a33ea0f [#465] objsvc: Set NETMAP_EPOCH xheader for auxiliary requests
All checks were successful
Vulncheck / Vulncheck (push) Successful in 4m45s
Tests and linters / Run gofumpt (push) Successful in 4m54s
Pre-commit hooks / Pre-commit (push) Successful in 5m12s
Build / Build Components (push) Successful in 5m46s
Tests and linters / Staticcheck (push) Successful in 6m3s
Tests and linters / gopls check (push) Successful in 6m5s
Tests and linters / Tests (push) Successful in 6m38s
Tests and linters / Tests with -race (push) Successful in 6m45s
Tests and linters / Lint (push) Successful in 6m59s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-26 09:17:58 +00:00
f6c5222952 [#1581] services/session: Use user.ID.EncodeToString() where possible
All checks were successful
Vulncheck / Vulncheck (push) Successful in 4m25s
Tests and linters / Run gofumpt (push) Successful in 4m33s
Build / Build Components (push) Successful in 5m14s
Pre-commit hooks / Pre-commit (push) Successful in 5m23s
Tests and linters / Staticcheck (push) Successful in 5m43s
Tests and linters / gopls check (push) Successful in 5m47s
Tests and linters / Tests (push) Successful in 6m0s
Tests and linters / Tests with -race (push) Successful in 6m6s
Tests and linters / Lint (push) Successful in 6m21s
gopatch:
```
@@
var id expression
@@
-base58.Encode(id.WalletBytes())
+id.EncodeToString()
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-25 18:09:36 +00:00
ea868e09f8
[#1582] adm: Use int64 type and the default value for --till flag
All checks were successful
Vulncheck / Vulncheck (pull_request) Successful in 7m43s
Pre-commit hooks / Pre-commit (pull_request) Successful in 8m36s
Build / Build Components (pull_request) Successful in 9m19s
Tests and linters / gopls check (pull_request) Successful in 9m28s
Tests and linters / Staticcheck (pull_request) Successful in 9m34s
Tests and linters / Lint (pull_request) Successful in 10m34s
DCO action / DCO (pull_request) Successful in 3m9s
Tests and linters / Run gofumpt (pull_request) Successful in 4m5s
Tests and linters / Tests (pull_request) Successful in 4m38s
Tests and linters / Tests with -race (pull_request) Successful in 5m49s
Vulncheck / Vulncheck (push) Successful in 4m14s
Tests and linters / Run gofumpt (push) Successful in 4m35s
Build / Build Components (push) Successful in 5m16s
Pre-commit hooks / Pre-commit (push) Successful in 5m15s
Tests and linters / Staticcheck (push) Successful in 5m36s
Tests and linters / gopls check (push) Successful in 5m45s
Tests and linters / Tests (push) Successful in 6m9s
Tests and linters / Tests with -race (push) Successful in 6m17s
Tests and linters / Lint (push) Successful in 6m32s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-25 14:22:28 +03:00
31d3d299bf
[#1582] adm: Unify promps for reading a password
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-25 14:22:28 +03:00
b5b4f78b49
[#1582] adm: Allow using the default account in deposit-notary
It has never worked, actually.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-25 14:22:28 +03:00
2832f44437 [#1531] metrics: Rename app_info metric
All checks were successful
Vulncheck / Vulncheck (push) Successful in 5m30s
Tests and linters / Run gofumpt (push) Successful in 5m52s
Pre-commit hooks / Pre-commit (push) Successful in 6m37s
Build / Build Components (push) Successful in 6m43s
Tests and linters / Staticcheck (push) Successful in 6m42s
Tests and linters / Tests (push) Successful in 7m37s
Tests and linters / Tests with -race (push) Successful in 7m33s
Tests and linters / gopls check (push) Successful in 7m29s
Tests and linters / Lint (push) Successful in 7m54s
Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-23 10:40:18 +00:00
7c3bcb0f44
[#1578] Makefile: Refill GAS with a single command in env-up
Some checks failed
DCO action / DCO (pull_request) Successful in 3m25s
Vulncheck / Vulncheck (pull_request) Successful in 3m48s
Pre-commit hooks / Pre-commit (pull_request) Successful in 4m17s
Tests and linters / Run gofumpt (pull_request) Successful in 4m11s
Build / Build Components (pull_request) Successful in 5m5s
Tests and linters / Staticcheck (pull_request) Successful in 4m59s
Tests and linters / gopls check (pull_request) Successful in 5m5s
Tests and linters / Tests (pull_request) Successful in 5m28s
Tests and linters / Lint (pull_request) Successful in 5m37s
Tests and linters / Tests with -race (pull_request) Successful in 5m38s
Build / Build Components (push) Has been cancelled
Pre-commit hooks / Pre-commit (push) Has been cancelled
Tests and linters / Lint (push) Has been cancelled
Tests and linters / Tests (push) Has been cancelled
Tests and linters / Tests with -race (push) Has been cancelled
Tests and linters / Staticcheck (push) Has been cancelled
Tests and linters / gopls check (push) Has been cancelled
Tests and linters / Run gofumpt (push) Has been cancelled
Vulncheck / Vulncheck (push) Has been cancelled
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-23 11:17:22 +03:00
e64871c3fd
[#1578] adm: Allow to transfer GAS to multiple recepients
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-23 11:17:22 +03:00
303cd35a01
[#1578] adm: Remove unnecessary comments in RefillGasCmd
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-23 11:17:22 +03:00
bb9ba1bce2
[#1578] adm: Remove bool flag from refillGas()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-23 11:17:22 +03:00
db03742d33
[#1578] adm: Reword help message for morph refill-gas
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-23 11:17:22 +03:00
148d68933b [#1573] node: Simplify bootstrapWithState()
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m33s
Tests and linters / Staticcheck (push) Successful in 3m39s
Tests and linters / Lint (push) Successful in 4m53s
Vulncheck / Vulncheck (push) Successful in 7m22s
Pre-commit hooks / Pre-commit (push) Successful in 7m57s
Tests and linters / Tests (push) Successful in 8m14s
Build / Build Components (push) Successful in 8m22s
Tests and linters / gopls check (push) Successful in 9m0s
Tests and linters / Tests with -race (push) Successful in 9m2s
After #1382 we have no need to use lambdas.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-20 08:17:05 +00:00
51ee132ea3
[#1342] network/cache: Add node address to error multiClient
All checks were successful
DCO action / DCO (pull_request) Successful in 4m33s
Tests and linters / gopls check (pull_request) Successful in 6m55s
Tests and linters / Staticcheck (pull_request) Successful in 7m4s
Tests and linters / Lint (pull_request) Successful in 7m55s
Tests and linters / Run gofumpt (pull_request) Successful in 10m49s
Vulncheck / Vulncheck (pull_request) Successful in 11m27s
Build / Build Components (pull_request) Successful in 12m7s
Tests and linters / Tests (pull_request) Successful in 8m0s
Pre-commit hooks / Pre-commit (pull_request) Successful in 12m58s
Tests and linters / Tests with -race (pull_request) Successful in 5m27s
Pre-commit hooks / Pre-commit (push) Successful in 3m20s
Tests and linters / Staticcheck (push) Successful in 3m25s
Tests and linters / gopls check (push) Successful in 3m49s
Tests and linters / Run gofumpt (push) Successful in 6m30s
Vulncheck / Vulncheck (push) Successful in 7m30s
Build / Build Components (push) Successful in 8m2s
Tests and linters / Tests (push) Successful in 8m22s
Tests and linters / Tests with -race (push) Successful in 8m24s
Tests and linters / Lint (push) Successful in 9m12s
Signed-off-by: Alexander Chuprov <a.chuprov@yadro.com>
2024-12-18 19:27:35 +03:00
226dd25dd0 [#1568] pilorama: Replace "containerID" with "container ID" in the error message
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m46s
Tests and linters / Staticcheck (push) Successful in 3m31s
Tests and linters / Lint (push) Successful in 5m0s
Vulncheck / Vulncheck (push) Successful in 7m2s
Build / Build Components (push) Successful in 7m38s
Pre-commit hooks / Pre-commit (push) Successful in 7m54s
Tests and linters / Tests (push) Successful in 8m11s
Tests and linters / Tests with -race (push) Successful in 8m39s
Tests and linters / gopls check (push) Successful in 8m57s
It is "container ID" in every other place.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-18 15:52:26 +00:00
bd0197eaa8 [#1568] storage: Remove "could not/can't/failed to" from error messages
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-18 15:52:26 +00:00
e44b84c18c
[#1569] cli: Remove unnecessary variable after refactoring
All checks were successful
DCO action / DCO (pull_request) Successful in 3m26s
Vulncheck / Vulncheck (pull_request) Successful in 3m43s
Tests and linters / Run gofumpt (pull_request) Successful in 5m6s
Tests and linters / Staticcheck (pull_request) Successful in 5m45s
Tests and linters / Lint (pull_request) Successful in 6m40s
Build / Build Components (pull_request) Successful in 8m35s
Pre-commit hooks / Pre-commit (pull_request) Successful in 9m13s
Tests and linters / Tests (pull_request) Successful in 10m19s
Tests and linters / Tests with -race (pull_request) Successful in 10m44s
Tests and linters / gopls check (pull_request) Successful in 10m52s
Tests and linters / Run gofumpt (push) Successful in 3m52s
Tests and linters / Staticcheck (push) Successful in 4m3s
Tests and linters / Lint (push) Successful in 5m41s
Vulncheck / Vulncheck (push) Successful in 8m33s
Pre-commit hooks / Pre-commit (push) Successful in 9m29s
Build / Build Components (push) Successful in 9m58s
Tests and linters / Tests (push) Successful in 9m58s
Tests and linters / Tests with -race (push) Successful in 10m20s
Tests and linters / gopls check (push) Successful in 10m56s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-18 10:17:04 +03:00
bed49e6ace
[#1569] cli: Make --range flag required in object hash
Previously, `object head` was used if no range was provided.
This is wrong on multiple levels:
1. We print an error if the checksum is missing in header,
   even though taking hash is possible.
2. We silently ignore --salt parameter.
3. `--range` is required for Object.RANGEHASH RPC, custom logic for one
   specific usecase has no value.

So we make it required and make CLI command follow more closely
the FrostFS API.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-18 10:17:04 +03:00
df05057ed4 [#1452] container: Add ListStream method
All checks were successful
Vulncheck / Vulncheck (pull_request) Successful in 3m5s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m36s
Tests and linters / gopls check (pull_request) Successful in 4m1s
Tests and linters / Run gofumpt (pull_request) Successful in 5m35s
DCO action / DCO (pull_request) Successful in 6m3s
Tests and linters / Tests with -race (pull_request) Successful in 6m35s
Build / Build Components (pull_request) Successful in 7m15s
Tests and linters / Staticcheck (pull_request) Successful in 7m38s
Tests and linters / Tests (pull_request) Successful in 7m56s
Tests and linters / Lint (pull_request) Successful in 8m42s
Tests and linters / Run gofumpt (push) Successful in 3m34s
Tests and linters / Staticcheck (push) Successful in 3m38s
Tests and linters / Lint (push) Successful in 5m12s
Vulncheck / Vulncheck (push) Successful in 6m7s
Build / Build Components (push) Successful in 6m43s
Pre-commit hooks / Pre-commit (push) Successful in 6m54s
Tests and linters / Tests (push) Successful in 7m31s
Tests and linters / Tests with -race (push) Successful in 8m5s
Tests and linters / gopls check (push) Successful in 8m13s
* Added new method for listing containers to container service.
  It opens stream and sends containers in batches.

* Added TransportSplitter wrapper around ExecutionService to
  split container ID list read from contract in parts that are
  smaller than grpc max message size. Batch size can be changed
  in node configuration file (as in example config file).

* Changed `container list` implementaion in cli: now ListStream
  is called by default. Old List is called only if ListStream
  is not implemented.

* Changed `internalclient.ListContainersPrm`.`Account` to
  `OwnerID` since `client.PrmContainerList`.`Account` was
  renamed to `OwnerID` in sdk.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-17 16:22:43 +03:00
b6c8ebf493 [#1453] container: Replace sort.Slice with slices.SortFunc
* Replaced `sort.Slice` with `slices.SortFunc` in
  `ListContainersRes.SortedIDList()` as it is a bit faster,
  according to 15102e6dfd.

Signed-off-by: Ekaterina Lebedeva <ekaterina.lebedeva@yadro.com>
2024-12-17 13:33:43 +03:00
6e82661c35 [#1563] tree: Wrap only ChainRouterError erros with ObjectAccessDenied
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 1m37s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m25s
Tests and linters / gopls check (pull_request) Successful in 3m47s
DCO action / DCO (pull_request) Successful in 5m54s
Tests and linters / Tests with -race (pull_request) Successful in 6m34s
Vulncheck / Vulncheck (pull_request) Successful in 7m3s
Build / Build Components (pull_request) Successful in 7m39s
Tests and linters / Tests (pull_request) Successful in 7m57s
Tests and linters / Staticcheck (pull_request) Successful in 8m17s
Tests and linters / Lint (pull_request) Successful in 8m42s
Tests and linters / Run gofumpt (push) Successful in 1m24s
Tests and linters / Staticcheck (push) Successful in 3m24s
Tests and linters / Lint (push) Successful in 4m48s
Vulncheck / Vulncheck (push) Successful in 6m26s
Build / Build Components (push) Successful in 7m8s
Tests and linters / Tests (push) Successful in 7m19s
Pre-commit hooks / Pre-commit (push) Successful in 7m36s
Tests and linters / Tests with -race (push) Successful in 7m52s
Tests and linters / gopls check (push) Successful in 8m4s
* Such wrapping helps to differentiate logical check errors and server internal
  errors.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-16 15:16:07 +03:00
1a091ea7bb [#1563] object: Wrap only ChainRouterError erros with ObjectAccessDenied
* Such wrapping helps to differentiate logical check errors and server internal
  errors.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-16 15:15:25 +03:00
7ac3542714 [#1563] ape: Introduce ChainRouterError error type
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-16 15:12:30 +03:00
f0c43c8d80
[#1502] Use zap.Error for logging errors
All checks were successful
Vulncheck / Vulncheck (pull_request) Successful in 3m1s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m29s
Tests and linters / gopls check (pull_request) Successful in 3m50s
Tests and linters / Lint (pull_request) Successful in 4m35s
DCO action / DCO (pull_request) Successful in 5m12s
Tests and linters / Run gofumpt (pull_request) Successful in 5m33s
Build / Build Components (pull_request) Successful in 5m45s
Tests and linters / Tests with -race (pull_request) Successful in 6m37s
Tests and linters / Tests (pull_request) Successful in 7m17s
Tests and linters / Staticcheck (pull_request) Successful in 7m36s
Tests and linters / Run gofumpt (push) Successful in 1m22s
Tests and linters / Staticcheck (push) Successful in 3m19s
Tests and linters / Lint (push) Successful in 4m35s
Vulncheck / Vulncheck (push) Successful in 5m20s
Build / Build Components (push) Successful in 6m16s
Pre-commit hooks / Pre-commit (push) Successful in 6m37s
Tests and linters / Tests (push) Successful in 6m48s
Tests and linters / Tests with -race (push) Successful in 7m15s
Tests and linters / gopls check (push) Successful in 7m27s
Use `zap.Error` instead of `zap.String` for logging errors: change all expressions like
`zap.String("error", err.Error())` or `zap.String("err", err.Error())` to `zap.Error(err)`.
Leave similar expressions with other messages unchanged, for example,
`zap.String("last_error", lastErr.Error())` or `zap.String("reason", ctx.Err().Error())`.

This change was made by applying the following patch:
```diff
@@
var err expression
@@
-zap.String("error", err.Error())
+zap.Error(err)

@@
var err expression
@@
-zap.String("err", err.Error())
+zap.Error(err)
```

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-16 11:13:42 +03:00
8ba9f31fca
[#1510] metabase/test: Fix BenchmarkListWithCursor
All checks were successful
DCO action / DCO (pull_request) Successful in 4m10s
Pre-commit hooks / Pre-commit (pull_request) Successful in 4m53s
Tests and linters / gopls check (pull_request) Successful in 5m9s
Build / Build Components (pull_request) Successful in 5m36s
Tests and linters / Lint (pull_request) Successful in 6m0s
Tests and linters / Tests (pull_request) Successful in 6m4s
Tests and linters / Run gofumpt (pull_request) Successful in 6m5s
Vulncheck / Vulncheck (pull_request) Successful in 6m48s
Tests and linters / Tests with -race (pull_request) Successful in 7m35s
Tests and linters / Staticcheck (pull_request) Successful in 7m42s
Tests and linters / Staticcheck (push) Successful in 3m50s
Tests and linters / gopls check (push) Successful in 3m57s
Build / Build Components (push) Successful in 4m30s
Tests and linters / Lint (push) Successful in 4m50s
Tests and linters / Run gofumpt (push) Successful in 5m38s
Vulncheck / Vulncheck (push) Successful in 6m51s
Pre-commit hooks / Pre-commit (push) Successful in 7m27s
Tests and linters / Tests (push) Successful in 7m45s
Tests and linters / Tests with -race (push) Successful in 8m26s
- Fix misplaced `(*DB).Close` (broken after 47dcfa20f3)
- Use `errors.Is` for error checking (broken after fcdbf5e509)

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-13 13:19:15 +03:00
2af3409d39
[#1510] metabase/test: Fix BenchmarkGet
Fix misplaced `(*DB).Close` (broken after 47dcfa20f3)

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-13 13:18:43 +03:00
d165ac042c
[#1558] morph/client: Reuse notary rpcclient wrapper
All checks were successful
DCO action / DCO (pull_request) Successful in 5m31s
Tests and linters / Run gofumpt (pull_request) Successful in 5m35s
Tests and linters / gopls check (pull_request) Successful in 6m9s
Pre-commit hooks / Pre-commit (pull_request) Successful in 6m25s
Tests and linters / Staticcheck (pull_request) Successful in 6m26s
Build / Build Components (pull_request) Successful in 7m19s
Vulncheck / Vulncheck (pull_request) Successful in 7m16s
Tests and linters / Tests (pull_request) Successful in 7m37s
Tests and linters / Tests with -race (pull_request) Successful in 7m56s
Tests and linters / Lint (pull_request) Successful in 8m44s
Tests and linters / Run gofumpt (push) Successful in 1m32s
Vulncheck / Vulncheck (push) Successful in 3m2s
Tests and linters / Staticcheck (push) Successful in 3m43s
Build / Build Components (push) Successful in 4m5s
Tests and linters / Lint (push) Successful in 4m29s
Pre-commit hooks / Pre-commit (push) Successful in 5m7s
Tests and linters / Tests (push) Successful in 5m16s
Tests and linters / Tests with -race (push) Successful in 5m29s
Tests and linters / gopls check (push) Successful in 5m37s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-12 15:30:12 +03:00
7151c71d51
[#1558] morph/client: Remove "could not"/"can't"/"failed to" from error messages
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-12 15:30:12 +03:00
91d9dc2676
[#1558] morph/event: Remove "could not" from error messages
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-12 15:30:12 +03:00
7853dbc315 [#1557] morph/event: Remove embedded structs from scriptHashWithValue
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m23s
Tests and linters / Staticcheck (push) Successful in 3m10s
Vulncheck / Vulncheck (push) Successful in 4m8s
Tests and linters / Lint (push) Successful in 4m33s
Build / Build Components (push) Successful in 4m36s
Pre-commit hooks / Pre-commit (push) Successful in 5m14s
Tests and linters / Tests (push) Successful in 5m20s
Tests and linters / Tests with -race (push) Successful in 6m7s
Tests and linters / gopls check (push) Successful in 6m12s
Also, make them public, because otherwise `unused` linter complains.
```
pkg/morph/event/utils.go:25:2  unused  field `typ` is unused
```
This complain is wrong, though: we _use_ `typ` field because the whole
struct is used as a map key.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-12 11:55:09 +00:00
3821645085
[#1555] engine: Refactor (*StorageEngine).GetLocks
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 3m25s
Pre-commit hooks / Pre-commit (pull_request) Successful in 4m41s
DCO action / DCO (pull_request) Successful in 4m57s
Vulncheck / Vulncheck (pull_request) Successful in 5m28s
Build / Build Components (pull_request) Successful in 5m46s
Tests and linters / Staticcheck (pull_request) Successful in 6m0s
Tests and linters / Tests (pull_request) Successful in 6m34s
Tests and linters / Lint (pull_request) Successful in 6m51s
Tests and linters / Tests with -race (pull_request) Successful in 7m50s
Tests and linters / gopls check (pull_request) Successful in 2m51s
Tests and linters / Run gofumpt (push) Successful in 1m16s
Tests and linters / Staticcheck (push) Successful in 3m13s
Vulncheck / Vulncheck (push) Successful in 3m46s
Build / Build Components (push) Successful in 4m11s
Tests and linters / Lint (push) Successful in 4m26s
Pre-commit hooks / Pre-commit (push) Successful in 4m47s
Tests and linters / Tests with -race (push) Successful in 6m8s
Tests and linters / gopls check (push) Successful in 6m13s
Tests and linters / Tests (push) Successful in 2m36s
Refactored after renaming the method to replace the confusing `locked`
variable with `locks`.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-11 15:06:38 +03:00
72470d6b48
[#1555] local_object_storage: Rename method GetLocked -> GetLocks
Renamed to better reflect the method's purpose of returning locks
for the specified object.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-11 15:06:37 +03:00
e9837bbcf9 [#1554] morph/event: Remove unused AlphabetUpdate event
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m16s
Tests and linters / Staticcheck (push) Successful in 3m14s
Vulncheck / Vulncheck (push) Successful in 3m41s
Build / Build Components (push) Successful in 4m5s
Tests and linters / Lint (push) Successful in 4m53s
Pre-commit hooks / Pre-commit (push) Successful in 5m15s
Tests and linters / Tests (push) Successful in 5m52s
Tests and linters / Tests with -race (push) Successful in 6m24s
Tests and linters / gopls check (push) Successful in 6m32s
Refs TrueCloudLab/frostfs-contract#138.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 12:01:17 +00:00
a641c91594 [#1550] Add CODEOWNERS
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m18s
Tests and linters / Staticcheck (push) Successful in 3m12s
Vulncheck / Vulncheck (push) Successful in 3m47s
Tests and linters / Lint (push) Successful in 4m15s
Build / Build Components (push) Successful in 4m19s
Pre-commit hooks / Pre-commit (push) Successful in 5m5s
Tests and linters / Tests (push) Successful in 5m29s
Tests and linters / Tests with -race (push) Successful in 6m3s
Tests and linters / gopls check (push) Successful in 6m9s
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
2024-12-11 10:34:57 +00:00
b1614a284d [#1546] morph/event: Export NotificationHandlerInfo fields
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m26s
Tests and linters / Staticcheck (push) Successful in 3m21s
Vulncheck / Vulncheck (push) Successful in 3m36s
Build / Build Components (push) Successful in 3m58s
Tests and linters / Lint (push) Successful in 4m30s
Pre-commit hooks / Pre-commit (push) Successful in 4m35s
Tests and linters / Tests (push) Successful in 5m15s
Tests and linters / Tests with -race (push) Successful in 5m33s
Tests and linters / gopls check (push) Successful in 5m45s
Hiding them achieves nothing, as the struct has no methods and is not
used concurrently.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 07:39:49 +00:00
d0ce835fbf [#1546] morph/event: Merge notification parser and handlers
They are decoupled, but it is an error to have a handler without a
corresponding parser. Register them together on the code level and get
rid of unreachable code.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 07:39:49 +00:00
dfa51048a8 [#1546] morph/event: Remove "is started" checks from event handler registrar
This codepath hides possible bugs in code.
All initialization function should run before init stage.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 07:39:49 +00:00
670305a721 [#1546] morph/event: Remove nil checks from event handler registrar
This codepath hides possible bugs in code.
We would rather panic then silently fail.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-11 07:39:49 +00:00
1f6cf57e30 [#1548] metabase: Check if EC parent is removed or expired
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m26s
Tests and linters / Staticcheck (push) Successful in 3m14s
Vulncheck / Vulncheck (push) Successful in 3m46s
Build / Build Components (push) Successful in 4m16s
Pre-commit hooks / Pre-commit (push) Successful in 4m27s
Tests and linters / Lint (push) Successful in 4m30s
Tests and linters / Tests (push) Successful in 5m22s
Tests and linters / Tests with -race (push) Successful in 5m35s
Tests and linters / gopls check (push) Successful in 5m46s
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-11 07:26:33 +00:00
386a12eea4 [#1548] engine: Rename parent -> ecParent
Parent could mean split parent or EC parent. In this case it is EC parent only.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-11 07:26:33 +00:00
15139d80c9 [#1548] policer: Do not replicate EC chunk if object already removed
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-11 07:26:33 +00:00
41da27dad5
[#1549] engine: Drop Async flag from evacuation parameters
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 4m4s
DCO action / DCO (pull_request) Successful in 5m4s
Pre-commit hooks / Pre-commit (pull_request) Successful in 5m5s
Vulncheck / Vulncheck (pull_request) Successful in 4m56s
Tests and linters / Staticcheck (pull_request) Successful in 5m10s
Build / Build Components (pull_request) Successful in 5m32s
Tests and linters / Tests with -race (pull_request) Successful in 6m24s
Tests and linters / Lint (pull_request) Successful in 6m36s
Tests and linters / Tests (pull_request) Successful in 6m46s
Tests and linters / gopls check (pull_request) Successful in 7m9s
Tests and linters / Run gofumpt (push) Successful in 1m34s
Tests and linters / Staticcheck (push) Successful in 3m22s
Vulncheck / Vulncheck (push) Successful in 3m43s
Tests and linters / Lint (push) Successful in 4m16s
Build / Build Components (push) Successful in 5m0s
Pre-commit hooks / Pre-commit (push) Successful in 5m3s
Tests and linters / Tests (push) Successful in 5m9s
Tests and linters / Tests with -race (push) Successful in 5m13s
Tests and linters / gopls check (push) Successful in 5m54s
Now it is only async evacuation.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-10 17:00:00 +03:00
ac0511d214
[#1549] controlSvc: Drop deprecated EvacuateShard rpc
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-10 16:59:52 +03:00
7e542906ef [#1539] go.mod: Bump frostfs-sdk-go version
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m49s
DCO action / DCO (pull_request) Successful in 3m5s
Vulncheck / Vulncheck (pull_request) Successful in 3m4s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m21s
Tests and linters / gopls check (pull_request) Successful in 3m29s
Build / Build Components (pull_request) Successful in 3m43s
Tests and linters / Staticcheck (pull_request) Successful in 4m22s
Tests and linters / Lint (pull_request) Successful in 5m3s
Tests and linters / Tests (pull_request) Successful in 5m23s
Tests and linters / Tests with -race (pull_request) Successful in 6m37s
Tests and linters / Run gofumpt (push) Successful in 2m18s
Tests and linters / Staticcheck (push) Successful in 4m36s
Vulncheck / Vulncheck (push) Successful in 5m14s
Build / Build Components (push) Successful in 5m41s
Pre-commit hooks / Pre-commit (push) Successful in 6m24s
Tests and linters / Tests with -race (push) Successful in 6m21s
Tests and linters / Lint (push) Successful in 6m57s
Tests and linters / gopls check (push) Successful in 7m27s
Tests and linters / Tests (push) Successful in 9m23s
* Also fix placement unit-test in object manager

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-12-06 15:29:37 +03:00
d1bc4351c3
[#1545] morph/event: Simplify frostfs contract event parsing
All checks were successful
DCO action / DCO (pull_request) Successful in 4m46s
Vulncheck / Vulncheck (pull_request) Successful in 5m22s
Build / Build Components (pull_request) Successful in 6m12s
Pre-commit hooks / Pre-commit (pull_request) Successful in 6m10s
Tests and linters / Run gofumpt (pull_request) Successful in 6m16s
Tests and linters / gopls check (pull_request) Successful in 6m19s
Tests and linters / Staticcheck (pull_request) Successful in 6m25s
Tests and linters / Lint (pull_request) Successful in 6m59s
Tests and linters / Tests (pull_request) Successful in 7m38s
Tests and linters / Tests with -race (pull_request) Successful in 8m37s
Tests and linters / Run gofumpt (push) Successful in 1m16s
Tests and linters / Staticcheck (push) Successful in 3m15s
Vulncheck / Vulncheck (push) Successful in 4m7s
Build / Build Components (push) Successful in 4m32s
Tests and linters / Lint (push) Successful in 4m50s
Pre-commit hooks / Pre-commit (push) Successful in 5m1s
Tests and linters / Tests (push) Successful in 5m14s
Tests and linters / Tests with -race (push) Successful in 5m54s
Tests and linters / gopls check (push) Successful in 6m2s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-06 14:00:23 +03:00
1c12f23b84 [#1541] morph/event: Simplify netmap contract event parsing
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 1m10s
Vulncheck / Vulncheck (push) Successful in 2m55s
Tests and linters / Staticcheck (push) Successful in 3m2s
Build / Build Components (push) Successful in 3m42s
Pre-commit hooks / Pre-commit (push) Successful in 3m46s
Tests and linters / Lint (push) Successful in 4m19s
Tests and linters / Tests (push) Successful in 4m23s
Tests and linters / gopls check (push) Successful in 4m44s
Tests and linters / Tests with -race (push) Successful in 5m18s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-06 10:26:39 +00:00
a353d45742 [#1541] morph/event: Simplify container contract event parsing
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-06 10:26:39 +00:00
d5c46d812a [#1541] go.mod: Update frostfs-contract
New version contains more idiomatic types in the auto-generated code.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-06 10:26:39 +00:00
d5d5ce2074 [#1541] morph/event: Simplify balance contract event parsing
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-06 10:26:39 +00:00
7df3520d48 [#1540] getSvc: Drop redundant returns
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m9s
Vulncheck / Vulncheck (push) Successful in 2m51s
Tests and linters / Staticcheck (push) Successful in 3m20s
Build / Build Components (push) Successful in 3m40s
Pre-commit hooks / Pre-commit (push) Successful in 3m42s
Tests and linters / gopls check (push) Successful in 4m16s
Tests and linters / Tests (push) Successful in 4m42s
Tests and linters / Lint (push) Successful in 4m49s
Tests and linters / Tests with -race (push) Successful in 5m6s
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-05 12:39:49 +00:00
5fe78e51d1 [#1540] getSvc: Do not log context canceled errors during EC assemble
Those errors are fired when it is enough chunks retrieved and error group
cancels other requests.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
2024-12-05 12:39:49 +00:00
84b4051b4d
[#1538] morph/container: Make opts struct similar to that of other contracts
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 3m42s
DCO action / DCO (pull_request) Successful in 4m23s
Vulncheck / Vulncheck (pull_request) Successful in 5m24s
Build / Build Components (pull_request) Successful in 5m59s
Tests and linters / Staticcheck (pull_request) Successful in 5m58s
Tests and linters / gopls check (pull_request) Successful in 6m3s
Pre-commit hooks / Pre-commit (pull_request) Successful in 6m13s
Tests and linters / Tests with -race (pull_request) Successful in 6m13s
Tests and linters / Lint (pull_request) Successful in 6m19s
Tests and linters / Tests (pull_request) Successful in 7m43s
Tests and linters / Run gofumpt (push) Successful in 2m13s
Vulncheck / Vulncheck (push) Successful in 2m50s
Tests and linters / Staticcheck (push) Successful in 3m0s
Build / Build Components (push) Successful in 3m36s
Pre-commit hooks / Pre-commit (push) Successful in 3m40s
Tests and linters / gopls check (push) Successful in 4m16s
Tests and linters / Lint (push) Successful in 4m27s
Tests and linters / Tests (push) Successful in 4m31s
Tests and linters / Tests with -race (push) Successful in 5m26s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 15:30:58 +03:00
6a51086030
[#1538] morph/client: Remove TryNotary() option from side-chain contracts
The notary is always enabled and this option does always work.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 15:30:58 +03:00
5c3b2d95ba
[#1538] node: Assume notary is enabled
Notaryless environments are not tested at all since a while.
We use neo-go only and it has notary contract enabled.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 15:30:58 +03:00
2d5d4093be
[#1537] morph: Use (user.ID).ScriptHash() where possible
All checks were successful
DCO action / DCO (pull_request) Successful in 4m46s
Vulncheck / Vulncheck (pull_request) Successful in 6m4s
Pre-commit hooks / Pre-commit (pull_request) Successful in 6m21s
Build / Build Components (pull_request) Successful in 6m39s
Tests and linters / Run gofumpt (pull_request) Successful in 1m50s
Tests and linters / gopls check (pull_request) Successful in 3m7s
Tests and linters / Staticcheck (pull_request) Successful in 3m9s
Tests and linters / Lint (pull_request) Successful in 4m6s
Tests and linters / Tests (pull_request) Successful in 4m28s
Tests and linters / Tests with -race (pull_request) Successful in 5m28s
Tests and linters / Run gofumpt (push) Successful in 2m9s
Vulncheck / Vulncheck (push) Successful in 2m43s
Tests and linters / Staticcheck (push) Successful in 3m2s
Build / Build Components (push) Successful in 3m15s
Pre-commit hooks / Pre-commit (push) Successful in 3m48s
Tests and linters / gopls check (push) Successful in 4m5s
Tests and linters / Lint (push) Successful in 4m33s
Tests and linters / Tests (push) Successful in 4m36s
Tests and linters / Tests with -race (push) Successful in 4m50s
Pick up changes from TrueCloudLab/frostfs-sdk-go#198.

gopatch:
```
@@
var user expression
@@
-address.StringToUint160(user.EncodeToString())
+user.ScriptHash()
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 13:25:44 +03:00
e3487d5af5 [#1535] morph: Unify test invoke error messages
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m10s
Tests and linters / Staticcheck (push) Successful in 2m52s
Vulncheck / Vulncheck (push) Successful in 2m50s
Build / Build Components (push) Successful in 3m23s
Pre-commit hooks / Pre-commit (push) Successful in 3m33s
Tests and linters / gopls check (push) Successful in 4m8s
Tests and linters / Lint (push) Successful in 4m16s
Tests and linters / Tests (push) Successful in 4m19s
Tests and linters / Tests with -race (push) Successful in 5m1s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 09:50:20 +00:00
e37dcdf88b [#1535] morph/netmap: Unify error messages for config retrieval
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 09:50:20 +00:00
6c679d1535 [#1535] morph: Unify client creation error messages
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 09:50:20 +00:00
281d65435e
[#1450] engine: Group object by shard before Inhume
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m1s
DCO action / DCO (pull_request) Successful in 2m20s
Vulncheck / Vulncheck (pull_request) Successful in 2m23s
Build / Build Components (pull_request) Successful in 3m15s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m21s
Tests and linters / gopls check (pull_request) Successful in 3m21s
Tests and linters / Staticcheck (pull_request) Successful in 3m49s
Tests and linters / Lint (pull_request) Successful in 4m37s
Tests and linters / Tests (pull_request) Successful in 5m0s
Tests and linters / Tests with -race (pull_request) Successful in 6m12s
Tests and linters / Run gofumpt (push) Successful in 1m46s
Vulncheck / Vulncheck (push) Successful in 2m36s
Pre-commit hooks / Pre-commit (push) Successful in 2m55s
Build / Build Components (push) Successful in 3m8s
Tests and linters / gopls check (push) Successful in 3m30s
Tests and linters / Staticcheck (push) Successful in 3m36s
Tests and linters / Lint (push) Successful in 4m31s
Tests and linters / Tests (push) Successful in 4m56s
Tests and linters / Tests with -race (push) Successful in 6m7s
```
goos: linux
goarch: amd64
pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine
cpu: 12th Gen Intel(R) Core(TM) i5-1235U
                                 │   old.txt    │              new.txt                │
                                 │    sec/op    │   sec/op     vs base                │
InhumeMultipart/objects=1-12        11.42m ± 1%   10.71m ± 0%   -6.27% (p=0.000 n=10)
InhumeMultipart/objects=10-12       113.5m ± 0%   100.9m ± 3%  -11.08% (p=0.000 n=10)
InhumeMultipart/objects=100-12     1135.4m ± 1%   681.3m ± 2%  -40.00% (p=0.000 n=10)
InhumeMultipart/objects=1000-12     11.358 ± 0%    1.089 ± 1%  -90.41% (p=0.000 n=10)
InhumeMultipart/objects=10000-12   113.251 ± 0%    1.645 ± 1%  -98.55% (p=0.000 n=10)
geomean                              1.136        265.5m       -76.63%
```

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-04 10:09:00 +03:00
b348b20289
[#1450] engine: Add benchmark for Inhume operation
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-04 10:08:34 +03:00
748edd1999
[#1450] engine: Return shard-level error if object is expired on inhume
Since we have errors defined on the shard-level, it looks strage that we
check an error againt the shard-level error `ErrLockObjectRemoval`, but
then return the metabase-level error. Let's return the same shard-level
error instead.

Since we have errors defined on the shard-level

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-04 10:06:57 +03:00
47dfd8840c [#1532] node: Allow to omit metabase.path if shard is disabled
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m15s
Vulncheck / Vulncheck (push) Successful in 2m44s
Build / Build Components (push) Successful in 3m9s
Tests and linters / Staticcheck (push) Successful in 3m10s
Pre-commit hooks / Pre-commit (push) Successful in 3m38s
Tests and linters / gopls check (push) Successful in 4m14s
Tests and linters / Tests (push) Successful in 4m27s
Tests and linters / Lint (push) Successful in 4m34s
Tests and linters / Tests with -race (push) Successful in 4m51s
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-12-04 03:30:19 +00:00
432042c534
[#1527] engine: Add tests for handling expired objects on inhume and lock
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m11s
DCO action / DCO (pull_request) Successful in 2m27s
Vulncheck / Vulncheck (pull_request) Successful in 2m38s
Pre-commit hooks / Pre-commit (pull_request) Successful in 3m3s
Build / Build Components (pull_request) Successful in 3m20s
Tests and linters / gopls check (pull_request) Successful in 3m27s
Tests and linters / Staticcheck (pull_request) Successful in 4m0s
Tests and linters / Lint (pull_request) Successful in 4m39s
Tests and linters / Tests (pull_request) Successful in 5m9s
Tests and linters / Tests with -race (pull_request) Successful in 6m33s
Tests and linters / Run gofumpt (push) Successful in 2m18s
Vulncheck / Vulncheck (push) Successful in 2m55s
Build / Build Components (push) Successful in 3m11s
Tests and linters / Staticcheck (push) Successful in 3m23s
Pre-commit hooks / Pre-commit (push) Successful in 3m45s
Tests and linters / gopls check (push) Successful in 4m6s
Tests and linters / Lint (push) Successful in 4m29s
Tests and linters / Tests (push) Successful in 4m32s
Tests and linters / Tests with -race (push) Successful in 4m41s
Currently, it's allowed to inhume or lock an expired object.
Consider the following scenario:

1) An user inhumes or locks an object
2) The object expires
3) GC hasn't yet deleted the object
4) The node loses the associated tombstone or lock
5) Another node replicates tombstone or lock to the first node

In this case, the second node succeeds, which is the desired behavior.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-03 12:29:45 +03:00
9cabca9dfe
[#1527] engine/test: Move default metabase options to separate function
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-02 16:13:37 +03:00
60feed3b5f
[#1527] engine/test: Allow to specify current epoch in epochState
Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-12-02 15:37:25 +03:00
635a292ae4 [#1528] cli: Keep order for required nodes in the result of object nodes
All checks were successful
Pre-commit hooks / Pre-commit (pull_request) Successful in 2m54s
DCO action / DCO (pull_request) Successful in 3m6s
Vulncheck / Vulncheck (pull_request) Successful in 3m59s
Build / Build Components (pull_request) Successful in 4m46s
Tests and linters / Run gofumpt (pull_request) Successful in 1m33s
Tests and linters / gopls check (pull_request) Successful in 2m46s
Tests and linters / Staticcheck (pull_request) Successful in 3m22s
Tests and linters / Tests (pull_request) Successful in 4m14s
Tests and linters / Lint (pull_request) Successful in 4m18s
Tests and linters / Tests with -race (pull_request) Successful in 5m7s
Tests and linters / Run gofumpt (push) Successful in 2m32s
Vulncheck / Vulncheck (push) Successful in 3m0s
Pre-commit hooks / Pre-commit (push) Successful in 3m14s
Build / Build Components (push) Successful in 3m34s
Tests and linters / Lint (push) Successful in 4m1s
Tests and linters / Staticcheck (push) Successful in 4m17s
Tests and linters / gopls check (push) Successful in 4m23s
Tests and linters / Tests (push) Successful in 5m12s
Tests and linters / Tests with -race (push) Successful in 6m6s
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-12-02 13:58:24 +03:00
edfa3f4825 [#1528] node: Keep order for equal elements when sort priority metrics
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
2024-12-02 13:58:19 +03:00
e0ac3a583f [#1523] metabase: Remove (*DB).IterateCoveredByTombstones
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 3m15s
DCO action / DCO (pull_request) Successful in 3m26s
Pre-commit hooks / Pre-commit (pull_request) Successful in 4m38s
Tests and linters / gopls check (pull_request) Successful in 4m53s
Tests and linters / Lint (pull_request) Successful in 5m16s
Build / Build Components (pull_request) Successful in 5m51s
Vulncheck / Vulncheck (pull_request) Successful in 5m47s
Tests and linters / Staticcheck (pull_request) Successful in 8m3s
Tests and linters / Tests (pull_request) Successful in 9m16s
Tests and linters / Tests with -race (pull_request) Successful in 9m19s
Tests and linters / Run gofumpt (push) Successful in 2m8s
Vulncheck / Vulncheck (push) Successful in 2m41s
Build / Build Components (push) Successful in 3m18s
Tests and linters / Staticcheck (push) Successful in 3m15s
Pre-commit hooks / Pre-commit (push) Successful in 3m49s
Tests and linters / gopls check (push) Successful in 4m14s
Tests and linters / Lint (push) Successful in 4m21s
Tests and linters / Tests (push) Successful in 4m24s
Tests and linters / Tests with -race (push) Successful in 4m36s
Remove this method because it isn't used anywhere since 7799f8e4c.

Signed-off-by: Aleksey Savchuk <a.savchuk@yadro.com>
2024-11-29 10:49:24 +00:00
00c608c05e [#1524] tree: Make check APE error get wrapped to api status
All checks were successful
Tests and linters / Run gofumpt (push) Successful in 2m57s
Tests and linters / Staticcheck (push) Successful in 3m40s
Vulncheck / Vulncheck (push) Successful in 3m47s
Build / Build Components (push) Successful in 4m40s
Pre-commit hooks / Pre-commit (push) Successful in 4m51s
Tests and linters / gopls check (push) Successful in 5m3s
Tests and linters / Tests with -race (push) Successful in 5m52s
Tests and linters / Tests (push) Successful in 6m47s
Tests and linters / Lint (push) Successful in 6m49s
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-29 10:48:16 +00:00
bba1892fa1 [#1524] ape: Make APE checker return error without status
Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-11-29 10:48:16 +00:00
01acec708f
[#1525] pilorama: Use AppendUint* helpers from stdlib
All checks were successful
Tests and linters / Run gofumpt (pull_request) Successful in 2m6s
DCO action / DCO (pull_request) Successful in 2m24s
Pre-commit hooks / Pre-commit (pull_request) Successful in 2m54s
Vulncheck / Vulncheck (pull_request) Successful in 2m49s
Build / Build Components (pull_request) Successful in 3m13s
Tests and linters / gopls check (pull_request) Successful in 3m23s
Tests and linters / Staticcheck (pull_request) Successful in 3m54s
Tests and linters / Lint (pull_request) Successful in 4m41s
Tests and linters / Tests (pull_request) Successful in 4m56s
Tests and linters / Tests with -race (pull_request) Successful in 5m57s
Tests and linters / Run gofumpt (push) Successful in 3m4s
Vulncheck / Vulncheck (push) Successful in 3m23s
Tests and linters / Staticcheck (push) Successful in 3m51s
Build / Build Components (push) Successful in 4m21s
Pre-commit hooks / Pre-commit (push) Successful in 4m41s
Tests and linters / gopls check (push) Successful in 4m41s
Tests and linters / Tests with -race (push) Successful in 5m15s
Tests and linters / Lint (push) Successful in 5m56s
Tests and linters / Tests (push) Successful in 6m7s
gopatch:
```
@@
var slice, e expression
@@
+import "encoding/binary"

-append(slice, byte(e), byte(e >> 8))
+binary.LittleEndian.AppendUint16(slice, e)
```

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-28 09:40:20 +03:00
aac65001e5 [#1522] adm/frostfsid: Remove unreachable condition
All checks were successful
Vulncheck / Vulncheck (push) Successful in 2m35s
Tests and linters / Staticcheck (push) Successful in 2m52s
Tests and linters / Run gofumpt (push) Successful in 2m55s
Build / Build Components (push) Successful in 3m13s
Pre-commit hooks / Pre-commit (push) Successful in 3m15s
Tests and linters / gopls check (push) Successful in 3m53s
Tests and linters / Lint (push) Successful in 4m4s
Tests and linters / Tests (push) Successful in 4m21s
Tests and linters / Tests with -race (push) Successful in 4m59s
SendConsensusTx() modifies SendTxs field, if it is not the case, there
is a bug in code.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
1170370753 [#1522] adm/helper: Rename createSingleAccounts() -> getSingleAccounts()
It doesn't create any accounts, purely finds them in the wallet.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
9e275d44c8 [#1522] adm/helper: Unexport DefaultClientContext()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
2469e0c683 [#1522] adm/helper: Remove NewActor() helper
It is used once, it is used only internally and it is single-statement.
I see no justification in having it as a separate function.
It introduces confusion, because we also have NewLocalActor().

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
a6ef4ab524 [#1522] adm/helper: Rename GetN3Client() -> NewRemoteClient()
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
49959c4166 [#1522] adm/helper: Unexport GetFrostfsIDAdmin()
It is used in `helper` package only, besides unit-tests.
Move unit-tests to the same package, where they belong.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
61ee1b5610 [#1522] adm: Simplify LocalClient.SendRawTransaction()
The old code was there before Copy() method was introduced.
It was also supposed to check errors, however, they are already checked
server-side.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
b10c954377 [#1522] adm: Split NewLocalClient() into functions
No functional changes.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
1605391628 [#1522] adm/helper: Simplify Client interface
Just reuse `actor.RPCActor`. No functional changes.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
b1766e47c7 [#1522] adm/helper: Remove unused GetCommittee() method from the Client interface
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
caa4253249 [#1522] adm: Remove unnecessary variable declaration
It is better to have small scope.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
2024-11-26 08:13:35 +00:00
239 changed files with 2230 additions and 2365 deletions

3
CODEOWNERS Normal file
View file

@ -0,0 +1,3 @@
.* @TrueCloudLab/storage-core-committers @TrueCloudLab/storage-core-developers
.forgejo/.* @potyarkin
Makefile @potyarkin

View file

@ -270,10 +270,12 @@ env-up: all
echo "Frostfs contracts not found"; exit 1; \
fi
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH}
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet01.json --gas 10.0
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet02.json --gas 10.0
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet03.json --gas 10.0
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet04.json --gas 10.0
${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --gas 10.0 \
--storage-wallet ./dev/storage/wallet01.json \
--storage-wallet ./dev/storage/wallet02.json \
--storage-wallet ./dev/storage/wallet03.json \
--storage-wallet ./dev/storage/wallet04.json
@if [ ! -f "$(LOCODE_DB_PATH)" ]; then \
make locode-download; \
fi

View file

@ -135,7 +135,7 @@ func createContainerInfoProvider(cli *client.Client) (container.InfoProvider, er
if err != nil {
return nil, fmt.Errorf("resolve container contract hash: %w", err)
}
cc, err := morphcontainer.NewFromMorph(cli, sh, 0, morphcontainer.TryNotary())
cc, err := morphcontainer.NewFromMorph(cli, sh, 0)
if err != nil {
return nil, fmt.Errorf("create morph container client: %w", err)
}

View file

@ -53,16 +53,15 @@ func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke {
}
func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
inv := invoker.New(c, nil)
var ch util.Uint160
r := management.NewReader(inv)
nnsCs, err := helper.GetContractByID(r, 1)
commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err)
ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract))
ch, err := helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract))
commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err)
invokerAdapter := &invokerAdapter{
@ -74,7 +73,7 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag
}
func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName)

View file

@ -51,7 +51,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
nmHash util.Uint160
)
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return err
}

View file

@ -26,7 +26,7 @@ import (
const forceConfigSet = "force"
func dumpNetworkConfig(cmd *cobra.Command, _ []string) error {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return fmt.Errorf("can't create N3 client: %w", err)
}

View file

@ -76,7 +76,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("invalid filename: %w", err)
}
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return fmt.Errorf("can't create N3 client: %w", err)
}
@ -157,7 +157,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo
}
func listContainers(cmd *cobra.Command, _ []string) error {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return fmt.Errorf("can't create N3 client: %w", err)
}

View file

@ -36,7 +36,7 @@ type contractDumpInfo struct {
}
func dumpContractHashes(cmd *cobra.Command, _ []string) error {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return fmt.Errorf("can't create N3 client: %w", err)
}

View file

@ -1,7 +1,6 @@
package frostfsid
import (
"errors"
"fmt"
"math/big"
"sort"
@ -489,10 +488,6 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) {
}
f.bw.Reset()
if len(f.wCtx.SentTxs) == 0 {
return nil, errors.New("no transactions to wait")
}
f.wCtx.Command.Println("Waiting for transactions to persist...")
return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil)
}
@ -514,7 +509,7 @@ func readIterator(inv *invoker.Invoker, iter *result.Iterator, batchSize int, se
}
func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Uint160) {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
inv := invoker.New(c, nil)

View file

@ -1,59 +1,12 @@
package frostfsid
import (
"encoding/hex"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestFrostfsIDConfig(t *testing.T) {
pks := make([]*keys.PrivateKey, 4)
for i := range pks {
pk, err := keys.NewPrivateKey()
require.NoError(t, err)
pks[i] = pk
}
fmts := []string{
pks[0].GetScriptHash().StringLE(),
address.Uint160ToString(pks[1].GetScriptHash()),
hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()),
hex.EncodeToString(pks[3].PublicKey().Bytes()),
}
for i := range fmts {
v := viper.New()
v.Set("frostfsid.admin", fmts[i])
actual, found, err := helper.GetFrostfsIDAdmin(v)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, pks[i].GetScriptHash(), actual)
}
t.Run("bad key", func(t *testing.T) {
v := viper.New()
v.Set("frostfsid.admin", "abc")
_, found, err := helper.GetFrostfsIDAdmin(v)
require.Error(t, err)
require.True(t, found)
})
t.Run("missing key", func(t *testing.T) {
v := viper.New()
_, found, err := helper.GetFrostfsIDAdmin(v)
require.NoError(t, err)
require.False(t, found)
})
}
func TestNamespaceRegexp(t *testing.T) {
for _, tc := range []struct {
name string

View file

@ -12,7 +12,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -141,60 +140,29 @@ func addMultisigAccount(w *wallet.Wallet, m int, name, password string, pubs key
}
func generateStorageCreds(cmd *cobra.Command, _ []string) error {
return refillGas(cmd, storageGasConfigFlag, true)
}
func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) {
// storage wallet path is not part of the config
storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag)
// wallet address is not part of the config
walletAddress, _ := cmd.Flags().GetString(walletAddressFlag)
var gasReceiver util.Uint160
if len(walletAddress) != 0 {
gasReceiver, err = address.StringToUint160(walletAddress)
if err != nil {
return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err)
}
} else {
if storageWalletPath == "" {
return fmt.Errorf("missing wallet path (use '--%s <out.json>')", commonflags.StorageWalletFlag)
}
var w *wallet.Wallet
if createWallet {
w, err = wallet.NewWallet(storageWalletPath)
} else {
w, err = wallet.NewWalletFromFile(storageWalletPath)
}
if err != nil {
return fmt.Errorf("can't create wallet: %w", err)
}
if createWallet {
var password string
label, _ := cmd.Flags().GetString(storageWalletLabelFlag)
password, err := config.GetStoragePassword(viper.GetViper(), label)
if err != nil {
return fmt.Errorf("can't fetch password: %w", err)
}
if label == "" {
label = constants.SingleAccountName
}
if err := w.CreateAccount(label, password); err != nil {
return fmt.Errorf("can't create account: %w", err)
}
}
gasReceiver = w.Accounts[0].Contract.ScriptHash()
walletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag)
w, err := wallet.NewWallet(walletPath)
if err != nil {
return fmt.Errorf("create wallet: %w", err)
}
label, _ := cmd.Flags().GetString(storageWalletLabelFlag)
password, err := config.GetStoragePassword(viper.GetViper(), label)
if err != nil {
return fmt.Errorf("can't fetch password: %w", err)
}
if label == "" {
label = constants.SingleAccountName
}
if err := w.CreateAccount(label, password); err != nil {
return fmt.Errorf("can't create account: %w", err)
}
return refillGas(cmd, storageGasConfigFlag, w.Accounts[0].ScriptHash())
}
func refillGas(cmd *cobra.Command, gasFlag string, gasReceivers ...util.Uint160) (err error) {
gasStr := viper.GetString(gasFlag)
gasAmount, err := helper.ParseGASAmount(gasStr)
@ -208,9 +176,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
}
bw := io.NewBufBinWriter()
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
for _, gasReceiver := range gasReceivers {
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
}
if bw.Err != nil {
return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err)
}

View file

@ -1,7 +1,12 @@
package generate
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@ -33,7 +38,27 @@ var (
_ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag))
},
RunE: func(cmd *cobra.Command, _ []string) error {
return refillGas(cmd, commonflags.RefillGasAmountFlag, false)
storageWalletPaths, _ := cmd.Flags().GetStringArray(commonflags.StorageWalletFlag)
walletAddresses, _ := cmd.Flags().GetStringArray(walletAddressFlag)
var gasReceivers []util.Uint160
for _, walletAddress := range walletAddresses {
addr, err := address.StringToUint160(walletAddress)
if err != nil {
return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err)
}
gasReceivers = append(gasReceivers, addr)
}
for _, storageWalletPath := range storageWalletPaths {
w, err := wallet.NewWalletFromFile(storageWalletPath)
if err != nil {
return fmt.Errorf("can't create wallet: %w", err)
}
gasReceivers = append(gasReceivers, w.Accounts[0].Contract.ScriptHash())
}
return refillGas(cmd, commonflags.RefillGasAmountFlag, gasReceivers...)
},
}
GenerateAlphabetCmd = &cobra.Command{
@ -50,10 +75,10 @@ var (
func initRefillGasCmd() {
RefillGasCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
RefillGasCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
RefillGasCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet")
RefillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet")
RefillGasCmd.Flags().StringArray(commonflags.StorageWalletFlag, nil, "Path to storage node wallet")
RefillGasCmd.Flags().StringArray(walletAddressFlag, nil, "Address of wallet")
RefillGasCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Additional amount of GAS to transfer")
RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, commonflags.StorageWalletFlag)
RefillGasCmd.MarkFlagsOneRequired(walletAddressFlag, commonflags.StorageWalletFlag)
}
func initGenerateStorageCmd() {

View file

@ -82,7 +82,7 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any
h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker)
}
if method != constants.UpdateMethodName || err == nil && !found {
h, found, err = GetFrostfsIDAdmin(viper.GetViper())
h, found, err = getFrostfsIDAdmin(viper.GetViper())
}
if err != nil {
return nil, err

View file

@ -11,7 +11,7 @@ import (
const frostfsIDAdminConfigKey = "frostfsid.admin"
func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) {
func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) {
admin := v.GetString(frostfsIDAdminConfigKey)
if admin == "" {
return util.Uint160{}, false, nil

View file

@ -0,0 +1,53 @@
package helper
import (
"encoding/hex"
"testing"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestFrostfsIDConfig(t *testing.T) {
pks := make([]*keys.PrivateKey, 4)
for i := range pks {
pk, err := keys.NewPrivateKey()
require.NoError(t, err)
pks[i] = pk
}
fmts := []string{
pks[0].GetScriptHash().StringLE(),
address.Uint160ToString(pks[1].GetScriptHash()),
hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()),
hex.EncodeToString(pks[3].PublicKey().Bytes()),
}
for i := range fmts {
v := viper.New()
v.Set("frostfsid.admin", fmts[i])
actual, found, err := getFrostfsIDAdmin(v)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, pks[i].GetScriptHash(), actual)
}
t.Run("bad key", func(t *testing.T) {
v := viper.New()
v.Set("frostfsid.admin", "abc")
_, found, err := getFrostfsIDAdmin(v)
require.Error(t, err)
require.True(t, found)
})
t.Run("missing key", func(t *testing.T) {
v := viper.New()
_, found, err := getFrostfsIDAdmin(v)
require.NoError(t, err)
require.False(t, found)
})
}

View file

@ -134,12 +134,12 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex
return nil, err
}
accounts, err := createWalletAccounts(wallets)
accounts, err := getSingleAccounts(wallets)
if err != nil {
return nil, err
}
cliCtx, err := DefaultClientContext(c, committeeAcc)
cliCtx, err := defaultClientContext(c, committeeAcc)
if err != nil {
return nil, fmt.Errorf("client context: %w", err)
}
@ -191,7 +191,7 @@ func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet)
}
c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String())
} else {
c, err = GetN3Client(v)
c, err = NewRemoteClient(v)
}
if err != nil {
return nil, fmt.Errorf("can't create N3 client: %w", err)
@ -211,7 +211,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) {
return ctrPath, nil
}
func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
func getSingleAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) {
accounts := make([]*wallet.Account, len(wallets))
for i, w := range wallets {
acc, err := GetWalletAccount(w, constants.SingleAccountName)

View file

@ -58,17 +58,59 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
return nil, err
}
m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount))
accounts := make([]*wallet.Account, len(wallets))
for i := range accounts {
accounts[i], err = GetWalletAccount(wallets[i], constants.ConsensusAccountName)
if err != nil {
return nil, err
go bc.Run()
accounts, err := getBlockSigningAccounts(cfg.ProtocolConfiguration, wallets)
if err != nil {
return nil, err
}
if cmd.Name() != "init" {
if err := restoreDump(bc, dumpPath); err != nil {
return nil, fmt.Errorf("restore dump: %w", err)
}
}
return &LocalClient{
bc: bc,
dumpPath: dumpPath,
accounts: accounts,
}, nil
}
func restoreDump(bc *core.Blockchain, dumpPath string) error {
f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600)
if err != nil {
return fmt.Errorf("can't open local dump: %w", err)
}
defer f.Close()
r := io.NewBinReaderFromIO(f)
var skip uint32
if bc.BlockHeight() != 0 {
skip = bc.BlockHeight() + 1
}
count := r.ReadU32LE() - skip
if err := chaindump.Restore(bc, r, skip, count, nil); err != nil {
return err
}
return nil
}
func getBlockSigningAccounts(cfg config.ProtocolConfiguration, wallets []*wallet.Wallet) ([]*wallet.Account, error) {
accounts := make([]*wallet.Account, len(wallets))
for i := range accounts {
acc, err := GetWalletAccount(wallets[i], constants.ConsensusAccountName)
if err != nil {
return nil, err
}
accounts[i] = acc
}
indexMap := make(map[string]int)
for i, pub := range cfg.ProtocolConfiguration.StandbyCommittee {
for i, pub := range cfg.StandbyCommittee {
indexMap[pub] = i
}
@ -77,37 +119,12 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
pj := accounts[j].PrivateKey().PublicKey().Bytes()
return indexMap[string(pi)] < indexMap[string(pj)]
})
sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool {
sort.Slice(accounts[:cfg.ValidatorsCount], func(i, j int) bool {
return accounts[i].PublicKey().Cmp(accounts[j].PublicKey()) == -1
})
go bc.Run()
if cmd.Name() != "init" {
f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600)
if err != nil {
return nil, fmt.Errorf("can't open local dump: %w", err)
}
defer f.Close()
r := io.NewBinReaderFromIO(f)
var skip uint32
if bc.BlockHeight() != 0 {
skip = bc.BlockHeight() + 1
}
count := r.ReadU32LE() - skip
if err := chaindump.Restore(bc, r, skip, count, nil); err != nil {
return nil, fmt.Errorf("can't restore local dump: %w", err)
}
}
return &LocalClient{
bc: bc,
dumpPath: dumpPath,
accounts: accounts[:m],
}, nil
m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ValidatorsCount))
return accounts[:m], nil
}
func (l *LocalClient) GetBlockCount() (uint32, error) {
@ -128,11 +145,6 @@ func (l *LocalClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul
return &a, nil
}
func (l *LocalClient) GetCommittee() (keys.PublicKeys, error) {
// not used by `morph init` command
panic("unexpected call")
}
// InvokeFunction is implemented via `InvokeScript`.
func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
var err error
@ -296,13 +308,7 @@ func (l *LocalClient) InvokeScript(script []byte, signers []transaction.Signer)
}
func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) {
// We need to test that transaction was formed correctly to catch as many errors as we can.
bs := tx.Bytes()
_, err := transaction.NewTransactionFromBytes(bs)
if err != nil {
return tx.Hash(), fmt.Errorf("invalid transaction: %w", err)
}
tx = tx.Copy()
l.transactions = append(l.transactions, tx)
return tx.Hash(), nil
}

View file

@ -10,7 +10,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
@ -25,15 +24,10 @@ import (
// Client represents N3 client interface capable of test-invoking scripts
// and sending signed transactions to chain.
type Client interface {
invoker.RPCInvoke
actor.RPCActor
GetBlockCount() (uint32, error)
GetNativeContracts() ([]state.Contract, error)
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
GetVersion() (*result.Version, error)
SendRawTransaction(*transaction.Transaction) (util.Uint256, error)
GetCommittee() (keys.PublicKeys, error)
CalculateNetworkFee(tx *transaction.Transaction) (int64, error)
}
type HashVUBPair struct {
@ -48,7 +42,7 @@ type ClientContext struct {
SentTxs []HashVUBPair
}
func GetN3Client(v *viper.Viper) (Client, error) {
func NewRemoteClient(v *viper.Viper) (Client, error) {
// number of opened connections
// by neo-go client per one host
const (
@ -88,8 +82,14 @@ func GetN3Client(v *viper.Viper) (Client, error) {
return c, nil
}
func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
commAct, err := NewActor(c, committeeAcc)
func defaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) {
commAct, err := actor.New(c, []actor.SignerAccount{{
Signer: transaction.Signer{
Account: committeeAcc.Contract.ScriptHash(),
Scopes: transaction.Global,
},
Account: committeeAcc,
}})
if err != nil {
return nil, err
}

View file

@ -15,10 +15,8 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/viper"
@ -87,16 +85,6 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er
return wallets, nil
}
func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) {
return actor.New(c, []actor.SignerAccount{{
Signer: transaction.Signer{
Account: committeeAcc.Contract.ScriptHash(),
Scopes: transaction.Global,
},
Account: committeeAcc,
}})
}
func ReadContract(ctrPath, ctrName string) (*ContractState, error) {
rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef"))
if err != nil {

View file

@ -13,7 +13,7 @@ import (
)
func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
inv := invoker.New(c, nil)

View file

@ -13,7 +13,7 @@ import (
func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
v := viper.GetViper()
c, err := helper.GetN3Client(v)
c, err := helper.NewRemoteClient(v)
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName)
@ -26,7 +26,7 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) {
}
func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err)
inv := invoker.New(c, nil)

View file

@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"math/big"
"strconv"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper"
@ -41,7 +40,8 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
}
accHash := w.GetChangeAddress()
if addr, err := cmd.Flags().GetString(walletAccountFlag); err == nil {
addr, _ := cmd.Flags().GetString(walletAccountFlag)
if addr != "" {
accHash, err = address.StringToUint160(addr)
if err != nil {
return fmt.Errorf("invalid address: %s", addr)
@ -53,7 +53,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("can't find account for %s", accHash)
}
prompt := fmt.Sprintf("Enter password for %s >", address.Uint160ToString(accHash))
prompt := fmt.Sprintf("Enter password for %s > ", address.Uint160ToString(accHash))
pass, err := input.ReadPassword(prompt)
if err != nil {
return fmt.Errorf("can't get password: %v", err)
@ -73,23 +73,16 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
return err
}
till := int64(defaultNotaryDepositLifetime)
tillStr, err := cmd.Flags().GetString(notaryDepositTillFlag)
if err != nil {
return err
}
if tillStr != "" {
till, err = strconv.ParseInt(tillStr, 10, 64)
if err != nil || till <= 0 {
return errInvalidNotaryDepositLifetime
}
till, _ := cmd.Flags().GetInt64(notaryDepositTillFlag)
if till <= 0 {
return errInvalidNotaryDepositLifetime
}
return transferGas(cmd, acc, accHash, gasAmount, till)
}
func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
if err != nil {
return err
}

View file

@ -20,7 +20,7 @@ func initDepositoryNotaryCmd() {
DepositCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet")
DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
DepositCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Amount of GAS to deposit")
DepositCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks")
DepositCmd.Flags().Int64(notaryDepositTillFlag, defaultNotaryDepositLifetime, "Notary deposit duration in blocks")
}
func init() {

View file

@ -62,7 +62,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error {
}
func dumpPolicyCmd(cmd *cobra.Command, _ []string) error {
c, err := helper.GetN3Client(viper.GetViper())
c, err := helper.NewRemoteClient(viper.GetViper())
commonCmd.ExitOnErr(cmd, "can't create N3 client:", err)
inv := invoker.New(c, nil)

View file

@ -20,23 +20,32 @@ const (
accountAddressFlag = "account"
)
func parseAddresses(cmd *cobra.Command) []util.Uint160 {
var addrs []util.Uint160
accs, _ := cmd.Flags().GetStringArray(accountAddressFlag)
for _, acc := range accs {
addr, err := address.StringToUint160(acc)
commonCmd.ExitOnErr(cmd, "invalid account: %w", err)
addrs = append(addrs, addr)
}
return addrs
}
func addProxyAccount(cmd *cobra.Command, _ []string) {
acc, _ := cmd.Flags().GetString(accountAddressFlag)
addr, err := address.StringToUint160(acc)
commonCmd.ExitOnErr(cmd, "invalid account: %w", err)
err = processAccount(cmd, addr, "addAccount")
addrs := parseAddresses(cmd)
err := processAccount(cmd, addrs, "addAccount")
commonCmd.ExitOnErr(cmd, "processing error: %w", err)
}
func removeProxyAccount(cmd *cobra.Command, _ []string) {
acc, _ := cmd.Flags().GetString(accountAddressFlag)
addr, err := address.StringToUint160(acc)
commonCmd.ExitOnErr(cmd, "invalid account: %w", err)
err = processAccount(cmd, addr, "removeAccount")
addrs := parseAddresses(cmd)
err := processAccount(cmd, addrs, "removeAccount")
commonCmd.ExitOnErr(cmd, "processing error: %w", err)
}
func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error {
func processAccount(cmd *cobra.Command, addrs []util.Uint160, method string) error {
wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper())
if err != nil {
return fmt.Errorf("can't initialize context: %w", err)
@ -54,7 +63,9 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error
}
bw := io.NewBufBinWriter()
emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr)
for _, addr := range addrs {
emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr)
}
if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil {
return err

View file

@ -29,13 +29,15 @@ var (
func initProxyAddAccount() {
AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string")
AddAccountCmd.Flags().StringArray(accountAddressFlag, nil, "Wallet address string")
_ = AddAccountCmd.MarkFlagRequired(accountAddressFlag)
AddAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
}
func initProxyRemoveAccount() {
RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string")
RemoveAccountCmd.Flags().StringArray(accountAddressFlag, nil, "Wallet address string")
_ = AddAccountCmd.MarkFlagRequired(accountAddressFlag)
RemoveAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
}

View file

@ -105,7 +105,7 @@ func storageConfig(cmd *cobra.Command, args []string) {
fatalOnErr(errors.New("can't find account in wallet"))
}
c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Account password for %s: ", c.Wallet.Account))
c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Enter password for %s > ", c.Wallet.Account))
fatalOnErr(err)
err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams())

View file

@ -9,7 +9,6 @@ import (
"io"
"os"
"slices"
"sort"
"strings"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
@ -78,13 +77,31 @@ func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContain
// SortedIDList returns sorted list of identifiers of user's containers.
func (x ListContainersRes) SortedIDList() []cid.ID {
list := x.cliRes.Containers()
sort.Slice(list, func(i, j int) bool {
lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString()
return strings.Compare(lhs, rhs) < 0
slices.SortFunc(list, func(lhs, rhs cid.ID) int {
return strings.Compare(lhs.EncodeToString(), rhs.EncodeToString())
})
return list
}
func ListContainersStream(ctx context.Context, prm ListContainersPrm, processCnr func(id cid.ID) bool) (err error) {
cliPrm := &client.PrmContainerListStream{
XHeaders: prm.XHeaders,
OwnerID: prm.OwnerID,
Session: prm.Session,
}
rdr, err := prm.cli.ContainerListInit(ctx, *cliPrm)
if err != nil {
return fmt.Errorf("init container list: %w", err)
}
err = rdr.Iterate(processCnr)
if err != nil {
return fmt.Errorf("read container list: %w", err)
}
return
}
// PutContainerPrm groups parameters of PutContainer operation.
type PutContainerPrm struct {
Client *client.Client

View file

@ -6,8 +6,11 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// flags of list command.
@ -51,44 +54,60 @@ var listContainersCmd = &cobra.Command{
var prm internalclient.ListContainersPrm
prm.SetClient(cli)
prm.Account = idUser
res, err := internalclient.ListContainers(cmd.Context(), prm)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
prm.OwnerID = idUser
prmGet := internalclient.GetContainerPrm{
Client: cli,
}
var containerIDs []cid.ID
err := internalclient.ListContainersStream(cmd.Context(), prm, func(id cid.ID) bool {
printContainer(cmd, prmGet, id)
return false
})
if err == nil {
return
}
if e, ok := status.FromError(err); ok && e.Code() == codes.Unimplemented {
res, err := internalclient.ListContainers(cmd.Context(), prm)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
containerIDs = res.SortedIDList()
} else {
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
}
containerIDs := res.SortedIDList()
for _, cnrID := range containerIDs {
if flagVarListName == "" && !flagVarListPrintAttr {
cmd.Println(cnrID.String())
continue
}
prmGet.ClientParams.ContainerID = &cnrID
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
if err != nil {
cmd.Printf(" failed to read attributes: %v\n", err)
continue
}
cnr := res.Container()
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
continue
}
cmd.Println(cnrID.String())
if flagVarListPrintAttr {
cnr.IterateUserAttributes(func(key, val string) {
cmd.Printf(" %s: %s\n", key, val)
})
}
printContainer(cmd, prmGet, cnrID)
}
},
}
func printContainer(cmd *cobra.Command, prmGet internalclient.GetContainerPrm, id cid.ID) {
if flagVarListName == "" && !flagVarListPrintAttr {
cmd.Println(id.String())
return
}
prmGet.ClientParams.ContainerID = &id
res, err := internalclient.GetContainer(cmd.Context(), prmGet)
if err != nil {
cmd.Printf(" failed to read attributes: %v\n", err)
return
}
cnr := res.Container()
if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName {
return
}
cmd.Println(id.String())
if flagVarListPrintAttr {
cnr.IterateUserAttributes(func(key, val string) {
cmd.Printf(" %s: %s\n", key, val)
})
}
}
func initContainerListContainersCmd() {
commonflags.Init(listContainersCmd)

View file

@ -1,56 +0,0 @@
package control
import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
"github.com/spf13/cobra"
)
const ignoreErrorsFlag = "no-errors"
var evacuateShardCmd = &cobra.Command{
Use: "evacuate",
Short: "Evacuate objects from shard",
Long: "Evacuate objects from shard to other shards",
Run: evacuateShard,
Deprecated: "use frostfs-cli control shards evacuation start",
}
func evacuateShard(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd)
req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)}
req.Body.Shard_ID = getShardIDList(cmd)
req.Body.IgnoreErrors, _ = cmd.Flags().GetBool(ignoreErrorsFlag)
signRequest(cmd, pk, req)
cli := getClient(cmd, pk)
var resp *control.EvacuateShardResponse
var err error
err = cli.ExecRaw(func(client *client.Client) error {
resp, err = control.EvacuateShard(client, req)
return err
})
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
cmd.Printf("Objects moved: %d\n", resp.GetBody().GetCount())
verifyResponse(cmd, resp.GetSignature(), resp.GetBody())
cmd.Println("Shard has successfully been evacuated.")
}
func initControlEvacuateShardCmd() {
initControlFlags(evacuateShardCmd)
flags := evacuateShardCmd.Flags()
flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding")
flags.Bool(shardAllFlag, false, "Process all shards")
flags.Bool(ignoreErrorsFlag, false, "Skip invalid/unreadable objects")
evacuateShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
}

View file

@ -17,10 +17,11 @@ import (
)
const (
awaitFlag = "await"
noProgressFlag = "no-progress"
scopeFlag = "scope"
repOneOnlyFlag = "rep-one-only"
awaitFlag = "await"
noProgressFlag = "no-progress"
scopeFlag = "scope"
repOneOnlyFlag = "rep-one-only"
ignoreErrorsFlag = "no-errors"
containerWorkerCountFlag = "container-worker-count"
objectWorkerCountFlag = "object-worker-count"

View file

@ -13,7 +13,6 @@ var shardsCmd = &cobra.Command{
func initControlShardsCmd() {
shardsCmd.AddCommand(listShardsCmd)
shardsCmd.AddCommand(setShardModeCmd)
shardsCmd.AddCommand(evacuateShardCmd)
shardsCmd.AddCommand(evacuationShardCmd)
shardsCmd.AddCommand(flushCacheCmd)
shardsCmd.AddCommand(doctorCmd)
@ -23,7 +22,6 @@ func initControlShardsCmd() {
initControlShardsListCmd()
initControlSetShardModeCmd()
initControlEvacuateShardCmd()
initControlEvacuationShardCmd()
initControlFlushCacheCmd()
initControlDoctorCmd()

View file

@ -9,7 +9,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"github.com/spf13/cobra"
@ -43,6 +42,8 @@ func initObjectHashCmd() {
_ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag)
flags.String("range", "", "Range to take hash from in the form offset1:length1,...")
_ = objectHashCmd.MarkFlagRequired("range")
flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'")
flags.String(getRangeHashSaltFlag, "", "Salt in hex format")
}
@ -66,36 +67,6 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd)
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
tz := typ == hashTz
fullHash := len(ranges) == 0
if fullHash {
var headPrm internalclient.HeadObjectPrm
headPrm.SetClient(cli)
Prepare(cmd, &headPrm)
headPrm.SetAddress(objAddr)
// get hash of full payload through HEAD (may be user can do it through dedicated command?)
res, err := internalclient.HeadObject(cmd.Context(), headPrm)
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
var cs checksum.Checksum
var csSet bool
if tz {
cs, csSet = res.Header().PayloadHomomorphicHash()
} else {
cs, csSet = res.Header().PayloadChecksum()
}
if csSet {
cmd.Println(hex.EncodeToString(cs.Value()))
} else {
cmd.Println("Missing checksum in object header.")
}
return
}
var hashPrm internalclient.HashPayloadRangesPrm
hashPrm.SetClient(cli)
Prepare(cmd, &hashPrm)
@ -104,7 +75,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) {
hashPrm.SetSalt(salt)
hashPrm.SetRanges(ranges)
if tz {
if typ == hashTz {
hashPrm.TZ()
}

View file

@ -1,15 +1,12 @@
package object
import (
"bytes"
"cmp"
"context"
"crypto/ecdsa"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"slices"
"sync"
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
@ -507,7 +504,6 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID,
}
func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
normilizeObjectNodesResult(objects, result)
if json, _ := cmd.Flags().GetBool(commonflags.JSON); json {
printObjectNodesAsJSON(cmd, objID, objects, result)
} else {
@ -515,34 +511,6 @@ func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, resul
}
}
func normilizeObjectNodesResult(objects []phyObject, result *objectNodesResult) {
slices.SortFunc(objects, func(lhs, rhs phyObject) int {
if lhs.ecHeader == nil && rhs.ecHeader == nil {
return bytes.Compare(lhs.objectID[:], rhs.objectID[:])
}
if lhs.ecHeader == nil {
return -1
}
if rhs.ecHeader == nil {
return 1
}
if lhs.ecHeader.parent == rhs.ecHeader.parent {
return cmp.Compare(lhs.ecHeader.index, rhs.ecHeader.index)
}
return bytes.Compare(lhs.ecHeader.parent[:], rhs.ecHeader.parent[:])
})
for _, obj := range objects {
op := result.placements[obj.objectID]
slices.SortFunc(op.confirmedNodes, func(lhs, rhs netmapSDK.NodeInfo) int {
return bytes.Compare(lhs.PublicKey(), rhs.PublicKey())
})
slices.SortFunc(op.requiredNodes, func(lhs, rhs netmapSDK.NodeInfo) int {
return bytes.Compare(lhs.PublicKey(), rhs.PublicKey())
})
result.placements[obj.objectID] = op
}
}
func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) {
fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects))

View file

@ -77,7 +77,7 @@ func (c *httpComponent) reload(ctx context.Context) {
log.Info(ctx, c.name+" config updated")
if err := c.shutdown(ctx); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()),
zap.Error(err),
)
} else {
c.init(ctx)

View file

@ -119,12 +119,12 @@ func shutdown(ctx context.Context) {
innerRing.Stop(ctx)
if err := metricsCmp.shutdown(ctx); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()),
zap.Error(err),
)
}
if err := pprofCmp.shutdown(ctx); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()),
zap.Error(err),
)
}

View file

@ -58,7 +58,7 @@ func (c *pprofComponent) reload(ctx context.Context) {
log.Info(ctx, c.name+" config updated")
if err := c.shutdown(ctx); err != nil {
log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer,
zap.String("error", err.Error()))
zap.Error(err))
return
}

View file

@ -19,6 +19,7 @@ func initAPEManagerService(c *cfg) {
c.cfgObject.cfgAccessPolicyEngine.policyContractHash)
execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage,
c.cfgMorph.client,
apemanager.WithLogger(c.log))
sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc)
auditSvc := apemanager.NewAuditService(sigsvc, c.log, c.audit)

View file

@ -591,8 +591,6 @@ type cfgMorph struct {
client *client.Client
notaryEnabled bool
// TTL of Sidechain cached values. Non-positive value disables caching.
cacheTTL time.Duration
@ -608,9 +606,10 @@ type cfgAccounting struct {
type cfgContainer struct {
scriptHash neogoutil.Uint160
parsers map[event.Type]event.NotificationParser
subscribers map[event.Type][]event.Handler
workerPool util.WorkerPool // pool for asynchronous handlers
parsers map[event.Type]event.NotificationParser
subscribers map[event.Type][]event.Handler
workerPool util.WorkerPool // pool for asynchronous handlers
containerBatchSize uint32
}
type cfgFrostfsID struct {
@ -1121,7 +1120,7 @@ func initLocalStorage(ctx context.Context, c *cfg) {
err := ls.Close(context.WithoutCancel(ctx))
if err != nil {
c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure,
zap.String("error", err.Error()),
zap.Error(err),
)
} else {
c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully)
@ -1211,7 +1210,7 @@ func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) {
if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch,
zap.Uint64("epoch", epoch),
zap.String("error", err.Error()))
zap.Error(err))
return
}
@ -1221,9 +1220,9 @@ func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) {
// bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract
// with the binary-encoded information from the current node's configuration.
// The state is set using the provided setter which MUST NOT be nil.
func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.NodeInfo)) error {
func (c *cfg) bootstrapWithState(ctx context.Context, state netmap.NodeState) error {
ni := c.cfgNodeInfo.localInfo
stateSetter(&ni)
ni.SetStatus(state)
prm := nmClient.AddPeerPrm{}
prm.SetNodeInfo(ni)
@ -1233,9 +1232,7 @@ func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.N
// bootstrapOnline calls cfg.bootstrapWithState with "online" state.
func bootstrapOnline(ctx context.Context, c *cfg) error {
return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Online)
})
return c.bootstrapWithState(ctx, netmap.Online)
}
// bootstrap calls bootstrapWithState with:
@ -1246,9 +1243,7 @@ func (c *cfg) bootstrap(ctx context.Context) error {
st := c.cfgNetmap.state.controlNetmapStatus()
if st == control.NetmapStatus_MAINTENANCE {
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState)
return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) {
ni.SetStatus(netmap.Maintenance)
})
return c.bootstrapWithState(ctx, netmap.Maintenance)
}
c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState,
@ -1466,7 +1461,7 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker {
func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider {
return container.NewInfoProvider(func() (container.Source, error) {
c.initMorphComponents(ctx)
cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary())
cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
if err != nil {
return nil, err
}

View file

@ -0,0 +1,27 @@
package containerconfig
import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
const (
subsection = "container"
listStreamSubsection = "list_stream"
// ContainerBatchSizeDefault represents the maximum amount of containers to send via stream at once.
ContainerBatchSizeDefault = 1000
)
// ContainerBatchSize returns the value of "batch_size" config parameter
// from "list_stream" subsection of "container" section.
//
// Returns ContainerBatchSizeDefault if the value is missing or if
// the value is not positive integer.
func ContainerBatchSize(c *config.Config) uint32 {
if c.Sub(subsection).Sub(listStreamSubsection).Value("batch_size") == nil {
return ContainerBatchSizeDefault
}
size := config.Uint32Safe(c.Sub(subsection).Sub(listStreamSubsection), "batch_size")
if size == 0 {
return ContainerBatchSizeDefault
}
return size
}

View file

@ -0,0 +1,27 @@
package containerconfig_test
import (
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container"
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
"github.com/stretchr/testify/require"
)
func TestContainerSection(t *testing.T) {
t.Run("defaults", func(t *testing.T) {
empty := configtest.EmptyConfig()
require.Equal(t, uint32(containerconfig.ContainerBatchSizeDefault), containerconfig.ContainerBatchSize(empty))
})
const path = "../../../../config/example/node"
fileConfigTest := func(c *config.Config) {
require.Equal(t, uint32(500), containerconfig.ContainerBatchSize(c))
}
configtest.ForEachFileType(path, fileConfigTest)
t.Run("ENV", func(t *testing.T) {
configtest.ForEnvFileType(t, path, fileConfigTest)
})
}

View file

@ -41,6 +41,10 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config)
c.Sub(si),
)
if sc.Mode() == mode.Disabled {
continue
}
// Path for the blobstor can't be present in the default section, because different shards
// must have different paths, so if it is missing, the shard is not here.
// At the same time checking for "blobstor" section doesn't work proper
@ -50,10 +54,6 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config)
}
(*config.Config)(sc).SetDefault(def)
if sc.Mode() == mode.Disabled {
continue
}
if err := f(sc); err != nil {
return err
}

View file

@ -18,6 +18,22 @@ import (
"github.com/stretchr/testify/require"
)
func TestIterateShards(t *testing.T) {
fileConfigTest := func(c *config.Config) {
var res []string
require.NoError(t,
engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error {
res = append(res, sc.Metabase().Path())
return nil
}))
require.Equal(t, []string{"abc", "xyz"}, res)
}
const cfgDir = "./testdata/shards"
configtest.ForEachFileType(cfgDir, fileConfigTest)
configtest.ForEnvFileType(t, cfgDir, fileConfigTest)
}
func TestEngineSection(t *testing.T) {
t.Run("defaults", func(t *testing.T) {
empty := configtest.EmptyConfig()

View file

@ -0,0 +1,3 @@
FROSTFS_STORAGE_SHARD_0_METABASE_PATH=abc
FROSTFS_STORAGE_SHARD_1_MODE=disabled
FROSTFS_STORAGE_SHARD_2_METABASE_PATH=xyz

View file

@ -0,0 +1,13 @@
{
"storage.shard": {
"0": {
"metabase.path": "abc"
},
"1": {
"mode": "disabled"
},
"2": {
"metabase.path": "xyz"
}
}
}

View file

@ -0,0 +1,7 @@
storage.shard:
0:
metabase.path: abc
1:
mode: disabled
2:
metabase.path: xyz

View file

@ -5,6 +5,7 @@ import (
"context"
"net"
containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container"
morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics"
@ -28,7 +29,7 @@ import (
func initContainerService(_ context.Context, c *cfg) {
// container wrapper that tries to invoke notary
// requests if chain is configured so
wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, cntClient.TryNotary())
wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0)
fatalOnErr(err)
c.shared.cnrClient = wrap
@ -47,6 +48,7 @@ func initContainerService(_ context.Context, c *cfg) {
}
c.shared.frostfsidClient = frostfsIDSubjectProvider
c.cfgContainer.containerBatchSize = containerconfig.ContainerBatchSize(c.appCfg)
defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides(
c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(),
@ -56,7 +58,9 @@ func initContainerService(_ context.Context, c *cfg) {
&c.key.PrivateKey,
containerService.NewAPEServer(defaultChainRouter, cnrRdr,
newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient,
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc),
containerService.NewSplitterService(
c.cfgContainer.containerBatchSize, c.respSvc,
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc)),
),
)
service = containerService.NewAuditService(service, c.log, c.audit)
@ -218,6 +222,7 @@ type morphContainerReader struct {
lister interface {
ContainersOf(*user.ID) ([]cid.ID, error)
IterateContainersOf(*user.ID, func(cid.ID) error) error
}
}
@ -233,6 +238,10 @@ func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) {
return x.lister.ContainersOf(id)
}
func (x *morphContainerReader) IterateContainersOf(id *user.ID, processCID func(cid.ID) error) error {
return x.lister.IterateContainersOf(id, processCID)
}
type morphContainerWriter struct {
neoClient *cntClient.Client
}

View file

@ -134,7 +134,7 @@ func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.C
err := stopper(ctx)
if err != nil {
c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name),
zap.String("error", err.Error()),
zap.Error(err),
)
}

View file

@ -35,20 +35,16 @@ func (c *cfg) initMorphComponents(ctx context.Context) {
lookupScriptHashesInNNS(c) // smart contract auto negotiation
if c.cfgMorph.notaryEnabled {
err := c.cfgMorph.client.EnableNotarySupport(
client.WithProxyContract(
c.cfgMorph.proxyScriptHash,
),
)
fatalOnErr(err)
}
c.log.Info(ctx, logs.FrostFSNodeNotarySupport,
zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled),
err := c.cfgMorph.client.EnableNotarySupport(
client.WithProxyContract(
c.cfgMorph.proxyScriptHash,
),
)
fatalOnErr(err)
wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary())
c.log.Info(ctx, logs.FrostFSNodeNotarySupport)
wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0)
fatalOnErr(err)
var netmapSource netmap.Source
@ -100,7 +96,7 @@ func initMorphClient(ctx context.Context, c *cfg) {
if err != nil {
c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient,
zap.Any("endpoints", addresses),
zap.String("error", err.Error()),
zap.Error(err),
)
fatalOnErr(err)
@ -116,15 +112,9 @@ func initMorphClient(ctx context.Context, c *cfg) {
}
c.cfgMorph.client = cli
c.cfgMorph.notaryEnabled = cli.ProbeNotary()
}
func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) {
// skip notary deposit in non-notary environments
if !c.cfgMorph.notaryEnabled {
return
}
tx, vub, err := makeNotaryDeposit(ctx, c)
fatalOnErr(err)
@ -161,7 +151,7 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error
}
func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error {
if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil {
if err := c.cfgMorph.client.WaitTxHalt(ctx, vub, tx); err != nil {
return err
}
@ -178,7 +168,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) {
fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey)
if err != nil {
fromSideChainBlock = 0
c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.Error(err))
}
subs, err = subscriber.New(ctx, &subscriber.Params{
@ -233,27 +223,17 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse
subs map[event.Type][]event.Handler,
) {
for typ, handlers := range subs {
pi := event.NotificationParserInfo{}
pi.SetType(typ)
pi.SetScriptHash(scHash)
p, ok := parsers[typ]
if !ok {
panic(fmt.Sprintf("missing parser for event %s", typ))
}
pi.SetParser(p)
lis.SetNotificationParser(pi)
for _, h := range handlers {
hi := event.NotificationHandlerInfo{}
hi.SetType(typ)
hi.SetScriptHash(scHash)
hi.SetHandler(h)
lis.RegisterNotificationHandler(hi)
}
lis.RegisterNotificationHandler(event.NotificationHandlerInfo{
Contract: scHash,
Type: typ,
Parser: p,
Handlers: handlers,
})
}
}
@ -282,10 +262,6 @@ func lookupScriptHashesInNNS(c *cfg) {
)
for _, t := range targets {
if t.nnsName == client.NNSProxyContractName && !c.cfgMorph.notaryEnabled {
continue // ignore proxy contract if notary disabled
}
if emptyHash.Equals(*t.h) {
*t.h, err = c.cfgMorph.client.NNSContractAddress(t.nnsName)
fatalOnErrDetails(fmt.Sprintf("can't resolve %s in NNS", t.nnsName), err)

View file

@ -193,16 +193,14 @@ func addNewEpochNotificationHandlers(c *cfg) {
}
})
if c.cfgMorph.notaryEnabled {
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) {
_, _, err := makeNotaryDeposit(ctx, c)
if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit,
zap.String("error", err.Error()),
)
}
})
}
addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) {
_, _, err := makeNotaryDeposit(ctx, c)
if err != nil {
c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit,
zap.Error(err),
)
}
})
}
// bootstrapNode adds current node to the Network map.
@ -425,7 +423,7 @@ func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient.
if err != nil {
return err
}
return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res)
return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res.VUB, res.Hash)
}
type netInfo struct {

View file

@ -13,7 +13,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
@ -59,7 +58,7 @@ func (c *cfg) MaxObjectSize() uint64 {
sz, err := c.cfgNetmap.wrapper.MaxObjectSize()
if err != nil {
c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue,
zap.String("error", err.Error()),
zap.Error(err),
)
}
@ -137,24 +136,6 @@ func (fn *innerRingFetcherWithNotary) InnerRingKeys() ([][]byte, error) {
return result, nil
}
type innerRingFetcherWithoutNotary struct {
nm *nmClient.Client
}
func (f *innerRingFetcherWithoutNotary) InnerRingKeys() ([][]byte, error) {
keys, err := f.nm.GetInnerRingList()
if err != nil {
return nil, fmt.Errorf("can't get inner ring keys from netmap contract: %w", err)
}
result := make([][]byte, 0, len(keys))
for i := range keys {
result = append(result, keys[i].Bytes())
}
return result, nil
}
func initObjectService(c *cfg) {
keyStorage := util.NewKeyStorage(&c.key.PrivateKey, c.privateTokenStore, c.cfgNetmap.state)
@ -288,7 +269,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl
_, err := ls.Inhume(ctx, inhumePrm)
if err != nil {
c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage,
zap.String("error", err.Error()),
zap.Error(err),
)
}
}),
@ -305,13 +286,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl
}
func createInnerRingFetcher(c *cfg) v2.InnerRingFetcher {
if c.cfgMorph.client.ProbeNotary() {
return &innerRingFetcherWithNotary{
sidechain: c.cfgMorph.client,
}
}
return &innerRingFetcherWithoutNotary{
nm: c.cfgNetmap.wrapper,
return &innerRingFetcherWithNotary{
sidechain: c.cfgMorph.client,
}
}

View file

@ -113,7 +113,7 @@ func initTreeService(c *cfg) {
// Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged.
c.log.Error(ctx, logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved,
zap.Stringer("cid", ev.ID),
zap.String("error", err.Error()))
zap.Error(err))
}
})

View file

@ -83,6 +83,9 @@ FROSTFS_POLICER_HEAD_TIMEOUT=15s
FROSTFS_REPLICATOR_PUT_TIMEOUT=15s
FROSTFS_REPLICATOR_POOL_SIZE=10
# Container service section
FROSTFS_CONTAINER_LIST_STREAM_BATCH_SIZE=500
# Object service section
FROSTFS_OBJECT_PUT_REMOTE_POOL_SIZE=100
FROSTFS_OBJECT_PUT_LOCAL_POOL_SIZE=200

View file

@ -124,6 +124,11 @@
"pool_size": 10,
"put_timeout": "15s"
},
"container": {
"list_stream": {
"batch_size": "500"
}
},
"object": {
"delete": {
"tombstone_lifetime": 10

View file

@ -108,6 +108,10 @@ replicator:
put_timeout: 15s # timeout for the Replicator PUT remote operation
pool_size: 10 # maximum amount of concurrent replications
container:
list_stream:
batch_size: 500 # container_batch_size is the maximum amount of containers to send via stream at once
object:
delete:
tombstone_lifetime: 10 # tombstone "local" lifetime in epochs

View file

@ -42,7 +42,6 @@
"FROSTFS_MORPH_DIAL_TIMEOUT":"30s",
"FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws",
"FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0",
"FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s",
"FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet01.json",
"FROSTFS_NODE_WALLET_PASSWORD":"",
"FROSTFS_NODE_ADDRESSES":"127.0.0.1:8080",
@ -98,7 +97,6 @@
"FROSTFS_MORPH_DIAL_TIMEOUT":"30s",
"FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws",
"FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0",
"FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s",
"FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet02.json",
"FROSTFS_NODE_WALLET_PASSWORD":"",
"FROSTFS_NODE_ADDRESSES":"127.0.0.1:8082",
@ -154,7 +152,6 @@
"FROSTFS_MORPH_DIAL_TIMEOUT":"30s",
"FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws",
"FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0",
"FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s",
"FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet03.json",
"FROSTFS_NODE_WALLET_PASSWORD":"",
"FROSTFS_NODE_ADDRESSES":"127.0.0.1:8084",
@ -210,7 +207,6 @@
"FROSTFS_MORPH_DIAL_TIMEOUT":"30s",
"FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws",
"FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0",
"FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s",
"FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet04.json",
"FROSTFS_NODE_WALLET_PASSWORD":"",
"FROSTFS_NODE_ADDRESSES":"127.0.0.1:8086",

34
go.mod
View file

@ -4,11 +4,11 @@ go 1.22
require (
code.gitea.io/sdk/gitea v0.17.1
git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4
git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76
git.frostfs.info/TrueCloudLab/hrw v1.2.1
git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972
git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88
@ -27,7 +27,7 @@ require (
github.com/klauspost/compress v1.17.4
github.com/mailru/easyjson v0.7.7
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.12.1
github.com/multiformats/go-multiaddr v0.14.0
github.com/nspcc-dev/neo-go v0.106.3
github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.9.0
@ -40,15 +40,15 @@ require (
github.com/ssgreg/journald v1.0.0
github.com/stretchr/testify v1.9.0
go.etcd.io/bbolt v1.3.10
go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/trace v1.28.0
go.opentelemetry.io/otel v1.31.0
go.opentelemetry.io/otel/trace v1.31.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/sync v0.7.0
golang.org/x/sys v0.22.0
golang.org/x/term v0.21.0
google.golang.org/grpc v1.66.2
google.golang.org/protobuf v1.34.2
golang.org/x/sync v0.10.0
golang.org/x/sys v0.28.0
golang.org/x/term v0.27.0
google.golang.org/grpc v1.69.2
google.golang.org/protobuf v1.36.1
gopkg.in/yaml.v3 v3.0.1
)
@ -119,15 +119,15 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
rsc.io/tmplfunc v0.0.3 // indirect

BIN
go.sum

Binary file not shown.

View file

@ -164,17 +164,9 @@ const (
EventNotaryParserNotSet = "notary parser not set"
EventCouldNotParseNotaryEvent = "could not parse notary event"
EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered"
EventIgnoreNilEventParser = "ignore nil event parser"
EventListenerHasBeenAlreadyStartedIgnoreParser = "listener has been already started, ignore parser"
EventRegisteredNewEventParser = "registered new event parser"
EventIgnoreNilEventHandler = "ignore nil event handler"
EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser"
EventRegisteredNewEventHandler = "registered new event handler"
EventIgnoreNilNotaryEventParser = "ignore nil notary event parser"
EventListenerHasBeenAlreadyStartedIgnoreNotaryParser = "listener has been already started, ignore notary parser"
EventIgnoreNilNotaryEventHandler = "ignore nil notary event handler"
EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser"
EventIgnoreNilBlockHandler = "ignore nil block handler"
StorageOperation = "local object storage operation"
BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB"
BlobovniczaOpeningBoltDB = "opening BoltDB"

View file

@ -12,8 +12,9 @@ type ApplicationInfo struct {
func NewApplicationInfo(version string) *ApplicationInfo {
appInfo := &ApplicationInfo{
versionValue: metrics.NewGaugeVec(prometheus.GaugeOpts{
Name: "app_info",
Help: "General information about the application.",
Namespace: namespace,
Name: "app_info",
Help: "General information about the application.",
}, []string{"version"}),
}
appInfo.versionValue.With(prometheus.Labels{"version": version})

View file

@ -31,9 +31,7 @@ type RPCActorProvider interface {
type ProxyVerificationContractStorage struct {
rpcActorProvider RPCActorProvider
acc *wallet.Account
proxyScriptHash util.Uint160
cosigners []actor.SignerAccount
policyScriptHash util.Uint160
}
@ -41,12 +39,27 @@ type ProxyVerificationContractStorage struct {
var _ ProxyAdaptedContractStorage = (*ProxyVerificationContractStorage)(nil)
func NewProxyVerificationContractStorage(rpcActorProvider RPCActorProvider, key *keys.PrivateKey, proxyScriptHash, policyScriptHash util.Uint160) *ProxyVerificationContractStorage {
acc := wallet.NewAccountFromPrivateKey(key)
return &ProxyVerificationContractStorage{
rpcActorProvider: rpcActorProvider,
acc: wallet.NewAccountFromPrivateKey(key),
proxyScriptHash: proxyScriptHash,
cosigners: []actor.SignerAccount{
{
Signer: transaction.Signer{
Account: proxyScriptHash,
Scopes: transaction.CustomContracts,
AllowedContracts: []util.Uint160{policyScriptHash},
},
Account: notary.FakeContractAccount(proxyScriptHash),
},
{
Signer: transaction.Signer{
Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry,
},
Account: acc,
},
},
policyScriptHash: policyScriptHash,
}
@ -64,7 +77,7 @@ func (n *contractStorageActorAdapter) GetRPCInvoker() invoker.RPCInvoke {
func (contractStorage *ProxyVerificationContractStorage) newContractStorageActor() (policy_morph.ContractStorageActor, error) {
rpcActor := contractStorage.rpcActorProvider.GetRPCActor()
act, err := actor.New(rpcActor, cosigners(contractStorage.acc, contractStorage.proxyScriptHash, contractStorage.policyScriptHash))
act, err := actor.New(rpcActor, contractStorage.cosigners)
if err != nil {
return nil, err
}
@ -98,31 +111,16 @@ func (contractStorage *ProxyVerificationContractStorage) RemoveMorphRuleChain(na
// ListMorphRuleChains lists morph rule chains from Policy contract using both Proxy contract and storage account as consigners.
func (contractStorage *ProxyVerificationContractStorage) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) {
// contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but
// ProxyVerificationContractStorage does not manage reconnections.
contractStorageActor, err := contractStorage.newContractStorageActor()
if err != nil {
return nil, err
}
return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).ListMorphRuleChains(name, target)
rpcActor := contractStorage.rpcActorProvider.GetRPCActor()
inv := &invokerAdapter{Invoker: invoker.New(rpcActor, nil), rpcInvoker: rpcActor}
return policy_morph.NewContractStorageReader(inv, contractStorage.policyScriptHash).ListMorphRuleChains(name, target)
}
func cosigners(acc *wallet.Account, proxyScriptHash, policyScriptHash util.Uint160) []actor.SignerAccount {
return []actor.SignerAccount{
{
Signer: transaction.Signer{
Account: proxyScriptHash,
Scopes: transaction.CustomContracts,
AllowedContracts: []util.Uint160{policyScriptHash},
},
Account: notary.FakeContractAccount(proxyScriptHash),
},
{
Signer: transaction.Signer{
Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry,
},
Account: acc,
},
}
type invokerAdapter struct {
*invoker.Invoker
rpcInvoker invoker.RPCInvoke
}
func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke {
return n.rpcInvoker
}

View file

@ -67,7 +67,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK
if err != nil {
// do not throw error, try best case matching
c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing,
zap.String("error", err.Error()))
zap.Error(err))
} else if isInnerRingNode {
return &ClassifyResult{
Role: acl.RoleInnerRing,
@ -84,7 +84,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK
// is not possible for previous epoch, so
// do not throw error, try best case matching
c.log.Debug(ctx, logs.V2CantCheckIfRequestFromContainerNode,
zap.String("error", err.Error()))
zap.Error(err))
} else if isContainerNode {
return &ClassifyResult{
Role: acl.RoleContainer,

View file

@ -8,7 +8,6 @@ type (
// ContractProcessor interface defines functions for binding event producers
// such as event.Listener and Timers with contract processor.
ContractProcessor interface {
ListenerNotificationParsers() []event.NotificationParserInfo
ListenerNotificationHandlers() []event.NotificationHandlerInfo
ListenerNotaryParsers() []event.NotaryParserInfo
ListenerNotaryHandlers() []event.NotaryHandlerInfo
@ -16,11 +15,6 @@ type (
)
func connectListenerWithProcessor(l event.Listener, p ContractProcessor) {
// register notification parsers
for _, parser := range p.ListenerNotificationParsers() {
l.SetNotificationParser(parser)
}
// register notification handlers
for _, handler := range p.ListenerNotificationHandlers() {
l.RegisterNotificationHandler(handler)

View file

@ -100,7 +100,7 @@ func (s *Server) initMainnet(ctx context.Context, cfg *viper.Viper, morphChain *
fromMainChainBlock, err := s.persistate.UInt32(persistateMainChainLastBlockKey)
if err != nil {
fromMainChainBlock = 0
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error()))
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.Error(err))
}
mainnetChain.from = fromMainChainBlock
@ -380,7 +380,6 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) {
// form morph container client's options
morphCnrOpts := make([]container.Option, 0, 3)
morphCnrOpts = append(morphCnrOpts,
container.TryNotary(),
container.AsAlphabet(),
)
@ -390,12 +389,12 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) {
}
s.containerClient = result.CnrClient
s.netmapClient, err = nmClient.NewFromMorph(s.morphClient, s.contracts.netmap, fee, nmClient.TryNotary(), nmClient.AsAlphabet())
s.netmapClient, err = nmClient.NewFromMorph(s.morphClient, s.contracts.netmap, fee, nmClient.AsAlphabet())
if err != nil {
return nil, err
}
s.balanceClient, err = balanceClient.NewFromMorph(s.morphClient, s.contracts.balance, fee, balanceClient.TryNotary(), balanceClient.AsAlphabet())
s.balanceClient, err = balanceClient.NewFromMorph(s.morphClient, s.contracts.balance, fee, balanceClient.AsAlphabet())
if err != nil {
return nil, err
}
@ -457,7 +456,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<-
fromSideChainBlock, err := s.persistate.UInt32(persistateSideChainLastBlockKey)
if err != nil {
fromSideChainBlock = 0
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error()))
s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.Error(err))
}
morphChain := &chainParams{

View file

@ -177,7 +177,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
if err != nil {
// we don't stop inner ring execution on this error
s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators,
zap.String("error", err.Error()))
zap.Error(err))
}
s.tickInitialExpoch(ctx)
@ -308,7 +308,7 @@ func (s *Server) Stop(ctx context.Context) {
for _, c := range s.closers {
if err := c(); err != nil {
s.log.Warn(ctx, logs.InnerringCloserError,
zap.String("error", err.Error()),
zap.Error(err),
)
}
}

View file

@ -33,7 +33,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool {
// there is no signature collecting, so we don't need extra fee
_, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod)
if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error()))
ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.Error(err))
return false
}
@ -47,7 +47,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool {
networkMap, err := ap.netmapClient.NetMap()
if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes,
zap.String("error", err.Error()))
zap.Error(err))
return false
}
@ -83,7 +83,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net
key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256())
if err != nil {
ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey,
zap.String("error", err.Error()))
zap.Error(err))
continue
}
@ -93,7 +93,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net
ap.log.Warn(ctx, logs.AlphabetCantTransferGas,
zap.String("receiver", key.Address()),
zap.Int64("amount", int64(gasPerNode)),
zap.String("error", err.Error()),
zap.Error(err),
)
}
}
@ -110,7 +110,7 @@ func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint
ap.log.Warn(ctx, logs.AlphabetCantTransferGasToWallet,
zap.Strings("receivers", receiversLog),
zap.Int64("amount", int64(gasPerNode)),
zap.String("error", err.Error()),
zap.Error(err),
)
}
}

View file

@ -114,11 +114,6 @@ func (ap *Processor) SetParsedWallets(parsedWallets []util.Uint160) {
ap.pwLock.Unlock()
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (ap *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
return nil
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
return nil

View file

@ -88,32 +88,16 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (bp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var parsers []event.NotificationParserInfo
// new lock event
lock := event.NotificationParserInfo{}
lock.SetType(lockNotification)
lock.SetScriptHash(bp.balanceSC)
lock.SetParser(balanceEvent.ParseLock)
parsers = append(parsers, lock)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var handlers []event.NotificationHandlerInfo
// lock handler
lock := event.NotificationHandlerInfo{}
lock.SetType(lockNotification)
lock.SetScriptHash(bp.balanceSC)
lock.SetHandler(bp.handleLock)
handlers = append(handlers, lock)
return handlers
return []event.NotificationHandlerInfo{
{
Contract: bp.balanceSC,
Type: lockNotification,
Parser: balanceEvent.ParseLock,
Handlers: []event.Handler{bp.handleLock},
},
}
}
// ListenerNotaryParsers for the 'event.Listener' event producer.

View file

@ -50,7 +50,7 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool
err := cp.checkPutContainer(pctx)
if err != nil {
cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed,
zap.String("error", err.Error()),
zap.Error(err),
)
return false
@ -58,7 +58,7 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool
if err := cp.morphClient.NotarySignAndInvokeTX(pctx.e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(ctx, logs.ContainerCouldNotApprovePutContainer,
zap.String("error", err.Error()),
zap.Error(err),
)
return false
}
@ -113,7 +113,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven
err := cp.checkDeleteContainer(e)
if err != nil {
cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed,
zap.String("error", err.Error()),
zap.Error(err),
)
return false
@ -121,7 +121,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven
if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(ctx, logs.ContainerCouldNotApproveDeleteContainer,
zap.String("error", err.Error()),
zap.Error(err),
)
return false

View file

@ -118,11 +118,6 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
return nil
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
return nil

View file

@ -73,7 +73,7 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De
err = np.morphClient.TransferGas(receiver, np.mintEmitValue)
if err != nil {
np.log.Error(ctx, logs.FrostFSCantTransferNativeGasToReceiver,
zap.String("error", err.Error()))
zap.Error(err))
return false
}

View file

@ -142,70 +142,34 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var (
parsers = make([]event.NotificationParserInfo, 0, 6)
p event.NotificationParserInfo
)
p.SetScriptHash(np.frostfsContract)
// deposit event
p.SetType(event.TypeFromString(depositNotification))
p.SetParser(frostfsEvent.ParseDeposit)
parsers = append(parsers, p)
// withdraw event
p.SetType(event.TypeFromString(withdrawNotification))
p.SetParser(frostfsEvent.ParseWithdraw)
parsers = append(parsers, p)
// cheque event
p.SetType(event.TypeFromString(chequeNotification))
p.SetParser(frostfsEvent.ParseCheque)
parsers = append(parsers, p)
// config event
p.SetType(event.TypeFromString(configNotification))
p.SetParser(frostfsEvent.ParseConfig)
parsers = append(parsers, p)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var (
handlers = make([]event.NotificationHandlerInfo, 0, 6)
h event.NotificationHandlerInfo
)
h.SetScriptHash(np.frostfsContract)
// deposit handler
h.SetType(event.TypeFromString(depositNotification))
h.SetHandler(np.handleDeposit)
handlers = append(handlers, h)
// withdraw handler
h.SetType(event.TypeFromString(withdrawNotification))
h.SetHandler(np.handleWithdraw)
handlers = append(handlers, h)
// cheque handler
h.SetType(event.TypeFromString(chequeNotification))
h.SetHandler(np.handleCheque)
handlers = append(handlers, h)
// config handler
h.SetType(event.TypeFromString(configNotification))
h.SetHandler(np.handleConfig)
handlers = append(handlers, h)
return handlers
return []event.NotificationHandlerInfo{
{
Contract: np.frostfsContract,
Type: event.TypeFromString(depositNotification),
Parser: frostfsEvent.ParseDeposit,
Handlers: []event.Handler{np.handleDeposit},
},
{
Contract: np.frostfsContract,
Type: event.TypeFromString(withdrawNotification),
Parser: frostfsEvent.ParseWithdraw,
Handlers: []event.Handler{np.handleWithdraw},
},
{
Contract: np.frostfsContract,
Type: event.TypeFromString(chequeNotification),
Parser: frostfsEvent.ParseCheque,
Handlers: []event.Handler{np.handleCheque},
},
{
Contract: np.frostfsContract,
Type: event.TypeFromString(configNotification),
Parser: frostfsEvent.ParseConfig,
Handlers: []event.Handler{np.handleConfig},
},
}
}
// ListenerNotaryParsers for the 'event.Listener' event producer.

View file

@ -28,21 +28,21 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25
mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList()
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromMainNet,
zap.String("error", err.Error()))
zap.Error(err))
return false
}
sidechainAlphabet, err := gp.morphClient.Committee()
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromSideChain,
zap.String("error", err.Error()))
zap.Error(err))
return false
}
newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet)
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain,
zap.String("error", err.Error()))
zap.Error(err))
return false
}
@ -65,7 +65,7 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25
err = gp.voter.VoteForSidechainValidator(ctx, votePrm)
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantVoteForSideChainCommittee,
zap.String("error", err.Error()))
zap.Error(err))
}
// 2. Update NeoFSAlphabet role in the sidechain.
@ -98,14 +98,14 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sid
innerRing, err := gp.irFetcher.InnerRingKeys()
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantFetchInnerRingListFromSideChain,
zap.String("error", err.Error()))
zap.Error(err))
return
}
newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet)
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys,
zap.String("error", err.Error()))
zap.Error(err))
return
}
@ -122,7 +122,7 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sid
if err = gp.morphClient.UpdateNeoFSAlphabetList(ctx, updPrm); err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys,
zap.String("error", err.Error()))
zap.Error(err))
}
}
@ -135,7 +135,7 @@ func (gp *Processor) updateNotaryRoleInSidechain(ctx context.Context, newAlphabe
err := gp.morphClient.UpdateNotaryList(ctx, updPrm)
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateListOfNotaryNodesInSideChain,
zap.String("error", err.Error()))
zap.Error(err))
}
}
@ -155,6 +155,6 @@ func (gp *Processor) updateFrostFSContractInMainnet(ctx context.Context, newAlph
err := gp.frostfsClient.AlphabetUpdate(ctx, prm)
if err != nil {
gp.log.Error(ctx, logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract,
zap.String("error", err.Error()))
zap.Error(err))
}
}

View file

@ -155,22 +155,16 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (gp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
var pi event.NotificationParserInfo
pi.SetScriptHash(gp.designate)
pi.SetType(event.TypeFromString(native.DesignationEventName))
pi.SetParser(rolemanagement.ParseDesignate)
return []event.NotificationParserInfo{pi}
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (gp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
var hi event.NotificationHandlerInfo
hi.SetScriptHash(gp.designate)
hi.SetType(event.TypeFromString(native.DesignationEventName))
hi.SetHandler(gp.HandleAlphabetSync)
return []event.NotificationHandlerInfo{hi}
return []event.NotificationHandlerInfo{
{
Contract: gp.designate,
Type: event.TypeFromString(native.DesignationEventName),
Parser: rolemanagement.ParseDesignate,
Handlers: []event.Handler{gp.HandleAlphabetSync},
},
}
}
// ListenerNotaryParsers for the 'event.Listener' event producer.

View file

@ -49,7 +49,7 @@ func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapClea
})
if err != nil {
np.log.Warn(ctx, logs.NetmapCantIterateOnNetmapCleanerCache,
zap.String("error", err.Error()))
zap.Error(err))
return false
}

View file

@ -17,7 +17,7 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc
epochDuration, err := np.netmapClient.EpochDuration()
if err != nil {
np.log.Warn(ctx, logs.NetmapCantGetEpochDuration,
zap.String("error", err.Error()))
zap.Error(err))
} else {
np.epochState.SetEpochDuration(epochDuration)
}
@ -28,19 +28,19 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc
if err != nil {
np.log.Warn(ctx, logs.NetmapCantGetTransactionHeight,
zap.String("hash", ev.TxHash().StringLE()),
zap.String("error", err.Error()))
zap.Error(err))
}
if err := np.epochTimer.ResetEpochTimer(h); err != nil {
np.log.Warn(ctx, logs.NetmapCantResetEpochTimer,
zap.String("error", err.Error()))
zap.Error(err))
}
// get new netmap snapshot
networkMap, err := np.netmapClient.NetMap()
if err != nil {
np.log.Warn(ctx, logs.NetmapCantGetNetmapSnapshotToPerformCleanup,
zap.String("error", err.Error()))
zap.Error(err))
return false
}

View file

@ -42,7 +42,7 @@ func (np *Processor) processAddPeer(ctx context.Context, ev netmapEvent.AddPeer)
err = np.nodeValidator.VerifyAndUpdate(&nodeInfo)
if err != nil {
np.log.Warn(ctx, logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate,
zap.String("error", err.Error()),
zap.Error(err),
)
return false

View file

@ -161,36 +161,16 @@ func New(p *Params) (*Processor, error) {
}, nil
}
// ListenerNotificationParsers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo {
parsers := make([]event.NotificationParserInfo, 0, 3)
var p event.NotificationParserInfo
p.SetScriptHash(np.netmapClient.ContractAddress())
// new epoch event
p.SetType(newEpochNotification)
p.SetParser(netmapEvent.ParseNewEpoch)
parsers = append(parsers, p)
return parsers
}
// ListenerNotificationHandlers for the 'event.Listener' event producer.
func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo {
handlers := make([]event.NotificationHandlerInfo, 0, 3)
var i event.NotificationHandlerInfo
i.SetScriptHash(np.netmapClient.ContractAddress())
// new epoch handler
i.SetType(newEpochNotification)
i.SetHandler(np.handleNewEpoch)
handlers = append(handlers, i)
return handlers
return []event.NotificationHandlerInfo{
{
Contract: np.netmapClient.ContractAddress(),
Type: newEpochNotification,
Parser: netmapEvent.ParseNewEpoch,
Handlers: []event.Handler{np.handleNewEpoch},
},
}
}
// ListenerNotaryParsers for the 'event.Listener' event producer.

View file

@ -62,7 +62,7 @@ func (s *Server) IsAlphabet(ctx context.Context) bool {
func (s *Server) InnerRingIndex(ctx context.Context) int {
index, err := s.statusIndex.InnerRingIndex()
if err != nil {
s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error()))
s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.Error(err))
return -1
}
@ -74,7 +74,7 @@ func (s *Server) InnerRingIndex(ctx context.Context) int {
func (s *Server) InnerRingSize(ctx context.Context) int {
size, err := s.statusIndex.InnerRingSize()
if err != nil {
s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error()))
s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.Error(err))
return 0
}
@ -86,7 +86,7 @@ func (s *Server) InnerRingSize(ctx context.Context) int {
func (s *Server) AlphabetIndex(ctx context.Context) int {
index, err := s.statusIndex.AlphabetIndex()
if err != nil {
s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error()))
s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.Error(err))
return -1
}
@ -132,7 +132,7 @@ func (s *Server) voteForSidechainValidator(ctx context.Context, prm governance.V
s.log.Warn(ctx, logs.InnerringCantInvokeVoteMethodInAlphabetContract,
zap.Int8("alphabet_index", int8(letter)),
zap.Uint64("epoch", epoch),
zap.String("error", err.Error()))
zap.Error(err))
}
})

View file

@ -129,7 +129,7 @@ func (b *Blobovnicza) initializeCounters(ctx context.Context) error {
})
})
if err != nil {
return fmt.Errorf("can't determine DB size: %w", err)
return fmt.Errorf("determine DB size: %w", err)
}
if (!sizeExists || !itemsCountExists) && !b.boltOptions.ReadOnly {
b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items))
@ -140,7 +140,7 @@ func (b *Blobovnicza) initializeCounters(ctx context.Context) error {
return saveItemsCount(tx, items)
}); err != nil {
b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items))
return fmt.Errorf("can't save blobovnicza's size and items count: %w", err)
return fmt.Errorf("save blobovnicza's size and items count: %w", err)
}
b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items))
}

View file

@ -146,7 +146,7 @@ func (b *Blobovnicza) Iterate(ctx context.Context, prm IteratePrm) (IterateRes,
if prm.ignoreErrors {
return nil
}
return fmt.Errorf("could not decode address key: %w", err)
return fmt.Errorf("decode address key: %w", err)
}
}

View file

@ -82,7 +82,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co
if !client.IsErrObjectNotFound(err) {
b.log.Debug(ctx, logs.BlobovniczatreeCouldNotRemoveObjectFromLevel,
zap.String("level", p),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)),
)
}

View file

@ -57,7 +57,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common
if !client.IsErrObjectNotFound(err) {
b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel,
zap.String("level", p),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
}
}

View file

@ -69,7 +69,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G
if !client.IsErrObjectNotFound(err) {
b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel,
zap.String("level", p),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)),
)
}
@ -115,13 +115,13 @@ func (b *Blobovniczas) getObject(ctx context.Context, blz *blobovnicza.Blobovnic
// decompress the data
data, err := b.compression.Decompress(res.Object())
if err != nil {
return common.GetRes{}, fmt.Errorf("could not decompress object data: %w", err)
return common.GetRes{}, fmt.Errorf("decompress object data: %w", err)
}
// unmarshal the object
obj := objectSDK.New()
if err := obj.Unmarshal(data); err != nil {
return common.GetRes{}, fmt.Errorf("could not unmarshal the object: %w", err)
return common.GetRes{}, fmt.Errorf("unmarshal the object: %w", err)
}
return common.GetRes{Object: obj, RawData: data}, nil

View file

@ -71,7 +71,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re
if !outOfBounds && !client.IsErrObjectNotFound(err) {
b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel,
zap.String("level", p),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
}
if outOfBounds {
@ -130,13 +130,13 @@ func (b *Blobovniczas) getObjectRange(ctx context.Context, blz *blobovnicza.Blob
// decompress the data
data, err := b.compression.Decompress(res.Object())
if err != nil {
return common.GetRangeRes{}, fmt.Errorf("could not decompress object data: %w", err)
return common.GetRangeRes{}, fmt.Errorf("decompress object data: %w", err)
}
// unmarshal the object
obj := objectSDK.New()
if err := obj.Unmarshal(data); err != nil {
return common.GetRangeRes{}, fmt.Errorf("could not unmarshal the object: %w", err)
return common.GetRangeRes{}, fmt.Errorf("unmarshal the object: %w", err)
}
from := prm.Range.GetOffset()

View file

@ -44,12 +44,12 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm
if prm.IgnoreErrors {
b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration,
zap.Stringer("address", elem.Address()),
zap.String("err", err.Error()),
zap.Error(err),
zap.String("storage_id", p),
zap.String("root_path", b.rootPath))
return nil
}
return fmt.Errorf("could not decompress object data: %w", err)
return fmt.Errorf("decompress object data: %w", err)
}
if prm.Handler != nil {
@ -77,12 +77,12 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo
if err != nil {
if ignoreErrors {
b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration,
zap.String("err", err.Error()),
zap.Error(err),
zap.String("storage_id", p),
zap.String("root_path", b.rootPath))
return false, nil
}
return false, fmt.Errorf("could not open blobovnicza %s: %w", p, err)
return false, fmt.Errorf("open blobovnicza %s: %w", p, err)
}
defer shBlz.Close(ctx)

View file

@ -69,10 +69,10 @@ func (b *sharedDB) Open(ctx context.Context) (*blobovnicza.Blobovnicza, error) {
)...)
if err := blz.Open(ctx); err != nil {
return nil, fmt.Errorf("could not open blobovnicza %s: %w", b.path, err)
return nil, fmt.Errorf("open blobovnicza %s: %w", b.path, err)
}
if err := blz.Init(ctx); err != nil {
return nil, fmt.Errorf("could not init blobovnicza %s: %w", b.path, err)
return nil, fmt.Errorf("init blobovnicza %s: %w", b.path, err)
}
b.refCount++
@ -97,7 +97,7 @@ func (b *sharedDB) Close(ctx context.Context) {
if err := b.blcza.Close(ctx); err != nil {
b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza,
zap.String("id", b.path),
zap.String("error", err.Error()),
zap.Error(err),
)
}
b.blcza = nil
@ -125,9 +125,9 @@ func (b *sharedDB) CloseAndRemoveFile(ctx context.Context) error {
if err := b.blcza.Close(ctx); err != nil {
b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza,
zap.String("id", b.path),
zap.String("error", err.Error()),
zap.Error(err),
)
return fmt.Errorf("failed to close blobovnicza (path = %s): %w", b.path, err)
return fmt.Errorf("close blobovnicza (path = %s): %w", b.path, err)
}
b.refCount = 0

View file

@ -83,7 +83,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error)
i.B.reportError(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err)
} else {
i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza,
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
}
@ -106,7 +106,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error)
} else {
i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza,
zap.String("path", active.SystemPath()),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
}
if errors.Is(err, blobovnicza.ErrNoSpace) {

View file

@ -74,7 +74,7 @@ func (b *BlobStor) Close(ctx context.Context) error {
for i := range b.storage {
err := b.storage[i].Storage.Close(ctx)
if err != nil {
b.log.Info(ctx, logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error()))
b.log.Info(ctx, logs.BlobstorCouldntCloseStorage, zap.Error(err))
if firstErr == nil {
firstErr = err
}

View file

@ -75,7 +75,7 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi
for _, err := range errors[:len(errors)-1] {
b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringObjectExistenceChecking,
zap.Stringer("address", prm.Address),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
}

View file

@ -153,7 +153,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr
if err != nil {
if prm.IgnoreErrors {
t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration,
zap.String("err", err.Error()),
zap.Error(err),
zap.String("directory_path", dirPath))
return nil
}
@ -202,7 +202,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr
if prm.IgnoreErrors {
t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration,
zap.Stringer("address", addr),
zap.String("err", err.Error()),
zap.Error(err),
zap.String("path", path))
continue
}
@ -538,7 +538,7 @@ func (t *FSTree) countFiles() (uint64, uint64, error) {
},
)
if err != nil {
return 0, 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err)
return 0, 0, fmt.Errorf("walk through %s directory: %w", t.RootPath, err)
}
return count, size, nil
@ -577,7 +577,7 @@ func (t *FSTree) ObjectsCount(ctx context.Context) (uint64, error) {
},
)
if err != nil {
return 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err)
return 0, fmt.Errorf("walk through %s directory: %w", t.RootPath, err)
}
success = true
return result, nil

View file

@ -45,7 +45,7 @@ func (b *BlobStor) Iterate(ctx context.Context, prm common.IteratePrm) (common.I
b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration,
zap.String("storage_path", b.storage[i].Storage.Path()),
zap.String("storage_type", b.storage[i].Storage.Type()),
zap.String("err", err.Error()))
zap.Error(err))
continue
}
return common.IterateRes{}, fmt.Errorf("blobstor iterator failure: %w", err)

View file

@ -47,13 +47,13 @@ func (s *memstoreImpl) Get(_ context.Context, req common.GetPrm) (common.GetRes,
// Decompress the data.
var err error
if data, err = s.compression.Decompress(data); err != nil {
return common.GetRes{}, fmt.Errorf("could not decompress object data: %w", err)
return common.GetRes{}, fmt.Errorf("decompress object data: %w", err)
}
// Unmarshal the SDK object.
obj := objectSDK.New()
if err := obj.Unmarshal(data); err != nil {
return common.GetRes{}, fmt.Errorf("could not unmarshal the object: %w", err)
return common.GetRes{}, fmt.Errorf("unmarshal the object: %w", err)
}
return common.GetRes{Object: obj, RawData: data}, nil

View file

@ -27,7 +27,7 @@ func (b *BlobStor) SetMode(ctx context.Context, m mode.Mode) error {
}
}
if err != nil {
return fmt.Errorf("can't set blobstor mode (old=%s, new=%s): %w", b.mode, m, err)
return fmt.Errorf("set blobstor mode (old=%s, new=%s): %w", b.mode, m, err)
}
b.mode = m

View file

@ -52,7 +52,7 @@ func (b *BlobStor) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, e
// marshal object
data, err := prm.Object.Marshal()
if err != nil {
return common.PutRes{}, fmt.Errorf("could not marshal the object: %w", err)
return common.PutRes{}, fmt.Errorf("marshal the object: %w", err)
}
prm.RawData = data
}

View file

@ -95,7 +95,7 @@ func (e *StorageEngine) Init(ctx context.Context) error {
err := eg.Wait()
close(errCh)
if err != nil {
return fmt.Errorf("failed to initialize shards: %w", err)
return fmt.Errorf("initialize shards: %w", err)
}
for res := range errCh {
@ -117,7 +117,7 @@ func (e *StorageEngine) Init(ctx context.Context) error {
continue
}
return fmt.Errorf("could not initialize shard %s: %w", res.id, res.err)
return fmt.Errorf("initialize shard %s: %w", res.id, res.err)
}
}
@ -167,7 +167,7 @@ func (e *StorageEngine) close(ctx context.Context, releasePools bool) error {
if err := sh.Close(ctx); err != nil {
e.log.Debug(ctx, logs.EngineCouldNotCloseShard,
zap.String("id", id),
zap.String("error", err.Error()),
zap.Error(err),
)
}
}
@ -320,7 +320,7 @@ loop:
for _, newID := range shardsToAdd {
sh, err := e.createShard(ctx, rcfg.shards[newID])
if err != nil {
return fmt.Errorf("could not add new shard with '%s' metabase path: %w", newID, err)
return fmt.Errorf("add new shard with '%s' metabase path: %w", newID, err)
}
idStr := sh.ID().String()
@ -331,13 +331,13 @@ loop:
}
if err != nil {
_ = sh.Close(ctx)
return fmt.Errorf("could not init %s shard: %w", idStr, err)
return fmt.Errorf("init %s shard: %w", idStr, err)
}
err = e.addShard(sh)
if err != nil {
_ = sh.Close(ctx)
return fmt.Errorf("could not add %s shard: %w", idStr, err)
return fmt.Errorf("add %s shard: %w", idStr, err)
}
e.log.Info(ctx, logs.EngineAddedNewShard, zap.String("id", idStr))

View file

@ -154,7 +154,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo
if err != nil {
e.log.Warn(ctx, logs.EngineErrorDuringSearchingForObjectChildren,
zap.Stringer("addr", addr),
zap.String("error", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
return false
}
@ -166,7 +166,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo
if err != nil {
e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard,
zap.Stringer("addr", addr),
zap.String("err", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
continue
}
@ -196,7 +196,7 @@ func (e *StorageEngine) deleteChunks(
if err != nil {
e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard,
zap.Stringer("addr", addr),
zap.String("err", err.Error()),
zap.Error(err),
zap.String("trace_id", tracingPkg.GetTraceID(ctx)))
continue
}

View file

@ -140,7 +140,7 @@ func (e *StorageEngine) reportShardError(
if isLogical(err) {
e.log.Warn(ctx, msg,
zap.Stringer("shard_id", sh.ID()),
zap.String("error", err.Error()))
zap.Error(err))
return
}
@ -151,7 +151,7 @@ func (e *StorageEngine) reportShardError(
e.log.Warn(ctx, msg, append([]zap.Field{
zap.Stringer("shard_id", sid),
zap.Uint32("error count", errCount),
zap.String("error", err.Error()),
zap.Error(err),
}, fields...)...)
if e.errorsThreshold == 0 || errCount < e.errorsThreshold {

View file

@ -17,10 +17,12 @@ import (
"github.com/stretchr/testify/require"
)
type epochState struct{}
type epochState struct {
currEpoch uint64
}
func (s epochState) CurrentEpoch() uint64 {
return 0
return s.currEpoch
}
type testEngineWrapper struct {
@ -87,12 +89,16 @@ func testGetDefaultShardOptions(t testing.TB) []shard.Option {
blobstor.WithLogger(test.NewLogger(t)),
),
shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))),
shard.WithMetaBaseOptions(
meta.WithPath(filepath.Join(t.TempDir(), "metabase")),
meta.WithPermissions(0o700),
meta.WithEpochState(epochState{}),
meta.WithLogger(test.NewLogger(t)),
),
shard.WithMetaBaseOptions(testGetDefaultMetabaseOptions(t)...),
}
}
func testGetDefaultMetabaseOptions(t testing.TB) []meta.Option {
return []meta.Option{
meta.WithPath(filepath.Join(t.TempDir(), "metabase")),
meta.WithPermissions(0o700),
meta.WithEpochState(epochState{}),
meta.WithLogger(test.NewLogger(t)),
}
}

View file

@ -86,7 +86,6 @@ type EvacuateShardPrm struct {
ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) (bool, error)
TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (bool, string, error)
IgnoreErrors bool
Async bool
Scope EvacuateScope
RepOneOnly bool
@ -211,10 +210,10 @@ var errMustHaveTwoShards = errors.New("must have at least 1 spare shard")
// Evacuate moves data from one shard to the others.
// The shard being moved must be in read-only mode.
func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*EvacuateShardRes, error) {
func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) error {
select {
case <-ctx.Done():
return nil, ctx.Err()
return ctx.Err()
default:
}
@ -226,7 +225,6 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Evacuate",
trace.WithAttributes(
attribute.StringSlice("shardIDs", shardIDs),
attribute.Bool("async", prm.Async),
attribute.Bool("ignoreErrors", prm.IgnoreErrors),
attribute.Stringer("scope", prm.Scope),
))
@ -234,7 +232,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev
shards, err := e.getActualShards(shardIDs, prm)
if err != nil {
return nil, err
return err
}
shardsToEvacuate := make(map[string]*shard.Shard)
@ -247,10 +245,10 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev
}
res := NewEvacuateShardRes()
ctx = ctxOrBackground(ctx, prm.Async)
eg, egCtx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res)
ctx = context.WithoutCancel(ctx)
eg, ctx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res)
if err != nil {
return nil, err
return err
}
var mtx sync.RWMutex
@ -262,21 +260,10 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev
return t
}
eg.Go(func() error {
return e.evacuateShards(egCtx, shardIDs, prm, res, copyShards, shardsToEvacuate)
return e.evacuateShards(ctx, shardIDs, prm, res, copyShards, shardsToEvacuate)
})
if prm.Async {
return nil, nil
}
return res, eg.Wait()
}
func ctxOrBackground(ctx context.Context, background bool) context.Context {
if background {
return context.Background()
}
return ctx
return nil
}
func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes,
@ -286,7 +273,6 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p
ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards",
trace.WithAttributes(
attribute.StringSlice("shardIDs", shardIDs),
attribute.Bool("async", prm.Async),
attribute.Bool("ignoreErrors", prm.IgnoreErrors),
attribute.Stringer("scope", prm.Scope),
attribute.Bool("repOneOnly", prm.RepOneOnly),
@ -592,7 +578,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree
func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm) (bool, string, error) {
if prm.TreeHandler == nil {
return false, "", fmt.Errorf("failed to evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID())
return false, "", fmt.Errorf("evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID())
}
return prm.TreeHandler(ctx, tree.CID, tree.TreeID, sh)

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