forked from TrueCloudLab/frostfs-api-go
Compare commits
12 commits
f69d2ad83c
...
cd2e46a17c
Author | SHA1 | Date | |
---|---|---|---|
cd2e46a17c | |||
c46cd37f71 | |||
ec0d0274fa | |||
73fde0e37c | |||
611f73ad0f | |||
e073c996fc | |||
d005bf0393 | |||
63eb4dc3ea | |||
3f7cb1b5ef | |||
bd67469f43 | |||
3af7645abf | |||
5faee63f60 |
31 changed files with 564 additions and 548 deletions
70
.github/logo.svg
vendored
70
.github/logo.svg
vendored
|
@ -1,70 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 184.2 51.8" style="enable-background:new 0 0 184.2 51.8;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{display:none;}
|
||||
.st1{display:inline;}
|
||||
.st2{fill:#01E397;}
|
||||
.st3{display:inline;fill:#010032;}
|
||||
.st4{display:inline;fill:#00E599;}
|
||||
.st5{display:inline;fill:#00AF92;}
|
||||
.st6{fill:#00C3E5;}
|
||||
</style>
|
||||
<g id="Layer_2">
|
||||
<g id="Layer_1-2" class="st0">
|
||||
<g class="st1">
|
||||
<path class="st2" d="M146.6,18.3v7.2h10.9V29h-10.9v10.7h-4V14.8h18v3.5H146.6z"/>
|
||||
<path class="st2" d="M180,15.7c1.7,0.9,3,2.2,4,3.8l-3,2.7c-0.6-1.3-1.5-2.4-2.6-3.3c-1.3-0.7-2.8-1-4.3-1
|
||||
c-1.4-0.1-2.8,0.3-4,1.1c-0.9,0.5-1.5,1.5-1.4,2.6c0,1,0.5,1.9,1.4,2.4c1.5,0.8,3.2,1.3,4.9,1.5c1.9,0.3,3.7,0.8,5.4,1.6
|
||||
c1.2,0.5,2.2,1.3,2.9,2.3c0.6,1,1,2.2,0.9,3.4c0,1.4-0.5,2.7-1.3,3.8c-0.9,1.2-2.1,2.1-3.5,2.6c-1.7,0.6-3.4,0.9-5.2,0.8
|
||||
c-5,0-8.6-1.6-10.7-5l2.9-2.8c0.7,1.4,1.8,2.5,3.1,3.3c1.5,0.7,3.1,1.1,4.7,1c1.5,0.1,2.9-0.2,4.2-0.9c0.9-0.5,1.5-1.5,1.5-2.6
|
||||
c0-0.9-0.5-1.8-1.3-2.2c-1.5-0.7-3.1-1.2-4.8-1.5c-1.9-0.3-3.7-0.8-5.5-1.5c-1.2-0.5-2.2-1.4-3-2.4c-0.6-1-1-2.2-0.9-3.4
|
||||
c0-1.4,0.4-2.7,1.2-3.8c0.8-1.2,2-2.2,3.3-2.8c1.6-0.7,3.4-1.1,5.2-1C176.1,14.3,178.2,14.8,180,15.7z"/>
|
||||
</g>
|
||||
<path class="st3" d="M73.3,16.3c1.9,1.9,2.9,4.5,2.7,7.1v15.9h-4V24.8c0-2.6-0.5-4.5-1.6-5.7c-1.2-1.2-2.8-1.8-4.5-1.7
|
||||
c-1.3,0-2.5,0.3-3.7,0.8c-1.2,0.7-2.2,1.7-2.9,2.9c-0.8,1.5-1.1,3.2-1.1,4.9v13.3h-4V15.1l3.6,1.5v1.7c0.8-1.5,2.1-2.6,3.6-3.3
|
||||
c1.5-0.8,3.2-1.2,4.9-1.1C68.9,13.8,71.3,14.7,73.3,16.3z"/>
|
||||
<path class="st3" d="M104.4,28.3H85.6c0.1,2.2,1,4.3,2.5,5.9c1.5,1.4,3.5,2.2,5.6,2.1c1.6,0.1,3.2-0.2,4.6-0.9
|
||||
c1.1-0.6,2-1.6,2.5-2.8l3.3,1.8c-0.9,1.7-2.3,3.1-4,4c-2,1-4.2,1.5-6.4,1.4c-3.7,0-6.7-1.1-8.8-3.4s-3.2-5.5-3.2-9.6s1-7.2,3-9.5
|
||||
s5-3.4,8.7-3.4c2.1-0.1,4.2,0.5,6.1,1.5c1.6,1,3,2.5,3.8,4.2c0.9,1.8,1.3,3.9,1.3,5.9C104.6,26.4,104.6,27.4,104.4,28.3z
|
||||
M88.1,19.3c-1.4,1.5-2.2,3.4-2.4,5.5h15.1c-0.2-2-1-3.9-2.3-5.5c-1.4-1.3-3.2-2-5.1-1.9C91.5,17.3,89.6,18,88.1,19.3z"/>
|
||||
<path class="st3" d="M131,17.3c2.2,2.3,3.2,5.5,3.2,9.5s-1,7.3-3.2,9.6s-5.1,3.4-8.8,3.4s-6.7-1.1-8.9-3.4s-3.2-5.5-3.2-9.6
|
||||
s1.1-7.2,3.2-9.5s5.1-3.4,8.9-3.4S128.9,15,131,17.3z M116.2,19.9c-1.5,2-2.2,4.4-2.1,6.9c-0.2,2.5,0.6,5,2.1,7
|
||||
c1.5,1.7,3.7,2.7,6,2.6c2.3,0.1,4.4-0.9,5.9-2.6c1.5-2,2.3-4.5,2.1-7c0.1-2.5-0.6-4.9-2.1-6.9c-1.5-1.7-3.6-2.7-5.9-2.6
|
||||
C119.9,17.2,117.7,18.2,116.2,19.9z"/>
|
||||
<polygon class="st4" points="0,9.1 0,43.7 22.5,51.8 22.5,16.9 46.8,7.9 24.8,0 "/>
|
||||
<polygon class="st5" points="24.3,17.9 24.3,36.8 46.8,44.9 46.8,9.6 "/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st6" d="M41.6,17.5H28.2v6.9h10.4v3.3H28.2v10.2h-3.9V14.2h17.2V17.5z"/>
|
||||
<path class="st6" d="M45.8,37.9v-18h3.3l0.4,3.2c0.5-1.2,1.2-2.1,2.1-2.7c0.9-0.6,2.1-0.9,3.5-0.9c0.4,0,0.7,0,1.1,0.1
|
||||
c0.4,0.1,0.7,0.2,0.9,0.3l-0.5,3.4c-0.3-0.1-0.6-0.2-0.9-0.2C55.4,23,54.9,23,54.4,23c-0.7,0-1.5,0.2-2.2,0.6
|
||||
c-0.7,0.4-1.3,1-1.8,1.8s-0.7,1.8-0.7,3v9.5H45.8z"/>
|
||||
<path class="st6" d="M68.6,19.6c1.8,0,3.3,0.4,4.6,1.1c1.3,0.7,2.4,1.8,3.1,3.2s1.1,3.1,1.1,5c0,1.9-0.4,3.6-1.1,5
|
||||
c-0.8,1.4-1.8,2.5-3.1,3.2c-1.3,0.7-2.9,1.1-4.6,1.1s-3.3-0.4-4.6-1.1c-1.3-0.7-2.4-1.8-3.2-3.2c-0.8-1.4-1.2-3.1-1.2-5
|
||||
c0-1.9,0.4-3.6,1.2-5s1.8-2.5,3.2-3.2C65.3,19.9,66.8,19.6,68.6,19.6z M68.6,22.6c-1.1,0-2,0.2-2.8,0.7c-0.8,0.5-1.3,1.2-1.7,2.1
|
||||
s-0.6,2.1-0.6,3.5c0,1.3,0.2,2.5,0.6,3.4s1,1.7,1.7,2.2s1.7,0.7,2.8,0.7c1.1,0,2-0.2,2.7-0.7c0.7-0.5,1.3-1.2,1.7-2.2
|
||||
s0.6-2.1,0.6-3.4c0-1.4-0.2-2.5-0.6-3.5s-1-1.6-1.7-2.1C70.6,22.8,69.6,22.6,68.6,22.6z"/>
|
||||
<path class="st6" d="M89.2,38.3c-1.8,0-3.4-0.3-4.9-1c-1.5-0.7-2.7-1.7-3.5-3l2.7-2.3c0.5,1,1.3,1.8,2.3,2.4
|
||||
c1,0.6,2.2,0.9,3.6,0.9c1.1,0,2-0.2,2.6-0.6c0.6-0.4,1-0.9,1-1.6c0-0.5-0.2-0.9-0.5-1.2s-0.9-0.6-1.7-0.8l-3.8-0.8
|
||||
c-1.9-0.4-3.3-1-4.1-1.9c-0.8-0.9-1.2-1.9-1.2-3.3c0-1,0.3-1.9,0.9-2.7c0.6-0.8,1.4-1.5,2.5-2s2.5-0.8,4-0.8c1.8,0,3.3,0.3,4.6,1
|
||||
c1.3,0.6,2.2,1.5,2.9,2.7l-2.7,2.2c-0.5-1-1.1-1.7-2-2.1c-0.9-0.5-1.8-0.7-2.8-0.7c-0.8,0-1.4,0.1-2,0.3c-0.6,0.2-1,0.5-1.3,0.8
|
||||
c-0.3,0.3-0.4,0.7-0.4,1.2c0,0.5,0.2,0.9,0.5,1.3s1,0.6,1.9,0.8l4.1,0.9c1.7,0.3,2.9,0.9,3.7,1.7c0.7,0.8,1.1,1.8,1.1,2.9
|
||||
c0,1.2-0.3,2.2-0.9,3c-0.6,0.9-1.5,1.6-2.6,2C92.1,38.1,90.7,38.3,89.2,38.3z"/>
|
||||
<path class="st6" d="M112.8,19.9v3H99.3v-3H112.8z M106.6,14.6v17.9c0,0.9,0.2,1.5,0.7,1.9c0.5,0.4,1.1,0.6,1.9,0.6
|
||||
c0.6,0,1.2-0.1,1.7-0.3c0.5-0.2,0.9-0.5,1.3-0.8l0.9,2.8c-0.6,0.5-1.2,0.9-2,1.1c-0.8,0.3-1.7,0.4-2.7,0.4c-1,0-2-0.2-2.8-0.5
|
||||
s-1.5-0.9-2-1.6c-0.5-0.8-0.7-1.7-0.8-3V15.7L106.6,14.6z"/>
|
||||
<path d="M137.9,17.5h-13.3v6.9h10.4v3.3h-10.4v10.2h-3.9V14.2h17.2V17.5z"/>
|
||||
<path d="M150.9,13.8c2.1,0,4,0.4,5.5,1.2c1.6,0.8,2.9,2,4,3.5l-2.6,2.5c-0.9-1.4-1.9-2.4-3.1-3c-1.1-0.6-2.5-0.9-4-0.9
|
||||
c-1.2,0-2.1,0.2-2.8,0.5c-0.7,0.3-1.3,0.7-1.6,1.2c-0.3,0.5-0.5,1.1-0.5,1.7c0,0.7,0.3,1.4,0.8,1.9c0.5,0.6,1.5,1,2.9,1.3
|
||||
l4.8,1.1c2.3,0.5,3.9,1.3,4.9,2.3c1,1,1.4,2.3,1.4,3.9c0,1.5-0.4,2.7-1.2,3.8c-0.8,1.1-1.9,1.9-3.3,2.5s-3.1,0.9-5,0.9
|
||||
c-1.7,0-3.2-0.2-4.5-0.6c-1.3-0.4-2.5-1-3.5-1.8c-1-0.7-1.8-1.6-2.5-2.6l2.7-2.7c0.5,0.8,1.1,1.6,1.9,2.2
|
||||
c0.8,0.7,1.7,1.2,2.7,1.5c1,0.4,2.2,0.5,3.4,0.5c1.1,0,2.1-0.1,2.9-0.4c0.8-0.3,1.4-0.7,1.8-1.2c0.4-0.5,0.6-1.1,0.6-1.9
|
||||
c0-0.7-0.2-1.3-0.7-1.8c-0.5-0.5-1.3-0.9-2.6-1.2l-5.2-1.2c-1.4-0.3-2.6-0.8-3.6-1.3c-0.9-0.6-1.6-1.3-2.1-2.1s-0.7-1.8-0.7-2.8
|
||||
c0-1.3,0.4-2.6,1.1-3.7c0.7-1.1,1.8-2,3.2-2.6C147.3,14.1,148.9,13.8,150.9,13.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.5 KiB |
21
.github/workflows/dco.yml
vendored
21
.github/workflows/dco.yml
vendored
|
@ -1,21 +0,0 @@
|
|||
name: DCO check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
commits_check_job:
|
||||
runs-on: ubuntu-latest
|
||||
name: Commits Check
|
||||
steps:
|
||||
- name: Get PR Commits
|
||||
id: 'get-pr-commits'
|
||||
uses: tim-actions/get-pr-commits@master
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: DCO Check
|
||||
uses: tim-actions/dco@master
|
||||
with:
|
||||
commits: ${{ steps.get-pr-commits.outputs.commits }}
|
64
.github/workflows/go.yml
vendored
64
.github/workflows/go.yml
vendored
|
@ -1,64 +0,0 @@
|
|||
name: neofs-api-go tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '*.md'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '*.md'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
go: [ '1.17.x', '1.18.x', '1.19.x' ]
|
||||
steps:
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.go }}
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cache go mod
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/go/pkg/mod
|
||||
key: ${{ runner.os }}-go-${{ matrix.go }}-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-${{ matrix.go }}-
|
||||
|
||||
- name: Get dependencies
|
||||
run: make dep
|
||||
|
||||
- name: Run go test
|
||||
run: go test -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
- name: Codecov
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.48.0
|
||||
only-new-issues: true
|
10
.gitlint
Normal file
10
.gitlint
Normal file
|
@ -0,0 +1,10 @@
|
|||
[general]
|
||||
fail-without-commits=true
|
||||
contrib=CC1
|
||||
|
||||
[title-match-regex]
|
||||
regex=^\[\#[0-9]+\]\s
|
||||
|
||||
[ignore-by-title]
|
||||
regex=^Release(.*)
|
||||
ignore=title-match-regex
|
|
@ -11,7 +11,7 @@ run:
|
|||
|
||||
skip-files:
|
||||
- (^|.*/)grpc/(.*)
|
||||
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
|
||||
|
@ -64,4 +64,4 @@ issues:
|
|||
|
||||
- linters: # ignore SA6002 since we use pool of []byte, however we can switch to *bytes.Buffer
|
||||
- staticcheck
|
||||
text: "SA6002:"
|
||||
text: "SA6002:"
|
||||
|
|
30
.pre-commit-config.yaml
Normal file
30
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,30 @@
|
|||
ci:
|
||||
autofix_prs: false
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: check-merge-conflict
|
||||
- id: check-json
|
||||
- id: check-xml
|
||||
- id: check-yaml
|
||||
- id: trailing-whitespace
|
||||
args: [--markdown-linebreak-ext=md]
|
||||
- id: end-of-file-fixer
|
||||
exclude: ".key$"
|
||||
|
||||
- repo: https://github.com/golangci/golangci-lint
|
||||
rev: v1.51.2
|
||||
hooks:
|
||||
- id: golangci-lint
|
||||
|
||||
- repo: https://github.com/jorisroovers/gitlint
|
||||
rev: v0.18.0
|
||||
hooks:
|
||||
- id: gitlint
|
||||
stages: [commit-msg]
|
34
CHANGELOG.md
34
CHANGELOG.md
|
@ -22,7 +22,7 @@
|
|||
- Mark all expiration methods as deprecated (#417)
|
||||
|
||||
### Updated
|
||||
- Minimal go version to 1.17 (#412)
|
||||
- Minimal go version to 1.17 (#412)
|
||||
- `neofs-crypto` to `v0.4.0` (#412)
|
||||
- `google.golang.org/grpc` to `v1.48.0` (#415)
|
||||
- `google.golang.org/protobuf` to `v1.28.0` (#415)
|
||||
|
@ -60,7 +60,7 @@ NeoFS API v2.13 support
|
|||
|
||||
### Fixed
|
||||
- Incompatible changes in signature scheme (#380)
|
||||
|
||||
|
||||
### Added
|
||||
- Public URI-parsing function `client.ParseURI()` (#383)
|
||||
|
||||
|
@ -92,9 +92,9 @@ NeoFS API v2.12 support
|
|||
|
||||
## [2.11.0] - 2021-12-02 - Sinjido (신지도, 薪智島)
|
||||
|
||||
NeoFS API v2.11 support. High level packages are moved to
|
||||
[neofs-sdk-go](https://github.com/nspcc-dev/neofs-sdk-go) repository.
|
||||
Repository restructured as Go module version 2 and synced with
|
||||
NeoFS API v2.11 support. High level packages are moved to
|
||||
[neofs-sdk-go](https://github.com/nspcc-dev/neofs-sdk-go) repository.
|
||||
Repository restructured as Go module version 2 and synced with
|
||||
[neofs-api](https://github.com/nspcc-dev/neofs-api) release version.
|
||||
|
||||
### Fixed
|
||||
|
@ -109,7 +109,7 @@ Repository restructured as Go module version 2 and synced with
|
|||
- neofs-api-go is now Go module version 2 (#201)
|
||||
|
||||
### Removed
|
||||
- All packages from `pkg` moved to
|
||||
- All packages from `pkg` moved to
|
||||
[neofs-sdk-go](https://github.com/nspcc-dev/neofs-sdk-go) (#201)
|
||||
|
||||
## [1.30.0] - 2021-10-19 - Udo (우도, 牛島)
|
||||
|
@ -126,7 +126,7 @@ NeoFS API v2.10 support.
|
|||
- pkg/client callback to parse internal response information (#337)
|
||||
- Service filter type in extended ACL from API v2.10 (#338)
|
||||
- Enhanced network info structures from API v2.10 (#339)
|
||||
- Well-known public-append basic ACL constant (#341)
|
||||
- Well-known public-append basic ACL constant (#341)
|
||||
- Native contract names support (#351)
|
||||
|
||||
### Changed
|
||||
|
@ -258,7 +258,7 @@ Raw client and support of NeoFS API v2.5.0 "Jebudo" release.
|
|||
### Added
|
||||
|
||||
- Raw client for peer to peer communication.
|
||||
- `client.WithKey` option to sign messages with different keys within single
|
||||
- `client.WithKey` option to sign messages with different keys within single
|
||||
client.
|
||||
- `Content-Type` well-known object attribute constant.
|
||||
|
||||
|
@ -271,7 +271,7 @@ Raw client and support of NeoFS API v2.5.0 "Jebudo" release.
|
|||
|
||||
Support changes from NeoFS API v2.4.0 "Ganghwado" release.
|
||||
|
||||
### Added
|
||||
### Added
|
||||
|
||||
- `netmap.NetworkInfo` definitions in `v2` and `pkg/netmap`.
|
||||
- `netmap.NetworkInfo` RPC support in `pkg/client`.
|
||||
|
@ -322,7 +322,7 @@ Support changes from NeoFS API v2.2.1 release.
|
|||
|
||||
### Fixed
|
||||
|
||||
- Remarks of the updated linter.
|
||||
- Remarks of the updated linter.
|
||||
|
||||
## [1.22.0] - 2020-12-30 - Yeouido (여의도, 汝矣島)
|
||||
|
||||
|
@ -335,7 +335,7 @@ Support changes from NeoFS API v2.2.0 "Yeouido" release.
|
|||
- Support of `StorageGroup` message.
|
||||
- Support of `DataAuditResult` message.
|
||||
- Stringer and string parser for `Checksum` type of client library.
|
||||
- Stringer and string parser for `Type` message.
|
||||
- Stringer and string parser for `Type` message.
|
||||
- Stringer and string parser for `Type` type of client library.
|
||||
- `AddTypeFilter` method on `SearchFilters` type of client library
|
||||
that adds filter by object type.
|
||||
|
@ -350,7 +350,7 @@ Support changes from NeoFS API v2.2.0 "Yeouido" release.
|
|||
- `Container.SetNonceUUID` setter of container nonce in UUID format.
|
||||
- `NewVerifiedContainerFromV2` container constructor that preliminary
|
||||
checks if container message argument meets NeoFS API V2 specification.
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- `Container.Nonce`/`Container.SetNonce` marked as deprecated.
|
||||
|
@ -368,7 +368,7 @@ Support neofs-api v2.1.1.
|
|||
|
||||
### Added
|
||||
|
||||
- `client.GetVerifiedContainerStructure` function to check
|
||||
- `client.GetVerifiedContainerStructure` function to check
|
||||
that the container structure matches the requested identifier.
|
||||
|
||||
## [1.21.0] - 2020-12-11 - Modo (모도, 茅島)
|
||||
|
@ -391,7 +391,7 @@ Support neofs-api v2.1.1.
|
|||
|
||||
### Renamed
|
||||
|
||||
- `AddLeafFilter` to `AddPhyFilter`
|
||||
- `AddLeafFilter` to `AddPhyFilter`
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -425,9 +425,9 @@ Support neofs-api v2.1.1.
|
|||
|
||||
## [1.20.0] - 2020-11-16 - Jindo (진도, 珍島)
|
||||
|
||||
Major API refactoring and simplification. From now on this library will have
|
||||
backward compatibility and support of major versions of NeoFS-API by having
|
||||
**version specific** files in `vN` dirs and **version independent** SDK
|
||||
Major API refactoring and simplification. From now on this library will have
|
||||
backward compatibility and support of major versions of NeoFS-API by having
|
||||
**version specific** files in `vN` dirs and **version independent** SDK
|
||||
structures and client in `pkg`. This version supports NeoFS-API v2.0.X
|
||||
|
||||
|
||||
|
|
0
Makefile
Normal file → Executable file
0
Makefile
Normal file → Executable file
|
@ -1,7 +1,7 @@
|
|||
package container
|
||||
|
||||
// SysAttributePrefix is a prefix of key to system attribute.
|
||||
const SysAttributePrefix = "__NEOFS__"
|
||||
const SysAttributePrefix = "__FROSTFS__"
|
||||
|
||||
const (
|
||||
// SysAttributeSubnet is a string ID of container's storage subnet.
|
||||
|
@ -17,6 +17,23 @@ const (
|
|||
SysAttributeHomomorphicHashing = SysAttributePrefix + "DISABLE_HOMOMORPHIC_HASHING"
|
||||
)
|
||||
|
||||
// SysAttributePrefixNeoFS is a prefix of key to system attribute.
|
||||
const SysAttributePrefixNeoFS = "__NEOFS__"
|
||||
|
||||
const (
|
||||
// SysAttributeSubnetNeoFS is a string ID of container's storage subnet.
|
||||
SysAttributeSubnetNeoFS = SysAttributePrefixNeoFS + "SUBNET"
|
||||
|
||||
// SysAttributeNameNeoFS is a string of human-friendly container name registered as the domain in NNS contract.
|
||||
SysAttributeNameNeoFS = SysAttributePrefixNeoFS + "NAME"
|
||||
|
||||
// SysAttributeZoneNeoFS is a string of zone for container name.
|
||||
SysAttributeZoneNeoFS = SysAttributePrefixNeoFS + "ZONE"
|
||||
|
||||
// SysAttributeHomomorphicHashingNeoFS is a container's homomorphic hashing state.
|
||||
SysAttributeHomomorphicHashingNeoFS = SysAttributePrefixNeoFS + "DISABLE_HOMOMORPHIC_HASHING"
|
||||
)
|
||||
|
||||
// SysAttributeZoneDefault is a default value for SysAttributeZone attribute.
|
||||
const SysAttributeZoneDefault = "container"
|
||||
|
||||
|
@ -33,7 +50,7 @@ const disabledHomomorphicHashingValue = "true"
|
|||
// See also SetHomomorphicHashingState.
|
||||
func (c Container) HomomorphicHashingState() bool {
|
||||
for i := range c.attr {
|
||||
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing {
|
||||
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS {
|
||||
return c.attr[i].GetValue() != disabledHomomorphicHashingValue
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +67,7 @@ func (c Container) HomomorphicHashingState() bool {
|
|||
// See also HomomorphicHashingState.
|
||||
func (c *Container) SetHomomorphicHashingState(enable bool) {
|
||||
for i := range c.attr {
|
||||
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing {
|
||||
if c.attr[i].GetKey() == SysAttributeHomomorphicHashing || c.attr[i].GetKey() == SysAttributeHomomorphicHashingNeoFS {
|
||||
if enable {
|
||||
// approach without allocation/waste
|
||||
// coping works since the attributes
|
||||
|
|
BIN
container/grpc/types.pb.go
generated
BIN
container/grpc/types.pb.go
generated
Binary file not shown.
6
go.mod
6
go.mod
|
@ -1,10 +1,11 @@
|
|||
module git.frostfs.info/TrueCloudLab/frostfs-api-go/v2
|
||||
|
||||
go 1.17
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/sync v0.1.0
|
||||
google.golang.org/grpc v1.48.0
|
||||
google.golang.org/protobuf v1.28.0
|
||||
)
|
||||
|
@ -13,10 +14,11 @@ require (
|
|||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
|
|
9
go.sum
9
go.sum
|
@ -46,8 +46,9 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
|
@ -82,13 +83,16 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -98,7 +102,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
|
|||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
|
BIN
lock/grpc/types.pb.go
generated
BIN
lock/grpc/types.pb.go
generated
Binary file not shown.
|
@ -9,7 +9,10 @@ import (
|
|||
)
|
||||
|
||||
// prefix of keys to subnet attributes.
|
||||
const attrSubnetPrefix = "__NEOFS__SUBNET_"
|
||||
const attrSubnetPrefix = "__FROSTFS__SUBNET_"
|
||||
|
||||
// prefix of keys to subnet attributes.
|
||||
const attrSubnetPrefixNeoFS = "__NEOFS__SUBNET_"
|
||||
|
||||
const (
|
||||
// subnet attribute's value denoting subnet entry
|
||||
|
@ -62,7 +65,7 @@ func subnetAttributeKey(id *refs.SubnetID) string {
|
|||
// - disables non-zero subnet;
|
||||
// - enables zero subnet.
|
||||
//
|
||||
// Attribute key is calculated from ID using format `__NEOFS__SUBNET_%s`.
|
||||
// Attribute key is calculated from ID using format `__FROSTFS__SUBNET_%s`.
|
||||
// Attribute Value is:
|
||||
// - `True` if node enters the subnet;
|
||||
// - `False`, otherwise.
|
||||
|
@ -143,8 +146,11 @@ func IterateSubnets(node *NodeInfo, f func(refs.SubnetID) error) error {
|
|||
// cut subnet ID string
|
||||
idTxt := strings.TrimPrefix(key, attrSubnetPrefix)
|
||||
if len(idTxt) == len(key) {
|
||||
// not a subnet attribute
|
||||
continue
|
||||
idTxt = strings.TrimPrefix(key, attrSubnetPrefixNeoFS)
|
||||
if len(idTxt) == len(key) {
|
||||
// not a subnet attribute
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// check value
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func subnetAttrKey(val string) string {
|
||||
return "__NEOFS__SUBNET_" + val
|
||||
return "__FROSTFS__SUBNET_" + val
|
||||
}
|
||||
|
||||
func assertSubnetAttrKey(t *testing.T, attr *netmap.Attribute, num uint32) {
|
||||
|
|
BIN
netmap/grpc/types.pb.go
generated
BIN
netmap/grpc/types.pb.go
generated
Binary file not shown.
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
// SysAttributePrefix is a prefix of key to system attribute.
|
||||
const SysAttributePrefix = "__NEOFS__"
|
||||
const SysAttributePrefix = "__FROSTFS__"
|
||||
|
||||
const (
|
||||
// SysAttributeUploadID marks smaller parts of a split bigger object.
|
||||
|
@ -25,6 +25,25 @@ const (
|
|||
SysAttributeTickTopic = SysAttributePrefix + "TICK_TOPIC"
|
||||
)
|
||||
|
||||
// SysAttributePrefixNeoFS is a prefix of key to system attribute.
|
||||
const SysAttributePrefixNeoFS = "__NEOFS__"
|
||||
|
||||
const (
|
||||
// SysAttributeUploadIDNeoFS marks smaller parts of a split bigger object.
|
||||
SysAttributeUploadIDNeoFS = SysAttributePrefixNeoFS + "UPLOAD_ID"
|
||||
|
||||
// SysAttributeExpEpochNeoFS tells GC to delete object after that epoch.
|
||||
SysAttributeExpEpochNeoFS = SysAttributePrefixNeoFS + "EXPIRATION_EPOCH"
|
||||
|
||||
// SysAttributeTickEpochNeoFS defines what epoch must produce object
|
||||
// notification.
|
||||
SysAttributeTickEpochNeoFS = SysAttributePrefixNeoFS + "TICK_EPOCH"
|
||||
|
||||
// SysAttributeTickTopicNeoFS defines what topic object notification
|
||||
// must be sent to.
|
||||
SysAttributeTickTopicNeoFS = SysAttributePrefixNeoFS + "TICK_TOPIC"
|
||||
)
|
||||
|
||||
// NotificationInfo groups information about object notification
|
||||
// that can be written to object.
|
||||
//
|
||||
|
@ -81,10 +100,10 @@ func WriteNotificationInfo(o *Object, ni NotificationInfo) {
|
|||
|
||||
for i := range attrs {
|
||||
switch attrs[i].GetKey() {
|
||||
case SysAttributeTickEpoch:
|
||||
case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS:
|
||||
attrs[i].SetValue(epoch)
|
||||
changedEpoch = true
|
||||
case SysAttributeTickTopic:
|
||||
case SysAttributeTickTopic, SysAttributeTickTopicNeoFS:
|
||||
changedTopic = true
|
||||
|
||||
if topic == "" {
|
||||
|
@ -141,7 +160,7 @@ func GetNotificationInfo(o *Object) (*NotificationInfo, error) {
|
|||
|
||||
for _, attr := range o.GetHeader().GetAttributes() {
|
||||
switch key := attr.GetKey(); key {
|
||||
case SysAttributeTickEpoch:
|
||||
case SysAttributeTickEpoch, SysAttributeTickEpochNeoFS:
|
||||
epoch, err := strconv.ParseUint(attr.GetValue(), 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not parse epoch: %w", err)
|
||||
|
@ -150,7 +169,7 @@ func GetNotificationInfo(o *Object) (*NotificationInfo, error) {
|
|||
ni.SetEpoch(epoch)
|
||||
|
||||
foundEpoch = true
|
||||
case SysAttributeTickTopic:
|
||||
case SysAttributeTickTopic, SysAttributeTickTopicNeoFS:
|
||||
ni.SetTopic(attr.GetValue())
|
||||
}
|
||||
}
|
||||
|
|
BIN
object/grpc/service_grpc.pb.go
generated
BIN
object/grpc/service_grpc.pb.go
generated
Binary file not shown.
BIN
object/grpc/types.pb.go
generated
BIN
object/grpc/types.pb.go
generated
Binary file not shown.
BIN
session/grpc/types.pb.go
generated
BIN
session/grpc/types.pb.go
generated
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
package session
|
||||
|
||||
// ReservedXHeaderPrefix is a prefix of keys to "well-known" X-headers.
|
||||
const ReservedXHeaderPrefix = "__NEOFS__"
|
||||
const ReservedXHeaderPrefix = "__FROSTFS__"
|
||||
|
||||
const (
|
||||
// XHeaderNetmapEpoch is a key to the reserved X-header that specifies netmap epoch
|
||||
|
@ -14,3 +14,18 @@ const (
|
|||
// set, the current epoch only will be used.
|
||||
XHeaderNetmapLookupDepth = ReservedXHeaderPrefix + "NETMAP_LOOKUP_DEPTH"
|
||||
)
|
||||
|
||||
// ReservedXHeaderPrefixNeoFS is a prefix of keys to "well-known" X-headers.
|
||||
const ReservedXHeaderPrefixNeoFS = "__NEOFS__"
|
||||
|
||||
const (
|
||||
// XHeaderNetmapEpochNeoFS is a key to the reserved X-header that specifies netmap epoch
|
||||
// to use for object placement calculation. If set to '0' or not set, the current
|
||||
// epoch only will be used.
|
||||
XHeaderNetmapEpochNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_EPOCH"
|
||||
|
||||
// XHeaderNetmapLookupDepthNeoFS is a key to the reserved X-header that limits
|
||||
// how many past epochs back the node will can lookup. If set to '0' or not
|
||||
// set, the current epoch only will be used.
|
||||
XHeaderNetmapLookupDepthNeoFS = ReservedXHeaderPrefixNeoFS + "NETMAP_LOOKUP_DEPTH"
|
||||
)
|
||||
|
|
115
signature/body.go
Normal file
115
signature/body.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
package signature
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/reputation"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
)
|
||||
|
||||
func serviceMessageBody(req interface{}) stableMarshaler {
|
||||
switch v := req.(type) {
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", req))
|
||||
|
||||
/* Accounting */
|
||||
case *accounting.BalanceRequest:
|
||||
return v.GetBody()
|
||||
case *accounting.BalanceResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Session */
|
||||
case *session.CreateRequest:
|
||||
return v.GetBody()
|
||||
case *session.CreateResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Container */
|
||||
case *container.PutRequest:
|
||||
return v.GetBody()
|
||||
case *container.PutResponse:
|
||||
return v.GetBody()
|
||||
case *container.DeleteRequest:
|
||||
return v.GetBody()
|
||||
case *container.DeleteResponse:
|
||||
return v.GetBody()
|
||||
case *container.GetRequest:
|
||||
return v.GetBody()
|
||||
case *container.GetResponse:
|
||||
return v.GetBody()
|
||||
case *container.ListRequest:
|
||||
return v.GetBody()
|
||||
case *container.ListResponse:
|
||||
return v.GetBody()
|
||||
case *container.SetExtendedACLRequest:
|
||||
return v.GetBody()
|
||||
case *container.SetExtendedACLResponse:
|
||||
return v.GetBody()
|
||||
case *container.GetExtendedACLRequest:
|
||||
return v.GetBody()
|
||||
case *container.GetExtendedACLResponse:
|
||||
return v.GetBody()
|
||||
case *container.AnnounceUsedSpaceRequest:
|
||||
return v.GetBody()
|
||||
case *container.AnnounceUsedSpaceResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Object */
|
||||
case *object.PutRequest:
|
||||
return v.GetBody()
|
||||
case *object.PutResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetResponse:
|
||||
return v.GetBody()
|
||||
case *object.HeadRequest:
|
||||
return v.GetBody()
|
||||
case *object.HeadResponse:
|
||||
return v.GetBody()
|
||||
case *object.SearchRequest:
|
||||
return v.GetBody()
|
||||
case *object.SearchResponse:
|
||||
return v.GetBody()
|
||||
case *object.DeleteRequest:
|
||||
return v.GetBody()
|
||||
case *object.DeleteResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeHashRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeHashResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Netmap */
|
||||
case *netmap.LocalNodeInfoRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.LocalNodeInfoResponse:
|
||||
return v.GetBody()
|
||||
case *netmap.NetworkInfoRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.NetworkInfoResponse:
|
||||
return v.GetBody()
|
||||
case *netmap.SnapshotRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.SnapshotResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Reputation */
|
||||
case *reputation.AnnounceLocalTrustRequest:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceLocalTrustResponse:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceIntermediateResultRequest:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceIntermediateResultResponse:
|
||||
return v.GetBody()
|
||||
}
|
||||
}
|
26
signature/marshaller.go
Normal file
26
signature/marshaller.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package signature
|
||||
|
||||
type stableMarshaler interface {
|
||||
StableMarshal([]byte) []byte
|
||||
StableSize() int
|
||||
}
|
||||
|
||||
type StableMarshalerWrapper struct {
|
||||
SM stableMarshaler
|
||||
}
|
||||
|
||||
func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) {
|
||||
if s.SM != nil {
|
||||
return s.SM.StableMarshal(buf), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s StableMarshalerWrapper) SignedDataSize() int {
|
||||
if s.SM != nil {
|
||||
return s.SM.StableSize()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
|
@ -2,17 +2,12 @@ package signature
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/reputation"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type serviceRequest interface {
|
||||
|
@ -27,179 +22,92 @@ type serviceResponse interface {
|
|||
SetVerificationHeader(*session.ResponseVerificationHeader)
|
||||
}
|
||||
|
||||
type stableMarshaler interface {
|
||||
StableMarshal([]byte) []byte
|
||||
StableSize() int
|
||||
}
|
||||
|
||||
type StableMarshalerWrapper struct {
|
||||
SM stableMarshaler
|
||||
}
|
||||
|
||||
type metaHeader interface {
|
||||
stableMarshaler
|
||||
getOrigin() metaHeader
|
||||
}
|
||||
|
||||
type verificationHeader interface {
|
||||
stableMarshaler
|
||||
|
||||
GetBodySignature() *refs.Signature
|
||||
type signatureReceiver interface {
|
||||
SetBodySignature(*refs.Signature)
|
||||
GetMetaSignature() *refs.Signature
|
||||
SetMetaSignature(*refs.Signature)
|
||||
GetOriginSignature() *refs.Signature
|
||||
SetOriginSignature(*refs.Signature)
|
||||
|
||||
setOrigin(stableMarshaler)
|
||||
getOrigin() verificationHeader
|
||||
}
|
||||
|
||||
type requestMetaHeader struct {
|
||||
*session.RequestMetaHeader
|
||||
}
|
||||
|
||||
type responseMetaHeader struct {
|
||||
*session.ResponseMetaHeader
|
||||
}
|
||||
|
||||
type requestVerificationHeader struct {
|
||||
*session.RequestVerificationHeader
|
||||
}
|
||||
|
||||
type responseVerificationHeader struct {
|
||||
*session.ResponseVerificationHeader
|
||||
}
|
||||
|
||||
func (h *requestMetaHeader) getOrigin() metaHeader {
|
||||
return &requestMetaHeader{
|
||||
RequestMetaHeader: h.GetOrigin(),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *responseMetaHeader) getOrigin() metaHeader {
|
||||
return &responseMetaHeader{
|
||||
ResponseMetaHeader: h.GetOrigin(),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *requestVerificationHeader) getOrigin() verificationHeader {
|
||||
if origin := h.GetOrigin(); origin != nil {
|
||||
return &requestVerificationHeader{
|
||||
RequestVerificationHeader: origin,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *requestVerificationHeader) setOrigin(m stableMarshaler) {
|
||||
if m != nil {
|
||||
h.SetOrigin(m.(*session.RequestVerificationHeader))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *responseVerificationHeader) getOrigin() verificationHeader {
|
||||
if origin := r.GetOrigin(); origin != nil {
|
||||
return &responseVerificationHeader{
|
||||
ResponseVerificationHeader: origin,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *responseVerificationHeader) setOrigin(m stableMarshaler) {
|
||||
if m != nil {
|
||||
r.SetOrigin(m.(*session.ResponseVerificationHeader))
|
||||
}
|
||||
}
|
||||
|
||||
func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) {
|
||||
if s.SM != nil {
|
||||
return s.SM.StableMarshal(buf), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s StableMarshalerWrapper) SignedDataSize() int {
|
||||
if s.SM != nil {
|
||||
return s.SM.StableSize()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// SignServiceMessage signes service message with key.
|
||||
func SignServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error {
|
||||
var (
|
||||
body, meta, verifyOrigin stableMarshaler
|
||||
verifyHdr verificationHeader
|
||||
verifyHdrSetter func(verificationHeader)
|
||||
)
|
||||
|
||||
switch v := msg.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
case serviceRequest:
|
||||
body = serviceMessageBody(v)
|
||||
meta = v.GetMetaHeader()
|
||||
verifyHdr = &requestVerificationHeader{new(session.RequestVerificationHeader)}
|
||||
verifyHdrSetter = func(h verificationHeader) {
|
||||
v.SetVerificationHeader(h.(*requestVerificationHeader).RequestVerificationHeader)
|
||||
}
|
||||
|
||||
if h := v.GetVerificationHeader(); h != nil {
|
||||
verifyOrigin = h
|
||||
}
|
||||
return signServiceRequest(key, v)
|
||||
case serviceResponse:
|
||||
body = serviceMessageBody(v)
|
||||
meta = v.GetMetaHeader()
|
||||
verifyHdr = &responseVerificationHeader{new(session.ResponseVerificationHeader)}
|
||||
verifyHdrSetter = func(h verificationHeader) {
|
||||
v.SetVerificationHeader(h.(*responseVerificationHeader).ResponseVerificationHeader)
|
||||
}
|
||||
|
||||
if h := v.GetVerificationHeader(); h != nil {
|
||||
verifyOrigin = h
|
||||
}
|
||||
return signServiceResponse(key, v)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||
}
|
||||
}
|
||||
|
||||
if verifyOrigin == nil {
|
||||
func signServiceRequest(key *ecdsa.PrivateKey, v serviceRequest) error {
|
||||
result := &session.RequestVerificationHeader{}
|
||||
body := serviceMessageBody(v)
|
||||
meta := v.GetMetaHeader()
|
||||
header := v.GetVerificationHeader()
|
||||
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
|
||||
return err
|
||||
}
|
||||
result.SetOrigin(header)
|
||||
v.SetVerificationHeader(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func signServiceResponse(key *ecdsa.PrivateKey, v serviceResponse) error {
|
||||
result := &session.ResponseVerificationHeader{}
|
||||
body := serviceMessageBody(v)
|
||||
meta := v.GetMetaHeader()
|
||||
header := v.GetVerificationHeader()
|
||||
if err := signMessageParts(key, body, meta, header, header != nil, result); err != nil {
|
||||
return err
|
||||
}
|
||||
result.SetOrigin(header)
|
||||
v.SetVerificationHeader(result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func signMessageParts(key *ecdsa.PrivateKey, body, meta, header stableMarshaler, hasHeader bool, result signatureReceiver) error {
|
||||
eg := &errgroup.Group{}
|
||||
if !hasHeader {
|
||||
// sign session message body
|
||||
if err := signServiceMessagePart(key, body, verifyHdr.SetBodySignature); err != nil {
|
||||
return fmt.Errorf("could not sign body: %w", err)
|
||||
}
|
||||
eg.Go(func() error {
|
||||
if err := signServiceMessagePart(key, body, result.SetBodySignature); err != nil {
|
||||
return fmt.Errorf("could not sign body: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// sign meta header
|
||||
if err := signServiceMessagePart(key, meta, verifyHdr.SetMetaSignature); err != nil {
|
||||
return fmt.Errorf("could not sign meta header: %w", err)
|
||||
}
|
||||
eg.Go(func() error {
|
||||
if err := signServiceMessagePart(key, meta, result.SetMetaSignature); err != nil {
|
||||
return fmt.Errorf("could not sign meta header: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// sign verification header origin
|
||||
if err := signServiceMessagePart(key, verifyOrigin, verifyHdr.SetOriginSignature); err != nil {
|
||||
return fmt.Errorf("could not sign origin of verification header: %w", err)
|
||||
}
|
||||
|
||||
// wrap origin verification header
|
||||
verifyHdr.setOrigin(verifyOrigin)
|
||||
|
||||
// update matryoshka verification header
|
||||
verifyHdrSetter(verifyHdr)
|
||||
|
||||
return nil
|
||||
eg.Go(func() error {
|
||||
if err := signServiceMessagePart(key, header, result.SetOriginSignature); err != nil {
|
||||
return fmt.Errorf("could not sign origin of verification header: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error {
|
||||
var sig *refs.Signature
|
||||
|
||||
wrapper := StableMarshalerWrapper{
|
||||
SM: part,
|
||||
}
|
||||
// sign part
|
||||
if err := signature.SignDataWithHandler(
|
||||
key,
|
||||
&StableMarshalerWrapper{part},
|
||||
wrapper,
|
||||
func(s *refs.Signature) {
|
||||
sig = s
|
||||
},
|
||||
|
@ -212,182 +120,3 @@ func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrit
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyServiceMessage(msg interface{}) error {
|
||||
var (
|
||||
meta metaHeader
|
||||
verify verificationHeader
|
||||
)
|
||||
|
||||
switch v := msg.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
case serviceRequest:
|
||||
meta = &requestMetaHeader{
|
||||
RequestMetaHeader: v.GetMetaHeader(),
|
||||
}
|
||||
|
||||
verify = &requestVerificationHeader{
|
||||
RequestVerificationHeader: v.GetVerificationHeader(),
|
||||
}
|
||||
case serviceResponse:
|
||||
meta = &responseMetaHeader{
|
||||
ResponseMetaHeader: v.GetMetaHeader(),
|
||||
}
|
||||
|
||||
verify = &responseVerificationHeader{
|
||||
ResponseVerificationHeader: v.GetVerificationHeader(),
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||
}
|
||||
|
||||
body := serviceMessageBody(msg)
|
||||
size := body.StableSize()
|
||||
if sz := meta.StableSize(); sz > size {
|
||||
size = sz
|
||||
}
|
||||
if sz := verify.StableSize(); sz > size {
|
||||
size = sz
|
||||
}
|
||||
|
||||
buf := make([]byte, 0, size)
|
||||
return verifyMatryoshkaLevel(body, meta, verify, buf)
|
||||
}
|
||||
|
||||
func verifyMatryoshkaLevel(body stableMarshaler, meta metaHeader, verify verificationHeader, buf []byte) error {
|
||||
if err := verifyServiceMessagePart(meta, verify.GetMetaSignature, buf); err != nil {
|
||||
return fmt.Errorf("could not verify meta header: %w", err)
|
||||
}
|
||||
|
||||
origin := verify.getOrigin()
|
||||
|
||||
if err := verifyServiceMessagePart(origin, verify.GetOriginSignature, buf); err != nil {
|
||||
return fmt.Errorf("could not verify origin of verification header: %w", err)
|
||||
}
|
||||
|
||||
if origin == nil {
|
||||
if err := verifyServiceMessagePart(body, verify.GetBodySignature, buf); err != nil {
|
||||
return fmt.Errorf("could not verify body: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if verify.GetBodySignature() != nil {
|
||||
return errors.New("body signature at the matryoshka upper level")
|
||||
}
|
||||
|
||||
return verifyMatryoshkaLevel(body, meta.getOrigin(), origin, buf)
|
||||
}
|
||||
|
||||
func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error {
|
||||
return signature.VerifyDataWithSource(
|
||||
&StableMarshalerWrapper{part},
|
||||
sigRdr,
|
||||
signature.WithBuffer(buf),
|
||||
)
|
||||
}
|
||||
|
||||
func serviceMessageBody(req interface{}) stableMarshaler {
|
||||
switch v := req.(type) {
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", req))
|
||||
|
||||
/* Accounting */
|
||||
case *accounting.BalanceRequest:
|
||||
return v.GetBody()
|
||||
case *accounting.BalanceResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Session */
|
||||
case *session.CreateRequest:
|
||||
return v.GetBody()
|
||||
case *session.CreateResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Container */
|
||||
case *container.PutRequest:
|
||||
return v.GetBody()
|
||||
case *container.PutResponse:
|
||||
return v.GetBody()
|
||||
case *container.DeleteRequest:
|
||||
return v.GetBody()
|
||||
case *container.DeleteResponse:
|
||||
return v.GetBody()
|
||||
case *container.GetRequest:
|
||||
return v.GetBody()
|
||||
case *container.GetResponse:
|
||||
return v.GetBody()
|
||||
case *container.ListRequest:
|
||||
return v.GetBody()
|
||||
case *container.ListResponse:
|
||||
return v.GetBody()
|
||||
case *container.SetExtendedACLRequest:
|
||||
return v.GetBody()
|
||||
case *container.SetExtendedACLResponse:
|
||||
return v.GetBody()
|
||||
case *container.GetExtendedACLRequest:
|
||||
return v.GetBody()
|
||||
case *container.GetExtendedACLResponse:
|
||||
return v.GetBody()
|
||||
case *container.AnnounceUsedSpaceRequest:
|
||||
return v.GetBody()
|
||||
case *container.AnnounceUsedSpaceResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Object */
|
||||
case *object.PutRequest:
|
||||
return v.GetBody()
|
||||
case *object.PutResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetResponse:
|
||||
return v.GetBody()
|
||||
case *object.HeadRequest:
|
||||
return v.GetBody()
|
||||
case *object.HeadResponse:
|
||||
return v.GetBody()
|
||||
case *object.SearchRequest:
|
||||
return v.GetBody()
|
||||
case *object.SearchResponse:
|
||||
return v.GetBody()
|
||||
case *object.DeleteRequest:
|
||||
return v.GetBody()
|
||||
case *object.DeleteResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeResponse:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeHashRequest:
|
||||
return v.GetBody()
|
||||
case *object.GetRangeHashResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Netmap */
|
||||
case *netmap.LocalNodeInfoRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.LocalNodeInfoResponse:
|
||||
return v.GetBody()
|
||||
case *netmap.NetworkInfoRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.NetworkInfoResponse:
|
||||
return v.GetBody()
|
||||
case *netmap.SnapshotRequest:
|
||||
return v.GetBody()
|
||||
case *netmap.SnapshotResponse:
|
||||
return v.GetBody()
|
||||
|
||||
/* Reputation */
|
||||
case *reputation.AnnounceLocalTrustRequest:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceLocalTrustResponse:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceIntermediateResultRequest:
|
||||
return v.GetBody()
|
||||
case *reputation.AnnounceIntermediateResultResponse:
|
||||
return v.GetBody()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,3 +70,56 @@ func TestBalanceResponse(t *testing.T) {
|
|||
// verification must fail
|
||||
require.Error(t, VerifyServiceMessage(req))
|
||||
}
|
||||
|
||||
func BenchmarkSignRequest(b *testing.B) {
|
||||
key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s")
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
dec := new(accounting.Decimal)
|
||||
dec.SetValue(100)
|
||||
|
||||
body := new(accounting.BalanceResponseBody)
|
||||
body.SetBalance(dec)
|
||||
|
||||
meta := new(session.ResponseMetaHeader)
|
||||
meta.SetTTL(1)
|
||||
|
||||
resp := new(accounting.BalanceResponse)
|
||||
resp.SetBody(body)
|
||||
resp.SetMetaHeader(meta)
|
||||
|
||||
b.StartTimer()
|
||||
SignServiceMessage(key, resp)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerifyRequest(b *testing.B) {
|
||||
key, _ := crypto.LoadPrivateKey("Kwk6k2eC3L3QuPvD8aiaNyoSXgQ2YL1bwS5CP1oKoA9waeAze97s")
|
||||
|
||||
b.ResetTimer()
|
||||
b.ReportAllocs()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
b.StopTimer()
|
||||
dec := new(accounting.Decimal)
|
||||
dec.SetValue(100)
|
||||
|
||||
body := new(accounting.BalanceResponseBody)
|
||||
body.SetBalance(dec)
|
||||
|
||||
meta := new(session.ResponseMetaHeader)
|
||||
meta.SetTTL(1)
|
||||
|
||||
resp := new(accounting.BalanceResponse)
|
||||
resp.SetBody(body)
|
||||
resp.SetMetaHeader(meta)
|
||||
SignServiceMessage(key, resp)
|
||||
b.StartTimer()
|
||||
|
||||
VerifyServiceMessage(resp)
|
||||
}
|
||||
}
|
||||
|
|
127
signature/verify.go
Normal file
127
signature/verify.go
Normal file
|
@ -0,0 +1,127 @@
|
|||
package signature
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type signatureProvider interface {
|
||||
GetBodySignature() *refs.Signature
|
||||
GetMetaSignature() *refs.Signature
|
||||
GetOriginSignature() *refs.Signature
|
||||
}
|
||||
|
||||
// VerifyServiceMessage verifies service message.
|
||||
func VerifyServiceMessage(msg interface{}) error {
|
||||
switch v := msg.(type) {
|
||||
case nil:
|
||||
return nil
|
||||
case serviceRequest:
|
||||
return verifyServiceRequest(v)
|
||||
case serviceResponse:
|
||||
return verifyServiceResponse(v)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported session message %T", v))
|
||||
}
|
||||
}
|
||||
|
||||
func verifyServiceRequest(v serviceRequest) error {
|
||||
meta := v.GetMetaHeader()
|
||||
verificationHeader := v.GetVerificationHeader()
|
||||
body := serviceMessageBody(v)
|
||||
return verifyServiceRequestRecursive(body, meta, verificationHeader)
|
||||
}
|
||||
|
||||
func verifyServiceRequestRecursive(body stableMarshaler, meta *session.RequestMetaHeader, verify *session.RequestVerificationHeader) error {
|
||||
verificationHeaderOrigin := verify.GetOrigin()
|
||||
metaOrigin := meta.GetOrigin()
|
||||
|
||||
stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stop {
|
||||
return nil
|
||||
}
|
||||
|
||||
return verifyServiceRequestRecursive(body, metaOrigin, verificationHeaderOrigin)
|
||||
}
|
||||
|
||||
func verifyMessageParts(body, meta, originHeader stableMarshaler, hasOriginHeader bool, sigProvider signatureProvider) (stop bool, err error) {
|
||||
eg := &errgroup.Group{}
|
||||
|
||||
eg.Go(func() error {
|
||||
if err := verifyServiceMessagePart(meta, sigProvider.GetMetaSignature); err != nil {
|
||||
return fmt.Errorf("could not verify meta header: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
eg.Go(func() error {
|
||||
if err := verifyServiceMessagePart(originHeader, sigProvider.GetOriginSignature); err != nil {
|
||||
return fmt.Errorf("could not verify origin of verification header: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if !hasOriginHeader {
|
||||
eg.Go(func() error {
|
||||
if err := verifyServiceMessagePart(body, sigProvider.GetBodySignature); err != nil {
|
||||
return fmt.Errorf("could not verify body: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
if err := eg.Wait(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !hasOriginHeader {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if sigProvider.GetBodySignature() != nil {
|
||||
return false, errors.New("body signature misses at the matryoshka upper level")
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func verifyServiceResponse(v serviceResponse) error {
|
||||
meta := v.GetMetaHeader()
|
||||
verificationHeader := v.GetVerificationHeader()
|
||||
body := serviceMessageBody(v)
|
||||
return verifyServiceResponseRecursive(body, meta, verificationHeader)
|
||||
}
|
||||
|
||||
func verifyServiceResponseRecursive(body stableMarshaler, meta *session.ResponseMetaHeader, verify *session.ResponseVerificationHeader) error {
|
||||
verificationHeaderOrigin := verify.GetOrigin()
|
||||
metaOrigin := meta.GetOrigin()
|
||||
|
||||
stop, err := verifyMessageParts(body, meta, verificationHeaderOrigin, verificationHeaderOrigin != nil, verify)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stop {
|
||||
return nil
|
||||
}
|
||||
|
||||
return verifyServiceResponseRecursive(body, metaOrigin, verificationHeaderOrigin)
|
||||
}
|
||||
|
||||
func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature) error {
|
||||
wrapper := StableMarshalerWrapper{
|
||||
SM: part,
|
||||
}
|
||||
|
||||
return signature.VerifyDataWithSource(
|
||||
wrapper,
|
||||
sigRdr,
|
||||
)
|
||||
}
|
BIN
storagegroup/grpc/types.pb.go
generated
BIN
storagegroup/grpc/types.pb.go
generated
Binary file not shown.
BIN
tombstone/grpc/types.pb.go
generated
BIN
tombstone/grpc/types.pb.go
generated
Binary file not shown.
29
util/signature/buffer.go
Normal file
29
util/signature/buffer.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package signature
|
||||
|
||||
import "sync"
|
||||
|
||||
const poolSliceMaxSize = 64 * 1024
|
||||
|
||||
var buffersPool = sync.Pool{
|
||||
New: func() any {
|
||||
return make([]byte, 0)
|
||||
},
|
||||
}
|
||||
|
||||
func newBufferFromPool(size int) []byte {
|
||||
result := buffersPool.Get().([]byte)
|
||||
if cap(result) < size {
|
||||
result = make([]byte, size)
|
||||
} else {
|
||||
result = result[:size]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func returnBufferToPool(buf []byte) {
|
||||
if cap(buf) > poolSliceMaxSize {
|
||||
return
|
||||
}
|
||||
buf = buf[:0]
|
||||
buffersPool.Put(buf)
|
||||
}
|
|
@ -35,7 +35,10 @@ func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySigna
|
|||
opts[i](cfg)
|
||||
}
|
||||
|
||||
data, err := readSignedData(cfg, src)
|
||||
buffer := newBufferFromPool(src.SignedDataSize())
|
||||
defer returnBufferToPool(buffer)
|
||||
|
||||
data, err := src.ReadSignedData(buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,7 +64,10 @@ func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ..
|
|||
opts[i](cfg)
|
||||
}
|
||||
|
||||
data, err := readSignedData(cfg, dataSrc)
|
||||
buffer := newBufferFromPool(dataSrc.SignedDataSize())
|
||||
defer returnBufferToPool(buffer)
|
||||
|
||||
data, err := dataSrc.ReadSignedData(buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -76,13 +82,3 @@ func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) er
|
|||
func VerifyData(src DataWithSignature, opts ...SignOption) error {
|
||||
return VerifyDataWithSource(src, src.GetSignature, opts...)
|
||||
}
|
||||
|
||||
func readSignedData(cfg *cfg, src DataSource) ([]byte, error) {
|
||||
size := src.SignedDataSize()
|
||||
if cfg.buffer == nil || cap(cfg.buffer) < size {
|
||||
cfg.buffer = make([]byte, size)
|
||||
} else {
|
||||
cfg.buffer = cfg.buffer[:size]
|
||||
}
|
||||
return src.ReadSignedData(cfg.buffer)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
type cfg struct {
|
||||
schemeFixed bool
|
||||
scheme refs.SignatureScheme
|
||||
buffer []byte
|
||||
}
|
||||
|
||||
func defaultCfg() *cfg {
|
||||
|
@ -36,9 +35,10 @@ func verify(cfg *cfg, data []byte, sig *refs.Signature) error {
|
|||
case refs.ECDSA_RFC6979_SHA256:
|
||||
return crypto.VerifyRFC6979(pub, data, sig.GetSign())
|
||||
case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
||||
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||||
base64.StdEncoding.Encode(buf, data)
|
||||
if !walletconnect.Verify(pub, buf, sig.GetSign()) {
|
||||
buffer := newBufferFromPool(base64.StdEncoding.EncodedLen(len(data)))
|
||||
defer returnBufferToPool(buffer)
|
||||
base64.StdEncoding.Encode(buffer, data)
|
||||
if !walletconnect.Verify(pub, buffer, sig.GetSign()) {
|
||||
return crypto.ErrInvalidSignature
|
||||
}
|
||||
return nil
|
||||
|
@ -54,9 +54,10 @@ func sign(cfg *cfg, key *ecdsa.PrivateKey, data []byte) ([]byte, error) {
|
|||
case refs.ECDSA_RFC6979_SHA256:
|
||||
return crypto.SignRFC6979(key, data)
|
||||
case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
|
||||
buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||||
base64.StdEncoding.Encode(buf, data)
|
||||
return walletconnect.Sign(key, buf)
|
||||
buffer := newBufferFromPool(base64.StdEncoding.EncodedLen(len(data)))
|
||||
defer returnBufferToPool(buffer)
|
||||
base64.StdEncoding.Encode(buffer, data)
|
||||
return walletconnect.Sign(key, buffer)
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported scheme %s", cfg.scheme))
|
||||
}
|
||||
|
@ -69,13 +70,6 @@ func SignWithRFC6979() SignOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithBuffer allows providing pre-allocated buffer for signature verification.
|
||||
func WithBuffer(buf []byte) SignOption {
|
||||
return func(c *cfg) {
|
||||
c.buffer = buf
|
||||
}
|
||||
}
|
||||
|
||||
func SignWithWalletConnect() SignOption {
|
||||
return func(c *cfg) {
|
||||
c.scheme = refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT
|
||||
|
|
Loading…
Reference in a new issue