forked from TrueCloudLab/frostfs-node
Compare commits
63 commits
master
...
support/v0
Author | SHA1 | Date | |
---|---|---|---|
|
db981e9c99 | ||
|
28ad4c6ebc | ||
c180c405b5 | |||
|
02049ca5b2 | ||
b9a24e99dc | |||
|
584f465eee | ||
|
2614aa1582 | ||
|
15d2091f42 | ||
056cb0d50e | |||
|
402bbba15a | ||
|
7cc0986e0c | ||
|
02676f05c3 | ||
|
e8d401e28d | ||
|
479601ceb9 | ||
|
27ca754dc1 | ||
|
56442c0be3 | ||
b167700b6f | |||
|
92cac5bbdf | ||
|
19a6ca7896 | ||
|
114018a7bd | ||
|
84f545dacc | ||
|
049ab58336 | ||
|
4ed5dcd9c8 | ||
|
cdbfd05704 | ||
|
8212020165 | ||
|
e538291c59 | ||
|
aa12fc57c9 | ||
|
5747187884 | ||
|
de2934aeaa | ||
|
2ba3abde5c | ||
|
f6f911b50c | ||
|
af54295ac6 | ||
|
ddba9180ef | ||
|
6acb831248 | ||
|
2a88b49bca | ||
|
01a226b3ec | ||
|
110f6e7864 | ||
|
c38ad2d339 | ||
|
51a9306e41 | ||
|
871be9d63d | ||
|
3eb2ac985d | ||
|
76b87c6d94 | ||
|
59eebc5eeb | ||
|
f79386e538 | ||
|
d2cce62934 | ||
|
a4a6d547a8 | ||
|
681400eed8 | ||
|
b580846630 | ||
|
6e2f7e291d | ||
|
7a75b3aaaf | ||
|
9cd8441dd5 | ||
|
163d8d778d | ||
|
52d85ca463 | ||
|
ba3db7fed5 | ||
|
2e89176892 | ||
|
855de87b62 | ||
|
289a7827c4 | ||
|
abf4a63585 | ||
|
3ee4260647 | ||
|
245da1e50e | ||
|
a386448ab9 | ||
|
3c1f788642 | ||
|
0de9efa685 |
1032 changed files with 8277 additions and 12881 deletions
|
@ -1,19 +1,19 @@
|
||||||
FROM golang:1.18 as builder
|
FROM golang:1.17 as builder
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG REPO=repository
|
ARG REPO=repository
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
RUN make bin/frostfs-adm
|
RUN make bin/neofs-adm
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM alpine AS frostfs-adm
|
FROM alpine AS neofs-adm
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
COPY --from=builder /src/bin/frostfs-adm /bin/frostfs-adm
|
COPY --from=builder /src/bin/neofs-adm /bin/neofs-adm
|
||||||
|
|
||||||
CMD ["frostfs-adm"]
|
CMD ["neofs-adm"]
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
FROM golang:1.19
|
|
||||||
|
|
||||||
WORKDIR /tmp
|
|
||||||
|
|
||||||
# Install apt packages
|
|
||||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
|
||||||
pip \
|
|
||||||
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Dash → Bash
|
|
||||||
RUN echo "dash dash/sh boolean false" | debconf-set-selections
|
|
||||||
RUN DEBIAN_FRONTEND=noninteractive dpkg-reconfigure dash
|
|
||||||
|
|
||||||
RUN useradd -u 1234 -d /home/ci -m ci
|
|
||||||
USER ci
|
|
||||||
|
|
||||||
ENV PATH="$PATH:/home/ci/.local/bin"
|
|
||||||
|
|
||||||
COPY .pre-commit-config.yaml .
|
|
||||||
|
|
||||||
RUN pip install "pre-commit==3.1.1" \
|
|
||||||
&& git init . \
|
|
||||||
&& pre-commit install-hooks \
|
|
||||||
&& rm -rf /tmp/*
|
|
|
@ -1,19 +1,19 @@
|
||||||
FROM golang:1.18 as builder
|
FROM golang:1.17 as builder
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG REPO=repository
|
ARG REPO=repository
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
RUN make bin/frostfs-cli
|
RUN make bin/neofs-cli
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM alpine AS frostfs-cli
|
FROM alpine AS neofs-cli
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||||
COPY --from=builder /src/bin/frostfs-cli /bin/frostfs-cli
|
COPY --from=builder /src/bin/neofs-cli /bin/neofs-cli
|
||||||
|
|
||||||
CMD ["frostfs-cli"]
|
CMD ["neofs-cli"]
|
||||||
|
|
|
@ -3,6 +3,6 @@ RUN apk add --no-cache bash ca-certificates
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY bin/frostfs-adm /bin/frostfs-adm
|
COPY bin/neofs-adm /bin/neofs-adm
|
||||||
|
|
||||||
CMD ["frostfs-adm"]
|
CMD ["neofs-adm"]
|
||||||
|
|
|
@ -3,6 +3,6 @@ RUN apk add --no-cache bash ca-certificates
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY bin/frostfs-cli /bin/frostfs-cli
|
COPY bin/neofs-cli /bin/neofs-cli
|
||||||
|
|
||||||
CMD ["frostfs-cli"]
|
CMD ["neofs-cli"]
|
||||||
|
|
|
@ -3,6 +3,6 @@ RUN apk add --no-cache bash ca-certificates
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY bin/frostfs-ir /bin/frostfs-ir
|
COPY bin/neofs-ir /bin/neofs-ir
|
||||||
|
|
||||||
CMD ["frostfs-ir"]
|
CMD ["neofs-ir"]
|
||||||
|
|
|
@ -3,6 +3,6 @@ RUN apk add --no-cache bash ca-certificates
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY bin/frostfs-node /bin/frostfs-node
|
COPY bin/neofs-node /bin/neofs-node
|
||||||
|
|
||||||
CMD ["frostfs-node"]
|
CMD ["neofs-node"]
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
FROM golang:1.18 as builder
|
FROM golang:1.17 as builder
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG REPO=repository
|
ARG REPO=repository
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
RUN make bin/frostfs-ir
|
RUN make bin/neofs-ir
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM alpine AS frostfs-ir
|
FROM alpine AS neofs-ir
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=builder /src/bin/frostfs-ir /bin/frostfs-ir
|
COPY --from=builder /src/bin/neofs-ir /bin/neofs-ir
|
||||||
|
|
||||||
CMD ["frostfs-ir"]
|
CMD ["neofs-ir"]
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
FROM golang:1.18 as builder
|
FROM golang:1.17 as builder
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG REPO=repository
|
ARG REPO=repository
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
RUN make bin/frostfs-node
|
RUN make bin/neofs-node
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM alpine AS frostfs-node
|
FROM alpine AS neofs-node
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=builder /src/bin/frostfs-node /bin/frostfs-node
|
COPY --from=builder /src/bin/neofs-node /bin/neofs-node
|
||||||
|
|
||||||
CMD ["frostfs-node"]
|
CMD ["neofs-node"]
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
FROM golang:1.18 as builder
|
FROM golang:1.17 as builder
|
||||||
ARG BUILD=now
|
ARG BUILD=now
|
||||||
ARG VERSION=dev
|
ARG VERSION=dev
|
||||||
ARG REPO=repository
|
ARG REPO=repository
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
RUN make bin/frostfs-node
|
RUN make bin/neofs-node
|
||||||
|
|
||||||
# Executable image
|
# Executable image
|
||||||
FROM alpine AS frostfs-node
|
FROM alpine AS neofs-node
|
||||||
RUN apk add --no-cache bash
|
RUN apk add --no-cache bash
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=builder /src/bin/frostfs-node /bin/frostfs-node
|
COPY --from=builder /src/bin/neofs-node /bin/neofs-node
|
||||||
COPY --from=builder /src/config/testnet/config.yml /config.yml
|
COPY --from=builder /src/config/testnet/config.yml /config.yml
|
||||||
|
|
||||||
CMD ["frostfs-node", "--config", "/config.yml"]
|
CMD ["neofs-node", "--config", "/config.yml"]
|
||||||
|
|
|
@ -6,4 +6,3 @@ Dockerfile
|
||||||
temp
|
temp
|
||||||
.dockerignore
|
.dockerignore
|
||||||
docker
|
docker
|
||||||
.cache
|
|
||||||
|
|
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* @alexvanin @carpawell @fyrchik @cthulhu-rider
|
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -43,7 +43,7 @@ assignees: ''
|
||||||
* Operating System and version (`uname -a`):
|
* Operating System and version (`uname -a`):
|
||||||
|
|
||||||
## Don't forget to add labels!
|
## Don't forget to add labels!
|
||||||
- component label (`frostfs-adm`, `frostfs-storage`, ...)
|
- component label (`neofs-adm`, `neofs-storage`, ...)
|
||||||
- `goodfirstissue`, `helpwanted` if needed
|
- `goodfirstissue`, `helpwanted` if needed
|
||||||
- does this issue belong to an epic?
|
- does this issue belong to an epic?
|
||||||
- priority (`P0`-`P4`) if already triaged
|
- priority (`P0`-`P4`) if already triaged
|
||||||
|
|
187
.github/logo.svg
vendored
187
.github/logo.svg
vendored
|
@ -1,70 +1,129 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
<svg
|
||||||
<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"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
viewBox="0 0 184.2 51.8" style="enable-background:new 0 0 184.2 51.8;" xml:space="preserve">
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
<style type="text/css">
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
.st0{display:none;}
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
.st1{display:inline;}
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
.st2{fill:#01E397;}
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
.st3{display:inline;fill:#010032;}
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
.st4{display:inline;fill:#00E599;}
|
sodipodi:docname="logo_fs.svg"
|
||||||
.st5{display:inline;fill:#00AF92;}
|
inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
|
||||||
.st6{fill:#00C3E5;}
|
id="svg57"
|
||||||
</style>
|
version="1.1"
|
||||||
<g id="Layer_2">
|
viewBox="0 0 105 25"
|
||||||
<g id="Layer_1-2" class="st0">
|
height="25mm"
|
||||||
<g class="st1">
|
width="105mm">
|
||||||
<path class="st2" d="M146.6,18.3v7.2h10.9V29h-10.9v10.7h-4V14.8h18v3.5H146.6z"/>
|
<defs
|
||||||
<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
|
id="defs51">
|
||||||
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
|
<clipPath
|
||||||
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
|
clipPathUnits="userSpaceOnUse"
|
||||||
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
|
id="clipPath434">
|
||||||
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
|
<path
|
||||||
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"/>
|
d="M 0,0 H 1366 V 768 H 0 Z"
|
||||||
|
id="path432" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-x="130"
|
||||||
|
inkscape:window-height="1040"
|
||||||
|
inkscape:window-width="1274"
|
||||||
|
height="50mm"
|
||||||
|
units="mm"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:document-rotation="0"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:cy="344.49897"
|
||||||
|
inkscape:cx="468.64708"
|
||||||
|
inkscape:zoom="0.7"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base" />
|
||||||
|
<metadata
|
||||||
|
id="metadata54">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
id="g424"
|
||||||
|
transform="matrix(0.35277777,0,0,-0.35277777,63.946468,10.194047)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 v -8.093 h 12.287 v -3.94 H 0 V -24.067 H -4.534 V 3.898 H 15.677 V 0 Z"
|
||||||
|
style="fill:#00e396;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path426" />
|
||||||
</g>
|
</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
|
<g
|
||||||
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
|
transform="matrix(0.35277777,0,0,-0.35277777,-315.43002,107.34005)"
|
||||||
c1.5-0.8,3.2-1.2,4.9-1.1C68.9,13.8,71.3,14.7,73.3,16.3z"/>
|
id="g428">
|
||||||
<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
|
<g
|
||||||
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
|
id="g430"
|
||||||
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
|
clip-path="url(#clipPath434)">
|
||||||
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"/>
|
<g
|
||||||
<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
|
id="g436"
|
||||||
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
|
transform="translate(1112.874,278.2981)">
|
||||||
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
|
<path
|
||||||
C119.9,17.2,117.7,18.2,116.2,19.9z"/>
|
d="M 0,0 C 1.822,-0.932 3.354,-2.359 4.597,-4.28 L 1.165,-7.373 c -0.791,1.695 -1.779,2.924 -2.966,3.686 -1.186,0.763 -2.768,1.145 -4.745,1.145 -1.949,0 -3.461,-0.389 -4.534,-1.166 -1.074,-0.777 -1.61,-1.772 -1.61,-2.987 0,-1.13 0.523,-2.027 1.568,-2.69 1.045,-0.664 2.909,-1.236 5.593,-1.716 2.514,-0.452 4.512,-1.024 5.995,-1.716 1.483,-0.693 2.564,-1.554 3.242,-2.585 0.677,-1.031 1.016,-2.309 1.016,-3.834 0,-1.639 -0.466,-3.079 -1.398,-4.322 -0.932,-1.243 -2.239,-2.197 -3.919,-2.86 -1.681,-0.664 -3.623,-0.996 -5.826,-0.996 -5.678,0 -9.689,1.892 -12.033,5.678 l 3.178,3.178 c 0.903,-1.695 2.068,-2.939 3.495,-3.729 1.426,-0.791 3.199,-1.186 5.318,-1.186 2.005,0 3.58,0.345 4.724,1.038 1.144,0.692 1.716,1.674 1.716,2.945 0,1.017 -0.516,1.835 -1.547,2.457 -1.031,0.621 -2.832,1.172 -5.402,1.653 -2.571,0.479 -4.618,1.073 -6.143,1.779 -1.526,0.706 -2.635,1.582 -3.326,2.627 -0.693,1.045 -1.039,2.316 -1.039,3.813 0,1.582 0.438,3.023 1.314,4.322 0.875,1.299 2.14,2.33 3.792,3.093 1.653,0.763 3.58,1.144 5.783,1.144 C -4.018,1.398 -1.822,0.932 0,0"
|
||||||
<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 "/>
|
style="fill:#00e396;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
<polygon class="st5" points="24.3,17.9 24.3,36.8 46.8,44.9 46.8,9.6 "/>
|
id="path438" />
|
||||||
</g>
|
</g>
|
||||||
<g>
|
<g
|
||||||
<g>
|
id="g440"
|
||||||
<path class="st6" d="M41.6,17.5H28.2v6.9h10.4v3.3H28.2v10.2h-3.9V14.2h17.2V17.5z"/>
|
transform="translate(993.0239,277.5454)">
|
||||||
<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
|
<path
|
||||||
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
|
d="m 0,0 c 2.054,-1.831 3.083,-4.465 3.083,-7.902 v -17.935 h -4.484 v 16.366 c 0,2.914 -0.626,5.024 -1.877,6.332 -1.253,1.308 -2.924,1.962 -5.016,1.962 -1.495,0 -2.896,-0.327 -4.204,-0.981 -1.308,-0.654 -2.381,-1.719 -3.222,-3.194 -0.841,-1.477 -1.261,-3.335 -1.261,-5.576 v -14.909 h -4.484 V 1.328 l 4.086,-1.674 0.118,-1.84 c 0.933,1.681 2.222,2.923 3.867,3.727 1.643,0.803 3.493,1.205 5.548,1.205 C -4.671,2.746 -2.055,1.83 0,0"
|
||||||
c-0.7,0.4-1.3,1-1.8,1.8s-0.7,1.8-0.7,3v9.5H45.8z"/>
|
style="fill:#000033;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
<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
|
id="path442" />
|
||||||
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
|
||||||
|
id="g444"
|
||||||
|
transform="translate(1027.9968,264.0386)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 h -21.128 c 0.261,-2.84 1.205,-5.044 2.83,-6.613 1.625,-1.57 3.727,-2.355 6.305,-2.355 2.054,0 3.763,0.356 5.128,1.065 1.363,0.71 2.288,1.738 2.774,3.083 l 3.755,-1.961 c -1.121,-1.981 -2.616,-3.495 -4.484,-4.54 -1.868,-1.046 -4.259,-1.569 -7.173,-1.569 -4.223,0 -7.538,1.289 -9.948,3.867 -2.41,2.578 -3.615,6.146 -3.615,10.704 0,4.558 1.149,8.127 3.447,10.705 2.298,2.578 5.557,3.867 9.779,3.867 2.615,0 4.876,-0.58 6.782,-1.738 1.905,-1.158 3.343,-2.728 4.315,-4.707 C -0.262,7.827 0.224,5.605 0.224,3.139 0.224,2.092 0.149,1.046 0,0 m -18.298,10.144 c -1.513,-1.457 -2.438,-3.512 -2.775,-6.165 h 16.982 c -0.3,2.615 -1.159,4.661 -2.578,6.137 -1.42,1.476 -3.307,2.214 -5.661,2.214 -2.466,0 -4.455,-0.728 -5.968,-2.186"
|
||||||
|
style="fill:#000033;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path446" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g448"
|
||||||
|
transform="translate(1057.8818,276.4246)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 2.41,-2.578 3.615,-6.147 3.615,-10.705 0,-4.558 -1.205,-8.126 -3.615,-10.704 -2.41,-2.578 -5.726,-3.867 -9.948,-3.867 -4.222,0 -7.537,1.289 -9.947,3.867 -2.41,2.578 -3.615,6.146 -3.615,10.704 0,4.558 1.205,8.127 3.615,10.705 2.41,2.578 5.725,3.867 9.947,3.867 C -5.726,3.867 -2.41,2.578 0,0 m -16.617,-2.858 c -1.607,-1.906 -2.41,-4.522 -2.41,-7.847 0,-3.326 0.803,-5.94 2.41,-7.846 1.607,-1.905 3.83,-2.858 6.669,-2.858 2.839,0 5.063,0.953 6.67,2.858 1.606,1.906 2.41,4.52 2.41,7.846 0,3.325 -0.804,5.941 -2.41,7.847 C -4.885,-0.953 -7.109,0 -9.948,0 c -2.839,0 -5.062,-0.953 -6.669,-2.858"
|
||||||
|
style="fill:#000033;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path450" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g452"
|
||||||
|
transform="matrix(0.35277777,0,0,-0.35277777,5.8329581,6.5590171)">
|
||||||
|
<path
|
||||||
|
d="m 0,0 0.001,-38.946 25.286,-9.076 V -8.753 L 52.626,1.321 27.815,10.207 Z"
|
||||||
|
style="fill:#00e599;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path454" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g456"
|
||||||
|
transform="matrix(0.35277777,0,0,-0.35277777,15.479008,10.041927)">
|
||||||
|
<path
|
||||||
|
d="M 0,0 V -21.306 L 25.293,-30.364 25.282,9.347 Z"
|
||||||
|
style="fill:#00b091;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||||
|
id="path458" />
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 6.5 KiB |
29
.github/workflows/changelog.yml
vendored
Normal file
29
.github/workflows/changelog.yml
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
name: CHANGELOG check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- support/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Check for updates
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Get changed CHANGELOG
|
||||||
|
id: changelog-diff
|
||||||
|
uses: tj-actions/changed-files@v29
|
||||||
|
with:
|
||||||
|
files: CHANGELOG.md
|
||||||
|
|
||||||
|
- name: Fail if changelog not updated
|
||||||
|
if: steps.changelog-diff.outputs.any_changed == 'false'
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('CHANGELOG.md has not been updated')
|
37
.github/workflows/config-update.yml
vendored
Normal file
37
.github/workflows/config-update.yml
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
name: Configuration check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- support/**
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: config-check
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Get changed config-related files
|
||||||
|
id: config-diff
|
||||||
|
uses: tj-actions/changed-files@v29
|
||||||
|
with:
|
||||||
|
files: |
|
||||||
|
config/**
|
||||||
|
cmd/neofs-node/config/**
|
||||||
|
|
||||||
|
- name: Get changed doc files
|
||||||
|
id: docs-diff
|
||||||
|
uses: tj-actions/changed-files@v29
|
||||||
|
with:
|
||||||
|
files: docs/**
|
||||||
|
|
||||||
|
- name: Fail if config files are changed but the documentation is not updated
|
||||||
|
if: steps.config-diff.outputs.any_changed == 'true' && steps.docs-diff.outputs.any_changed == 'false'
|
||||||
|
uses: actions/github-script@v3
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
core.setFailed('Documentation has not been updated')
|
22
.github/workflows/dco.yml
vendored
Normal file
22
.github/workflows/dco.yml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
name: DCO check
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- support/**
|
||||||
|
|
||||||
|
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 }}
|
60
.github/workflows/go.yml
vendored
Normal file
60
.github/workflows/go.yml
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
name: neofs-node tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- support/**
|
||||||
|
paths-ignore:
|
||||||
|
- '*.md'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- support/**
|
||||||
|
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: 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:
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
version: v1.50.0
|
||||||
|
args: --timeout=5m
|
||||||
|
only-new-issues: true
|
20
.gitignore
vendored
20
.gitignore
vendored
|
@ -30,22 +30,4 @@ testfile
|
||||||
.neofs-cli.yml
|
.neofs-cli.yml
|
||||||
|
|
||||||
# debhelpers
|
# debhelpers
|
||||||
debian/*debhelper*
|
**/.debhelper
|
||||||
|
|
||||||
# logfiles
|
|
||||||
debian/*.log
|
|
||||||
|
|
||||||
# .substvars
|
|
||||||
debian/*.substvars
|
|
||||||
|
|
||||||
# .bash-completion
|
|
||||||
debian/*.bash-completion
|
|
||||||
|
|
||||||
# Install folders and files
|
|
||||||
debian/frostfs-cli/
|
|
||||||
debian/frostfs-ir/
|
|
||||||
debian/files
|
|
||||||
debian/frostfs-storage/
|
|
||||||
debian/changelog
|
|
||||||
man/
|
|
||||||
debs/
|
|
||||||
|
|
11
.gitlint
11
.gitlint
|
@ -1,11 +0,0 @@
|
||||||
[general]
|
|
||||||
fail-without-commits=true
|
|
||||||
regex-style-search=true
|
|
||||||
contrib=CC1
|
|
||||||
|
|
||||||
[title-match-regex]
|
|
||||||
regex=^\[\#[0-9X]+\]\s
|
|
||||||
|
|
||||||
[ignore-by-title]
|
|
||||||
regex=^Release(.*)
|
|
||||||
ignore=title-match-regex
|
|
|
@ -4,7 +4,7 @@
|
||||||
# options for analysis running
|
# options for analysis running
|
||||||
run:
|
run:
|
||||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||||
timeout: 10m
|
timeout: 5m
|
||||||
|
|
||||||
# include test files or not, default is true
|
# include test files or not, default is true
|
||||||
tests: false
|
tests: false
|
||||||
|
@ -24,13 +24,6 @@ linters-settings:
|
||||||
govet:
|
govet:
|
||||||
# report about shadowed variables
|
# report about shadowed variables
|
||||||
check-shadowing: false
|
check-shadowing: false
|
||||||
staticcheck:
|
|
||||||
checks: ["all", "-SA1019"] # TODO Enable SA1019 after deprecated warning are fixed.
|
|
||||||
funlen:
|
|
||||||
lines: 80 # default 60
|
|
||||||
statements: 60 # default 40
|
|
||||||
gocognit:
|
|
||||||
min-complexity: 40 # default 30
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
|
@ -58,9 +51,6 @@ linters:
|
||||||
- predeclared
|
- predeclared
|
||||||
- reassign
|
- reassign
|
||||||
- whitespace
|
- whitespace
|
||||||
- containedctx
|
|
||||||
- funlen
|
|
||||||
- gocognit
|
|
||||||
- contextcheck
|
|
||||||
disable-all: true
|
disable-all: true
|
||||||
fast: false
|
fast: false
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
ci:
|
|
||||||
autofix_prs: false
|
|
||||||
|
|
||||||
repos:
|
|
||||||
- repo: https://github.com/jorisroovers/gitlint
|
|
||||||
rev: v0.19.1
|
|
||||||
hooks:
|
|
||||||
- id: gitlint
|
|
||||||
stages: [commit-msg]
|
|
||||||
|
|
||||||
- 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/shellcheck-py/shellcheck-py
|
|
||||||
rev: v0.9.0.2
|
|
||||||
hooks:
|
|
||||||
- id: shellcheck
|
|
||||||
|
|
||||||
- repo: https://github.com/golangci/golangci-lint
|
|
||||||
rev: v1.51.2
|
|
||||||
hooks:
|
|
||||||
- id: golangci-lint
|
|
|
@ -1,17 +0,0 @@
|
||||||
pipeline:
|
|
||||||
# Kludge for non-root containers under WoodPecker
|
|
||||||
fix-ownership:
|
|
||||||
image: alpine:latest
|
|
||||||
commands: chown -R 1234:1234 .
|
|
||||||
|
|
||||||
pre-commit:
|
|
||||||
image: git.frostfs.info/truecloudlab/frostfs-ci:v0.36
|
|
||||||
commands:
|
|
||||||
- export HOME="$(getent passwd $(id -u) | cut '-d:' -f6)"
|
|
||||||
- pre-commit run
|
|
||||||
|
|
||||||
unit:
|
|
||||||
image: git.frostfs.info/truecloudlab/frostfs-ci:v0.36
|
|
||||||
commands:
|
|
||||||
- export HOME="$(getent passwd $(id -u) | cut '-d:' -f6)"
|
|
||||||
- make test
|
|
129
CHANGELOG.md
129
CHANGELOG.md
|
@ -1,113 +1,26 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
Changelog for FrostFS Node
|
Changelog for NeoFS Node
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Add GAS pouring mechanism for a configurable list of wallets (#128)
|
|
||||||
- Separate batching for replicated operations over the same container in pilorama (#1621)
|
|
||||||
- Doc for extended headers (#2128)
|
|
||||||
- New `frostfs_node_object_container_size` metric for tracking size of reqular objects in a container (#2116)
|
|
||||||
- New `frostfs_node_object_payload_size` metric for tracking size of reqular objects on a single shard (#1794)
|
|
||||||
- Add command `frostfs-adm morph netmap-candidates` (#1889)
|
|
||||||
- `object.delete.tombstone_lifetime` config parameter to set tombstone lifetime in the DELETE service (#2246)
|
|
||||||
- Reload config for pprof and metrics on SIGHUP in `neofs-node` (#1868)
|
|
||||||
- Multiple configs support (#44)
|
|
||||||
- Parameters `nns-name` and `nns-zone` for command `frostfs-cli container create` (#37)
|
|
||||||
- Tree service now saves the last synchronization height which persists across restarts (#82)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Change `frostfs_node_engine_container_size` to counting sizes of logical objects
|
|
||||||
- `common.PrintVerbose` prints via `cobra.Command.Printf` (#1962)
|
|
||||||
- Env prefix in configuration changed to `FROSTFS_*` (#43)
|
|
||||||
- Link object is broadcast throughout the whole container now (#57)
|
|
||||||
- Pilorama now can merge multiple batches into one (#2231)
|
|
||||||
- Storage engine now can start even when some shard components are unavailable (#2238)
|
|
||||||
- `neofs-cli` buffer for object put increased from 4 KiB to 3 MiB (#2243)
|
|
||||||
- Expired locked object is available for reading (#56)
|
|
||||||
- Initialize write-cache asynchronously (#32)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Increase payload size metric on shards' `put` operation (#1794)
|
|
||||||
- Big object removal with non-local parts (#1978)
|
|
||||||
- Disable pilorama when moving to degraded mode (#2197)
|
|
||||||
- Fetching blobovnicza objects that not found in write-cache (#2206)
|
|
||||||
- Do not search for the small objects in FSTree (#2206)
|
|
||||||
- Correct status error for expired session token (#2207)
|
|
||||||
- Set flag `mode` required for `frostfs-cli control shards set-mode` (#8)
|
|
||||||
- Fix `dirty` suffix in debian package version (#53)
|
|
||||||
- Prevent node process from killing by systemd when shutting down (#1465)
|
|
||||||
- Restore subscriptions correctly on morph client switch (#2212)
|
|
||||||
- Expired objects could be returned if not marked with GC yet (#2213)
|
|
||||||
- `neofs-adm morph dump-hashes` now properly iterates over custom domain (#2224)
|
|
||||||
- Possible deadlock in write-cache (#2239)
|
|
||||||
- Fix `*_req_count` and `*_req_count_success` metric values (#2241)
|
|
||||||
- Storage ID update by write-cache (#2244)
|
|
||||||
- `neo-go` client deadlock on subscription restoration (#2244)
|
|
||||||
- Possible panic during write-cache initialization (#2234)
|
|
||||||
- Do not fetch an object if `meta` is missing it (#61)
|
|
||||||
- Create contract wallet only by `init` and `update-config` command (#63)
|
|
||||||
- Actually use `object.put.pool_size_local` and independent pool for local puts (#64).
|
|
||||||
- Pretty printer of basic ACL in the NeoFS CLI (#2259)
|
|
||||||
- Adding of public key for nns group `group.frostfs` at init step (#130)
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
### Updated
|
|
||||||
- `neo-go` to `v0.100.1`
|
|
||||||
- `github.com/klauspost/compress` to `v1.15.13`
|
|
||||||
- `github.com/multiformats/go-multiaddr` to `v0.8.0`
|
|
||||||
- `golang.org/x/term` to `v0.3.0`
|
|
||||||
- `google.golang.org/grpc` to `v1.51.0`
|
|
||||||
- `github.com/nats-io/nats.go` to `v1.22.1`
|
|
||||||
- `github.com/TrueCloudLab/hrw` to `v.1.1.1`
|
|
||||||
- Minimum go version to v1.18
|
|
||||||
|
|
||||||
### Updating from v0.35.0
|
|
||||||
|
|
||||||
You need to change configuration environment variables to `FROSTFS_*` if you use any.
|
|
||||||
|
|
||||||
New config field `object.delete.tombstone_lifetime` allows to set tombstone lifetime
|
|
||||||
more appropriate for a specific deployment.
|
|
||||||
|
|
||||||
## [0.35.0] - 2022-12-28 - Sindo (신도, 信島)
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- `morph list-containers` in `neofs-adm` (#1689)
|
|
||||||
- `--binary` flag in `neofs-cli object put/get/delete` commands (#1338)
|
|
||||||
- `session` flag support to `neofs-cli object hash` (#2029)
|
- `session` flag support to `neofs-cli object hash` (#2029)
|
||||||
- Shard can now change mode when encountering background disk errors (#2035)
|
- Shard can now change mode when encountering background disk errors (#2035)
|
||||||
- Background workers and object service now use separate client caches (#2048)
|
- Background workers and object service now use separate client caches (#2048)
|
||||||
- `replicator.pool_size` config field to tune replicator pool size (#2049)
|
- `replicator.pool_size` config field to tune replicator pool size (#2049)
|
||||||
- Fix NNS hash parsing in morph client (#2063)
|
- Fix NNS hash parsing in morph client (#2063)
|
||||||
- `neofs-cli neofs-cli acl basic/extended print` commands (#2012)
|
|
||||||
- `neofs_node_object_*_req_count_success` prometheus metrics for tracking successfully executed requests (#1984)
|
|
||||||
- Metric 'readonly' to get shards mode (#2022)
|
|
||||||
- Tree service replication timeout (#2159)
|
|
||||||
- `apiclient.reconnect_timeout` setting allowing to ignore failed clients for some time (#2164)
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- `object lock` command reads CID and OID the same way other commands do (#1971)
|
- `object lock` command reads CID and OID the same way other commands do (#1971)
|
||||||
- `LOCK` object are stored on every container node (#1502)
|
- `LOCK` object are stored on every container node (#1502)
|
||||||
- `neofs-cli container get-eacl` print ACL table in json format only with arg `--json' (#2012)
|
|
||||||
- Side chain notary deposits use max uint32 as till parameter (#1486)
|
|
||||||
- Allow object removal without linking object (#2100)
|
|
||||||
- `neofs-cli container delete` command pre-checks container ownership (#2106)
|
|
||||||
- Policer cache size is now 1024 (#2158)
|
|
||||||
- Tree service now synchronizes with container nodes in a random order (#2127)
|
|
||||||
- Pilorama no longer tries to apply already applied operations (#2161)
|
|
||||||
- Use `sync.Pool` in Object.PUT service (#2139)
|
|
||||||
- Shard uses metabase for `HEAD` requests by default, not write-cache (#2167)
|
|
||||||
- Clarify help for `--expire-at` parameter for commands `object lock/put` and `bearer create` (#2097)
|
|
||||||
- Node spawns `GETRANGE` requests signed with the node's key if session key was not found for `RANGEHASH` (#2144)
|
|
||||||
- Full list of container is no longer cached (#2176)
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Open FSTree in sync mode by default (#1992)
|
- Open FSTree in sync mode by default (#1992)
|
||||||
- `neofs-cli container nodes`'s output (#1991)
|
- `neofs-cli container nodes`'s output (#1991)
|
||||||
- Increase error counter for write-cache flush errors (#1818)
|
|
||||||
- Correctly select the shard for applying tree service operations (#1996)
|
|
||||||
- Do not panic and return correct errors for bad inputs in `GET_RANGE` (#2007, #2024)
|
- Do not panic and return correct errors for bad inputs in `GET_RANGE` (#2007, #2024)
|
||||||
|
- Correctly select the shard for applying tree service operations (#1996)
|
||||||
- Physical child object removal by GC (#1699)
|
- Physical child object removal by GC (#1699)
|
||||||
|
- Increase error counter for write-cache flush errors (#1818)
|
||||||
- Broadcasting helper objects (#1972)
|
- Broadcasting helper objects (#1972)
|
||||||
- `neofs-cli lock object`'s `lifetime` flag handling (#1972)
|
- `neofs-cli lock object`'s `lifetime` flag handling (#1972)
|
||||||
- Do not move write-cache in read-only mode for flushing (#1906)
|
- Do not move write-cache in read-only mode for flushing (#1906)
|
||||||
|
@ -123,49 +36,17 @@ more appropriate for a specific deployment.
|
||||||
- Panic in IR when performing HEAD requests (#2069)
|
- Panic in IR when performing HEAD requests (#2069)
|
||||||
- Write-cache flush duplication (#2074)
|
- Write-cache flush duplication (#2074)
|
||||||
- Ignore error if a transaction already exists in a morph client (#2075)
|
- Ignore error if a transaction already exists in a morph client (#2075)
|
||||||
- ObjectID signature output in the CLI (#2104)
|
|
||||||
- Pack arguments of `setPrice` invocation during contract update (#2078)
|
- Pack arguments of `setPrice` invocation during contract update (#2078)
|
||||||
- `neofs-cli object hash` panic (#2079)
|
- `neofs-cli object hash` panic (#2079)
|
||||||
- Closing `neo-go` WS clients on shutdown and switch processes (#2080)
|
|
||||||
- Making notary deposits with a zero GAS balance (#2080)
|
|
||||||
- Notary requests on shutdown (#2075)
|
|
||||||
- `neofs-cli container create ` check the sufficiency of the number of nodes in the selector for replicas (#2038)
|
|
||||||
- Data duplication during request forwarding (#2047)
|
|
||||||
- Tree service panic on `TreeMove` operation (#2140)
|
|
||||||
- Panic in `GETRANGE` with zero length (#2095)
|
|
||||||
- Spawning useless `GETRANGE` with zero length for a big object (#2101)
|
|
||||||
- Incomplete object put errors do contain the deepest error's message (#2092)
|
|
||||||
- Prioritize internal addresses for clients (#2156)
|
|
||||||
- Force object removal via control service (#2145)
|
|
||||||
- Synchronizing a tree now longer reports an error for a single-node container (#2154)
|
|
||||||
- Prevent leaking goroutines in the tree service (#2162)
|
|
||||||
- Do not search for LOCK objects when delete container when session provided (#2152)
|
|
||||||
- Race conditions on shard's mode switch (#1956)
|
|
||||||
- Returning expired/removed objects from write-cache (#2016)
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `-g` option from `neofs-cli control ...` and `neofs-cli container create` commands (#2089)
|
|
||||||
- `--header` from `neofs-cli object get` (#2090)
|
|
||||||
|
|
||||||
### Updated
|
### Updated
|
||||||
- `neo-go` to `v0.100.0`
|
|
||||||
- `spf13/cobra` to `v1.6.1`
|
|
||||||
- `spf13/viper` to `v1.8.0`
|
|
||||||
- `google.golang.org/grpc` to `v1.50.1`
|
|
||||||
|
|
||||||
### Updating from v0.34.0
|
### Updating from v0.34.0
|
||||||
Pass CID and OID parameters via the `--cid` and `--oid` flags, not as the command arguments.
|
Pass CID and OID parameters via the `--cid` and `--oid` flags, not as the command arguments.
|
||||||
|
|
||||||
Replicator pool size can now be fine-tuned with `replicator.pool_size` config field.
|
Replicator pool size can now be fine-tuned with `replicator.pool_size` config field.
|
||||||
The default value is taken from `object.put.pool_size_remote` as in earlier versions.
|
The default value is taken from `object.put.pool_size_remote` as in earlier versions.
|
||||||
|
|
||||||
Added `neofs_node_object_*_req_count_success` metrics for tracking successfully executed requests.
|
|
||||||
|
|
||||||
`neofs-cli container delete` command now requires given account or session issuer
|
|
||||||
to match the container owner. Use `--force` (`-f`) flag to bypass this requirement.
|
|
||||||
|
|
||||||
Tree service network replication can now be fine-tuned with `tree.replication_timeout` config field.
|
|
||||||
|
|
||||||
## [0.34.0] - 2022-10-31 - Marado (마라도, 馬羅島)
|
## [0.34.0] - 2022-10-31 - Marado (마라도, 馬羅島)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1575,8 +1456,8 @@ NeoFS-API v2.0 support and updated brand-new storage node application.
|
||||||
## [0.10.0] - 2020-07-10
|
## [0.10.0] - 2020-07-10
|
||||||
|
|
||||||
First public review release.
|
First public review release.
|
||||||
[Unreleased]: https://github.com/nspcc-dev/neofs-node/compare/v0.35.0...master
|
|
||||||
[0.35.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.34.0...v0.35.0
|
[Unreleased]: https://github.com/nspcc-dev/neofs-node/compare/v0.34.0...master
|
||||||
[0.34.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.33.0...v0.34.0
|
[0.34.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.33.0...v0.34.0
|
||||||
[0.33.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.32.0...v0.33.0
|
[0.33.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.32.0...v0.33.0
|
||||||
[0.32.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.31.0...v0.32.0
|
[0.32.0]: https://github.com/nspcc-dev/neofs-node/compare/v0.31.0...v0.32.0
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
First, thank you for contributing! We love and encourage pull requests from
|
First, thank you for contributing! We love and encourage pull requests from
|
||||||
everyone. Please follow the guidelines:
|
everyone. Please follow the guidelines:
|
||||||
|
|
||||||
- Check the open [issues](https://github.com/TrueCloudLab/frostfs-node/issues) and
|
- Check the open [issues](https://github.com/nspcc-dev/neofs-node/issues) and
|
||||||
[pull requests](https://github.com/TrueCloudLab/frostfs-node/pulls) for existing
|
[pull requests](https://github.com/nspcc-dev/neofs-node/pulls) for existing
|
||||||
discussions.
|
discussions.
|
||||||
|
|
||||||
- Open an issue first, to discuss a new feature or enhancement.
|
- Open an issue first, to discuss a new feature or enhancement.
|
||||||
|
@ -23,23 +23,23 @@ everyone. Please follow the guidelines:
|
||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
Start by forking the `frostfs-node` repository, make changes in a branch and then
|
Start by forking the `neofs-node` repository, make changes in a branch and then
|
||||||
send a pull request. We encourage pull requests to discuss code changes. Here
|
send a pull request. We encourage pull requests to discuss code changes. Here
|
||||||
are the steps in details:
|
are the steps in details:
|
||||||
|
|
||||||
### Set up your GitHub Repository
|
### Set up your GitHub Repository
|
||||||
Fork [FrostFS node upstream](https://github.com/TrueCloudLab/frostfs-node/fork) source
|
Fork [NeoFS node upstream](https://github.com/nspcc-dev/neofs-node/fork) source
|
||||||
repository to your own personal repository. Copy the URL of your fork (you will
|
repository to your own personal repository. Copy the URL of your fork (you will
|
||||||
need it for the `git clone` command below).
|
need it for the `git clone` command below).
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ git clone https://github.com/TrueCloudLab/frostfs-node
|
$ git clone https://github.com/nspcc-dev/neofs-node
|
||||||
```
|
```
|
||||||
|
|
||||||
### Set up git remote as ``upstream``
|
### Set up git remote as ``upstream``
|
||||||
```sh
|
```sh
|
||||||
$ cd frostfs-node
|
$ cd neofs-node
|
||||||
$ git remote add upstream https://github.com/TrueCloudLab/frostfs-node
|
$ git remote add upstream https://github.com/nspcc-dev/neofs-node
|
||||||
$ git fetch upstream
|
$ git fetch upstream
|
||||||
$ git merge upstream/master
|
$ git merge upstream/master
|
||||||
...
|
...
|
||||||
|
@ -79,7 +79,7 @@ Description
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git commit -sam '[#123] Add some feature'
|
$ git commit -am '[#123] Add some feature'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Push to the branch
|
### Push to the branch
|
||||||
|
@ -106,8 +106,7 @@ contributors".
|
||||||
To sign your work, just add a line like this at the end of your commit message:
|
To sign your work, just add a line like this at the end of your commit message:
|
||||||
|
|
||||||
```
|
```
|
||||||
Signed-off-by: Samii Sakisaka <samii@ivunojikan.co.jp>
|
Signed-off-by: Samii Sakisaka <samii@nspcc.ru>
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This can easily be done with the `--signoff` option to `git commit`.
|
This can easily be done with the `--signoff` option to `git commit`.
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
FrostFS continues the development of NeoFS.
|
|
||||||
|
|
||||||
Initial NeoFS research and development (2018-2020) was done by
|
Initial NeoFS research and development (2018-2020) was done by
|
||||||
[NeoSPCC](https://nspcc.ru) team.
|
[NeoSPCC](https://nspcc.ru) team.
|
||||||
|
|
||||||
|
|
35
Makefile
Executable file → Normal file
35
Makefile
Executable file → Normal file
|
@ -4,10 +4,10 @@ SHELL = bash
|
||||||
REPO ?= $(shell go list -m)
|
REPO ?= $(shell go list -m)
|
||||||
VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop")
|
VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop")
|
||||||
|
|
||||||
HUB_IMAGE ?= truecloudlab/frostfs
|
HUB_IMAGE ?= nspccdev/neofs
|
||||||
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
|
HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')"
|
||||||
|
|
||||||
GO_VERSION ?= 1.19
|
GO_VERSION ?= 1.17
|
||||||
LINT_VERSION ?= 1.50.0
|
LINT_VERSION ?= 1.50.0
|
||||||
ARCH = amd64
|
ARCH = amd64
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ RELEASE = release
|
||||||
DIRS = $(BIN) $(RELEASE)
|
DIRS = $(BIN) $(RELEASE)
|
||||||
|
|
||||||
# List of binaries to build.
|
# List of binaries to build.
|
||||||
CMDS = $(notdir $(basename $(wildcard cmd/frostfs-*)))
|
CMDS = $(notdir $(basename $(wildcard cmd/*)))
|
||||||
BINS = $(addprefix $(BIN)/, $(CMDS))
|
BINS = $(addprefix $(BIN)/, $(CMDS))
|
||||||
|
|
||||||
# .deb package versioning
|
# .deb package versioning
|
||||||
|
@ -26,10 +26,10 @@ PKG_VERSION ?= $(shell echo $(VERSION) | sed "s/^v//" | \
|
||||||
sed "s/-/~/")-${OS_RELEASE}
|
sed "s/-/~/")-${OS_RELEASE}
|
||||||
|
|
||||||
.PHONY: help all images dep clean fmts fmt imports test lint docker/lint
|
.PHONY: help all images dep clean fmts fmt imports test lint docker/lint
|
||||||
prepare-release debpackage pre-commit unpre-commit
|
prepare-release debpackage
|
||||||
|
|
||||||
# To build a specific binary, use it's name prefix with bin/ as a target
|
# To build a specific binary, use it's name prefix with bin/ as a target
|
||||||
# For example `make bin/frostfs-node` will build only storage node binary
|
# For example `make bin/neofs-node` will build only storage node binary
|
||||||
# Just `make` will build all possible binaries
|
# Just `make` will build all possible binaries
|
||||||
all: $(DIRS) $(BINS)
|
all: $(DIRS) $(BINS)
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ $(DIRS):
|
||||||
# Prepare binaries and archives for release
|
# Prepare binaries and archives for release
|
||||||
.ONESHELL:
|
.ONESHELL:
|
||||||
prepare-release: docker/all
|
prepare-release: docker/all
|
||||||
@for file in `ls -1 $(BIN)/frostfs-*`; do
|
@for file in `ls -1 $(BIN)/neofs-*`; do
|
||||||
cp $$file $(RELEASE)/`basename $$file`-$(ARCH)
|
cp $$file $(RELEASE)/`basename $$file`-$(ARCH)
|
||||||
strip $(RELEASE)/`basename $$file`-$(ARCH)
|
strip $(RELEASE)/`basename $$file`-$(ARCH)
|
||||||
tar -czf $(RELEASE)/`basename $$file`-$(ARCH).tar.gz $(RELEASE)/`basename $$file`-$(ARCH)
|
tar -czf $(RELEASE)/`basename $$file`-$(ARCH).tar.gz $(RELEASE)/`basename $$file`-$(ARCH)
|
||||||
|
@ -67,26 +67,26 @@ dep:
|
||||||
|
|
||||||
# Regenerate proto files:
|
# Regenerate proto files:
|
||||||
protoc:
|
protoc:
|
||||||
@GOPRIVATE=github.com/TrueCloudLab go mod vendor
|
@GOPRIVATE=github.com/nspcc-dev go mod vendor
|
||||||
# Install specific version for protobuf lib
|
# Install specific version for protobuf lib
|
||||||
@go list -f '{{.Path}}/...@{{.Version}}' -m github.com/golang/protobuf | xargs go install -v
|
@go list -f '{{.Path}}/...@{{.Version}}' -m github.com/golang/protobuf | xargs go install -v
|
||||||
@GOBIN=$(abspath $(BIN)) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen
|
@GOBIN=$(abspath $(BIN)) go install -mod=mod -v github.com/nspcc-dev/neofs-api-go/v2/util/protogen
|
||||||
# Protoc generate
|
# Protoc generate
|
||||||
@for f in `find . -type f -name '*.proto' -not -path './vendor/*'`; do \
|
@for f in `find . -type f -name '*.proto' -not -path './vendor/*'`; do \
|
||||||
echo "⇒ Processing $$f "; \
|
echo "⇒ Processing $$f "; \
|
||||||
protoc \
|
protoc \
|
||||||
--proto_path=.:./vendor:/usr/local/include \
|
--proto_path=.:./vendor:/usr/local/include \
|
||||||
--plugin=protoc-gen-go-frostfs=$(BIN)/protogen \
|
--plugin=protoc-gen-go-neofs=$(BIN)/protogen \
|
||||||
--go-frostfs_out=. --go-frostfs_opt=paths=source_relative \
|
--go-neofs_out=. --go-neofs_opt=paths=source_relative \
|
||||||
--go_out=. --go_opt=paths=source_relative \
|
--go_out=. --go_opt=paths=source_relative \
|
||||||
--go-grpc_opt=require_unimplemented_servers=false \
|
--go-grpc_opt=require_unimplemented_servers=false \
|
||||||
--go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \
|
--go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \
|
||||||
done
|
done
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
|
|
||||||
# Build FrostFS component's docker image
|
# Build NeoFS component's docker image
|
||||||
image-%:
|
image-%:
|
||||||
@echo "⇒ Build FrostFS $* docker image "
|
@echo "⇒ Build NeoFS $* docker image "
|
||||||
@docker build \
|
@docker build \
|
||||||
--build-arg REPO=$(REPO) \
|
--build-arg REPO=$(REPO) \
|
||||||
--build-arg VERSION=$(VERSION) \
|
--build-arg VERSION=$(VERSION) \
|
||||||
|
@ -140,19 +140,10 @@ docker/lint:
|
||||||
--env HOME=/src \
|
--env HOME=/src \
|
||||||
golangci/golangci-lint:v$(LINT_VERSION) bash -c 'cd /src/ && make lint'
|
golangci/golangci-lint:v$(LINT_VERSION) bash -c 'cd /src/ && make lint'
|
||||||
|
|
||||||
# Activate pre-commit hooks
|
|
||||||
pre-commit:
|
|
||||||
pre-commit install -t pre-commit -t commit-msg
|
|
||||||
|
|
||||||
# Deactivate pre-commit hooks
|
|
||||||
unpre-commit:
|
|
||||||
pre-commit uninstall -t pre-commit -t commit-msg
|
|
||||||
|
|
||||||
# Print version
|
# Print version
|
||||||
version:
|
version:
|
||||||
@echo $(VERSION)
|
@echo $(VERSION)
|
||||||
|
|
||||||
# Delete built artifacts
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf vendor
|
rm -rf vendor
|
||||||
rm -rf .cache
|
rm -rf .cache
|
||||||
|
@ -161,7 +152,7 @@ clean:
|
||||||
|
|
||||||
# Package for Debian
|
# Package for Debian
|
||||||
debpackage:
|
debpackage:
|
||||||
dch -b --package frostfs-node \
|
dch --package neofs-node \
|
||||||
--controlmaint \
|
--controlmaint \
|
||||||
--newversion $(PKG_VERSION) \
|
--newversion $(PKG_VERSION) \
|
||||||
--distribution $(OS_RELEASE) \
|
--distribution $(OS_RELEASE) \
|
||||||
|
|
41
README.md
41
README.md
|
@ -1,40 +1,39 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="./.github/logo.svg" width="500px" alt="FrostFS">
|
<img src="./.github/logo.svg" width="500px" alt="NeoFS">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://frostfs.info">FrostFS</a> is a decentralized distributed object storage integrated with the <a href="https://neo.org">NEO Blockchain</a>.
|
<a href="https://fs.neo.org">NeoFS</a> is a decentralized distributed object storage integrated with the <a href="https://neo.org">NEO Blockchain</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
[![Report](https://goreportcard.com/badge/github.com/TrueCloudLab/frostfs-node)](https://goreportcard.com/report/github.com/TrueCloudLab/frostfs-node)
|
[![Report](https://goreportcard.com/badge/github.com/nspcc-dev/neofs-node)](https://goreportcard.com/report/github.com/nspcc-dev/neofs-node)
|
||||||
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/TrueCloudLab/frostfs-node?sort=semver)
|
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/nspcc-dev/neofs-node?sort=semver)
|
||||||
![License](https://img.shields.io/github/license/TrueCloudLab/frostfs-node.svg?style=popout)
|
![License](https://img.shields.io/github/license/nspcc-dev/neofs-node.svg?style=popout)
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
FrostFS Nodes are organized in a peer-to-peer network that takes care of storing
|
NeoFS Nodes are organized in a peer-to-peer network that takes care of storing
|
||||||
and distributing user's data. Any Neo user may participate in the network and
|
and distributing user's data. Any Neo user may participate in the network and
|
||||||
get paid for providing storage resources to other users or store their data in
|
get paid for providing storage resources to other users or store their data in
|
||||||
FrostFS and pay a competitive price for it.
|
NeoFS and pay a competitive price for it.
|
||||||
|
|
||||||
Users can reliably store object data in the FrostFS network and have a transparent
|
Users can reliably store object data in the NeoFS network and have a transparent
|
||||||
data placement process due to a decentralized architecture and flexible storage
|
data placement process due to a decentralized architecture and flexible storage
|
||||||
policies. Each node is responsible for executing the storage policies that the
|
policies. Each node is responsible for executing the storage policies that the
|
||||||
users select for geographical location, reliability level, number of nodes, type
|
users select for geographical location, reliability level, number of nodes, type
|
||||||
of disks, capacity, etc. Thus, FrostFS gives full control over data to users.
|
of disks, capacity, etc. Thus, NeoFS gives full control over data to users.
|
||||||
|
|
||||||
Deep [Neo Blockchain](https://neo.org) integration allows FrostFS to be used by
|
Deep [Neo Blockchain](https://neo.org) integration allows NeoFS to be used by
|
||||||
dApps directly from
|
dApps directly from
|
||||||
[NeoVM](https://docs.neo.org/docs/en-us/basic/technology/neovm.html) on the
|
[NeoVM](https://docs.neo.org/docs/en-us/basic/technology/neovm.html) on the
|
||||||
[Smart Contract](https://docs.neo.org/docs/en-us/intro/glossary.html)
|
[Smart Contract](https://docs.neo.org/docs/en-us/intro/glossary.html)
|
||||||
code level. This way dApps are not limited to on-chain storage and can
|
code level. This way dApps are not limited to on-chain storage and can
|
||||||
manipulate large amounts of data without paying a prohibitive price.
|
manipulate large amounts of data without paying a prohibitive price.
|
||||||
|
|
||||||
FrostFS has a native [gRPC API](https://git.frostfs.info/TrueCloudLab/frostfs-api) and has
|
NeoFS has a native [gRPC API](https://github.com/nspcc-dev/neofs-api) and has
|
||||||
protocol gateways for popular protocols such as [AWS
|
protocol gateways for popular protocols such as [AWS
|
||||||
S3](https://github.com/TrueCloudLab/frostfs-s3-gw),
|
S3](https://github.com/nspcc-dev/neofs-s3-gw),
|
||||||
[HTTP](https://github.com/TrueCloudLab/frostfs-http-gw),
|
[HTTP](https://github.com/nspcc-dev/neofs-http-gw),
|
||||||
[FUSE](https://wikipedia.org/wiki/Filesystem_in_Userspace) and
|
[FUSE](https://wikipedia.org/wiki/Filesystem_in_Userspace) and
|
||||||
[sFTP](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) allowing
|
[sFTP](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) allowing
|
||||||
developers to integrate applications without rewriting their code.
|
developers to integrate applications without rewriting their code.
|
||||||
|
@ -44,12 +43,12 @@ developers to integrate applications without rewriting their code.
|
||||||
Now, we only support GNU/Linux on amd64 CPUs with AVX/AVX2 instructions. More
|
Now, we only support GNU/Linux on amd64 CPUs with AVX/AVX2 instructions. More
|
||||||
platforms will be officially supported after release `1.0`.
|
platforms will be officially supported after release `1.0`.
|
||||||
|
|
||||||
The latest version of frostfs-node works with frostfs-contract
|
The latest version of neofs-node works with neofs-contract
|
||||||
[v0.16.0](https://github.com/TrueCloudLab/frostfs-contract/releases/tag/v0.16.0).
|
[v0.16.0](https://github.com/nspcc-dev/neofs-contract/releases/tag/v0.16.0).
|
||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
To make all binaries you need Go 1.18+ and `make`:
|
To make all binaries you need Go 1.17+ and `make`:
|
||||||
```
|
```
|
||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
@ -57,7 +56,7 @@ The resulting binaries will appear in `bin/` folder.
|
||||||
|
|
||||||
To make a specific binary use:
|
To make a specific binary use:
|
||||||
```
|
```
|
||||||
make bin/frostfs-<name>
|
make bin/neofs-<name>
|
||||||
```
|
```
|
||||||
See the list of all available commands in the `cmd` folder.
|
See the list of all available commands in the `cmd` folder.
|
||||||
|
|
||||||
|
@ -66,12 +65,12 @@ See the list of all available commands in the `cmd` folder.
|
||||||
Building can also be performed in a container:
|
Building can also be performed in a container:
|
||||||
```
|
```
|
||||||
make docker/all # build all binaries
|
make docker/all # build all binaries
|
||||||
make docker/bin/frostfs-<name> # build a specific binary
|
make docker/bin/neofs-<name> # build a specific binary
|
||||||
```
|
```
|
||||||
|
|
||||||
## Docker images
|
## Docker images
|
||||||
|
|
||||||
To make docker images suitable for use in [frostfs-dev-env](https://github.com/TrueCloudLab/frostfs-dev-env/) use:
|
To make docker images suitable for use in [neofs-dev-env](https://github.com/nspcc-dev/neofs-dev-env/) use:
|
||||||
```
|
```
|
||||||
make images
|
make images
|
||||||
```
|
```
|
||||||
|
@ -86,7 +85,7 @@ the feature/topic you are going to implement.
|
||||||
|
|
||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
FrostFS is maintained by [True Cloud Lab](https://github.com/TrueCloudLab/) with the help and
|
NeoFS is maintained by [NeoSPCC](https://nspcc.ru) with the help and
|
||||||
contributions from community members.
|
contributions from community members.
|
||||||
|
|
||||||
Please see [CREDITS](CREDITS.md) for details.
|
Please see [CREDITS](CREDITS.md) for details.
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
v0.35.0
|
v0.34.0
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package commonflags
|
|
||||||
|
|
||||||
const (
|
|
||||||
ConfigFlag = "config"
|
|
||||||
ConfigFlagShorthand = "c"
|
|
||||||
ConfigFlagUsage = "Config file"
|
|
||||||
|
|
||||||
ConfigDirFlag = "config-dir"
|
|
||||||
ConfigDirFlagUsage = "Config directory"
|
|
||||||
|
|
||||||
Verbose = "verbose"
|
|
||||||
VerboseShorthand = "v"
|
|
||||||
VerboseUsage = "Verbose output"
|
|
||||||
)
|
|
Binary file not shown.
|
@ -1,29 +0,0 @@
|
||||||
package morph
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) {
|
|
||||||
c, err := getN3Client(viper.GetViper())
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err)
|
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
|
||||||
|
|
||||||
cs, err := c.GetContractStateByID(1)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err)
|
|
||||||
|
|
||||||
nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs")
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err)
|
|
||||||
|
|
||||||
res, err := inv.Call(nmHash, "netmapCandidates")
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't fetch list of network config keys from the netmap contract", err)
|
|
||||||
nm, err := netmap.DecodeNetMap(res.Stack)
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to decode netmap: %w", err)
|
|
||||||
commonCmd.PrettyPrintNetMap(cmd, *nm, !viper.GetBool(commonflags.Verbose))
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
package modules
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/storagecfg"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/misc"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/autocomplete"
|
|
||||||
utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/gendoc"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
rootCmd = &cobra.Command{
|
|
||||||
Use: "frostfs-adm",
|
|
||||||
Short: "FrostFS Administrative Tool",
|
|
||||||
Long: `FrostFS Administrative Tool provides functions to setup and
|
|
||||||
manage FrostFS network deployment.`,
|
|
||||||
RunE: entryPoint,
|
|
||||||
SilenceUsage: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
cobra.OnInitialize(func() { initConfig(rootCmd) })
|
|
||||||
// we need to init viper config to bind viper and cobra configurations for
|
|
||||||
// rpc endpoint, alphabet wallet dir, key credentials, etc.
|
|
||||||
|
|
||||||
// use stdout as default output for cmd.Print()
|
|
||||||
rootCmd.SetOut(os.Stdout)
|
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage)
|
|
||||||
rootCmd.PersistentFlags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage)
|
|
||||||
rootCmd.PersistentFlags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, commonflags.VerboseUsage)
|
|
||||||
_ = viper.BindPFlag(commonflags.Verbose, rootCmd.PersistentFlags().Lookup(commonflags.Verbose))
|
|
||||||
rootCmd.Flags().Bool("version", false, "Application version")
|
|
||||||
|
|
||||||
rootCmd.AddCommand(config.RootCmd)
|
|
||||||
rootCmd.AddCommand(morph.RootCmd)
|
|
||||||
rootCmd.AddCommand(storagecfg.RootCmd)
|
|
||||||
|
|
||||||
rootCmd.AddCommand(autocomplete.Command("frostfs-adm"))
|
|
||||||
rootCmd.AddCommand(gendoc.Command(rootCmd))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Execute() error {
|
|
||||||
return rootCmd.Execute()
|
|
||||||
}
|
|
||||||
|
|
||||||
func entryPoint(cmd *cobra.Command, args []string) error {
|
|
||||||
printVersion, _ := cmd.Flags().GetBool("version")
|
|
||||||
if printVersion {
|
|
||||||
cmd.Print(misc.BuildInfo("FrostFS Adm"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd.Usage()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initConfig(cmd *cobra.Command) {
|
|
||||||
configFile, err := cmd.Flags().GetString(commonflags.ConfigFlag)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if configFile != "" {
|
|
||||||
viper.SetConfigType("yml")
|
|
||||||
viper.SetConfigFile(configFile)
|
|
||||||
_ = viper.ReadInConfig() // if config file is set but unavailable, ignore it
|
|
||||||
}
|
|
||||||
|
|
||||||
configDir, err := cmd.Flags().GetString(commonflags.ConfigDirFlag)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if configDir != "" {
|
|
||||||
_ = utilConfig.ReadConfigDir(viper.GetViper(), configDir) // if config files cannot be read, ignore it
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
# Extended headers
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Extended headers are used for request/response. They may contain any
|
|
||||||
user-defined headers to be interpreted on application level. Key name must be a
|
|
||||||
unique valid UTF-8 string. Value can't be empty. Requests or Responses with
|
|
||||||
duplicated header names or headers with empty values are considered invalid.
|
|
||||||
|
|
||||||
## Existing headers
|
|
||||||
|
|
||||||
There are some "well-known" headers starting with `__FROSTFS__` prefix that
|
|
||||||
affect system behaviour. For backward compatibility, the same set of
|
|
||||||
"well-known" headers may also use `__NEOFS__` prefix:
|
|
||||||
|
|
||||||
* `__FROSTFS__NETMAP_EPOCH` - netmap epoch to use for object placement calculation. The `value` is string
|
|
||||||
encoded `uint64` in decimal presentation. If set to '0' or omitted, the
|
|
||||||
current epoch only will be used.
|
|
||||||
* `__FROSTFS__NETMAP_LOOKUP_DEPTH` - if object can't be found using current epoch's netmap, this header limits
|
|
||||||
how many past epochs the node can look up through. Depth is applied to a current epoch or the value
|
|
||||||
of `__FROSTFS__NETMAP_EPOCH` attribute. The `value` is string encoded `uint64` in decimal presentation.
|
|
||||||
If set to '0' or not set, only the current epoch is used.
|
|
||||||
|
|
||||||
## `frostfs-cli` commands with `--xhdr`
|
|
||||||
|
|
||||||
List of commands with support of extended headers:
|
|
||||||
* `container list-objects`
|
|
||||||
* `object delete/get/hash/head/lock/put/range/search`
|
|
||||||
* `storagegroup delete/get/list/put`
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```shell
|
|
||||||
$ frostfs-cli object put -r s01.frostfs.devenv:8080 -w wallet.json --cid CID --file FILE --xhdr "__FROSTFS__NETMAP_EPOCH=777"
|
|
||||||
```
|
|
|
@ -1,15 +0,0 @@
|
||||||
// Package internal provides functionality for FrostFS CLI application
|
|
||||||
// communication with FrostFS network.
|
|
||||||
//
|
|
||||||
// The base client for accessing remote nodes via FrostFS API is a FrostFS SDK
|
|
||||||
// Go API client. However, although it encapsulates a useful piece of business
|
|
||||||
// logic (e.g. the signature mechanism), the FrostFS CLI application does not
|
|
||||||
// fully use the client's flexible interface.
|
|
||||||
//
|
|
||||||
// In this regard, this package provides functions over base API client
|
|
||||||
// necessary for the application. This allows you to concentrate the entire
|
|
||||||
// spectrum of the client's use in one place (this will be convenient both when
|
|
||||||
// updating the base client and for evaluating the UX of SDK library). So it is
|
|
||||||
// expected that all application packages will be limited to this package for
|
|
||||||
// the development of functionality requiring FrostFS API communication.
|
|
||||||
package internal
|
|
|
@ -1,7 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import cmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
cmd.Execute()
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
package basic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var printACLCmd = &cobra.Command{
|
|
||||||
Use: "print",
|
|
||||||
Short: "Pretty print basic ACL from the HEX representation",
|
|
||||||
Example: `frostfs-cli acl basic print 0x1C8C8CCC`,
|
|
||||||
Long: `Pretty print basic ACL from the HEX representation.
|
|
||||||
Few roles have exclusive default access to set of operation, even if particular bit deny it.
|
|
||||||
Container have access to the operations of the data replication mechanism:
|
|
||||||
Get, Head, Put, Search, Hash.
|
|
||||||
InnerRing members are allowed to data audit ops only:
|
|
||||||
Get, Head, Hash, Search.`,
|
|
||||||
Run: printACL,
|
|
||||||
Args: cobra.ExactArgs(1),
|
|
||||||
}
|
|
||||||
|
|
||||||
func printACL(cmd *cobra.Command, args []string) {
|
|
||||||
var bacl acl.Basic
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to parse basic acl: %w", bacl.DecodeString(args[0]))
|
|
||||||
util.PrettyPrintTableBACL(cmd, &bacl)
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
package basic
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Cmd = &cobra.Command{
|
|
||||||
Use: "basic",
|
|
||||||
Short: "Operations with Basic Access Control Lists",
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
Cmd.AddCommand(printACLCmd)
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
package extended
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var createCmd = &cobra.Command{
|
|
||||||
Use: "create",
|
|
||||||
Short: "Create extended ACL from the text representation",
|
|
||||||
Long: `Create extended ACL from the text representation.
|
|
||||||
|
|
||||||
Rule consist of these blocks: <action> <operation> [<filter1> ...] [<target1> ...]
|
|
||||||
|
|
||||||
Action is 'allow' or 'deny'.
|
|
||||||
|
|
||||||
Operation is an object service verb: 'get', 'head', 'put', 'search', 'delete', 'getrange', or 'getrangehash'.
|
|
||||||
|
|
||||||
Filter consists of <typ>:<key><match><value>
|
|
||||||
Typ is 'obj' for object applied filter or 'req' for request applied filter.
|
|
||||||
Key is a valid unicode string corresponding to object or request header key.
|
|
||||||
Well-known system object headers start with '$Object:' prefix.
|
|
||||||
User defined headers start without prefix.
|
|
||||||
Read more about filter keys at git.frostfs.info.com/TrueCloudLab/frostfs-api/src/branch/master/proto-docs/acl.md#message-eaclrecordfilter
|
|
||||||
Match is '=' for matching and '!=' for non-matching filter.
|
|
||||||
Value is a valid unicode string corresponding to object or request header value.
|
|
||||||
|
|
||||||
Target is
|
|
||||||
'user' for container owner,
|
|
||||||
'system' for Storage nodes in container and Inner Ring nodes,
|
|
||||||
'others' for all other request senders,
|
|
||||||
'pubkey:<key1>,<key2>,...' for exact request sender, where <key> is a hex-encoded 33-byte public key.
|
|
||||||
|
|
||||||
When both '--rule' and '--file' arguments are used, '--rule' records will be placed higher in resulting extended ACL table.
|
|
||||||
`,
|
|
||||||
Example: `frostfs-cli acl extended create --cid EutHBsdT1YCzHxjCfQHnLPL1vFrkSyLSio4vkphfnEk -f rules.txt --out table.json
|
|
||||||
frostfs-cli acl extended create --cid EutHBsdT1YCzHxjCfQHnLPL1vFrkSyLSio4vkphfnEk -r 'allow get obj:Key=Value others' -r 'deny put others'`,
|
|
||||||
Run: createEACL,
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
createCmd.Flags().StringArrayP("rule", "r", nil, "Extended ACL table record to apply")
|
|
||||||
createCmd.Flags().StringP("file", "f", "", "Read list of extended ACL table records from text file")
|
|
||||||
createCmd.Flags().StringP("out", "o", "", "Save JSON formatted extended ACL table in file")
|
|
||||||
createCmd.Flags().StringP(commonflags.CIDFlag, "", "", commonflags.CIDFlagUsage)
|
|
||||||
|
|
||||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), "file")
|
|
||||||
_ = cobra.MarkFlagFilename(createCmd.Flags(), "out")
|
|
||||||
}
|
|
||||||
|
|
||||||
func createEACL(cmd *cobra.Command, _ []string) {
|
|
||||||
rules, _ := cmd.Flags().GetStringArray("rule")
|
|
||||||
fileArg, _ := cmd.Flags().GetString("file")
|
|
||||||
outArg, _ := cmd.Flags().GetString("out")
|
|
||||||
cidArg, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
|
||||||
|
|
||||||
var containerID cid.ID
|
|
||||||
if cidArg != "" {
|
|
||||||
if err := containerID.DecodeString(cidArg); err != nil {
|
|
||||||
cmd.PrintErrf("invalid container ID: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rulesFile, err := getRulesFromFile(fileArg)
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrf("can't read rules from file: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rules = append(rules, rulesFile...)
|
|
||||||
if len(rules) == 0 {
|
|
||||||
cmd.PrintErrln("no extended ACL rules has been provided")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
tb := eacl.NewTable()
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to parse provided rules: %w", util.ParseEACLRules(tb, rules))
|
|
||||||
|
|
||||||
tb.SetCID(containerID)
|
|
||||||
|
|
||||||
data, err := tb.MarshalJSON()
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
|
||||||
err = json.Indent(buf, data, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(outArg) == 0 {
|
|
||||||
cmd.Println(buf)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = os.WriteFile(outArg, buf.Bytes(), 0644)
|
|
||||||
if err != nil {
|
|
||||||
cmd.PrintErrln(err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRulesFromFile(filename string) ([]string, error) {
|
|
||||||
if len(filename) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := os.ReadFile(filename)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Split(strings.TrimSpace(string(data)), "\n"), nil
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package extended
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var printEACLCmd = &cobra.Command{
|
|
||||||
Use: "print",
|
|
||||||
Short: "Pretty print extended ACL from the file(in text or json format) or for given container.",
|
|
||||||
Run: printEACL,
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flags := printEACLCmd.Flags()
|
|
||||||
flags.StringP("file", "f", "",
|
|
||||||
"Read list of extended ACL table records from text or json file")
|
|
||||||
_ = printEACLCmd.MarkFlagRequired("file")
|
|
||||||
}
|
|
||||||
|
|
||||||
func printEACL(cmd *cobra.Command, _ []string) {
|
|
||||||
file, _ := cmd.Flags().GetString("file")
|
|
||||||
eaclTable := new(eacl.Table)
|
|
||||||
data, err := os.ReadFile(file)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't read file with EACL: %w", err)
|
|
||||||
if strings.HasSuffix(file, ".json") {
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to parse json: %w", eaclTable.UnmarshalJSON(data))
|
|
||||||
} else {
|
|
||||||
rules := strings.Split(strings.TrimSpace(string(data)), "\n")
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't parse file with EACL: %w", util.ParseEACLRules(eaclTable, rules))
|
|
||||||
}
|
|
||||||
util.PrettyPrintTableEACL(cmd, eaclTable)
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package acl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/acl/basic"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/acl/extended"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Cmd = &cobra.Command{
|
|
||||||
Use: "acl",
|
|
||||||
Short: "Operations with Access Control Lists",
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
Cmd.AddCommand(extended.Cmd)
|
|
||||||
Cmd.AddCommand(basic.Cmd)
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/autocomplete"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rootCmd.AddCommand(autocomplete.Command("frostfs-cli"))
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
package container
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
|
|
||||||
"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"
|
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var deleteContainerCmd = &cobra.Command{
|
|
||||||
Use: "delete",
|
|
||||||
Short: "Delete existing container",
|
|
||||||
Long: `Delete existing container.
|
|
||||||
Only owner of the container has a permission to remove container.`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
id := parseContainerID(cmd)
|
|
||||||
|
|
||||||
tok := getSession(cmd)
|
|
||||||
|
|
||||||
pk := key.Get(cmd)
|
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
|
||||||
|
|
||||||
if force, _ := cmd.Flags().GetBool(commonflags.ForceFlag); !force {
|
|
||||||
common.PrintVerbose(cmd, "Reading the container to check ownership...")
|
|
||||||
|
|
||||||
var getPrm internalclient.GetContainerPrm
|
|
||||||
getPrm.SetClient(cli)
|
|
||||||
getPrm.SetContainer(id)
|
|
||||||
|
|
||||||
resGet, err := internalclient.GetContainer(getPrm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't get the container: %w", err)
|
|
||||||
|
|
||||||
owner := resGet.Container().Owner()
|
|
||||||
|
|
||||||
if tok != nil {
|
|
||||||
common.PrintVerbose(cmd, "Checking session issuer...")
|
|
||||||
|
|
||||||
if !tok.Issuer().Equals(owner) {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer()))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
common.PrintVerbose(cmd, "Checking provided account...")
|
|
||||||
|
|
||||||
var acc user.ID
|
|
||||||
user.IDFromKey(&acc, pk.PublicKey)
|
|
||||||
|
|
||||||
if !acc.Equals(owner) {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
common.PrintVerbose(cmd, "Account matches the container owner.")
|
|
||||||
|
|
||||||
if tok != nil {
|
|
||||||
common.PrintVerbose(cmd, "Skip searching for LOCK objects - session provided.")
|
|
||||||
} else {
|
|
||||||
fs := objectSDK.NewSearchFilters()
|
|
||||||
fs.AddTypeFilter(objectSDK.MatchStringEqual, objectSDK.TypeLock)
|
|
||||||
|
|
||||||
var searchPrm internalclient.SearchObjectsPrm
|
|
||||||
searchPrm.SetClient(cli)
|
|
||||||
searchPrm.SetContainerID(id)
|
|
||||||
searchPrm.SetFilters(fs)
|
|
||||||
searchPrm.SetTTL(2)
|
|
||||||
|
|
||||||
common.PrintVerbose(cmd, "Searching for LOCK objects...")
|
|
||||||
|
|
||||||
res, err := internalclient.SearchObjects(searchPrm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't search for LOCK objects: %w", err)
|
|
||||||
|
|
||||||
if len(res.IDList()) != 0 {
|
|
||||||
commonCmd.ExitOnErr(cmd, "",
|
|
||||||
fmt.Errorf("Container wasn't removed because LOCK objects were found.\n"+
|
|
||||||
"Use --%s flag to remove anyway.", commonflags.ForceFlag))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var delPrm internalclient.DeleteContainerPrm
|
|
||||||
delPrm.SetClient(cli)
|
|
||||||
delPrm.SetContainer(id)
|
|
||||||
|
|
||||||
if tok != nil {
|
|
||||||
delPrm.WithinSession(*tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := internalclient.DeleteContainer(delPrm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
cmd.Println("container delete method invoked")
|
|
||||||
|
|
||||||
if containerAwait {
|
|
||||||
cmd.Println("awaiting...")
|
|
||||||
|
|
||||||
var getPrm internalclient.GetContainerPrm
|
|
||||||
getPrm.SetClient(cli)
|
|
||||||
getPrm.SetContainer(id)
|
|
||||||
|
|
||||||
for i := 0; i < awaitTimeout; i++ {
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
|
|
||||||
_, err := internalclient.GetContainer(getPrm)
|
|
||||||
if err != nil {
|
|
||||||
cmd.Println("container has been removed:", containerID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errDeleteTimeout)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func initContainerDeleteCmd() {
|
|
||||||
flags := deleteContainerCmd.Flags()
|
|
||||||
|
|
||||||
flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
|
||||||
flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
|
|
||||||
flags.StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage)
|
|
||||||
|
|
||||||
flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
|
||||||
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is removed")
|
|
||||||
flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Skip validation checks (ownership, presence of LOCK objects)")
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package control
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
|
||||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func initControlFlags(cmd *cobra.Command) {
|
|
||||||
ff := cmd.Flags()
|
|
||||||
ff.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage)
|
|
||||||
ff.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
|
|
||||||
ff.String(controlRPC, controlRPCDefault, controlRPCUsage)
|
|
||||||
ff.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage)
|
|
||||||
}
|
|
||||||
|
|
||||||
func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) {
|
|
||||||
err := controlSvc.SignMessage(pk, req)
|
|
||||||
commonCmd.ExitOnErr(cmd, "could not sign request: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyResponse(cmd *cobra.Command,
|
|
||||||
sigControl interface {
|
|
||||||
GetKey() []byte
|
|
||||||
GetSign() []byte
|
|
||||||
},
|
|
||||||
body interface {
|
|
||||||
StableMarshal([]byte) []byte
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
if sigControl == nil {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errors.New("missing response signature"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(@cthulhu-rider): #1387 use Signature message from NeoFS API to avoid conversion
|
|
||||||
var sigV2 refs.Signature
|
|
||||||
sigV2.SetScheme(refs.ECDSA_SHA512)
|
|
||||||
sigV2.SetKey(sigControl.GetKey())
|
|
||||||
sigV2.SetSign(sigControl.GetSign())
|
|
||||||
|
|
||||||
var sig frostfscrypto.Signature
|
|
||||||
commonCmd.ExitOnErr(cmd, "can't read signature: %w", sig.ReadFromV2(sigV2))
|
|
||||||
|
|
||||||
if !sig.Verify(body.StableMarshal(nil)) {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", errors.New("invalid response signature"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getClient(cmd *cobra.Command, pk *ecdsa.PrivateKey) *client.Client {
|
|
||||||
return internalclient.GetSDKClientByFlag(cmd, pk, controlRPC)
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package object
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"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"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var objectDelCmd = &cobra.Command{
|
|
||||||
Use: "delete",
|
|
||||||
Aliases: []string{"del"},
|
|
||||||
Short: "Delete object from FrostFS",
|
|
||||||
Long: "Delete object from FrostFS",
|
|
||||||
Run: deleteObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
func initObjectDeleteCmd() {
|
|
||||||
commonflags.Init(objectDelCmd)
|
|
||||||
initFlagSession(objectDelCmd, "DELETE")
|
|
||||||
|
|
||||||
flags := objectDelCmd.Flags()
|
|
||||||
|
|
||||||
flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
|
||||||
flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
|
|
||||||
flags.Bool(binaryFlag, false, "Deserialize object structure from given file.")
|
|
||||||
flags.String(fileFlag, "", "File with object payload")
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteObject(cmd *cobra.Command, _ []string) {
|
|
||||||
var cnr cid.ID
|
|
||||||
var obj oid.ID
|
|
||||||
var objAddr oid.Address
|
|
||||||
|
|
||||||
binary, _ := cmd.Flags().GetBool(binaryFlag)
|
|
||||||
if binary {
|
|
||||||
filename, _ := cmd.Flags().GetString(fileFlag)
|
|
||||||
if filename == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", fileFlag))
|
|
||||||
}
|
|
||||||
objAddr = readObjectAddressBin(cmd, &cnr, &obj, filename)
|
|
||||||
} else {
|
|
||||||
cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag)
|
|
||||||
if cidVal == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
|
|
||||||
}
|
|
||||||
|
|
||||||
oidVal, _ := cmd.Flags().GetString(commonflags.OIDFlag)
|
|
||||||
if oidVal == "" {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.OIDFlag))
|
|
||||||
}
|
|
||||||
|
|
||||||
objAddr = readObjectAddress(cmd, &cnr, &obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
pk := key.GetOrGenerate(cmd)
|
|
||||||
|
|
||||||
var prm internalclient.DeleteObjectPrm
|
|
||||||
ReadOrOpenSession(cmd, &prm, pk, cnr, &obj)
|
|
||||||
Prepare(cmd, &prm)
|
|
||||||
prm.SetAddress(objAddr)
|
|
||||||
|
|
||||||
res, err := internalclient.DeleteObject(prm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
tomb := res.Tombstone()
|
|
||||||
|
|
||||||
cmd.Println("Object removed successfully.")
|
|
||||||
cmd.Printf(" ID: %s\n CID: %s\n", tomb, cnr)
|
|
||||||
}
|
|
|
@ -1,142 +0,0 @@
|
||||||
package object
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"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"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
||||||
"github.com/cheggaaa/pb"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var objectGetCmd = &cobra.Command{
|
|
||||||
Use: "get",
|
|
||||||
Short: "Get object from FrostFS",
|
|
||||||
Long: "Get object from FrostFS",
|
|
||||||
Run: getObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
func initObjectGetCmd() {
|
|
||||||
commonflags.Init(objectGetCmd)
|
|
||||||
initFlagSession(objectGetCmd, "GET")
|
|
||||||
|
|
||||||
flags := objectGetCmd.Flags()
|
|
||||||
|
|
||||||
flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
|
||||||
_ = objectGetCmd.MarkFlagRequired(commonflags.CIDFlag)
|
|
||||||
|
|
||||||
flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
|
|
||||||
_ = objectGetCmd.MarkFlagRequired(commonflags.OIDFlag)
|
|
||||||
|
|
||||||
flags.String(fileFlag, "", "File to write object payload to(with -b together with signature and header). Default: stdout.")
|
|
||||||
flags.Bool(rawFlag, false, rawFlagDesc)
|
|
||||||
flags.Bool(noProgressFlag, false, "Do not show progress bar")
|
|
||||||
flags.Bool(binaryFlag, false, "Serialize whole object structure into given file(id + signature + header + payload).")
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func getObject(cmd *cobra.Command, _ []string) {
|
|
||||||
var cnr cid.ID
|
|
||||||
var obj oid.ID
|
|
||||||
|
|
||||||
objAddr := readObjectAddress(cmd, &cnr, &obj)
|
|
||||||
|
|
||||||
var out io.Writer
|
|
||||||
filename := cmd.Flag(fileFlag).Value.String()
|
|
||||||
if filename == "" {
|
|
||||||
out = os.Stdout
|
|
||||||
} else {
|
|
||||||
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
|
||||||
if err != nil {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
out = f
|
|
||||||
}
|
|
||||||
|
|
||||||
pk := key.GetOrGenerate(cmd)
|
|
||||||
|
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
|
||||||
|
|
||||||
var prm internalclient.GetObjectPrm
|
|
||||||
prm.SetClient(cli)
|
|
||||||
Prepare(cmd, &prm)
|
|
||||||
readSession(cmd, &prm, pk, cnr, obj)
|
|
||||||
|
|
||||||
raw, _ := cmd.Flags().GetBool(rawFlag)
|
|
||||||
prm.SetRawFlag(raw)
|
|
||||||
prm.SetAddress(objAddr)
|
|
||||||
|
|
||||||
var p *pb.ProgressBar
|
|
||||||
noProgress, _ := cmd.Flags().GetBool(noProgressFlag)
|
|
||||||
|
|
||||||
var payloadWriter io.Writer
|
|
||||||
var payloadBuffer *bytes.Buffer
|
|
||||||
binary, _ := cmd.Flags().GetBool(binaryFlag)
|
|
||||||
if binary {
|
|
||||||
payloadBuffer = new(bytes.Buffer)
|
|
||||||
payloadWriter = payloadBuffer
|
|
||||||
} else {
|
|
||||||
payloadWriter = out
|
|
||||||
}
|
|
||||||
|
|
||||||
if filename == "" || noProgress {
|
|
||||||
prm.SetPayloadWriter(payloadWriter)
|
|
||||||
} else {
|
|
||||||
p = pb.New64(0)
|
|
||||||
p.Output = cmd.OutOrStdout()
|
|
||||||
prm.SetPayloadWriter(p.NewProxyWriter(payloadWriter))
|
|
||||||
prm.SetHeaderCallback(func(o *object.Object) {
|
|
||||||
p.SetTotal64(int64(o.PayloadSize()))
|
|
||||||
p.Start()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := internalclient.GetObject(prm)
|
|
||||||
if p != nil {
|
|
||||||
p.Finish()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
if ok := printSplitInfoErr(cmd, err); ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if binary {
|
|
||||||
objToStore := res.Header()
|
|
||||||
// TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload
|
|
||||||
objToStore.SetPayload(payloadBuffer.Bytes())
|
|
||||||
objBytes, err := objToStore.Marshal()
|
|
||||||
commonCmd.ExitOnErr(cmd, "", err)
|
|
||||||
_, err = out.Write(objBytes)
|
|
||||||
commonCmd.ExitOnErr(cmd, "unable to write binary object in out: %w ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if filename != "" && !strictOutput(cmd) {
|
|
||||||
cmd.Printf("[%s] Object successfully saved\n", filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print header only if file is not streamed to stdout.
|
|
||||||
if filename != "" {
|
|
||||||
err = printHeader(cmd, res.Header())
|
|
||||||
commonCmd.ExitOnErr(cmd, "", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func strictOutput(cmd *cobra.Command) bool {
|
|
||||||
toJSON, _ := cmd.Flags().GetBool(commonflags.JSON)
|
|
||||||
toProto, _ := cmd.Flags().GetBool("proto")
|
|
||||||
return toJSON || toProto
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package storagegroup
|
|
||||||
|
|
||||||
import (
|
|
||||||
internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
|
|
||||||
objectCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/storagegroup"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
var sgListCmd = &cobra.Command{
|
|
||||||
Use: "list",
|
|
||||||
Short: "List storage groups in FrostFS container",
|
|
||||||
Long: "List storage groups in FrostFS container",
|
|
||||||
Run: listSG,
|
|
||||||
}
|
|
||||||
|
|
||||||
func initSGListCmd() {
|
|
||||||
commonflags.Init(sgListCmd)
|
|
||||||
|
|
||||||
sgListCmd.Flags().String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
|
|
||||||
_ = sgListCmd.MarkFlagRequired(commonflags.CIDFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listSG(cmd *cobra.Command, _ []string) {
|
|
||||||
var cnr cid.ID
|
|
||||||
readCID(cmd, &cnr)
|
|
||||||
|
|
||||||
pk := key.GetOrGenerate(cmd)
|
|
||||||
|
|
||||||
cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC)
|
|
||||||
|
|
||||||
var prm internalclient.SearchObjectsPrm
|
|
||||||
objectCli.Prepare(cmd, &prm)
|
|
||||||
prm.SetClient(cli)
|
|
||||||
prm.SetContainerID(cnr)
|
|
||||||
prm.SetFilters(storagegroup.SearchQuery())
|
|
||||||
|
|
||||||
res, err := internalclient.SearchObjects(prm)
|
|
||||||
commonCmd.ExitOnErr(cmd, "rpc error: %w", err)
|
|
||||||
|
|
||||||
ids := res.IDList()
|
|
||||||
|
|
||||||
cmd.Printf("Found %d storage groups.\n", len(ids))
|
|
||||||
|
|
||||||
for i := range ids {
|
|
||||||
cmd.Println(ids[i].String())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package storagegroup
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address {
|
|
||||||
readCID(cmd, cnr)
|
|
||||||
readSGID(cmd, obj)
|
|
||||||
|
|
||||||
var addr oid.Address
|
|
||||||
addr.SetContainer(*cnr)
|
|
||||||
addr.SetObject(*obj)
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func readCID(cmd *cobra.Command, id *cid.ID) {
|
|
||||||
f := cmd.Flag(commonflags.CIDFlag)
|
|
||||||
if f == nil {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := id.DecodeString(f.Value.String())
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readSGID(cmd *cobra.Command, id *oid.ID) {
|
|
||||||
const flag = "id"
|
|
||||||
|
|
||||||
f := cmd.Flag(flag)
|
|
||||||
if f == nil {
|
|
||||||
commonCmd.ExitOnErr(cmd, "", fmt.Errorf("missing storage group flag (%s)", flag))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := id.DecodeString(f.Value.String())
|
|
||||||
commonCmd.ExitOnErr(cmd, "decode storage group ID string: %w", err)
|
|
||||||
}
|
|
|
@ -1,327 +0,0 @@
|
||||||
package util
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
"github.com/flynn-archive/go-shlex"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/olekukonko/tablewriter"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PrettyPrintTableBACL print basic ACL in table format.
|
|
||||||
func PrettyPrintTableBACL(cmd *cobra.Command, bacl *acl.Basic) {
|
|
||||||
// Header
|
|
||||||
w := tabwriter.NewWriter(cmd.OutOrStdout(), 1, 4, 4, ' ', 0)
|
|
||||||
fmt.Fprintln(w, "\tRangeHASH\tRange\tSearch\tDelete\tPut\tHead\tGet")
|
|
||||||
// Bits
|
|
||||||
bits := []string{
|
|
||||||
boolToString(bacl.Sticky()) + " " + boolToString(!bacl.Extendable()),
|
|
||||||
getRoleBitsForOperation(bacl, acl.OpObjectHash), getRoleBitsForOperation(bacl, acl.OpObjectRange),
|
|
||||||
getRoleBitsForOperation(bacl, acl.OpObjectSearch), getRoleBitsForOperation(bacl, acl.OpObjectDelete),
|
|
||||||
getRoleBitsForOperation(bacl, acl.OpObjectPut), getRoleBitsForOperation(bacl, acl.OpObjectHead),
|
|
||||||
getRoleBitsForOperation(bacl, acl.OpObjectGet),
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, strings.Join(bits, "\t"))
|
|
||||||
// Footer
|
|
||||||
footer := []string{"X F"}
|
|
||||||
for i := 0; i < 7; i++ {
|
|
||||||
footer = append(footer, "U S O B")
|
|
||||||
}
|
|
||||||
fmt.Fprintln(w, strings.Join(footer, "\t"))
|
|
||||||
|
|
||||||
w.Flush()
|
|
||||||
|
|
||||||
cmd.Println(" X-Sticky F-Final U-User S-System O-Others B-Bearer")
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRoleBitsForOperation(bacl *acl.Basic, op acl.Op) string {
|
|
||||||
return boolToString(bacl.IsOpAllowed(op, acl.RoleOwner)) + " " +
|
|
||||||
boolToString(bacl.IsOpAllowed(op, acl.RoleContainer)) + " " +
|
|
||||||
boolToString(bacl.IsOpAllowed(op, acl.RoleOthers)) + " " +
|
|
||||||
boolToString(bacl.AllowedBearerRules(op))
|
|
||||||
}
|
|
||||||
|
|
||||||
func boolToString(b bool) string {
|
|
||||||
if b {
|
|
||||||
return "1"
|
|
||||||
}
|
|
||||||
return "0"
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrettyPrintTableEACL print extended ACL in table format.
|
|
||||||
func PrettyPrintTableEACL(cmd *cobra.Command, table *eacl.Table) {
|
|
||||||
out := tablewriter.NewWriter(cmd.OutOrStdout())
|
|
||||||
out.SetHeader([]string{"Operation", "Action", "Filters", "Targets"})
|
|
||||||
out.SetAlignment(tablewriter.ALIGN_CENTER)
|
|
||||||
out.SetRowLine(true)
|
|
||||||
|
|
||||||
out.SetAutoWrapText(false)
|
|
||||||
|
|
||||||
for _, r := range table.Records() {
|
|
||||||
out.Append([]string{
|
|
||||||
r.Operation().String(),
|
|
||||||
r.Action().String(),
|
|
||||||
eaclFiltersToString(r.Filters()),
|
|
||||||
eaclTargetsToString(r.Targets()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
out.Render()
|
|
||||||
}
|
|
||||||
|
|
||||||
func eaclTargetsToString(ts []eacl.Target) string {
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
for _, t := range ts {
|
|
||||||
keysExists := len(t.BinaryKeys()) > 0
|
|
||||||
switch t.Role() {
|
|
||||||
case eacl.RoleUser:
|
|
||||||
b.WriteString("User")
|
|
||||||
if keysExists {
|
|
||||||
b.WriteString(": ")
|
|
||||||
}
|
|
||||||
case eacl.RoleSystem:
|
|
||||||
b.WriteString("System")
|
|
||||||
if keysExists {
|
|
||||||
b.WriteString(": ")
|
|
||||||
}
|
|
||||||
case eacl.RoleOthers:
|
|
||||||
b.WriteString("Others")
|
|
||||||
if keysExists {
|
|
||||||
b.WriteString(": ")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
b.WriteString("Unknown")
|
|
||||||
if keysExists {
|
|
||||||
b.WriteString(": ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, pub := range t.BinaryKeys() {
|
|
||||||
if i != 0 {
|
|
||||||
b.WriteString(" ")
|
|
||||||
}
|
|
||||||
b.WriteString(hex.EncodeToString(pub))
|
|
||||||
b.WriteString("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func eaclFiltersToString(fs []eacl.Filter) string {
|
|
||||||
b := bytes.NewBuffer(nil)
|
|
||||||
tw := tabwriter.NewWriter(b, 0, 0, 1, ' ', 0)
|
|
||||||
|
|
||||||
for _, f := range fs {
|
|
||||||
switch f.From() {
|
|
||||||
case eacl.HeaderFromObject:
|
|
||||||
_, _ = tw.Write([]byte("O:\t"))
|
|
||||||
case eacl.HeaderFromRequest:
|
|
||||||
_, _ = tw.Write([]byte("R:\t"))
|
|
||||||
case eacl.HeaderFromService:
|
|
||||||
_, _ = tw.Write([]byte("S:\t"))
|
|
||||||
default:
|
|
||||||
_, _ = tw.Write([]byte(" \t"))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = tw.Write([]byte(f.Key()))
|
|
||||||
|
|
||||||
switch f.Matcher() {
|
|
||||||
case eacl.MatchStringEqual:
|
|
||||||
_, _ = tw.Write([]byte("\t==\t"))
|
|
||||||
case eacl.MatchStringNotEqual:
|
|
||||||
_, _ = tw.Write([]byte("\t!=\t"))
|
|
||||||
case eacl.MatchUnknown:
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _ = tw.Write([]byte(f.Value() + "\t"))
|
|
||||||
_, _ = tw.Write([]byte("\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = tw.Flush()
|
|
||||||
|
|
||||||
// To have nice output with tabwriter, we must append newline
|
|
||||||
// after the last line. Here we strip it to delete empty line
|
|
||||||
// in the final output.
|
|
||||||
s := b.String()
|
|
||||||
if len(s) > 0 {
|
|
||||||
s = s[:len(s)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseEACLRules parses eACL table.
|
|
||||||
// Uses ParseEACLRule.
|
|
||||||
//
|
|
||||||
//nolint:godot
|
|
||||||
func ParseEACLRules(table *eacl.Table, rules []string) error {
|
|
||||||
if len(rules) == 0 {
|
|
||||||
return errors.New("no extended ACL rules has been provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ruleStr := range rules {
|
|
||||||
err := ParseEACLRule(table, ruleStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't create extended acl record from rule '%s': %v", ruleStr, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseEACLRule parses eACL table from the following form:
|
|
||||||
// <action> <operation> [<filter1> ...] [<target1> ...]
|
|
||||||
//
|
|
||||||
// Examples:
|
|
||||||
// allow get req:X-Header=123 obj:Attr=value others:0xkey1,key2 system:key3 user:key4
|
|
||||||
//
|
|
||||||
//nolint:godot
|
|
||||||
func ParseEACLRule(table *eacl.Table, rule string) error {
|
|
||||||
r, err := shlex.Split(rule)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't parse rule '%s': %v", rule, err)
|
|
||||||
}
|
|
||||||
return parseEACLTable(table, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseEACLTable(tb *eacl.Table, args []string) error {
|
|
||||||
if len(args) < 2 {
|
|
||||||
return errors.New("at least 2 arguments must be provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
var action eacl.Action
|
|
||||||
if !action.FromString(strings.ToUpper(args[0])) {
|
|
||||||
return errors.New("invalid action (expected 'allow' or 'deny')")
|
|
||||||
}
|
|
||||||
|
|
||||||
ops, err := eaclOperationsFromString(args[1])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := parseEACLRecord(args[2:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r.SetAction(action)
|
|
||||||
|
|
||||||
for _, op := range ops {
|
|
||||||
r := *r
|
|
||||||
r.SetOperation(op)
|
|
||||||
tb.AddRecord(&r)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseEACLRecord(args []string) (*eacl.Record, error) {
|
|
||||||
r := new(eacl.Record)
|
|
||||||
for _, arg := range args {
|
|
||||||
before, after, found := strings.Cut(arg, ":")
|
|
||||||
|
|
||||||
switch prefix := strings.ToLower(before); prefix {
|
|
||||||
case "req", "obj": // filters
|
|
||||||
if !found {
|
|
||||||
return nil, fmt.Errorf("invalid filter or target: %s", arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
var key, value string
|
|
||||||
var op eacl.Match
|
|
||||||
var f bool
|
|
||||||
|
|
||||||
key, value, f = strings.Cut(after, "!=")
|
|
||||||
if f {
|
|
||||||
op = eacl.MatchStringNotEqual
|
|
||||||
} else {
|
|
||||||
key, value, f = strings.Cut(after, "=")
|
|
||||||
if !f {
|
|
||||||
return nil, fmt.Errorf("invalid filter key-value pair: %s", after)
|
|
||||||
}
|
|
||||||
op = eacl.MatchStringEqual
|
|
||||||
}
|
|
||||||
|
|
||||||
typ := eacl.HeaderFromRequest
|
|
||||||
if before == "obj" {
|
|
||||||
typ = eacl.HeaderFromObject
|
|
||||||
}
|
|
||||||
|
|
||||||
r.AddFilter(typ, op, key, value)
|
|
||||||
case "others", "system", "user", "pubkey": // targets
|
|
||||||
var err error
|
|
||||||
|
|
||||||
var pubs []ecdsa.PublicKey
|
|
||||||
if found {
|
|
||||||
pubs, err = parseKeyList(after)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var role eacl.Role
|
|
||||||
if prefix != "pubkey" {
|
|
||||||
role, err = eaclRoleFromString(prefix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eacl.AddFormedTarget(r, role, pubs...)
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("invalid prefix: %s", before)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// eaclRoleFromString parses eacl.Role from string.
|
|
||||||
func eaclRoleFromString(s string) (eacl.Role, error) {
|
|
||||||
var r eacl.Role
|
|
||||||
if !r.FromString(strings.ToUpper(s)) {
|
|
||||||
return r, fmt.Errorf("unexpected role %s", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseKeyList parses list of hex-encoded public keys separated by comma.
|
|
||||||
func parseKeyList(s string) ([]ecdsa.PublicKey, error) {
|
|
||||||
ss := strings.Split(s, ",")
|
|
||||||
pubs := make([]ecdsa.PublicKey, len(ss))
|
|
||||||
for i := range ss {
|
|
||||||
st := strings.TrimPrefix(ss[i], "0x")
|
|
||||||
pub, err := keys.NewPublicKeyFromString(st)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid public key '%s': %w", ss[i], err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pubs[i] = ecdsa.PublicKey(*pub)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pubs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// eaclOperationsFromString parses list of eacl.Operation separated by comma.
|
|
||||||
func eaclOperationsFromString(s string) ([]eacl.Operation, error) {
|
|
||||||
ss := strings.Split(s, ",")
|
|
||||||
ops := make([]eacl.Operation, len(ss))
|
|
||||||
|
|
||||||
for i := range ss {
|
|
||||||
if !ops[i].FromString(strings.ToUpper(ss[i])) {
|
|
||||||
return nil, fmt.Errorf("invalid operation: %s", ss[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ops, nil
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
type closer struct {
|
|
||||||
name string
|
|
||||||
fn func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCloser(c *cfg, name string) *closer {
|
|
||||||
for _, clsr := range c.closers {
|
|
||||||
if clsr.name == name {
|
|
||||||
return &clsr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func delCloser(c *cfg, name string) {
|
|
||||||
for i, clsr := range c.closers {
|
|
||||||
if clsr.name == name {
|
|
||||||
c.closers[i] = c.closers[len(c.closers)-1]
|
|
||||||
c.closers = c.closers[:len(c.closers)-1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package objectconfig
|
|
||||||
|
|
||||||
import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
|
||||||
|
|
||||||
const (
|
|
||||||
deleteSubsection = "delete"
|
|
||||||
|
|
||||||
// DefaultTombstoneLifetime is the default value of tombstone lifetime in epochs.
|
|
||||||
DefaultTombstoneLifetime = 5
|
|
||||||
)
|
|
||||||
|
|
||||||
// TombstoneLifetime returns the value of `tombstone_lifetime` config parameter.
|
|
||||||
func TombstoneLifetime(c *config.Config) uint64 {
|
|
||||||
ts := config.UintSafe(c.Sub(subsection).Sub(deleteSubsection), "tombstone_lifetime")
|
|
||||||
if ts <= 0 {
|
|
||||||
return DefaultTombstoneLifetime
|
|
||||||
}
|
|
||||||
return ts
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
type httpComponent struct {
|
|
||||||
address string
|
|
||||||
name string
|
|
||||||
handler http.Handler
|
|
||||||
shutdownDur time.Duration
|
|
||||||
enabled bool
|
|
||||||
cfg *cfg
|
|
||||||
preReload func(c *cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmp *httpComponent) init(c *cfg) {
|
|
||||||
if !cmp.enabled {
|
|
||||||
c.log.Info(fmt.Sprintf("%s is disabled", cmp.name))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Init server with parameters
|
|
||||||
srv := httputil.New(
|
|
||||||
*httputil.NewHTTPSrvPrm(
|
|
||||||
cmp.address,
|
|
||||||
cmp.handler,
|
|
||||||
),
|
|
||||||
httputil.WithShutdownTimeout(
|
|
||||||
cmp.shutdownDur,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
c.closers = append(c.closers, closer{
|
|
||||||
cmp.name,
|
|
||||||
func() { stopAndLog(c, cmp.name, srv.Shutdown) },
|
|
||||||
})
|
|
||||||
c.workers = append(c.workers, worker{
|
|
||||||
cmp.name,
|
|
||||||
func(ctx context.Context) {
|
|
||||||
runAndLog(c, cmp.name, false, func(c *cfg) {
|
|
||||||
fatalOnErr(srv.Serve())
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmp *httpComponent) reload() error {
|
|
||||||
if cmp.preReload != nil {
|
|
||||||
cmp.preReload(cmp.cfg)
|
|
||||||
}
|
|
||||||
// Shutdown server
|
|
||||||
closer := getCloser(cmp.cfg, cmp.name)
|
|
||||||
if closer != nil {
|
|
||||||
closer.fn()
|
|
||||||
}
|
|
||||||
// Cleanup
|
|
||||||
delCloser(cmp.cfg, cmp.name)
|
|
||||||
delWorker(cmp.cfg, cmp.name)
|
|
||||||
// Init server with new parameters
|
|
||||||
cmp.init(cmp.cfg)
|
|
||||||
// Start worker
|
|
||||||
if cmp.enabled {
|
|
||||||
startWorker(cmp.cfg, *getWorker(cmp.cfg, cmp.name))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
metricsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/metrics"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func metricsComponent(c *cfg) (*httpComponent, bool) {
|
|
||||||
var updated bool
|
|
||||||
// check if it has been inited before
|
|
||||||
if c.dynamicConfiguration.metrics == nil {
|
|
||||||
c.dynamicConfiguration.metrics = new(httpComponent)
|
|
||||||
c.dynamicConfiguration.metrics.cfg = c
|
|
||||||
c.dynamicConfiguration.metrics.name = "metrics"
|
|
||||||
c.dynamicConfiguration.metrics.handler = promhttp.Handler()
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// (re)init read configuration
|
|
||||||
enabled := metricsconfig.Enabled(c.appCfg)
|
|
||||||
if enabled != c.dynamicConfiguration.metrics.enabled {
|
|
||||||
c.dynamicConfiguration.metrics.enabled = enabled
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
address := metricsconfig.Address(c.appCfg)
|
|
||||||
if address != c.dynamicConfiguration.metrics.address {
|
|
||||||
c.dynamicConfiguration.metrics.address = address
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
dur := metricsconfig.ShutdownTimeout(c.appCfg)
|
|
||||||
if dur != c.dynamicConfiguration.metrics.shutdownDur {
|
|
||||||
c.dynamicConfiguration.metrics.shutdownDur = dur
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.dynamicConfiguration.metrics, updated
|
|
||||||
}
|
|
||||||
|
|
||||||
func enableMetricsSvc(c *cfg) {
|
|
||||||
c.shared.metricsSvc.Enable()
|
|
||||||
}
|
|
||||||
|
|
||||||
func disableMetricsSvc(c *cfg) {
|
|
||||||
c.shared.metricsSvc.Disable()
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler"
|
|
||||||
httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func pprofComponent(c *cfg) (*httpComponent, bool) {
|
|
||||||
var updated bool
|
|
||||||
// check if it has been inited before
|
|
||||||
if c.dynamicConfiguration.pprof == nil {
|
|
||||||
c.dynamicConfiguration.pprof = new(httpComponent)
|
|
||||||
c.dynamicConfiguration.pprof.cfg = c
|
|
||||||
c.dynamicConfiguration.pprof.name = "pprof"
|
|
||||||
c.dynamicConfiguration.pprof.handler = httputil.Handler()
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// (re)init read configuration
|
|
||||||
enabled := profilerconfig.Enabled(c.appCfg)
|
|
||||||
if enabled != c.dynamicConfiguration.pprof.enabled {
|
|
||||||
c.dynamicConfiguration.pprof.enabled = enabled
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
address := profilerconfig.Address(c.appCfg)
|
|
||||||
if address != c.dynamicConfiguration.pprof.address {
|
|
||||||
c.dynamicConfiguration.pprof.address = address
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
dur := profilerconfig.ShutdownTimeout(c.appCfg)
|
|
||||||
if dur != c.dynamicConfiguration.pprof.shutdownDur {
|
|
||||||
c.dynamicConfiguration.pprof.shutdownDur = dur
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.dynamicConfiguration.pprof, updated
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
)
|
|
||||||
|
|
||||||
type worker struct {
|
|
||||||
name string
|
|
||||||
fn func(context.Context)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newWorkerFromFunc(fn func(ctx context.Context)) worker {
|
|
||||||
return worker{
|
|
||||||
fn: fn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startWorkers(c *cfg) {
|
|
||||||
for _, wrk := range c.workers {
|
|
||||||
startWorker(c, wrk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func startWorker(c *cfg, wrk worker) {
|
|
||||||
c.wg.Add(1)
|
|
||||||
|
|
||||||
go func(w worker) {
|
|
||||||
w.fn(c.ctx)
|
|
||||||
c.wg.Done()
|
|
||||||
}(wrk)
|
|
||||||
}
|
|
||||||
|
|
||||||
func delWorker(c *cfg, name string) {
|
|
||||||
for i, worker := range c.workers {
|
|
||||||
if worker.name == name {
|
|
||||||
c.workers = append(c.workers[:i], c.workers[i+1:]...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getWorker(c *cfg, name string) *worker {
|
|
||||||
for _, wrk := range c.workers {
|
|
||||||
if wrk.name == name {
|
|
||||||
return &wrk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,24 +1,25 @@
|
||||||
# FrostFS Admin Tool
|
# NeoFS Admin Tool
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Admin tool provides an easier way to deploy and maintain private installation
|
Admin tool provides an easier way to deploy and maintain private installation
|
||||||
of FrostFS. Private installation provides a set of N3 consensus nodes, FrostFS
|
of NeoFS. Private installation provides a set of N3 consensus nodes, NeoFS
|
||||||
Alphabet, and Storage nodes. Admin tool generates consensus keys, initializes
|
Alphabet, and Storage nodes. Admin tool generates consensus keys, initializes
|
||||||
the sidechain, and provides functions to update the network and register new
|
the sidechain, and provides functions to update the network and register new
|
||||||
Storage nodes.
|
Storage nodes.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
To build binary locally, use `make bin/frostfs-adm` command.
|
To build binary locally, use `make bin/neofs-adm` command.
|
||||||
|
|
||||||
For clean build inside a docker container, use `make docker/bin/frostfs-adm`.
|
For clean build inside a docker container, use `make docker/bin/neofs-adm`.
|
||||||
|
|
||||||
Build docker image with `make image-adm`.
|
Build docker image with `make image-adm`.
|
||||||
|
|
||||||
At FrostFS private install deployment, frostfs-adm requires compiled FrostFS
|
At NeoFS private install deployment, neofs-adm requires compiled NeoFS
|
||||||
contracts. Find them in the latest release of
|
contracts. Find them in the latest release of
|
||||||
[frostfs-contract repository](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases).
|
[neofs-contract repository](https://github.com/nspcc-dev/neofs-contract/releases).
|
||||||
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
@ -34,8 +35,8 @@ Config example:
|
||||||
rpc-endpoint: https://address:port # sidechain RPC node endpoint
|
rpc-endpoint: https://address:port # sidechain RPC node endpoint
|
||||||
alphabet-wallets: /path # path to consensus node / alphabet wallets storage
|
alphabet-wallets: /path # path to consensus node / alphabet wallets storage
|
||||||
network:
|
network:
|
||||||
max_object_size: 67108864 # max size of a single FrostFS object, bytes
|
max_object_size: 67108864 # max size of a single NeoFS object, bytes
|
||||||
epoch_duration: 240 # duration of a FrostFS epoch in blocks, consider block generation frequency in the sidechain
|
epoch_duration: 240 # duration of a NeoFS epoch in blocks, consider block generation frequency in the sidechain
|
||||||
basic_income_rate: 0 # basic income rate, for private consider 0
|
basic_income_rate: 0 # basic income rate, for private consider 0
|
||||||
fee:
|
fee:
|
||||||
audit: 0 # network audit fee, for private installation consider 0
|
audit: 0 # network audit fee, for private installation consider 0
|
||||||
|
@ -61,18 +62,18 @@ credentials: # passwords for consensus node / alphabet wallets
|
||||||
Alphabet nodes.
|
Alphabet nodes.
|
||||||
|
|
||||||
- `init` initializes the sidechain by deploying smart contracts and
|
- `init` initializes the sidechain by deploying smart contracts and
|
||||||
setting provided FrostFS network configuration.
|
setting provided NeoFS network configuration.
|
||||||
|
|
||||||
- `generate-storage-wallet` generates a wallet for the Storage node that
|
- `generate-storage-wallet` generates a wallet for the Storage node that
|
||||||
is ready for deployment. It also transfers a bit of sidechain GAS, so this
|
is ready for deployment. It also transfers a bit of sidechain GAS, so this
|
||||||
wallet can be used for FrostFS bootstrap.
|
wallet can be used for NeoFS bootstrap.
|
||||||
|
|
||||||
#### Network maintenance
|
#### Network maintenance
|
||||||
|
|
||||||
- `set-config` add/update configuration values in the Netmap contract.
|
- `set-config` add/update configuration values in the Netmap contract.
|
||||||
|
|
||||||
- `force-new-epoch` increments FrostFS epoch number and executes new epoch
|
- `force-new-epoch` increments NeoFS epoch number and executes new epoch
|
||||||
handlers in FrostFS nodes.
|
handlers in NeoFS nodes.
|
||||||
|
|
||||||
- `refill-gas` transfers sidechain GAS to the specified wallet.
|
- `refill-gas` transfers sidechain GAS to the specified wallet.
|
||||||
|
|
||||||
|
@ -89,13 +90,11 @@ info. These commands **do not migrate actual objects**.
|
||||||
- `restore-containers` restores previously saved containers by their repeated registration in
|
- `restore-containers` restores previously saved containers by their repeated registration in
|
||||||
the container contract.
|
the container contract.
|
||||||
|
|
||||||
- `list-containers` output all containers ids.
|
|
||||||
|
|
||||||
#### Network info
|
#### Network info
|
||||||
|
|
||||||
- `dump-config` prints FrostFS network configuration.
|
- `dump-config` prints NeoFS network configuration.
|
||||||
|
|
||||||
- `dump-hashes` prints FrostFS contract addresses stored in NNS.
|
- `dump-hashes` prints NeoFS contract addresses stored in NNS.
|
||||||
|
|
||||||
|
|
||||||
## Private network deployment
|
## Private network deployment
|
|
@ -1,16 +1,16 @@
|
||||||
# Step-by-step private FrostFS deployment
|
# Step-by-step private NeoFS deployment
|
||||||
|
|
||||||
This is a short guide on how to deploy a private FrostFS storage network on bare
|
This is a short guide on how to deploy a private NeoFS storage network on bare
|
||||||
metal without docker images. This guide does not cover details on how to start
|
metal without docker images. This guide does not cover details on how to start
|
||||||
consensus, Alphabet, or Storage nodes. This guide covers only `frostfs-adm`
|
consensus, Alphabet, or Storage nodes. This guide covers only `neofs-adm`
|
||||||
related configuration details.
|
related configuration details.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
To follow this guide you need:
|
To follow this guide you need:
|
||||||
- latest released version of [neo-go](https://github.com/nspcc-dev/neo-go/releases) (v0.97.2 at the moment),
|
- latest released version of [neo-go](https://github.com/nspcc-dev/neo-go/releases) (v0.97.2 at the moment),
|
||||||
- latest released version of [frostfs-adm](https://github.com/TrueCloudLab/frostfs-node/releases) utility (v0.25.1 at the moment),
|
- latest released version of [neofs-adm](https://github.com/nspcc-dev/neofs-node/releases) utility (v0.25.1 at the moment),
|
||||||
- latest released version of compiled [frostfs-contract](https://github.com/TrueCloudLab/frostfs-contract/releases) (v0.11.0 at the moment).
|
- latest released version of compiled [neofs-contract](https://github.com/nspcc-dev/neofs-contract/releases) (v0.11.0 at the moment).
|
||||||
|
|
||||||
## Step 1: Prepare network configuration
|
## Step 1: Prepare network configuration
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@ Alphabet nodes and any number of Storage nodes. While the number of Storage
|
||||||
nodes can be scaled almost infinitely, the number of consensus and Alphabet
|
nodes can be scaled almost infinitely, the number of consensus and Alphabet
|
||||||
nodes can't be changed so easily right now. Consider this before going any further.
|
nodes can't be changed so easily right now. Consider this before going any further.
|
||||||
|
|
||||||
It is easier to use`frostfs-adm` with a predefined configuration. First, create
|
It is easier to use`neofs-adm` with a predefined configuration. First, create
|
||||||
a network configuration file. In this example, there is going to be only one
|
a network configuration file. In this example, there is going to be only one
|
||||||
consensus / Alphabet node in the network.
|
consensus / Alphabet node in the network.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ frostfs-adm config init --path foo.network.yml
|
$ neofs-adm config init --path foo.network.yml
|
||||||
Initial config file saved to foo.network.yml
|
Initial config file saved to foo.network.yml
|
||||||
|
|
||||||
$ cat foo.network.yml
|
$ cat foo.network.yml
|
||||||
|
@ -57,7 +57,7 @@ wallets will be used for Alphabet nodes. Make sure, that dir for alphabet
|
||||||
wallets already exists.
|
wallets already exists.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ frostfs-adm -c foo.network.yml morph generate-alphabet --size 1
|
$ neofs-adm -c foo.network.yml morph generate-alphabet --size 1
|
||||||
size: 1
|
size: 1
|
||||||
alphabet-wallets: /home/user/deploy/alphabet-wallets
|
alphabet-wallets: /home/user/deploy/alphabet-wallets
|
||||||
wallet[0]: hunter2
|
wallet[0]: hunter2
|
||||||
|
@ -118,19 +118,19 @@ and possible overload issues.
|
||||||
|
|
||||||
## Step 3: Initialize sidechain
|
## Step 3: Initialize sidechain
|
||||||
|
|
||||||
Use archive with compiled FrostFS contracts to initialize the sidechain.
|
Use archive with compiled NeoFS contracts to initialize the sidechain.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ tar -xzvf frostfs-contract-v0.11.0.tar.gz
|
$ tar -xzvf neofs-contract-v0.11.0.tar.gz
|
||||||
|
|
||||||
$ ./frostfs-adm -c foo.network.yml morph init --contracts ./frostfs-contract-v0.11.0
|
$ ./neofs-adm -c foo.network.yml morph init --contracts ./neofs-contract-v0.11.0
|
||||||
Stage 1: transfer GAS to alphabet nodes.
|
Stage 1: transfer GAS to alphabet nodes.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
Stage 2: set notary and alphabet nodes in designate contract.
|
Stage 2: set notary and alphabet nodes in designate contract.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
Stage 3: deploy NNS contract.
|
Stage 3: deploy NNS contract.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
Stage 4: deploy FrostFS contracts.
|
Stage 4: deploy NeoFS contracts.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
Stage 4.1: Transfer GAS to proxy contract.
|
Stage 4.1: Transfer GAS to proxy contract.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
|
@ -140,14 +140,14 @@ Stage 6: transfer NEO to alphabet contracts.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
Stage 7: set addresses in NNS.
|
Stage 7: set addresses in NNS.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
NNS: Set alphabet0.frostfs -> f692dfb4d43a15b464eb51a7041160fb29c44b6a
|
NNS: Set alphabet0.neofs -> f692dfb4d43a15b464eb51a7041160fb29c44b6a
|
||||||
NNS: Set audit.frostfs -> 7df847b993affb3852074345a7c2bd622171ee0d
|
NNS: Set audit.neofs -> 7df847b993affb3852074345a7c2bd622171ee0d
|
||||||
NNS: Set balance.frostfs -> 103519b3067a66307080a66570c0491ee8f68879
|
NNS: Set balance.neofs -> 103519b3067a66307080a66570c0491ee8f68879
|
||||||
NNS: Set container.frostfs -> cae60bdd689d185901e495352d0247752ce50846
|
NNS: Set container.neofs -> cae60bdd689d185901e495352d0247752ce50846
|
||||||
NNS: Set frostfsid.frostfs -> c421fb60a3895865a8f24d197d6a80ef686041d2
|
NNS: Set neofsid.neofs -> c421fb60a3895865a8f24d197d6a80ef686041d2
|
||||||
NNS: Set netmap.frostfs -> 894eb854632f50fb124412ce7951ebc00763525e
|
NNS: Set netmap.neofs -> 894eb854632f50fb124412ce7951ebc00763525e
|
||||||
NNS: Set proxy.frostfs -> ac6e6fe4b373d0ca0ca4969d1e58fa0988724e7d
|
NNS: Set proxy.neofs -> ac6e6fe4b373d0ca0ca4969d1e58fa0988724e7d
|
||||||
NNS: Set reputation.frostfs -> 6eda57c9d93d990573646762d1fea327ce41191f
|
NNS: Set reputation.neofs -> 6eda57c9d93d990573646762d1fea327ce41191f
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -177,7 +177,7 @@ contracts:
|
||||||
Generate a new wallet for a Storage node.
|
Generate a new wallet for a Storage node.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ frostfs-adm -c foo.network.yml morph generate-storage-wallet --storage-wallet ./sn01.json --initial-gas 10.0
|
$ neofs-adm -c foo.network.yml morph generate-storage-wallet --storage-wallet ./sn01.json --initial-gas 10.0
|
||||||
New password >
|
New password >
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
|
|
||||||
|
@ -196,16 +196,16 @@ node:
|
||||||
password: "foobar"
|
password: "foobar"
|
||||||
```
|
```
|
||||||
|
|
||||||
The storage node will be included in the network map in the next FrostFS epoch. To
|
The storage node will be included in the network map in the next NeoFS epoch. To
|
||||||
speed up this process, you can increment epoch counter immediately.
|
speed up this process, you can increment epoch counter immediately.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ frostfs-adm -c foo.network.yml morph force-new-epoch
|
$ neofs-adm -c foo.network.yml morph force-new-epoch
|
||||||
Current epoch: 8, increase to 9.
|
Current epoch: 8, increase to 9.
|
||||||
Waiting for transactions to persist...
|
Waiting for transactions to persist...
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
After that, FrostFS Storage is ready to work. You can access it directly or
|
After that, NeoFS Storage is ready to work. You can access it directly or
|
||||||
with protocol gates.
|
with protocol gates.
|
|
@ -1,6 +1,6 @@
|
||||||
# FrostFS subnetwork creation
|
# NeoFS subnetwork creation
|
||||||
|
|
||||||
This is a short guide on how to create FrostFS subnetworks. This guide
|
This is a short guide on how to create NeoFS subnetworks. This guide
|
||||||
considers that the sidechain and the inner ring (alphabet nodes) have already been
|
considers that the sidechain and the inner ring (alphabet nodes) have already been
|
||||||
deployed and the sidechain contains a deployed `subnet` contract.
|
deployed and the sidechain contains a deployed `subnet` contract.
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ deployed and the sidechain contains a deployed `subnet` contract.
|
||||||
|
|
||||||
To follow this guide, you need:
|
To follow this guide, you need:
|
||||||
- neo-go sidechain RPC endpoint;
|
- neo-go sidechain RPC endpoint;
|
||||||
- latest released version of [frostfs-adm](https://github.com/TrueCloudLab/frostfs-node/releases);
|
- latest released version of [neofs-adm](https://github.com/nspcc-dev/neofs-node/releases);
|
||||||
- wallet with FrostFS account.
|
- wallet with NeoFS account.
|
||||||
|
|
||||||
## Creation
|
## Creation
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet create \
|
$ neofs-adm morph subnet create \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
-w </path/to/owner/wallet> \
|
-w </path/to/owner/wallet> \
|
||||||
--notary
|
--notary
|
||||||
|
@ -31,7 +31,7 @@ of the just created subnetwork.
|
||||||
You can check if your subnetwork was created successfully:
|
You can check if your subnetwork was created successfully:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet get \
|
$ neofs-adm morph subnet get \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
--subnet <subnet_ID>
|
--subnet <subnet_ID>
|
||||||
Owner: NUc734PMJXiqa2J9jRtvskU3kCdyyuSN8Q
|
Owner: NUc734PMJXiqa2J9jRtvskU3kCdyyuSN8Q
|
|
@ -1,18 +1,18 @@
|
||||||
# Managing Subnetworks
|
# Managing Subnetworks
|
||||||
|
|
||||||
This is a short guide on how to manage FrostFS subnetworks. This guide
|
This is a short guide on how to manage NeoFS subnetworks. This guide
|
||||||
considers that the sidechain and the inner ring (alphabet nodes) have already been
|
considers that the sidechain and the inner ring (alphabet nodes) have already been
|
||||||
deployed, and the sidechain contains a deployed `subnet` contract.
|
deployed, and the sidechain contains a deployed `subnet` contract.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- neo-go sidechain RPC endpoint;
|
- neo-go sidechain RPC endpoint;
|
||||||
- latest released version of [frostfs-adm](https://github.com/TrueCloudLab/frostfs-node/releases);
|
- latest released version of [neofs-adm](https://github.com/nspcc-dev/neofs-node/releases);
|
||||||
- [created](subnetwork-creation.md) subnetwork;
|
- [created](subnetwork-creation.md) subnetwork;
|
||||||
- wallet with the account that owns the subnetwork;
|
- wallet with the account that owns the subnetwork;
|
||||||
- public key of the Storage Node;
|
- public key of the Storage Node;
|
||||||
- public keys of the node and client administrators;
|
- public keys of the node and client administrators;
|
||||||
- owner IDs of the FrostFS users.
|
- owner IDs of the NeoFS users.
|
||||||
|
|
||||||
## Add node administrator
|
## Add node administrator
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ the whitelist of the nodes which can be included to a subnetwork. Only the subne
|
||||||
owner is allowed to add and remove node administrators from the subnetwork.
|
owner is allowed to add and remove node administrators from the subnetwork.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet admin add \
|
$ neofs-adm morph subnet admin add \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
-w </path/to/owner/wallet> \
|
-w </path/to/owner/wallet> \
|
||||||
--admin <HEX_admin_public_key> \
|
--admin <HEX_admin_public_key> \
|
||||||
|
@ -37,7 +37,7 @@ the list of the allowed nodes. Node is not required to be bootstrapped at the
|
||||||
moment of its inclusion.
|
moment of its inclusion.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet node add \
|
$ neofs-adm morph subnet node add \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
-w </path/to/node_admin/wallet> \
|
-w </path/to/node_admin/wallet> \
|
||||||
--node <HEX_node_public_key> \
|
--node <HEX_node_public_key> \
|
||||||
|
@ -55,7 +55,7 @@ subnetwork. Only the subnet owner is allowed to add and remove client
|
||||||
administrators from the subnetwork.
|
administrators from the subnetwork.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet admin add \
|
$ neofs-adm morph subnet admin add \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
-w </path/to/owner/wallet> \
|
-w </path/to/owner/wallet> \
|
||||||
--admin <HEX_admin_public_key> \
|
--admin <HEX_admin_public_key> \
|
||||||
|
@ -72,7 +72,7 @@ positive integer number.
|
||||||
## Add client
|
## Add client
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-adm morph subnet client add \
|
$ neofs-adm morph subnet client add \
|
||||||
-r <side_chain_RPC_endpoint> \
|
-r <side_chain_RPC_endpoint> \
|
||||||
-w </path/to/client_admin/wallet> \
|
-w </path/to/client_admin/wallet> \
|
||||||
--client <client_ownerID> \
|
--client <client_ownerID> \
|
||||||
|
@ -99,7 +99,7 @@ configuration:
|
||||||
node:
|
node:
|
||||||
...
|
...
|
||||||
subnet:
|
subnet:
|
||||||
entries: # list of IDs of subnets to enter in a text format of FrostFS API protocol (overrides corresponding attributes)
|
entries: # list of IDs of subnets to enter in a text format of NeoFS API protocol (overrides corresponding attributes)
|
||||||
- <subnetwork_ID>
|
- <subnetwork_ID>
|
||||||
...
|
...
|
||||||
...
|
...
|
||||||
|
@ -129,9 +129,9 @@ To create a container in a private network, your wallet must be added to
|
||||||
the client whitelist by the client admins or the subnet owners:
|
the client whitelist by the client admins or the subnet owners:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-cli container create \
|
$ neofs-cli container create \
|
||||||
--policy 'REP 1' \
|
--policy 'REP 1' \
|
||||||
-w </path/to/wallet> \
|
-w </path/to/wallet> \
|
||||||
-r s01.frostfs.devenv:8080 \
|
-r s01.neofs.devenv:8080 \
|
||||||
--subnet <subnet_ID>
|
--subnet <subnet_ID>
|
||||||
```
|
```
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -41,7 +41,7 @@ network:
|
||||||
container: {{ .ContainerFee}}
|
container: {{ .ContainerFee}}
|
||||||
container_alias: {{ .ContainerAliasFee }}
|
container_alias: {{ .ContainerAliasFee }}
|
||||||
withdraw: {{ .WithdrawFee}}
|
withdraw: {{ .WithdrawFee}}
|
||||||
# if credentials section is omitted, then frostfs-adm will require manual password input
|
# if credentials section is omitted, then neofs-adm will require manual password input
|
||||||
credentials:
|
credentials:
|
||||||
contract: password # wallet for contract group signature{{ range.Glagolitics}}
|
contract: password # wallet for contract group signature{{ range.Glagolitics}}
|
||||||
{{.}}: password{{end}}
|
{{.}}: password{{end}}
|
||||||
|
@ -99,7 +99,7 @@ func defaultConfigPath() (string, error) {
|
||||||
return "", fmt.Errorf("getting home dir path: %w", err)
|
return "", fmt.Errorf("getting home dir path: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(home, ".frostfs", "adm", "config.yml"), nil
|
return filepath.Join(home, ".neofs", "adm", "config.yml"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateConfigExample builds .yml representation of the config file. It is
|
// generateConfigExample builds .yml representation of the config file. It is
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ import (
|
||||||
func TestGenerateConfigExample(t *testing.T) {
|
func TestGenerateConfigExample(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
n = 10
|
n = 10
|
||||||
appDir = "/home/example/.frostfs"
|
appDir = "/home/example/.neofs"
|
||||||
)
|
)
|
||||||
|
|
||||||
configText, err := generateConfigExample(appDir, n)
|
configText, err := generateConfigExample(appDir, n)
|
|
@ -10,14 +10,14 @@ var (
|
||||||
// RootCmd is a root command of config section.
|
// RootCmd is a root command of config section.
|
||||||
RootCmd = &cobra.Command{
|
RootCmd = &cobra.Command{
|
||||||
Use: "config",
|
Use: "config",
|
||||||
Short: "Section for frostfs-adm config related commands",
|
Short: "Section for neofs-adm config related commands",
|
||||||
}
|
}
|
||||||
|
|
||||||
initCmd = &cobra.Command{
|
initCmd = &cobra.Command{
|
||||||
Use: "init",
|
Use: "init",
|
||||||
Short: "Initialize basic frostfs-adm configuration file",
|
Short: "Initialize basic neofs-adm configuration file",
|
||||||
Example: `frostfs-adm config init
|
Example: `neofs-adm config init
|
||||||
frostfs-adm config init --path .config/frostfs-adm.yml`,
|
neofs-adm config init --path .config/neofs-adm.yml`,
|
||||||
RunE: initConfig,
|
RunE: initConfig,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -25,5 +25,5 @@ frostfs-adm config init --path .config/frostfs-adm.yml`,
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.AddCommand(initCmd)
|
RootCmd.AddCommand(initCmd)
|
||||||
|
|
||||||
initCmd.Flags().String(configPathFlag, "", "Path to config (default ~/.frostfs/adm/config.yml)")
|
initCmd.Flags().String(configPathFlag, "", "Path to config (default ~/.neofs/adm/config.yml)")
|
||||||
}
|
}
|
|
@ -6,23 +6,22 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"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/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/nns"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -44,7 +43,6 @@ const (
|
||||||
notaryEnabled = true
|
notaryEnabled = true
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint: funlen, gocognit
|
|
||||||
func dumpBalances(cmd *cobra.Command, _ []string) error {
|
func dumpBalances(cmd *cobra.Command, _ []string) error {
|
||||||
var (
|
var (
|
||||||
dumpStorage, _ = cmd.Flags().GetBool(dumpBalancesStorageFlag)
|
dumpStorage, _ = cmd.Flags().GetBool(dumpBalancesStorageFlag)
|
||||||
|
@ -61,24 +59,39 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
||||||
|
ns, err := getNativeHashes(c)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't fetch the list of native contracts: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gasHash, ok := ns[nativenames.Gas]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't find the %s native contract hash", nativenames.Gas)
|
||||||
|
}
|
||||||
|
|
||||||
|
desigHash, ok := ns[nativenames.Designation]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't find the %s native contract hash", nativenames.Designation)
|
||||||
|
}
|
||||||
|
|
||||||
if !notaryEnabled || dumpStorage || dumpAlphabet || dumpProxy {
|
if !notaryEnabled || dumpStorage || dumpAlphabet || dumpProxy {
|
||||||
nnsCs, err = c.GetContractStateByID(1)
|
nnsCs, err = c.GetContractStateByID(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get NNS contract info: %w", err)
|
return fmt.Errorf("can't get NNS contract info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nmHash, err = nnsResolveHash(inv, nnsCs.Hash, netmapContract+".frostfs")
|
nmHash, err = nnsResolveHash(inv, nnsCs.Hash, netmapContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
irList, err := fetchIRNodes(c, nmHash, rolemgmt.Hash)
|
irList, err := fetchIRNodes(c, nmHash, desigHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fetchBalances(inv, gas.Hash, irList); err != nil {
|
if err := fetchBalances(inv, gasHash, irList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printBalances(cmd, "Inner ring nodes balances:", irList)
|
printBalances(cmd, "Inner ring nodes balances:", irList)
|
||||||
|
@ -110,20 +123,20 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
|
||||||
snList[i].scriptHash = pub.GetScriptHash()
|
snList[i].scriptHash = pub.GetScriptHash()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fetchBalances(inv, gas.Hash, snList); err != nil {
|
if err := fetchBalances(inv, gasHash, snList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printBalances(cmd, "\nStorage node balances:", snList)
|
printBalances(cmd, "\nStorage node balances:", snList)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dumpProxy {
|
if dumpProxy {
|
||||||
h, err := nnsResolveHash(inv, nnsCs.Hash, proxyContract+".frostfs")
|
h, err := nnsResolveHash(inv, nnsCs.Hash, proxyContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get hash of the proxy contract: %w", err)
|
return fmt.Errorf("can't get hash of the proxy contract: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyList := []accBalancePair{{scriptHash: h}}
|
proxyList := []accBalancePair{{scriptHash: h}}
|
||||||
if err := fetchBalances(inv, gas.Hash, proxyList); err != nil {
|
if err := fetchBalances(inv, gasHash, proxyList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printBalances(cmd, "\nProxy contract balance:", proxyList)
|
printBalances(cmd, "\nProxy contract balance:", proxyList)
|
||||||
|
@ -155,7 +168,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
|
||||||
alphaList[i].scriptHash = h
|
alphaList[i].scriptHash = h
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := fetchBalances(inv, gas.Hash, alphaList); err != nil {
|
if err := fetchBalances(inv, gasHash, alphaList); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
printBalances(cmd, "\nAlphabet contracts balances:", alphaList)
|
printBalances(cmd, "\nAlphabet contracts balances:", alphaList)
|
|
@ -35,7 +35,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("can't get NNS contract info: %w", err)
|
return fmt.Errorf("can't get NNS contract info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs")
|
nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("can't get NNS contract info: %w", err)
|
return fmt.Errorf("can't get NNS contract info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs")
|
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -140,14 +140,14 @@ func setConfigCmd(cmd *cobra.Command, args []string) error {
|
||||||
return wCtx.awaitTx()
|
return wCtx.awaitTx()
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConfigPair(kvStr string, force bool) (key string, val any, err error) {
|
func parseConfigPair(kvStr string, force bool) (key string, val interface{}, err error) {
|
||||||
k, v, found := strings.Cut(kvStr, "=")
|
kv := strings.SplitN(kvStr, "=", 2)
|
||||||
if !found {
|
if len(kv) != 2 {
|
||||||
return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr)
|
return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
key = k
|
key = kv[0]
|
||||||
valRaw := v
|
valRaw := kv[1]
|
||||||
|
|
||||||
switch key {
|
switch key {
|
||||||
case netmapAuditFeeKey, netmapBasicIncomeRateKey,
|
case netmapAuditFeeKey, netmapBasicIncomeRateKey,
|
||||||
|
@ -162,7 +162,7 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error)
|
||||||
case netmapEigenTrustAlphaKey:
|
case netmapEigenTrustAlphaKey:
|
||||||
// just check that it could
|
// just check that it could
|
||||||
// be parsed correctly
|
// be parsed correctly
|
||||||
_, err = strconv.ParseFloat(v, 64)
|
_, err = strconv.ParseFloat(kv[1], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err)
|
err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err)
|
||||||
}
|
}
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
|
@ -16,43 +15,13 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errInvalidContainerResponse = errors.New("invalid response from container contract")
|
var errInvalidContainerResponse = errors.New("invalid response from container contract")
|
||||||
|
|
||||||
func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker, c Client) (util.Uint160, error) {
|
|
||||||
s, err := cmd.Flags().GetString(containerContractFlag)
|
|
||||||
var ch util.Uint160
|
|
||||||
if err == nil {
|
|
||||||
ch, err = util.Uint160DecodeStringLE(s)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
nnsCs, err := c.GetContractStateByID(1)
|
|
||||||
if err != nil {
|
|
||||||
return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err)
|
|
||||||
}
|
|
||||||
ch, err = nnsResolveHash(inv, nnsCs.Hash, containerContract+".frostfs")
|
|
||||||
if err != nil {
|
|
||||||
return util.Uint160{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ch, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getContainersList(inv *invoker.Invoker, ch util.Uint160) ([][]byte, error) {
|
|
||||||
res, err := inv.Call(ch, "list", "")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
|
||||||
}
|
|
||||||
itm, err := unwrap.Item(res, err)
|
|
||||||
if _, ok := itm.(stackitem.Null); !ok {
|
|
||||||
return unwrap.ArrayOfBytes(res, err)
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func dumpContainers(cmd *cobra.Command, _ []string) error {
|
func dumpContainers(cmd *cobra.Command, _ []string) error {
|
||||||
filename, err := cmd.Flags().GetString(containerDumpFlag)
|
filename, err := cmd.Flags().GetString(containerDumpFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,12 +35,24 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
||||||
ch, err := getContainerContractHash(cmd, inv, c)
|
nnsCs, err := c.GetContractStateByID(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to get contaract hash: %w", err)
|
return fmt.Errorf("can't get NNS contract state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cids, err := getContainersList(inv, ch)
|
var ch util.Uint160
|
||||||
|
s, err := cmd.Flags().GetString(containerContractFlag)
|
||||||
|
if err == nil {
|
||||||
|
ch, err = util.Uint160DecodeStringLE(s)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
ch, err = nnsResolveHash(inv, nnsCs.Hash, containerContract+".neofs")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cids, err := unwrap.ArrayOfBytes(inv.Call(ch, "list", ""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
return fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
||||||
}
|
}
|
||||||
|
@ -123,36 +104,6 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
|
||||||
return os.WriteFile(filename, out, 0o660)
|
return os.WriteFile(filename, out, 0o660)
|
||||||
}
|
}
|
||||||
|
|
||||||
func listContainers(cmd *cobra.Command, _ []string) error {
|
|
||||||
c, err := getN3Client(viper.GetViper())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't create N3 client: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
|
||||||
|
|
||||||
ch, err := getContainerContractHash(cmd, inv, c)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to get contaract hash: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cids, err := getContainersList(inv, ch)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, id := range cids {
|
|
||||||
var idCnr cid.ID
|
|
||||||
err = idCnr.Decode(id)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to decode container id: %w", err)
|
|
||||||
}
|
|
||||||
cmd.Println(idCnr)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func restoreContainers(cmd *cobra.Command, _ []string) error {
|
func restoreContainers(cmd *cobra.Command, _ []string) error {
|
||||||
filename, err := cmd.Flags().GetString(containerDumpFlag)
|
filename, err := cmd.Flags().GetString(containerDumpFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -170,7 +121,7 @@ func restoreContainers(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("can't get NNS contract state: %w", err)
|
return fmt.Errorf("can't get NNS contract state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, containerContract+".frostfs")
|
ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, containerContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't fetch container contract hash: %w", err)
|
return fmt.Errorf("can't fetch container contract hash: %w", err)
|
||||||
}
|
}
|
|
@ -6,16 +6,16 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
"github.com/nspcc-dev/neo-go/cli/cmdargs"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params"
|
"github.com/nspcc-dev/neo-go/pkg/services/rpcsrv/params"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/nns"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -35,7 +35,7 @@ Optionally, arguments can be provided to be passed to a contract's _deploy funct
|
||||||
The syntax is the same as for 'neo-go contract testinvokefunction' command.
|
The syntax is the same as for 'neo-go contract testinvokefunction' command.
|
||||||
Compiled contract file name must contain '_contract.nef' suffix.
|
Compiled contract file name must contain '_contract.nef' suffix.
|
||||||
Contract's manifest file name must be 'config.json'.
|
Contract's manifest file name must be 'config.json'.
|
||||||
NNS name is taken by stripping '_contract.nef' from the NEF file (similar to frostfs contracts).`,
|
NNS name is taken by stripping '_contract.nef' from the NEF file (similar to neofs contracts).`,
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
|
@ -54,10 +54,9 @@ func init() {
|
||||||
_ = deployCmd.MarkFlagFilename(contractPathFlag)
|
_ = deployCmd.MarkFlagFilename(contractPathFlag)
|
||||||
|
|
||||||
ff.Bool(updateFlag, false, "Update an existing contract")
|
ff.Bool(updateFlag, false, "Update an existing contract")
|
||||||
ff.String(customZoneFlag, "frostfs", "Custom zone for NNS")
|
ff.String(customZoneFlag, "neofs", "Custom zone for NNS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func deployContractCmd(cmd *cobra.Command, args []string) error {
|
func deployContractCmd(cmd *cobra.Command, args []string) error {
|
||||||
v := viper.GetViper()
|
v := viper.GetViper()
|
||||||
c, err := newInitializeContext(cmd, v)
|
c, err := newInitializeContext(cmd, v)
|
||||||
|
@ -82,7 +81,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("can't fetch NNS contract state: %w", err)
|
return fmt.Errorf("can't fetch NNS contract state: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
callHash := management.Hash
|
callHash := c.nativeHash(nativenames.Management)
|
||||||
method := deployMethodName
|
method := deployMethodName
|
||||||
zone, _ := cmd.Flags().GetString(customZoneFlag)
|
zone, _ := cmd.Flags().GetString(customZoneFlag)
|
||||||
domain := ctrName + "." + zone
|
domain := ctrName + "." + zone
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
func downloadContractsFromGithub(cmd *cobra.Command) (io.ReadCloser, error) {
|
func downloadContractsFromGithub(cmd *cobra.Command) (io.ReadCloser, error) {
|
||||||
gcl := github.NewClient(nil)
|
gcl := github.NewClient(nil)
|
||||||
release, _, err := gcl.Repositories.GetLatestRelease(context.Background(), "nspcc-dev", "frostfs-contract")
|
release, _, err := gcl.Repositories.GetLatestRelease(context.Background(), "nspcc-dev", "neofs-contract")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't fetch release info: %w", err)
|
return nil, fmt.Errorf("can't fetch release info: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ func downloadContractsFromGithub(cmd *cobra.Command) (io.ReadCloser, error) {
|
||||||
|
|
||||||
var url string
|
var url string
|
||||||
for _, a := range release.Assets {
|
for _, a := range release.Assets {
|
||||||
if strings.HasPrefix(a.GetName(), "frostfs-contract") {
|
if strings.HasPrefix(a.GetName(), "neofs-contract") {
|
||||||
url = a.GetBrowserDownloadURL()
|
url = a.GetBrowserDownloadURL()
|
||||||
break
|
break
|
||||||
}
|
}
|
|
@ -2,13 +2,10 @@ package morph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
|
||||||
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||||
|
@ -18,6 +15,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/nns"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -85,7 +83,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error {
|
||||||
for _, ctrName := range contractList {
|
for _, ctrName := range contractList {
|
||||||
bw.Reset()
|
bw.Reset()
|
||||||
emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly,
|
emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly,
|
||||||
ctrName+".frostfs", int64(nns.TXT))
|
ctrName+".neofs", int64(nns.TXT))
|
||||||
|
|
||||||
res, err := c.InvokeScript(bw.Bytes(), nil)
|
res, err := c.InvokeScript(bw.Bytes(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -109,30 +107,31 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error {
|
||||||
|
|
||||||
func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c Client) error {
|
func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c Client) error {
|
||||||
const nnsMaxTokens = 100
|
const nnsMaxTokens = 100
|
||||||
|
|
||||||
inv := invoker.New(c, nil)
|
inv := invoker.New(c, nil)
|
||||||
|
|
||||||
|
arr, err := unwrap.Array(inv.CallAndExpandIterator(nnsHash, "tokens", nnsMaxTokens))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't get a list of NNS domains: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !strings.HasPrefix(zone, ".") {
|
if !strings.HasPrefix(zone, ".") {
|
||||||
zone = "." + zone
|
zone = "." + zone
|
||||||
}
|
}
|
||||||
|
|
||||||
var infos []contractDumpInfo
|
var infos []contractDumpInfo
|
||||||
processItem := func(item stackitem.Item) {
|
for i := range arr {
|
||||||
bs, err := item.TryBytes()
|
bs, err := arr[i].TryBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrf("Invalid NNS record: %v\n", err)
|
continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.HasSuffix(bs, []byte(zone)) || bytes.HasPrefix(bs, []byte(morphClient.NNSGroupKeyName)) {
|
if !bytes.HasSuffix(bs, []byte(zone)) {
|
||||||
// Related https://github.com/nspcc-dev/neofs-contract/issues/316.
|
continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h, err := nnsResolveHash(inv, nnsHash, string(bs))
|
h, err := nnsResolveHash(inv, nnsHash, string(bs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.PrintErrf("Could not resolve name %s: %v\n", string(bs), err)
|
continue
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
infos = append(infos, contractDumpInfo{
|
infos = append(infos, contractDumpInfo{
|
||||||
|
@ -141,39 +140,6 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionID, iter, err := unwrap.SessionIterator(inv.Call(nnsHash, "tokens"))
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, unwrap.ErrNoSessionID) {
|
|
||||||
items, err := unwrap.Array(inv.CallAndExpandIterator(nnsHash, "tokens", nnsMaxTokens))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("can't get a list of NNS domains: %w", err)
|
|
||||||
}
|
|
||||||
if len(items) == nnsMaxTokens {
|
|
||||||
cmd.PrintErrln("Provided RPC endpoint doesn't support sessions, some hashes might be lost.")
|
|
||||||
}
|
|
||||||
for i := range items {
|
|
||||||
processItem(items[i])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
defer func() {
|
|
||||||
_ = inv.TerminateSession(sessionID)
|
|
||||||
}()
|
|
||||||
|
|
||||||
items, err := inv.TraverseIterator(sessionID, &iter, nnsMaxTokens)
|
|
||||||
for err == nil && len(items) != 0 {
|
|
||||||
for i := range items {
|
|
||||||
processItem(items[i])
|
|
||||||
}
|
|
||||||
items, err = inv.TraverseIterator(sessionID, &iter, nnsMaxTokens)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error during NNS domains iteration: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fillContractVersion(cmd, c, infos)
|
fillContractVersion(cmd, c, infos)
|
||||||
printContractInfo(cmd, infos)
|
printContractInfo(cmd, infos)
|
||||||
|
|
|
@ -24,7 +24,7 @@ func forceNewEpochCmd(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("can't get NNS contract info: %w", err)
|
return fmt.Errorf("can't get NNS contract info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs")
|
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
||||||
}
|
}
|
|
@ -6,19 +6,19 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"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/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"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"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -198,8 +198,10 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gasHash := wCtx.nativeHash(nativenames.Gas)
|
||||||
|
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All,
|
emit.AppCall(bw.BinWriter, gasHash, "transfer", callflag.All,
|
||||||
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
|
wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil)
|
||||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||||
if bw.Err != nil {
|
if bw.Err != nil {
|
|
@ -9,11 +9,11 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
|
@ -6,11 +6,11 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
|
@ -7,9 +7,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"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/core/transaction"
|
||||||
|
@ -19,6 +16,9 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -43,6 +43,7 @@ type initializeContext struct {
|
||||||
Contracts map[string]*contractState
|
Contracts map[string]*contractState
|
||||||
Command *cobra.Command
|
Command *cobra.Command
|
||||||
ContractPath string
|
ContractPath string
|
||||||
|
Natives map[string]util.Uint160
|
||||||
}
|
}
|
||||||
|
|
||||||
func initializeSideChainCmd(cmd *cobra.Command, args []string) error {
|
func initializeSideChainCmd(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -108,7 +109,6 @@ func (c *initializeContext) close() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) {
|
func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) {
|
||||||
walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag))
|
walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag))
|
||||||
wallets, err := openAlphabetWallets(v, walletDir)
|
wallets, err := openAlphabetWallets(v, walletDir)
|
||||||
|
@ -116,10 +116,8 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
|
|
||||||
|
|
||||||
var w *wallet.Wallet
|
var w *wallet.Wallet
|
||||||
if needContracts {
|
if cmd.Name() != "deploy" {
|
||||||
w, err = openContractWallet(v, cmd, walletDir)
|
w, err = openContractWallet(v, cmd, walletDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -160,6 +158,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init"
|
||||||
if needContracts {
|
if needContracts {
|
||||||
ctrPath, err = cmd.Flags().GetString(contractsInitFlag)
|
ctrPath, err = cmd.Flags().GetString(contractsInitFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -167,7 +166,8 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkNotaryEnabled(c); err != nil {
|
nativeHashes, err := getNativeHashes(c)
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
Command: cmd,
|
Command: cmd,
|
||||||
Contracts: make(map[string]*contractState),
|
Contracts: make(map[string]*contractState),
|
||||||
ContractPath: ctrPath,
|
ContractPath: ctrPath,
|
||||||
|
Natives: nativeHashes,
|
||||||
}
|
}
|
||||||
|
|
||||||
if needContracts {
|
if needContracts {
|
||||||
|
@ -207,6 +208,10 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
|
||||||
return initCtx, nil
|
return initCtx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *initializeContext) nativeHash(name string) util.Uint160 {
|
||||||
|
return c.Natives[name]
|
||||||
|
}
|
||||||
|
|
||||||
func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) {
|
func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) {
|
||||||
walletFiles, err := os.ReadDir(walletDir)
|
walletFiles, err := os.ReadDir(walletDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -445,10 +450,10 @@ func getWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) {
|
||||||
return nil, fmt.Errorf("account for '%s' not found", typ)
|
return nil, fmt.Errorf("account for '%s' not found", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkNotaryEnabled(c Client) error {
|
func getNativeHashes(c Client) (map[string]util.Uint160, error) {
|
||||||
ns, err := c.GetNativeContracts()
|
ns, err := c.GetNativeContracts()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get native contract hashes: %w", err)
|
return nil, fmt.Errorf("can't get native contract hashes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
notaryEnabled := false
|
notaryEnabled := false
|
||||||
|
@ -460,7 +465,7 @@ func checkNotaryEnabled(c Client) error {
|
||||||
nativeHashes[ns[i].Manifest.Name] = ns[i].Hash
|
nativeHashes[ns[i].Manifest.Name] = ns[i].Hash
|
||||||
}
|
}
|
||||||
if !notaryEnabled {
|
if !notaryEnabled {
|
||||||
return errors.New("notary contract must be enabled")
|
return nil, errors.New("notary contract must be enabled")
|
||||||
}
|
}
|
||||||
return nil
|
return nativeHashes, nil
|
||||||
}
|
}
|
|
@ -12,17 +12,13 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/common"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"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/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
io2 "github.com/nspcc-dev/neo-go/pkg/io"
|
io2 "github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
"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/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
@ -31,18 +27,22 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/common"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/nns"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
nnsContract = "nns"
|
nnsContract = "nns"
|
||||||
frostfsContract = "frostfs" // not deployed in side-chain.
|
neofsContract = "neofs" // not deployed in side-chain.
|
||||||
processingContract = "processing" // not deployed in side-chain.
|
processingContract = "processing" // not deployed in side-chain.
|
||||||
alphabetContract = "alphabet"
|
alphabetContract = "alphabet"
|
||||||
auditContract = "audit"
|
auditContract = "audit"
|
||||||
balanceContract = "balance"
|
balanceContract = "balance"
|
||||||
containerContract = "container"
|
containerContract = "container"
|
||||||
frostfsIDContract = "frostfsid"
|
neofsIDContract = "neofsid"
|
||||||
netmapContract = "netmap"
|
netmapContract = "netmap"
|
||||||
proxyContract = "proxy"
|
proxyContract = "proxy"
|
||||||
reputationContract = "reputation"
|
reputationContract = "reputation"
|
||||||
|
@ -72,7 +72,7 @@ var (
|
||||||
auditContract,
|
auditContract,
|
||||||
balanceContract,
|
balanceContract,
|
||||||
containerContract,
|
containerContract,
|
||||||
frostfsIDContract,
|
neofsIDContract,
|
||||||
netmapContract,
|
netmapContract,
|
||||||
proxyContract,
|
proxyContract,
|
||||||
reputationContract,
|
reputationContract,
|
||||||
|
@ -80,7 +80,7 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
fullContractList = append([]string{
|
fullContractList = append([]string{
|
||||||
frostfsContract,
|
neofsContract,
|
||||||
processingContract,
|
processingContract,
|
||||||
nnsContract,
|
nnsContract,
|
||||||
alphabetContract,
|
alphabetContract,
|
||||||
|
@ -128,7 +128,7 @@ func (c *initializeContext) deployNNS(method string) error {
|
||||||
Scopes: transaction.CalledByEntry,
|
Scopes: transaction.CalledByEntry,
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeHash := management.Hash
|
invokeHash := c.nativeHash(nativenames.Management)
|
||||||
if method == updateMethodName {
|
if method == updateMethodName {
|
||||||
invokeHash = nnsCs.Hash
|
invokeHash = nnsCs.Hash
|
||||||
}
|
}
|
||||||
|
@ -156,8 +156,8 @@ func (c *initializeContext) deployNNS(method string) error {
|
||||||
return c.awaitTx()
|
return c.awaitTx()
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func (c *initializeContext) updateContracts() error {
|
func (c *initializeContext) updateContracts() error {
|
||||||
|
mgmtHash := c.nativeHash(nativenames.Management)
|
||||||
alphaCs := c.getContract(alphabetContract)
|
alphaCs := c.getContract(alphabetContract)
|
||||||
|
|
||||||
nnsCs, err := c.nnsContractState()
|
nnsCs, err := c.nnsContractState()
|
||||||
|
@ -168,7 +168,7 @@ func (c *initializeContext) updateContracts() error {
|
||||||
|
|
||||||
w := io2.NewBufBinWriter()
|
w := io2.NewBufBinWriter()
|
||||||
|
|
||||||
var keysParam []any
|
var keysParam []interface{}
|
||||||
|
|
||||||
// Update script size for a single-node committee is close to the maximum allowed size of 65535.
|
// Update script size for a single-node committee is close to the maximum allowed size of 65535.
|
||||||
// Because of this we want to reuse alphabet contract NEF and manifest for different updates.
|
// Because of this we want to reuse alphabet contract NEF and manifest for different updates.
|
||||||
|
@ -228,7 +228,7 @@ func (c *initializeContext) updateContracts() error {
|
||||||
cs := c.getContract(ctrName)
|
cs := c.getContract(ctrName)
|
||||||
|
|
||||||
method := updateMethodName
|
method := updateMethodName
|
||||||
ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, ctrName+".frostfs")
|
ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, ctrName+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errMissingNNSRecord) {
|
if errors.Is(err, errMissingNNSRecord) {
|
||||||
// if contract not found we deploy it instead of update
|
// if contract not found we deploy it instead of update
|
||||||
|
@ -243,7 +243,7 @@ func (c *initializeContext) updateContracts() error {
|
||||||
return fmt.Errorf("can't sign manifest group: %v", err)
|
return fmt.Errorf("can't sign manifest group: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
invokeHash := management.Hash
|
invokeHash := mgmtHash
|
||||||
if method == updateMethodName {
|
if method == updateMethodName {
|
||||||
invokeHash = ctrHash
|
invokeHash = ctrHash
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ func (c *initializeContext) updateContracts() error {
|
||||||
|
|
||||||
if method == deployMethodName {
|
if method == deployMethodName {
|
||||||
// same actions are done in initializeContext.setNNS, can be unified
|
// same actions are done in initializeContext.setNNS, can be unified
|
||||||
domain := ctrName + ".frostfs"
|
domain := ctrName + ".neofs"
|
||||||
script, ok, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain)
|
script, ok, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -298,9 +298,10 @@ func (c *initializeContext) updateContracts() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) deployContracts() error {
|
func (c *initializeContext) deployContracts() error {
|
||||||
|
mgmtHash := c.nativeHash(nativenames.Management)
|
||||||
alphaCs := c.getContract(alphabetContract)
|
alphaCs := c.getContract(alphabetContract)
|
||||||
|
|
||||||
var keysParam []any
|
var keysParam []interface{}
|
||||||
|
|
||||||
baseGroups := alphaCs.Manifest.Groups
|
baseGroups := alphaCs.Manifest.Groups
|
||||||
|
|
||||||
|
@ -326,7 +327,7 @@ func (c *initializeContext) deployContracts() error {
|
||||||
return fmt.Errorf("could not create actor: %w", err)
|
return fmt.Errorf("could not create actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
txHash, vub, err := act.SendCall(management.Hash, deployMethodName, params...)
|
txHash, vub, err := act.SendCall(mgmtHash, deployMethodName, params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err)
|
return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err)
|
||||||
}
|
}
|
||||||
|
@ -349,7 +350,7 @@ func (c *initializeContext) deployContracts() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam))
|
params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam))
|
||||||
res, err := c.CommitteeAct.MakeCall(management.Hash, deployMethodName, params...)
|
res, err := c.CommitteeAct.MakeCall(mgmtHash, deployMethodName, params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
|
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
|
||||||
}
|
}
|
||||||
|
@ -511,22 +512,22 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getContractDeployParameters(cs *contractState, deployData []any) []any {
|
func getContractDeployParameters(cs *contractState, deployData []interface{}) []interface{} {
|
||||||
return []any{cs.RawNEF, cs.RawManifest, deployData}
|
return []interface{}{cs.RawNEF, cs.RawManifest, deployData}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any) []any {
|
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []interface{}) []interface{} {
|
||||||
items := make([]any, 1, 6)
|
items := make([]interface{}, 1, 6)
|
||||||
items[0] = false // notaryDisabled is false
|
items[0] = false // notaryDisabled is false
|
||||||
|
|
||||||
switch ctrName {
|
switch ctrName {
|
||||||
case frostfsContract:
|
case neofsContract:
|
||||||
items = append(items,
|
items = append(items,
|
||||||
c.Contracts[processingContract].Hash,
|
c.Contracts[processingContract].Hash,
|
||||||
keysParam,
|
keysParam,
|
||||||
smartcontract.Parameter{})
|
smartcontract.Parameter{})
|
||||||
case processingContract:
|
case processingContract:
|
||||||
items = append(items, c.Contracts[frostfsContract].Hash)
|
items = append(items, c.Contracts[neofsContract].Hash)
|
||||||
return items[1:] // no notary info
|
return items[1:] // no notary info
|
||||||
case auditContract:
|
case auditContract:
|
||||||
items = append(items, c.Contracts[netmapContract].Hash)
|
items = append(items, c.Contracts[netmapContract].Hash)
|
||||||
|
@ -544,15 +545,15 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
|
||||||
items = append(items,
|
items = append(items,
|
||||||
c.Contracts[netmapContract].Hash,
|
c.Contracts[netmapContract].Hash,
|
||||||
c.Contracts[balanceContract].Hash,
|
c.Contracts[balanceContract].Hash,
|
||||||
c.Contracts[frostfsIDContract].Hash,
|
c.Contracts[neofsIDContract].Hash,
|
||||||
nnsCs.Hash,
|
nnsCs.Hash,
|
||||||
"container")
|
"container")
|
||||||
case frostfsIDContract:
|
case neofsIDContract:
|
||||||
items = append(items,
|
items = append(items,
|
||||||
c.Contracts[netmapContract].Hash,
|
c.Contracts[netmapContract].Hash,
|
||||||
c.Contracts[containerContract].Hash)
|
c.Contracts[containerContract].Hash)
|
||||||
case netmapContract:
|
case netmapContract:
|
||||||
configParam := []any{
|
configParam := []interface{}{
|
||||||
netmapEpochKey, viper.GetInt64(epochDurationInitFlag),
|
netmapEpochKey, viper.GetInt64(epochDurationInitFlag),
|
||||||
netmapMaxObjectSizeKey, viper.GetInt64(maxObjectSizeInitFlag),
|
netmapMaxObjectSizeKey, viper.GetInt64(maxObjectSizeInitFlag),
|
||||||
netmapAuditFeeKey, viper.GetInt64(auditFeeInitFlag),
|
netmapAuditFeeKey, viper.GetInt64(auditFeeInitFlag),
|
||||||
|
@ -581,8 +582,8 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) getAlphabetDeployItems(i, n int) []any {
|
func (c *initializeContext) getAlphabetDeployItems(i, n int) []interface{} {
|
||||||
items := make([]any, 6)
|
items := make([]interface{}, 6)
|
||||||
items[0] = false
|
items[0] = false
|
||||||
items[1] = c.Contracts[netmapContract].Hash
|
items[1] = c.Contracts[netmapContract].Hash
|
||||||
items[2] = c.Contracts[proxyContract].Hash
|
items[2] = c.Contracts[proxyContract].Hash
|
|
@ -7,8 +7,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
|
|
||||||
morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"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/encoding/address"
|
||||||
|
@ -22,6 +20,8 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
||||||
|
"github.com/nspcc-dev/neofs-contract/nns"
|
||||||
|
morphClient "github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second
|
const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second
|
||||||
|
@ -32,13 +32,13 @@ func (c *initializeContext) setNNS() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, err := c.nnsRootRegistered(nnsCs.Hash, "frostfs")
|
ok, err := c.nnsRootRegistered(nnsCs.Hash, "neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !ok {
|
} else if !ok {
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All,
|
emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All,
|
||||||
"frostfs", c.CommitteeAcc.Contract.ScriptHash(),
|
"neofs", c.CommitteeAcc.Contract.ScriptHash(),
|
||||||
"ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
|
"ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600))
|
||||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||||
if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil {
|
if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil {
|
||||||
|
@ -63,7 +63,7 @@ func (c *initializeContext) setNNS() error {
|
||||||
for _, ctrName := range contractList {
|
for _, ctrName := range contractList {
|
||||||
cs := c.getContract(ctrName)
|
cs := c.getContract(ctrName)
|
||||||
|
|
||||||
domain := ctrName + ".frostfs"
|
domain := ctrName + ".neofs"
|
||||||
if err := c.nnsRegisterDomain(nnsCs.Hash, cs.Hash, domain); err != nil {
|
if err := c.nnsRegisterDomain(nnsCs.Hash, cs.Hash, domain); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -82,13 +82,13 @@ func (c *initializeContext) setNNS() error {
|
||||||
|
|
||||||
func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.PublicKey) error {
|
func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.PublicKey) error {
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
keyAlreadyAdded, domainRegCodeEmitted, err := c.emitUpdateNNSGroupScript(bw, nnsHash, pub)
|
needUpdate, needRegister, err := c.emitUpdateNNSGroupScript(bw, nnsHash, pub)
|
||||||
if keyAlreadyAdded || err != nil {
|
if !needUpdate || err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
script := bw.Bytes()
|
script := bw.Bytes()
|
||||||
if domainRegCodeEmitted {
|
if needRegister {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1})
|
emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1})
|
||||||
wrapRegisterScriptWithPrice(w, nnsHash, script)
|
wrapRegisterScriptWithPrice(w, nnsHash, script)
|
||||||
|
@ -125,15 +125,15 @@ func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas
|
||||||
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
emit.Opcodes(bw.BinWriter, opcode.ASSERT)
|
||||||
}
|
}
|
||||||
|
|
||||||
emit.AppCall(bw.BinWriter, nnsHash, "deleteRecords", callflag.All, "group.frostfs", int64(nns.TXT))
|
emit.AppCall(bw.BinWriter, nnsHash, "deleteRecords", callflag.All, "group.neofs", int64(nns.TXT))
|
||||||
emit.AppCall(bw.BinWriter, nnsHash, "addRecord", callflag.All,
|
emit.AppCall(bw.BinWriter, nnsHash, "addRecord", callflag.All,
|
||||||
"group.frostfs", int64(nns.TXT), hex.EncodeToString(pub.Bytes()))
|
"group.neofs", int64(nns.TXT), hex.EncodeToString(pub.Bytes()))
|
||||||
|
|
||||||
return false, isAvail, nil
|
return false, isAvail, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAlphabetNNSDomain(i int) string {
|
func getAlphabetNNSDomain(i int) string {
|
||||||
return alphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs"
|
return alphabetContract + strconv.FormatUint(uint64(i), 10) + ".neofs"
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrapRegisterScriptWithPrice wraps a given script with `getPrice`/`setPrice` calls for NNS.
|
// wrapRegisterScriptWithPrice wraps a given script with `getPrice`/`setPrice` calls for NNS.
|
||||||
|
@ -228,28 +228,21 @@ func nnsResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stac
|
||||||
}
|
}
|
||||||
|
|
||||||
func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
|
func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) {
|
||||||
res, err := nnsResolve(inv, nnsHash, domain)
|
item, err := nnsResolve(inv, nnsHash, domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, ok := res.Value().(stackitem.Null); ok {
|
v, ok := item.Value().(stackitem.Null)
|
||||||
|
if ok {
|
||||||
return nil, errors.New("NNS record is missing")
|
return nil, errors.New("NNS record is missing")
|
||||||
}
|
}
|
||||||
arr, ok := res.Value().([]stackitem.Item)
|
bs, err := v.TryBytes()
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("API of the NNS contract method `resolve` has changed")
|
|
||||||
}
|
|
||||||
for i := range arr {
|
|
||||||
var bs []byte
|
|
||||||
bs, err = arr[i].TryBytes()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
return nil, errors.New("malformed response")
|
||||||
}
|
}
|
||||||
|
|
||||||
return keys.NewPublicKeyFromString(string(bs))
|
return keys.NewPublicKeyFromString(string(bs))
|
||||||
}
|
}
|
||||||
return nil, errors.New("no valid keys are found")
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNNSResolveResult parses the result of resolving NNS record.
|
// parseNNSResolveResult parses the result of resolving NNS record.
|
||||||
// It works with multiple formats (corresponding to multiple NNS versions).
|
// It works with multiple formats (corresponding to multiple NNS versions).
|
||||||
|
@ -288,7 +281,7 @@ func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) {
|
||||||
case *rpcclient.Client:
|
case *rpcclient.Client:
|
||||||
return ct.NNSIsAvailable(nnsHash, name)
|
return ct.NNSIsAvailable(nnsHash, name)
|
||||||
default:
|
default:
|
||||||
b, err := unwrap.Bool(invokeFunction(c, nnsHash, "isAvailable", []any{name}, nil))
|
b, err := unwrap.Bool(invokeFunction(c, nnsHash, "isAvailable", []interface{}{name}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
|
return false, fmt.Errorf("`isAvailable`: invalid response: %w", err)
|
||||||
}
|
}
|
|
@ -5,11 +5,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"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/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
@ -21,7 +21,7 @@ import (
|
||||||
const initialAlphabetNEOAmount = native.NEOTotalSupply
|
const initialAlphabetNEOAmount = native.NEOTotalSupply
|
||||||
|
|
||||||
func (c *initializeContext) registerCandidates() error {
|
func (c *initializeContext) registerCandidates() error {
|
||||||
neoHash := neo.Hash
|
neoHash := c.nativeHash(nativenames.Neo)
|
||||||
|
|
||||||
cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neoHash, "getCandidates"))
|
cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neoHash, "getCandidates"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -83,7 +83,7 @@ func (c *initializeContext) registerCandidates() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) transferNEOToAlphabetContracts() error {
|
func (c *initializeContext) transferNEOToAlphabetContracts() error {
|
||||||
neoHash := neo.Hash
|
neoHash := c.nativeHash(nativenames.Neo)
|
||||||
|
|
||||||
ok, err := c.transferNEOFinished(neoHash)
|
ok, err := c.transferNEOFinished(neoHash)
|
||||||
if ok || err != nil {
|
if ok || err != nil {
|
||||||
|
@ -120,7 +120,7 @@ func (c *initializeContext) getCandidateRegisterPrice() (int64, error) {
|
||||||
case *rpcclient.Client:
|
case *rpcclient.Client:
|
||||||
return ct.GetCandidateRegisterPrice()
|
return ct.GetCandidateRegisterPrice()
|
||||||
default:
|
default:
|
||||||
neoHash := neo.Hash
|
neoHash := c.nativeHash(nativenames.Neo)
|
||||||
res, err := invokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil)
|
res, err := invokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
|
@ -1,9 +1,9 @@
|
||||||
package morph
|
package morph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
)
|
)
|
||||||
|
@ -16,15 +16,17 @@ func (c *initializeContext) setNotaryAndAlphabetNodes() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var pubs []any
|
designateHash := c.nativeHash(nativenames.Designation)
|
||||||
|
|
||||||
|
var pubs []interface{}
|
||||||
for _, acc := range c.Accounts {
|
for _, acc := range c.Accounts {
|
||||||
pubs = append(pubs, acc.PrivateKey().PublicKey().Bytes())
|
pubs = append(pubs, acc.PrivateKey().PublicKey().Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole",
|
emit.AppCall(w.BinWriter, designateHash, "designateAsRole",
|
||||||
callflag.States|callflag.AllowNotify, int64(noderoles.P2PNotary), pubs)
|
callflag.States|callflag.AllowNotify, int64(noderoles.P2PNotary), pubs)
|
||||||
emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole",
|
emit.AppCall(w.BinWriter, designateHash, "designateAsRole",
|
||||||
callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs)
|
callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs)
|
||||||
|
|
||||||
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil {
|
if err := c.sendCommitteeTx(w.Bytes(), false); err != nil {
|
||||||
|
@ -40,6 +42,7 @@ func (c *initializeContext) setRolesFinished() (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pubs, err := getDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height)
|
h := c.nativeHash(nativenames.Designation)
|
||||||
|
pubs, err := getDesignatedByRole(c.ReadOnlyInvoker, h, noderoles.NeoFSAlphabet, height)
|
||||||
return len(pubs) == len(c.Wallets), err
|
return len(pubs) == len(c.Wallets), err
|
||||||
}
|
}
|
|
@ -7,29 +7,26 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/innerring"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
contractsPath = "../../../../../../frostfs-contract/frostfs-contract-v0.16.0.tar.gz"
|
contractsPath = "../../../../../../neofs-contract/neofs-contract-v0.16.0.tar.gz"
|
||||||
protoFileName = "proto.yml"
|
protoFileName = "proto.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitialize(t *testing.T) {
|
func TestInitialize(t *testing.T) {
|
||||||
// This test needs frostfs-contract tarball, so it is skipped by default.
|
// This test needs neofs-contract tarball, so it is skipped by default.
|
||||||
// It is here for performing local testing after the changes.
|
// It is here for performing local testing after the changes.
|
||||||
t.Skip()
|
t.Skip()
|
||||||
|
|
||||||
t.Run("1 nodes", func(t *testing.T) {
|
|
||||||
testInitialize(t, 1)
|
|
||||||
})
|
|
||||||
t.Run("4 nodes", func(t *testing.T) {
|
t.Run("4 nodes", func(t *testing.T) {
|
||||||
testInitialize(t, 4)
|
testInitialize(t, 4)
|
||||||
})
|
})
|
||||||
|
@ -99,7 +96,6 @@ func generateTestData(t *testing.T, dir string, size int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := config.Config{}
|
cfg := config.Config{}
|
||||||
cfg.ProtocolConfiguration.Magic = 12345
|
|
||||||
cfg.ProtocolConfiguration.ValidatorsCount = size
|
cfg.ProtocolConfiguration.ValidatorsCount = size
|
||||||
cfg.ProtocolConfiguration.SecondsPerBlock = 1
|
cfg.ProtocolConfiguration.SecondsPerBlock = 1
|
||||||
cfg.ProtocolConfiguration.StandbyCommittee = pubs // sorted by glagolic letters
|
cfg.ProtocolConfiguration.StandbyCommittee = pubs // sorted by glagolic letters
|
|
@ -4,11 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/neo"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
scContext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
|
scContext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
|
@ -33,12 +32,15 @@ func (c *initializeContext) transferFunds() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gasHash := c.nativeHash(nativenames.Gas)
|
||||||
|
neoHash := c.nativeHash(nativenames.Neo)
|
||||||
|
|
||||||
var transfers []rpcclient.TransferTarget
|
var transfers []rpcclient.TransferTarget
|
||||||
for _, acc := range c.Accounts {
|
for _, acc := range c.Accounts {
|
||||||
to := acc.Contract.ScriptHash()
|
to := acc.Contract.ScriptHash()
|
||||||
transfers = append(transfers,
|
transfers = append(transfers,
|
||||||
rpcclient.TransferTarget{
|
rpcclient.TransferTarget{
|
||||||
Token: gas.Hash,
|
Token: gasHash,
|
||||||
Address: to,
|
Address: to,
|
||||||
Amount: initialAlphabetGASAmount,
|
Amount: initialAlphabetGASAmount,
|
||||||
},
|
},
|
||||||
|
@ -48,12 +50,12 @@ func (c *initializeContext) transferFunds() error {
|
||||||
// It is convenient to have all funds at the committee account.
|
// It is convenient to have all funds at the committee account.
|
||||||
transfers = append(transfers,
|
transfers = append(transfers,
|
||||||
rpcclient.TransferTarget{
|
rpcclient.TransferTarget{
|
||||||
Token: gas.Hash,
|
Token: gasHash,
|
||||||
Address: c.CommitteeAcc.Contract.ScriptHash(),
|
Address: c.CommitteeAcc.Contract.ScriptHash(),
|
||||||
Amount: (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2,
|
Amount: (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2,
|
||||||
},
|
},
|
||||||
rpcclient.TransferTarget{
|
rpcclient.TransferTarget{
|
||||||
Token: neo.Hash,
|
Token: neoHash,
|
||||||
Address: c.CommitteeAcc.Contract.ScriptHash(),
|
Address: c.CommitteeAcc.Contract.ScriptHash(),
|
||||||
Amount: native.NEOTotalSupply,
|
Amount: native.NEOTotalSupply,
|
||||||
},
|
},
|
||||||
|
@ -78,9 +80,10 @@ func (c *initializeContext) transferFunds() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) transferFundsFinished() (bool, error) {
|
func (c *initializeContext) transferFundsFinished() (bool, error) {
|
||||||
|
gasHash := c.nativeHash(nativenames.Gas)
|
||||||
acc := c.Accounts[0]
|
acc := c.Accounts[0]
|
||||||
|
|
||||||
res, err := c.Client.NEP17BalanceOf(gas.Hash, acc.Contract.ScriptHash())
|
res, err := c.Client.NEP17BalanceOf(gasHash, acc.Contract.ScriptHash())
|
||||||
return res > initialAlphabetGASAmount/2, err
|
return res > initialAlphabetGASAmount/2, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,15 +147,16 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *initializeContext) transferGASToProxy() error {
|
func (c *initializeContext) transferGASToProxy() error {
|
||||||
|
gasHash := c.nativeHash(nativenames.Gas)
|
||||||
proxyCs := c.getContract(proxyContract)
|
proxyCs := c.getContract(proxyContract)
|
||||||
|
|
||||||
bal, err := c.Client.NEP17BalanceOf(gas.Hash, proxyCs.Hash)
|
bal, err := c.Client.NEP17BalanceOf(gasHash, proxyCs.Hash)
|
||||||
if err != nil || bal > 0 {
|
if err != nil || bal > 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, 0, []rpcclient.TransferTarget{{
|
tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, 0, []rpcclient.TransferTarget{{
|
||||||
Token: gas.Hash,
|
Token: gasHash,
|
||||||
Address: proxyCs.Hash,
|
Address: proxyCs.Hash,
|
||||||
Amount: initialProxyGASAmount,
|
Amount: initialProxyGASAmount,
|
||||||
}}, nil)
|
}}, nil)
|
|
@ -18,7 +18,7 @@ func StringifySubnetClientGroupID(id *SubnetClientGroupID) string {
|
||||||
return string(text)
|
return string(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalText encodes SubnetClientGroupID into text format according to FrostFS API V2 protocol:
|
// MarshalText encodes SubnetClientGroupID into text format according to NeoFS API V2 protocol:
|
||||||
// value in base-10 integer string format.
|
// value in base-10 integer string format.
|
||||||
//
|
//
|
||||||
// It implements encoding.TextMarshaler.
|
// It implements encoding.TextMarshaler.
|
||||||
|
@ -28,7 +28,7 @@ func (x *SubnetClientGroupID) MarshalText() ([]byte, error) {
|
||||||
return []byte(strconv.FormatUint(uint64(num), 10)), nil
|
return []byte(strconv.FormatUint(uint64(num), 10)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalText decodes the SubnetID from the text according to FrostFS API V2 protocol:
|
// UnmarshalText decodes the SubnetID from the text according to NeoFS API V2 protocol:
|
||||||
// should be base-10 integer string format with bitsize = 32.
|
// should be base-10 integer string format with bitsize = 32.
|
||||||
//
|
//
|
||||||
// Returns strconv.ErrRange if integer overflows uint32.
|
// Returns strconv.ErrRange if integer overflows uint32.
|
||||||
|
@ -47,13 +47,13 @@ func (x *SubnetClientGroupID) UnmarshalText(txt []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marshal encodes the SubnetClientGroupID into a binary format of FrostFS API V2 protocol
|
// Marshal encodes the SubnetClientGroupID into a binary format of NeoFS API V2 protocol
|
||||||
// (Protocol Buffers with direct field order).
|
// (Protocol Buffers with direct field order).
|
||||||
func (x *SubnetClientGroupID) Marshal() ([]byte, error) {
|
func (x *SubnetClientGroupID) Marshal() ([]byte, error) {
|
||||||
return proto.Marshal(x)
|
return proto.Marshal(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal decodes the SubnetClientGroupID from FrostFS API V2 binary format (see Marshal). Must not be called on nil.
|
// Unmarshal decodes the SubnetClientGroupID from NeoFS API V2 binary format (see Marshal). Must not be called on nil.
|
||||||
func (x *SubnetClientGroupID) Unmarshal(data []byte) error {
|
func (x *SubnetClientGroupID) Unmarshal(data []byte) error {
|
||||||
return proto.Unmarshal(data, x)
|
return proto.Unmarshal(data, x)
|
||||||
}
|
}
|
BIN
cmd/neofs-adm/internal/modules/morph/internal/types.pb.go
generated
Normal file
BIN
cmd/neofs-adm/internal/modules/morph/internal/types.pb.go
generated
Normal file
Binary file not shown.
|
@ -2,9 +2,9 @@ syntax = "proto3";
|
||||||
|
|
||||||
package neo.fs.v2.refs;
|
package neo.fs.v2.refs;
|
||||||
|
|
||||||
option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/internal";
|
option go_package = "github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/morph/internal";
|
||||||
|
|
||||||
// Client group identifier in the FrostFS subnet.
|
// Client group identifier in the NeoFS subnet.
|
||||||
//
|
//
|
||||||
// String representation of a value is base-10 integer.
|
// String representation of a value is base-10 integer.
|
||||||
//
|
//
|
|
@ -1,12 +1,12 @@
|
||||||
package morph
|
package morph
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"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/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
||||||
|
@ -57,7 +56,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bc, err := core.NewBlockchain(storage.NewMemoryStore(), cfg.Blockchain(), zap.NewNop())
|
bc, err := core.NewBlockchain(storage.NewMemoryStore(), cfg.ProtocolConfiguration, zap.NewNop())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -82,7 +81,9 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet
|
||||||
return indexMap[string(pi)] < indexMap[string(pj)]
|
return indexMap[string(pi)] < indexMap[string(pj)]
|
||||||
})
|
})
|
||||||
sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool {
|
sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool {
|
||||||
return accounts[i].PublicKey().Cmp(accounts[j].PublicKey()) == -1
|
pi := accounts[i].PrivateKey().PublicKey().Bytes()
|
||||||
|
pj := accounts[j].PrivateKey().PublicKey().Bytes()
|
||||||
|
return bytes.Compare(pi, pj) == -1
|
||||||
})
|
})
|
||||||
|
|
||||||
go bc.Run()
|
go bc.Run()
|
||||||
|
@ -190,7 +191,7 @@ func (l *localClient) GetCommittee() (keys.PublicKeys, error) {
|
||||||
func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
|
func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
pp := make([]any, len(sPrm))
|
pp := make([]interface{}, len(sPrm))
|
||||||
for i, p := range sPrm {
|
for i, p := range sPrm {
|
||||||
pp[i], err = smartcontract.ExpandParameterToEmitable(p)
|
pp[i], err = smartcontract.ExpandParameterToEmitable(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -228,24 +229,7 @@ func (l *localClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item,
|
||||||
|
|
||||||
// GetVersion return default version.
|
// GetVersion return default version.
|
||||||
func (l *localClient) GetVersion() (*result.Version, error) {
|
func (l *localClient) GetVersion() (*result.Version, error) {
|
||||||
c := l.bc.GetConfig()
|
return &result.Version{}, nil
|
||||||
return &result.Version{
|
|
||||||
Protocol: result.Protocol{
|
|
||||||
AddressVersion: address.NEO3Prefix,
|
|
||||||
Network: c.Magic,
|
|
||||||
MillisecondsPerBlock: int(c.TimePerBlock / time.Millisecond),
|
|
||||||
MaxTraceableBlocks: c.MaxTraceableBlocks,
|
|
||||||
MaxValidUntilBlockIncrement: c.MaxValidUntilBlockIncrement,
|
|
||||||
MaxTransactionsPerBlock: c.MaxTransactionsPerBlock,
|
|
||||||
MemoryPoolMaxTransactions: c.MemPoolSize,
|
|
||||||
ValidatorsCount: byte(c.ValidatorsCount),
|
|
||||||
InitialGasDistribution: c.InitialGASSupply,
|
|
||||||
CommitteeHistory: c.CommitteeHistory,
|
|
||||||
P2PSigExtensions: c.P2PSigExtensions,
|
|
||||||
StateRootInHeader: c.StateRootInHeader,
|
|
||||||
ValidatorsHistory: c.ValidatorsHistory,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *localClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
|
func (l *localClient) InvokeContractVerify(contract util.Uint160, params []smartcontract.Parameter, signers []transaction.Signer, witnesses ...transaction.Witness) (*result.Invoke, error) {
|
||||||
|
@ -346,7 +330,7 @@ func getSigners(sender *wallet.Account, cosigners []rpcclient.SignerAccount) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *localClient) NEP17BalanceOf(h util.Uint160, acc util.Uint160) (int64, error) {
|
func (l *localClient) NEP17BalanceOf(h util.Uint160, acc util.Uint160) (int64, error) {
|
||||||
res, err := invokeFunction(l, h, "balanceOf", []any{acc}, nil)
|
res, err := invokeFunction(l, h, "balanceOf", []interface{}{acc}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -451,7 +435,7 @@ func (l *localClient) putTransactions() error {
|
||||||
return l.bc.AddBlock(b)
|
return l.bc.AddBlock(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) {
|
func invokeFunction(c Client, h util.Uint160, method string, parameters []interface{}, signers []transaction.Signer) (*result.Invoke, error) {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.Array(w.BinWriter, parameters...)
|
emit.Array(w.BinWriter, parameters...)
|
||||||
emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All)
|
emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All)
|
|
@ -6,13 +6,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"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/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/notary"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -22,7 +21,6 @@ import (
|
||||||
// https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/native/notary.go#L48
|
// https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/native/notary.go#L48
|
||||||
const defaultNotaryDepositLifetime = 5760
|
const defaultNotaryDepositLifetime = 5760
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func depositNotary(cmd *cobra.Command, _ []string) error {
|
func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
p, err := cmd.Flags().GetString(storageWalletFlag)
|
p, err := cmd.Flags().GetString(storageWalletFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,8 +84,18 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := checkNotaryEnabled(c); err != nil {
|
nhs, err := getNativeHashes(c)
|
||||||
return err
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't get native contract hashes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gasHash, ok := nhs[nativenames.Gas]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't retrieve %s contract hash", nativenames.Gas)
|
||||||
|
}
|
||||||
|
notaryHash, ok := nhs[nativenames.Notary]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("can't retrieve %s contract hash", nativenames.Notary)
|
||||||
}
|
}
|
||||||
|
|
||||||
height, err := c.GetBlockCount()
|
height, err := c.GetBlockCount()
|
||||||
|
@ -106,13 +114,13 @@ func depositNotary(cmd *cobra.Command, _ []string) error {
|
||||||
return fmt.Errorf("could not create actor: %w", err)
|
return fmt.Errorf("could not create actor: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gasActor := nep17.New(act, gas.Hash)
|
gas := nep17.New(act, gasHash)
|
||||||
|
|
||||||
txHash, vub, err := gasActor.Transfer(
|
txHash, vub, err := gas.Transfer(
|
||||||
accHash,
|
accHash,
|
||||||
notary.Hash,
|
notaryHash,
|
||||||
big.NewInt(int64(gasAmount)),
|
big.NewInt(int64(gasAmount)),
|
||||||
[]any{nil, int64(height) + till},
|
[]interface{}{nil, int64(height) + till},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not send tx: %w", err)
|
return fmt.Errorf("could not send tx: %w", err)
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/policy"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -25,25 +25,27 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("can't to initialize context: %w", err)
|
return fmt.Errorf("can't to initialize context: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
policyHash := wCtx.nativeHash(nativenames.Policy)
|
||||||
|
|
||||||
bw := io.NewBufBinWriter()
|
bw := io.NewBufBinWriter()
|
||||||
for i := range args {
|
for i := range args {
|
||||||
k, v, found := strings.Cut(args[i], "=")
|
kv := strings.SplitN(args[i], "=", 2)
|
||||||
if !found {
|
if len(kv) != 2 {
|
||||||
return fmt.Errorf("invalid parameter format, must be Parameter=Value")
|
return fmt.Errorf("invalid parameter format, must be Parameter=Value")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch k {
|
switch kv[0] {
|
||||||
case execFeeParam, storagePriceParam, setFeeParam:
|
case execFeeParam, storagePriceParam, setFeeParam:
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam)
|
return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
value, err := strconv.ParseUint(v, 10, 32)
|
value, err := strconv.ParseUint(kv[1], 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err)
|
return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value))
|
emit.AppCall(bw.BinWriter, policyHash, "set"+kv[0], callflag.All, int64(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {
|
if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil {
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||||
|
netmapcontract "github.com/nspcc-dev/neofs-contract/netmap"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error {
|
||||||
return fmt.Errorf("can't get NNS contract info: %w", err)
|
return fmt.Errorf("can't get NNS contract info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs")
|
nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
return fmt.Errorf("can't get netmap contract hash: %w", err)
|
||||||
}
|
}
|
|
@ -108,7 +108,7 @@ var (
|
||||||
|
|
||||||
forceNewEpoch = &cobra.Command{
|
forceNewEpoch = &cobra.Command{
|
||||||
Use: "force-new-epoch",
|
Use: "force-new-epoch",
|
||||||
Short: "Create new FrostFS epoch event in the side chain",
|
Short: "Create new NeoFS epoch event in the side chain",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
|
@ -130,7 +130,7 @@ var (
|
||||||
setConfig = &cobra.Command{
|
setConfig = &cobra.Command{
|
||||||
Use: "set-config key1=val1 [key2=val2 ...]",
|
Use: "set-config key1=val1 [key2=val2 ...]",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Short: "Add/update global config value in the FrostFS network",
|
Short: "Add/update global config value in the NeoFS network",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
|
@ -164,7 +164,7 @@ var (
|
||||||
|
|
||||||
dumpNetworkConfigCmd = &cobra.Command{
|
dumpNetworkConfigCmd = &cobra.Command{
|
||||||
Use: "dump-config",
|
Use: "dump-config",
|
||||||
Short: "Dump FrostFS network config",
|
Short: "Dump NeoFS network config",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
},
|
},
|
||||||
|
@ -182,7 +182,7 @@ var (
|
||||||
|
|
||||||
updateContractsCmd = &cobra.Command{
|
updateContractsCmd = &cobra.Command{
|
||||||
Use: "update-contracts",
|
Use: "update-contracts",
|
||||||
Short: "Update FrostFS contracts",
|
Short: "Update NeoFS contracts",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
|
@ -192,7 +192,7 @@ var (
|
||||||
|
|
||||||
dumpContainersCmd = &cobra.Command{
|
dumpContainersCmd = &cobra.Command{
|
||||||
Use: "dump-containers",
|
Use: "dump-containers",
|
||||||
Short: "Dump FrostFS containers to file",
|
Short: "Dump NeoFS containers to file",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
},
|
},
|
||||||
|
@ -201,7 +201,7 @@ var (
|
||||||
|
|
||||||
restoreContainersCmd = &cobra.Command{
|
restoreContainersCmd = &cobra.Command{
|
||||||
Use: "restore-containers",
|
Use: "restore-containers",
|
||||||
Short: "Restore FrostFS containers from file",
|
Short: "Restore NeoFS containers from file",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
||||||
|
@ -209,15 +209,6 @@ var (
|
||||||
RunE: restoreContainers,
|
RunE: restoreContainers,
|
||||||
}
|
}
|
||||||
|
|
||||||
listContainersCmd = &cobra.Command{
|
|
||||||
Use: "list-containers",
|
|
||||||
Short: "List FrostFS containers",
|
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
|
||||||
},
|
|
||||||
RunE: listContainers,
|
|
||||||
}
|
|
||||||
|
|
||||||
depositNotaryCmd = &cobra.Command{
|
depositNotaryCmd = &cobra.Command{
|
||||||
Use: "deposit-notary",
|
Use: "deposit-notary",
|
||||||
Short: "Deposit GAS for notary service",
|
Short: "Deposit GAS for notary service",
|
||||||
|
@ -226,19 +217,8 @@ var (
|
||||||
},
|
},
|
||||||
RunE: depositNotary,
|
RunE: depositNotary,
|
||||||
}
|
}
|
||||||
|
|
||||||
netmapCandidatesCmd = &cobra.Command{
|
|
||||||
Use: "netmap-candidates",
|
|
||||||
Short: "List netmap candidates nodes",
|
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
|
||||||
_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
|
|
||||||
_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
|
|
||||||
},
|
|
||||||
Run: listNetmapCandidatesNodes,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func init() {
|
func init() {
|
||||||
RootCmd.AddCommand(generateAlphabetCmd)
|
RootCmd.AddCommand(generateAlphabetCmd)
|
||||||
generateAlphabetCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
generateAlphabetCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
||||||
|
@ -247,8 +227,8 @@ func init() {
|
||||||
RootCmd.AddCommand(initCmd)
|
RootCmd.AddCommand(initCmd)
|
||||||
initCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
initCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
||||||
initCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
initCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
initCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts (default fetched from latest github release)")
|
initCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled NeoFS contracts (default fetched from latest github release)")
|
||||||
initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch")
|
initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one NeoFS epoch")
|
||||||
initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes")
|
initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes")
|
||||||
initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing")
|
initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing")
|
||||||
// Defaults are taken from neo-preodolenie.
|
// Defaults are taken from neo-preodolenie.
|
||||||
|
@ -300,7 +280,7 @@ func init() {
|
||||||
RootCmd.AddCommand(updateContractsCmd)
|
RootCmd.AddCommand(updateContractsCmd)
|
||||||
updateContractsCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
updateContractsCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
||||||
updateContractsCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
updateContractsCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
updateContractsCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts (default fetched from latest github release)")
|
updateContractsCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled NeoFS contracts (default fetched from latest github release)")
|
||||||
|
|
||||||
RootCmd.AddCommand(dumpContainersCmd)
|
RootCmd.AddCommand(dumpContainersCmd)
|
||||||
dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
|
@ -314,10 +294,6 @@ func init() {
|
||||||
restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from")
|
restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from")
|
||||||
restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore")
|
restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore")
|
||||||
|
|
||||||
RootCmd.AddCommand(listContainersCmd)
|
|
||||||
listContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
|
||||||
listContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)")
|
|
||||||
|
|
||||||
RootCmd.AddCommand(refillGasCmd)
|
RootCmd.AddCommand(refillGasCmd)
|
||||||
refillGasCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
refillGasCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir")
|
||||||
refillGasCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
refillGasCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
||||||
|
@ -334,7 +310,4 @@ func init() {
|
||||||
depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
|
depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address")
|
||||||
depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit")
|
depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit")
|
||||||
depositNotaryCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks")
|
depositNotaryCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks")
|
||||||
|
|
||||||
RootCmd.AddCommand(netmapCandidatesCmd)
|
|
||||||
netmapCandidatesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
|
|
||||||
}
|
}
|
|
@ -5,12 +5,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/internal"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/subnet"
|
|
||||||
subnetid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/subnet/id"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
@ -26,6 +20,12 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/morph/internal"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/util/rand"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/subnet"
|
||||||
|
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/user"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
@ -39,7 +39,7 @@ func viperBindFlags(cmd *cobra.Command, flags ...string) {
|
||||||
// subnet command section.
|
// subnet command section.
|
||||||
var cmdSubnet = &cobra.Command{
|
var cmdSubnet = &cobra.Command{
|
||||||
Use: "subnet",
|
Use: "subnet",
|
||||||
Short: "FrostFS subnet management",
|
Short: "NeoFS subnet management",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
endpointFlag,
|
endpointFlag,
|
||||||
|
@ -112,7 +112,7 @@ func readSubnetKey(key *keys.PrivateKey) error {
|
||||||
// create subnet command.
|
// create subnet command.
|
||||||
var cmdSubnetCreate = &cobra.Command{
|
var cmdSubnetCreate = &cobra.Command{
|
||||||
Use: "create",
|
Use: "create",
|
||||||
Short: "Create FrostFS subnet",
|
Short: "Create NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetWallet,
|
flagSubnetWallet,
|
||||||
|
@ -177,7 +177,7 @@ var errZeroSubnet = errors.New("zero subnet")
|
||||||
// remove subnet command.
|
// remove subnet command.
|
||||||
var cmdSubnetRemove = &cobra.Command{
|
var cmdSubnetRemove = &cobra.Command{
|
||||||
Use: "remove",
|
Use: "remove",
|
||||||
Short: "Remove FrostFS subnet",
|
Short: "Remove NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetWallet,
|
flagSubnetWallet,
|
||||||
|
@ -226,7 +226,7 @@ const (
|
||||||
// get subnet command.
|
// get subnet command.
|
||||||
var cmdSubnetGet = &cobra.Command{
|
var cmdSubnetGet = &cobra.Command{
|
||||||
Use: "get",
|
Use: "get",
|
||||||
Short: "Read information about the FrostFS subnet",
|
Short: "Read information about the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetGetID,
|
flagSubnetGetID,
|
||||||
|
@ -290,7 +290,7 @@ const (
|
||||||
// command to manage subnet admins.
|
// command to manage subnet admins.
|
||||||
var cmdSubnetAdmin = &cobra.Command{
|
var cmdSubnetAdmin = &cobra.Command{
|
||||||
Use: "admin",
|
Use: "admin",
|
||||||
Short: "Manage administrators of the FrostFS subnet",
|
Short: "Manage administrators of the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetWallet,
|
flagSubnetWallet,
|
||||||
|
@ -307,8 +307,6 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// common executor cmdSubnetAdminAdd and cmdSubnetAdminRemove commands.
|
// common executor cmdSubnetAdminAdd and cmdSubnetAdminRemove commands.
|
||||||
//
|
|
||||||
// nolint: funlen
|
|
||||||
func manageSubnetAdmins(cmd *cobra.Command, rm bool) error {
|
func manageSubnetAdmins(cmd *cobra.Command, rm bool) error {
|
||||||
// read private key
|
// read private key
|
||||||
var key keys.PrivateKey
|
var key keys.PrivateKey
|
||||||
|
@ -342,7 +340,7 @@ func manageSubnetAdmins(cmd *cobra.Command, rm bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare call parameters
|
// prepare call parameters
|
||||||
prm := make([]any, 0, 3)
|
prm := make([]interface{}, 0, 3)
|
||||||
prm = append(prm, id.Marshal())
|
prm = append(prm, id.Marshal())
|
||||||
|
|
||||||
var method string
|
var method string
|
||||||
|
@ -399,7 +397,7 @@ func manageSubnetAdmins(cmd *cobra.Command, rm bool) error {
|
||||||
// command to add subnet admin.
|
// command to add subnet admin.
|
||||||
var cmdSubnetAdminAdd = &cobra.Command{
|
var cmdSubnetAdminAdd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Add admin to the FrostFS subnet",
|
Short: "Add admin to the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetAdminAddGroup,
|
flagSubnetAdminAddGroup,
|
||||||
|
@ -414,7 +412,7 @@ var cmdSubnetAdminAdd = &cobra.Command{
|
||||||
// command to remove subnet admin.
|
// command to remove subnet admin.
|
||||||
var cmdSubnetAdminRemove = &cobra.Command{
|
var cmdSubnetAdminRemove = &cobra.Command{
|
||||||
Use: "remove",
|
Use: "remove",
|
||||||
Short: "Remove admin of the FrostFS subnet",
|
Short: "Remove admin of the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetAdminClient,
|
flagSubnetAdminClient,
|
||||||
|
@ -435,7 +433,7 @@ const (
|
||||||
// command to manage subnet clients.
|
// command to manage subnet clients.
|
||||||
var cmdSubnetClient = &cobra.Command{
|
var cmdSubnetClient = &cobra.Command{
|
||||||
Use: "client",
|
Use: "client",
|
||||||
Short: "Manage clients of the FrostFS subnet",
|
Short: "Manage clients of the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetWallet,
|
flagSubnetWallet,
|
||||||
|
@ -518,7 +516,7 @@ func manageSubnetClients(cmd *cobra.Command, rm bool) error {
|
||||||
// command to add subnet client.
|
// command to add subnet client.
|
||||||
var cmdSubnetClientAdd = &cobra.Command{
|
var cmdSubnetClientAdd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Add client to the FrostFS subnet",
|
Short: "Add client to the NeoFS subnet",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return manageSubnetClients(cmd, false)
|
return manageSubnetClients(cmd, false)
|
||||||
},
|
},
|
||||||
|
@ -527,7 +525,7 @@ var cmdSubnetClientAdd = &cobra.Command{
|
||||||
// command to remove subnet client.
|
// command to remove subnet client.
|
||||||
var cmdSubnetClientRemove = &cobra.Command{
|
var cmdSubnetClientRemove = &cobra.Command{
|
||||||
Use: "remove",
|
Use: "remove",
|
||||||
Short: "Remove client of the FrostFS subnet",
|
Short: "Remove client of the NeoFS subnet",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return manageSubnetClients(cmd, true)
|
return manageSubnetClients(cmd, true)
|
||||||
},
|
},
|
||||||
|
@ -600,7 +598,7 @@ func manageSubnetNodes(cmd *cobra.Command, rm bool) error {
|
||||||
// command to manage subnet nodes.
|
// command to manage subnet nodes.
|
||||||
var cmdSubnetNode = &cobra.Command{
|
var cmdSubnetNode = &cobra.Command{
|
||||||
Use: "node",
|
Use: "node",
|
||||||
Short: "Manage nodes of the FrostFS subnet",
|
Short: "Manage nodes of the NeoFS subnet",
|
||||||
PreRun: func(cmd *cobra.Command, _ []string) {
|
PreRun: func(cmd *cobra.Command, _ []string) {
|
||||||
viperBindFlags(cmd,
|
viperBindFlags(cmd,
|
||||||
flagSubnetWallet,
|
flagSubnetWallet,
|
||||||
|
@ -613,7 +611,7 @@ var cmdSubnetNode = &cobra.Command{
|
||||||
// command to add subnet node.
|
// command to add subnet node.
|
||||||
var cmdSubnetNodeAdd = &cobra.Command{
|
var cmdSubnetNodeAdd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Add node to the FrostFS subnet",
|
Short: "Add node to the NeoFS subnet",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return manageSubnetNodes(cmd, false)
|
return manageSubnetNodes(cmd, false)
|
||||||
},
|
},
|
||||||
|
@ -622,7 +620,7 @@ var cmdSubnetNodeAdd = &cobra.Command{
|
||||||
// command to remove subnet node.
|
// command to remove subnet node.
|
||||||
var cmdSubnetNodeRemove = &cobra.Command{
|
var cmdSubnetNodeRemove = &cobra.Command{
|
||||||
Use: "remove",
|
Use: "remove",
|
||||||
Short: "Remove node from the FrostFS subnet",
|
Short: "Remove node from the NeoFS subnet",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
return manageSubnetNodes(cmd, true)
|
return manageSubnetNodes(cmd, true)
|
||||||
},
|
},
|
||||||
|
@ -653,8 +651,6 @@ func addCommandInheritPreRun(par *cobra.Command, subs ...*cobra.Command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// registers flags and binds sub-commands for subnet commands.
|
// registers flags and binds sub-commands for subnet commands.
|
||||||
//
|
|
||||||
// nolint: funlen
|
|
||||||
func init() {
|
func init() {
|
||||||
cmdSubnetCreate.Flags().StringP(flagSubnetWallet, "w", "", "Path to file with wallet")
|
cmdSubnetCreate.Flags().StringP(flagSubnetWallet, "w", "", "Path to file with wallet")
|
||||||
_ = cmdSubnetCreate.MarkFlagRequired(flagSubnetWallet)
|
_ = cmdSubnetCreate.MarkFlagRequired(flagSubnetWallet)
|
||||||
|
@ -697,7 +693,7 @@ func init() {
|
||||||
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientSubnet)
|
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientSubnet)
|
||||||
clientFlags.String(flagSubnetClientGroup, "", "ID of the client group to work with")
|
clientFlags.String(flagSubnetClientGroup, "", "ID of the client group to work with")
|
||||||
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientGroup)
|
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientGroup)
|
||||||
clientFlags.String(flagSubnetClientID, "", "Client's user ID in FrostFS system in text format")
|
clientFlags.String(flagSubnetClientID, "", "Client's user ID in NeoFS system in text format")
|
||||||
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientID)
|
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetClientID)
|
||||||
clientFlags.StringP(flagSubnetWallet, "w", "", "Path to file with wallet")
|
clientFlags.StringP(flagSubnetWallet, "w", "", "Path to file with wallet")
|
||||||
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetWallet)
|
_ = cmdSubnetClient.MarkFlagRequired(flagSubnetWallet)
|
||||||
|
@ -746,7 +742,7 @@ func init() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testInvokeMethod(key keys.PrivateKey, method string, args ...any) ([]stackitem.Item, error) {
|
func testInvokeMethod(key keys.PrivateKey, method string, args ...interface{}) ([]stackitem.Item, error) {
|
||||||
c, err := getN3Client(viper.GetViper())
|
c, err := getN3Client(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("morph client creation: %w", err)
|
return nil, fmt.Errorf("morph client creation: %w", err)
|
||||||
|
@ -766,7 +762,7 @@ func testInvokeMethod(key keys.PrivateKey, method string, args ...any) ([]stacki
|
||||||
|
|
||||||
inv := invoker.New(c, cosigner)
|
inv := invoker.New(c, cosigner)
|
||||||
|
|
||||||
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".frostfs")
|
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("subnet hash resolving: %w", err)
|
return nil, fmt.Errorf("subnet hash resolving: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -784,7 +780,7 @@ func testInvokeMethod(key keys.PrivateKey, method string, args ...any) ([]stacki
|
||||||
return res.Stack, nil
|
return res.Stack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...any) error {
|
func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...interface{}) error {
|
||||||
c, err := getN3Client(viper.GetViper())
|
c, err := getN3Client(viper.GetViper())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("morph client creation: %w", err)
|
return fmt.Errorf("morph client creation: %w", err)
|
||||||
|
@ -825,7 +821,7 @@ func invokeMethod(key keys.PrivateKey, tryNotary bool, method string, args ...an
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...any) error {
|
func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...interface{}) error {
|
||||||
nnsCs, err := c.GetContractStateByID(1)
|
nnsCs, err := c.GetContractStateByID(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("NNS contract resolving: %w", err)
|
return fmt.Errorf("NNS contract resolving: %w", err)
|
||||||
|
@ -849,7 +845,7 @@ func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...any)
|
||||||
|
|
||||||
inv := invoker.New(c, cosigner)
|
inv := invoker.New(c, cosigner)
|
||||||
|
|
||||||
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".frostfs")
|
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("subnet hash resolving: %w", err)
|
return fmt.Errorf("subnet hash resolving: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -872,8 +868,7 @@ func invokeNonNotary(c Client, key keys.PrivateKey, method string, args ...any)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.Uint160, args ...interface{}) error {
|
||||||
func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.Uint160, args ...any) error {
|
|
||||||
nnsCs, err := c.GetContractStateByID(1)
|
nnsCs, err := c.GetContractStateByID(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("NNS contract resolving: %w", err)
|
return fmt.Errorf("NNS contract resolving: %w", err)
|
||||||
|
@ -896,7 +891,7 @@ func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.
|
||||||
|
|
||||||
inv := invoker.New(c, cosigners)
|
inv := invoker.New(c, cosigners)
|
||||||
|
|
||||||
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".frostfs")
|
subnetHash, err := nnsResolveHash(inv, nnsCs.Hash, subnetContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("subnet hash resolving: %w", err)
|
return fmt.Errorf("subnet hash resolving: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -973,7 +968,7 @@ func invokeNotary(c Client, key keys.PrivateKey, method string, notaryHash util.
|
||||||
|
|
||||||
func notaryCosigners(c Client, notaryHash util.Uint160, nnsCs *state.Contract,
|
func notaryCosigners(c Client, notaryHash util.Uint160, nnsCs *state.Contract,
|
||||||
key keys.PrivateKey, alphabetAccount util.Uint160) ([]transaction.Signer, error) {
|
key keys.PrivateKey, alphabetAccount util.Uint160) ([]transaction.Signer, error) {
|
||||||
proxyHash, err := nnsResolveHash(invoker.New(c, nil), nnsCs.Hash, proxyContract+".frostfs")
|
proxyHash, err := nnsResolveHash(invoker.New(c, nil), nnsCs.Hash, proxyContract+".neofs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("proxy hash resolving: %w", err)
|
return nil, fmt.Errorf("proxy hash resolving: %w", err)
|
||||||
}
|
}
|
71
cmd/neofs-adm/internal/modules/root.go
Normal file
71
cmd/neofs-adm/internal/modules/root.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/config"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/morph"
|
||||||
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules/storagecfg"
|
||||||
|
"github.com/nspcc-dev/neofs-node/misc"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/util/autocomplete"
|
||||||
|
"github.com/nspcc-dev/neofs-node/pkg/util/gendoc"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rootCmd = &cobra.Command{
|
||||||
|
Use: "neofs-adm",
|
||||||
|
Short: "NeoFS Administrative Tool",
|
||||||
|
Long: `NeoFS Administrative Tool provides functions to setup and
|
||||||
|
manage NeoFS network deployment.`,
|
||||||
|
RunE: entryPoint,
|
||||||
|
SilenceUsage: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
configFlag = "config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cobra.OnInitialize(func() { initConfig(rootCmd) })
|
||||||
|
// we need to init viper config to bind viper and cobra configurations for
|
||||||
|
// rpc endpoint, alphabet wallet dir, key credentials, etc.
|
||||||
|
|
||||||
|
// use stdout as default output for cmd.Print()
|
||||||
|
rootCmd.SetOut(os.Stdout)
|
||||||
|
|
||||||
|
rootCmd.PersistentFlags().StringP(configFlag, "c", "", "Config file")
|
||||||
|
rootCmd.Flags().Bool("version", false, "Application version")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(config.RootCmd)
|
||||||
|
rootCmd.AddCommand(morph.RootCmd)
|
||||||
|
rootCmd.AddCommand(storagecfg.RootCmd)
|
||||||
|
|
||||||
|
rootCmd.AddCommand(autocomplete.Command("neofs-adm"))
|
||||||
|
rootCmd.AddCommand(gendoc.Command(rootCmd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute() error {
|
||||||
|
return rootCmd.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
|
func entryPoint(cmd *cobra.Command, args []string) error {
|
||||||
|
printVersion, _ := cmd.Flags().GetBool("version")
|
||||||
|
if printVersion {
|
||||||
|
cmd.Print(misc.BuildInfo("NeoFS Adm"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd.Usage()
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig(cmd *cobra.Command) {
|
||||||
|
configFile, err := cmd.Flags().GetString(configFlag)
|
||||||
|
if err != nil || configFile == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.SetConfigType("yml")
|
||||||
|
viper.SetConfigFile(configFile)
|
||||||
|
_ = viper.ReadInConfig() // if config file is set but unavailable, ignore it
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ node:
|
||||||
relay: {{ .Relay }} # start Storage node in relay mode without bootstrapping into the Network map
|
relay: {{ .Relay }} # start Storage node in relay mode without bootstrapping into the Network map
|
||||||
subnet:
|
subnet:
|
||||||
exit_zero: false # toggle entrance to zero subnet (overrides corresponding attribute and occurrence in entries)
|
exit_zero: false # toggle entrance to zero subnet (overrides corresponding attribute and occurrence in entries)
|
||||||
entries: [] # list of IDs of subnets to enter in a text format of FrostFS API protocol (overrides corresponding attributes)
|
entries: [] # list of IDs of subnets to enter in a text format of NeoFS API protocol (overrides corresponding attributes)
|
||||||
|
|
||||||
grpc:
|
grpc:
|
||||||
num: 1 # total number of listener endpoints
|
num: 1 # total number of listener endpoints
|
|
@ -16,20 +16,20 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
netutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
|
||||||
"github.com/chzyer/readline"
|
"github.com/chzyer/readline"
|
||||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||||
"github.com/nspcc-dev/neo-go/cli/input"
|
"github.com/nspcc-dev/neo-go/cli/input"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"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/encoding/address"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/gas"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
"github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||||
|
netutil "github.com/nspcc-dev/neofs-node/pkg/network"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -79,7 +79,6 @@ type config struct {
|
||||||
MetabasePath string
|
MetabasePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: funlen
|
|
||||||
func storageConfig(cmd *cobra.Command, args []string) {
|
func storageConfig(cmd *cobra.Command, args []string) {
|
||||||
var outPath string
|
var outPath string
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
|
@ -91,7 +90,7 @@ func storageConfig(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
historyPath := filepath.Join(os.TempDir(), "frostfs-adm.history")
|
historyPath := filepath.Join(os.TempDir(), "neofs-adm.history")
|
||||||
readline.SetHistoryPath(historyPath)
|
readline.SetHistoryPath(historyPath)
|
||||||
|
|
||||||
var c config
|
var c config
|
||||||
|
@ -154,7 +153,7 @@ func storageConfig(cmd *cobra.Command, args []string) {
|
||||||
validator := netutil.Address{}
|
validator := netutil.Address{}
|
||||||
err := validator.FromString(c.AnnouncedAddress)
|
err := validator.FromString(c.AnnouncedAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cmd.Println("Incorrect address format. See https://git.frostfs.info/TrueCloudLab/frostfs-node/src/branch/master/pkg/network/address.go for details.")
|
cmd.Println("Incorrect address format. See https://github.com/nspcc-dev/neofs-node/blob/master/pkg/network/address.go for details.")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
uriAddr, err := url.Parse(validator.URIAddr())
|
uriAddr, err := url.Parse(validator.URIAddr())
|
||||||
|
@ -210,7 +209,7 @@ func storageConfig(cmd *cobra.Command, args []string) {
|
||||||
out := applyTemplate(c)
|
out := applyTemplate(c)
|
||||||
fatalOnErr(os.WriteFile(outPath, out, 0644))
|
fatalOnErr(os.WriteFile(outPath, out, 0644))
|
||||||
|
|
||||||
cmd.Println("Node is ready for work! Run `frostfs-node -config " + outPath + "`")
|
cmd.Println("Node is ready for work! Run `neofs-node -config " + outPath + "`")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWalletAccount(w *wallet.Wallet, prompt string) string {
|
func getWalletAccount(w *wallet.Wallet, prompt string) string {
|
||||||
|
@ -350,12 +349,17 @@ func depositGas(cmd *cobra.Command, acc *wallet.Account, network string) {
|
||||||
mainClient := initClient(n3config[network].RPC)
|
mainClient := initClient(n3config[network].RPC)
|
||||||
neofsHash, _ := util.Uint160DecodeStringLE(n3config[network].NeoFSContract)
|
neofsHash, _ := util.Uint160DecodeStringLE(n3config[network].NeoFSContract)
|
||||||
|
|
||||||
|
gasHash, err := mainClient.GetNativeContractHash(nativenames.Gas)
|
||||||
|
if err != nil {
|
||||||
|
fatalOnErr(fmt.Errorf("gas contract hash: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
mainActor, err := actor.NewSimple(mainClient, acc)
|
mainActor, err := actor.NewSimple(mainClient, acc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalOnErr(fmt.Errorf("creating actor over main chain client: %w", err))
|
fatalOnErr(fmt.Errorf("creating actor over main chain client: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
mainGas := nep17.New(mainActor, gas.Hash)
|
mainGas := nep17.New(mainActor, gasHash)
|
||||||
|
|
||||||
txHash, _, err := mainGas.Transfer(accSH, neofsHash, amount, nil)
|
txHash, _, err := mainGas.Transfer(accSH, neofsHash, amount, nil)
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -3,7 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules"
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
|
@ -1,8 +1,8 @@
|
||||||
# How FrostFS CLI uses session mechanism of the FrostFS
|
# How NeoFS CLI uses session mechanism of the NeoFS
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
FrostFS sessions implement a mechanism for issuing a power of attorney by one
|
NeoFS sessions implement a mechanism for issuing a power of attorney by one
|
||||||
party to another. A trusted party can provide a so-called session token as
|
party to another. A trusted party can provide a so-called session token as
|
||||||
proof of the right to act on behalf of another member of the network. The
|
proof of the right to act on behalf of another member of the network. The
|
||||||
client of operations carried out with such a token will be the user who opened
|
client of operations carried out with such a token will be the user who opened
|
||||||
|
@ -15,7 +15,7 @@ attached session token is treated as performed by the original client.
|
||||||
|
|
||||||
## Types
|
## Types
|
||||||
|
|
||||||
FrostFS CLI supports two ways to execute operation within a session depending on
|
NeoFS CLI supports two ways to execute operation within a session depending on
|
||||||
whether the user of the command application is an original user (1) or a trusted
|
whether the user of the command application is an original user (1) or a trusted
|
||||||
one (2).
|
one (2).
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ to the trusted server. At the moment, the approach is applicable only to
|
||||||
creating objects.
|
creating objects.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-cli session create --rpc-endpoint <server_ip> --out ./blank_token
|
$ neofs-cli session create --rpc-endpoint <server_ip> --out ./blank_token
|
||||||
```
|
```
|
||||||
After this example command remote node holds session private key while its
|
After this example command remote node holds session private key while its
|
||||||
public part is written into the session token encoded into the output file.
|
public part is written into the session token encoded into the output file.
|
||||||
|
@ -49,7 +49,7 @@ original client, and the CLI uses it only for reading. Ready token MUST have:
|
||||||
|
|
||||||
To sign the session token, exec:
|
To sign the session token, exec:
|
||||||
```shell
|
```shell
|
||||||
$ frostfs-cli --wallet <client_wallet> util sign session-token --from ./blank_token --to ./token
|
$ neofs-cli --wallet <client_wallet> util sign session-token --from ./blank_token --to ./token
|
||||||
```
|
```
|
||||||
Once the token is signed, it MUST NOT be modified.
|
Once the token is signed, it MUST NOT be modified.
|
||||||
|
|
|
@ -7,15 +7,15 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting"
|
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
containerSDK "github.com/nspcc-dev/neofs-sdk-go/container"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
"github.com/nspcc-dev/neofs-sdk-go/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BalanceOfPrm groups parameters of BalanceOf operation.
|
// BalanceOfPrm groups parameters of BalanceOf operation.
|
||||||
|
@ -34,7 +34,7 @@ func (x BalanceOfRes) Balance() accounting.Decimal {
|
||||||
return x.cliRes.Amount()
|
return x.cliRes.Amount()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceOf requests the current balance of a FrostFS user.
|
// BalanceOf requests the current balance of a NeoFS user.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) {
|
func BalanceOf(prm BalanceOfPrm) (res BalanceOfRes, err error) {
|
||||||
|
@ -59,7 +59,7 @@ func (x ListContainersRes) IDList() []cid.ID {
|
||||||
return x.cliRes.Containers()
|
return x.cliRes.Containers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListContainers requests a list of FrostFS user's containers.
|
// ListContainers requests a list of NeoFS user's containers.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) {
|
func ListContainers(prm ListContainersPrm) (res ListContainersRes, err error) {
|
||||||
|
@ -84,7 +84,7 @@ func (x PutContainerRes) ID() cid.ID {
|
||||||
return x.cnr
|
return x.cnr
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutContainer sends a request to save the container in FrostFS.
|
// PutContainer sends a request to save the container in NeoFS.
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and not guaranteed even in the absence of errors.
|
// Operation is asynchronous and not guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -122,7 +122,7 @@ func (x GetContainerRes) Container() containerSDK.Container {
|
||||||
return x.cliRes.Container()
|
return x.cliRes.Container()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainer reads a container from FrostFS by ID.
|
// GetContainer reads a container from NeoFS by ID.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) {
|
func GetContainer(prm GetContainerPrm) (res GetContainerRes, err error) {
|
||||||
|
@ -140,7 +140,7 @@ func IsACLExtendable(c *client.Client, cnr cid.ID) (bool, error) {
|
||||||
|
|
||||||
res, err := GetContainer(prm)
|
res, err := GetContainer(prm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("get container from the FrostFS: %w", err)
|
return false, fmt.Errorf("get container from the NeoFS: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.Container().BasicACL().Extendable(), nil
|
return res.Container().BasicACL().Extendable(), nil
|
||||||
|
@ -155,7 +155,7 @@ type DeleteContainerPrm struct {
|
||||||
// DeleteContainerRes groups the resulting values of DeleteContainer operation.
|
// DeleteContainerRes groups the resulting values of DeleteContainer operation.
|
||||||
type DeleteContainerRes struct{}
|
type DeleteContainerRes struct{}
|
||||||
|
|
||||||
// DeleteContainer sends a request to remove a container from FrostFS by ID.
|
// DeleteContainer sends a request to remove a container from NeoFS by ID.
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and not guaranteed even in the absence of errors.
|
// Operation is asynchronous and not guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -185,7 +185,7 @@ func (x EACLRes) EACL() eacl.Table {
|
||||||
return x.cliRes.Table()
|
return x.cliRes.Table()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EACL reads eACL table from FrostFS by container ID.
|
// EACL reads eACL table from NeoFS by container ID.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func EACL(prm EACLPrm) (res EACLRes, err error) {
|
func EACL(prm EACLPrm) (res EACLRes, err error) {
|
||||||
|
@ -203,7 +203,7 @@ type SetEACLPrm struct {
|
||||||
// SetEACLRes groups the resulting values of SetEACL operation.
|
// SetEACLRes groups the resulting values of SetEACL operation.
|
||||||
type SetEACLRes struct{}
|
type SetEACLRes struct{}
|
||||||
|
|
||||||
// SetEACL requests to save an eACL table in FrostFS.
|
// SetEACL requests to save an eACL table in NeoFS.
|
||||||
//
|
//
|
||||||
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
// Operation is asynchronous and no guaranteed even in the absence of errors.
|
||||||
// The required time is also not predictable.
|
// The required time is also not predictable.
|
||||||
|
@ -228,12 +228,12 @@ type NetworkInfoRes struct {
|
||||||
cliRes *client.ResNetworkInfo
|
cliRes *client.ResNetworkInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInfo returns structured information about the FrostFS network.
|
// NetworkInfo returns structured information about the NeoFS network.
|
||||||
func (x NetworkInfoRes) NetworkInfo() netmap.NetworkInfo {
|
func (x NetworkInfoRes) NetworkInfo() netmap.NetworkInfo {
|
||||||
return x.cliRes.Info()
|
return x.cliRes.Info()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkInfo reads information about the FrostFS network.
|
// NetworkInfo reads information about the NeoFS network.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) {
|
func NetworkInfo(prm NetworkInfoPrm) (res NetworkInfoRes, err error) {
|
||||||
|
@ -258,12 +258,12 @@ func (x NodeInfoRes) NodeInfo() netmap.NodeInfo {
|
||||||
return x.cliRes.NodeInfo()
|
return x.cliRes.NodeInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LatestVersion returns the latest FrostFS API version in use.
|
// LatestVersion returns the latest NeoFS API version in use.
|
||||||
func (x NodeInfoRes) LatestVersion() version.Version {
|
func (x NodeInfoRes) LatestVersion() version.Version {
|
||||||
return x.cliRes.LatestVersion()
|
return x.cliRes.LatestVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeInfo requests information about the remote server from FrostFS netmap.
|
// NodeInfo requests information about the remote server from NeoFS netmap.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) {
|
func NodeInfo(prm NodeInfoPrm) (res NodeInfoRes, err error) {
|
||||||
|
@ -282,7 +282,7 @@ type NetMapSnapshotRes struct {
|
||||||
cliRes *client.ResNetMapSnapshot
|
cliRes *client.ResNetMapSnapshot
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetMap returns current local snapshot of the FrostFS network map.
|
// NetMap returns current local snapshot of the NeoFS network map.
|
||||||
func (x NetMapSnapshotRes) NetMap() netmap.NetMap {
|
func (x NetMapSnapshotRes) NetMap() netmap.NetMap {
|
||||||
return x.cliRes.NetMap()
|
return x.cliRes.NetMap()
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ func (x PutObjectRes) ID() oid.ID {
|
||||||
return x.id
|
return x.id
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObject saves the object in FrostFS network.
|
// PutObject saves the object in NeoFS network.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func PutObject(prm PutObjectPrm) (*PutObjectRes, error) {
|
func PutObject(prm PutObjectPrm) (*PutObjectRes, error) {
|
||||||
|
@ -404,7 +404,8 @@ func PutObject(prm PutObjectPrm) (*PutObjectRes, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if prm.rdr != nil {
|
if prm.rdr != nil {
|
||||||
const defaultBufferSizePut = 3 << 20 // Maximum chunk size is 3 MiB in the SDK.
|
// TODO: (neofs-node#1198) explore better values or configure it
|
||||||
|
const defaultBufferSizePut = 4096
|
||||||
|
|
||||||
if sz == 0 || sz > defaultBufferSizePut {
|
if sz == 0 || sz > defaultBufferSizePut {
|
||||||
sz = defaultBufferSizePut
|
sz = defaultBufferSizePut
|
||||||
|
@ -459,7 +460,7 @@ func (x DeleteObjectRes) Tombstone() oid.ID {
|
||||||
return x.tomb
|
return x.tomb
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObject marks an object to be removed from FrostFS through tombstone placement.
|
// DeleteObject marks an object to be removed from NeoFS through tombstone placement.
|
||||||
//
|
//
|
||||||
// Returns any error which prevented the operation from completing correctly in error return.
|
// Returns any error which prevented the operation from completing correctly in error return.
|
||||||
func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) {
|
func DeleteObject(prm DeleteObjectPrm) (*DeleteObjectRes, error) {
|
||||||
|
@ -575,7 +576,7 @@ type HeadObjectPrm struct {
|
||||||
mainOnly bool
|
mainOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of FrostFS API.
|
// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of NeoFS API.
|
||||||
func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) {
|
func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) {
|
||||||
x.mainOnly = v
|
x.mainOnly = v
|
||||||
}
|
}
|
||||||
|
@ -811,7 +812,7 @@ func (x *PayloadRangePrm) SetRange(rng *object.Range) {
|
||||||
// PayloadRangeRes groups the resulting values of PayloadRange operation.
|
// PayloadRangeRes groups the resulting values of PayloadRange operation.
|
||||||
type PayloadRangeRes struct{}
|
type PayloadRangeRes struct{}
|
||||||
|
|
||||||
// PayloadRange reads object payload range from FrostFS and writes it to the specified writer.
|
// PayloadRange reads object payload range from NeoFS and writes it to the specified writer.
|
||||||
//
|
//
|
||||||
// Interrupts on any writer error.
|
// Interrupts on any writer error.
|
||||||
//
|
//
|
||||||
|
@ -871,7 +872,7 @@ func (s *SyncContainerPrm) SetContainer(c *containerSDK.Container) {
|
||||||
// operation.
|
// operation.
|
||||||
type SyncContainerRes struct{}
|
type SyncContainerRes struct{}
|
||||||
|
|
||||||
// SyncContainerSettings reads global network config from FrostFS and
|
// SyncContainerSettings reads global network config from NeoFS and
|
||||||
// syncs container settings with it.
|
// syncs container settings with it.
|
||||||
//
|
//
|
||||||
// Interrupts on any writer error.
|
// Interrupts on any writer error.
|
12
cmd/neofs-cli/internal/client/doc.go
Normal file
12
cmd/neofs-cli/internal/client/doc.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Package internal provides functionality for NeoFS CLI application communication with NeoFS network.
|
||||||
|
//
|
||||||
|
// The base client for accessing remote nodes via NeoFS API is a NeoFS SDK Go API client.
|
||||||
|
// However, although it encapsulates a useful piece of business logic (e.g. the signature mechanism),
|
||||||
|
// the NeoFS CLI application does not fully use the client's flexible interface.
|
||||||
|
//
|
||||||
|
// In this regard, this package provides functions over base API client necessary for the application.
|
||||||
|
// This allows you to concentrate the entire spectrum of the client's use in one place (this will be convenient
|
||||||
|
// both when updating the base client and for evaluating the UX of SDK library). So it is expected that all
|
||||||
|
// application packages will be limited to this package for the development of functionality requiring
|
||||||
|
// NeoFS API communication.
|
||||||
|
package internal
|
|
@ -3,11 +3,11 @@ package internal
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
// here are small structures with public setters to share between parameter structures
|
// here are small structures with public setters to share between parameter structures
|
||||||
|
@ -16,7 +16,7 @@ type commonPrm struct {
|
||||||
cli *client.Client
|
cli *client.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetClient sets the base client for FrostFS API communication.
|
// SetClient sets the base client for NeoFS API communication.
|
||||||
func (x *commonPrm) SetClient(cli *client.Client) {
|
func (x *commonPrm) SetClient(cli *client.Client) {
|
||||||
x.cli = cli
|
x.cli = cli
|
||||||
}
|
}
|
|
@ -8,39 +8,38 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
|
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
|
||||||
commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
|
"github.com/nspcc-dev/neofs-node/pkg/network"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
|
"github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errInvalidEndpoint = errors.New("provided RPC endpoint is incorrect")
|
var errInvalidEndpoint = errors.New("provided RPC endpoint is incorrect")
|
||||||
|
|
||||||
// GetSDKClientByFlag returns default frostfs-sdk-go client using the specified flag for the address.
|
// GetSDKClientByFlag returns default neofs-sdk-go client using the specified flag for the address.
|
||||||
// On error, outputs to stderr of cmd and exits with non-zero code.
|
// On error, outputs to stderr of cmd and exits with non-zero code.
|
||||||
func GetSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) *client.Client {
|
func GetSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) *client.Client {
|
||||||
cli, err := getSDKClientByFlag(cmd, key, endpointFlag)
|
cli, err := getSDKClientByFlag(key, endpointFlag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
commonCmd.ExitOnErr(cmd, "can't create API client: %w", err)
|
common.ExitOnErr(cmd, "can't create API client: %w", err)
|
||||||
}
|
}
|
||||||
return cli
|
return cli
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) {
|
func getSDKClientByFlag(key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) {
|
||||||
var addr network.Address
|
var addr network.Address
|
||||||
|
|
||||||
err := addr.FromString(viper.GetString(endpointFlag))
|
err := addr.FromString(viper.GetString(endpointFlag))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%v: %w", errInvalidEndpoint, err)
|
return nil, fmt.Errorf("%v: %w", errInvalidEndpoint, err)
|
||||||
}
|
}
|
||||||
return GetSDKClient(cmd, key, addr)
|
return GetSDKClient(key, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSDKClient returns default frostfs-sdk-go client.
|
// GetSDKClient returns default neofs-sdk-go client.
|
||||||
func GetSDKClient(cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Address) (*client.Client, error) {
|
func GetSDKClient(key *ecdsa.PrivateKey, addr network.Address) (*client.Client, error) {
|
||||||
var (
|
var (
|
||||||
c client.Client
|
c client.Client
|
||||||
prmInit client.PrmInit
|
prmInit client.PrmInit
|
||||||
|
@ -48,7 +47,7 @@ func GetSDKClient(cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Addres
|
||||||
)
|
)
|
||||||
|
|
||||||
prmInit.SetDefaultPrivateKey(*key)
|
prmInit.SetDefaultPrivateKey(*key)
|
||||||
prmInit.ResolveFrostFSFailures()
|
prmInit.ResolveNeoFSFailures()
|
||||||
prmDial.SetServerURI(addr.URIAddr())
|
prmDial.SetServerURI(addr.URIAddr())
|
||||||
if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 {
|
if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 {
|
||||||
// In CLI we can only set a timeout for the whole operation.
|
// In CLI we can only set a timeout for the whole operation.
|
||||||
|
@ -57,7 +56,7 @@ func GetSDKClient(cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Addres
|
||||||
prmDial.SetTimeout(timeout)
|
prmDial.SetTimeout(timeout)
|
||||||
prmDial.SetStreamTimeout(timeout)
|
prmDial.SetStreamTimeout(timeout)
|
||||||
|
|
||||||
common.PrintVerbose(cmd, "Set request timeout to %s.", timeout)
|
common.PrintVerbose("Set request timeout to %s.", timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Init(prmInit)
|
c.Init(prmInit)
|
||||||
|
@ -70,7 +69,7 @@ func GetSDKClient(cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Addres
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentEpoch returns current epoch.
|
// GetCurrentEpoch returns current epoch.
|
||||||
func GetCurrentEpoch(ctx context.Context, cmd *cobra.Command, endpoint string) (uint64, error) {
|
func GetCurrentEpoch(ctx context.Context, endpoint string) (uint64, error) {
|
||||||
var addr network.Address
|
var addr network.Address
|
||||||
|
|
||||||
if err := addr.FromString(endpoint); err != nil {
|
if err := addr.FromString(endpoint); err != nil {
|
||||||
|
@ -82,7 +81,7 @@ func GetCurrentEpoch(ctx context.Context, cmd *cobra.Command, endpoint string) (
|
||||||
return 0, fmt.Errorf("can't generate key to sign query: %w", err)
|
return 0, fmt.Errorf("can't generate key to sign query: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := GetSDKClient(cmd, key, addr)
|
c, err := GetSDKClient(key, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue