forked from TrueCloudLab/frostfs-node
[#283] morph/client: Implement all calls for audit contract
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
7174abcc7c
commit
fe2b1fdc4b
5 changed files with 312 additions and 30 deletions
|
@ -23,18 +23,30 @@ type Option func(*cfg)
|
|||
|
||||
type cfg struct {
|
||||
putResultMethod, // put audit result method name for invocation
|
||||
listResultsMethod string // list audit results method name for invocation
|
||||
getResultMethod, // get audit result method name for invocation
|
||||
listResultsMethod string // list all audit result IDs method name for invocation
|
||||
listByEpochResultsMethod string // list audit result IDs by epoch method name for invocation
|
||||
listByCIDResultsMethod string // list audit result IDs by epoch and CID method name for invocation
|
||||
listByNodeResultsMethod string // list audit result IDs by epoch, CID, and node key method name for invocation
|
||||
}
|
||||
|
||||
const (
|
||||
defaultPutResultMethod = "put" // default "put audit result" method name
|
||||
defaultListResultsMethod = "list" // default "list audit results" method name
|
||||
defaultPutResultMethod = "put" // default "put audit result" method name
|
||||
defaultGetResultMethod = "get" // default "get audit result" method name
|
||||
defaultListResultsMethod = "list" // default "list all audit result IDs" method name
|
||||
defaultListByEpochResultsMethod = "listByEpoch" // default "list audit result IDs by epoch" method name
|
||||
defaultListByCIDResultsMethod = "listByCID" // default "list audit result IDs by epoch and CID" method name
|
||||
defaultListByNodeResultsMethod = "listByNode" // default "list audit result IDs by epoch, CID and node key" method name
|
||||
)
|
||||
|
||||
func defaultConfig() *cfg {
|
||||
return &cfg{
|
||||
putResultMethod: defaultPutResultMethod,
|
||||
listResultsMethod: defaultListResultsMethod,
|
||||
putResultMethod: defaultPutResultMethod,
|
||||
getResultMethod: defaultGetResultMethod,
|
||||
listResultsMethod: defaultListResultsMethod,
|
||||
listByEpochResultsMethod: defaultListByEpochResultsMethod,
|
||||
listByCIDResultsMethod: defaultListByCIDResultsMethod,
|
||||
listByNodeResultsMethod: defaultListByNodeResultsMethod,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,8 +85,20 @@ func WithPutAuditResultMethod(n string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithGetAuditResultMethod returns a client constructor option that
|
||||
// specifies the "get audit result" method name.
|
||||
//
|
||||
// Ignores empty value.
|
||||
func WithGetAuditResultMethod(n string) Option {
|
||||
return func(c *cfg) {
|
||||
if n != "" {
|
||||
c.getResultMethod = n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithListResultsMethod returns a client constructor option that
|
||||
// specifies the "list audit results" method name.
|
||||
// specifies the "list all audit result IDs" method name.
|
||||
//
|
||||
// Ignores empty value.
|
||||
func WithListResultsMethod(n string) Option {
|
||||
|
@ -84,3 +108,39 @@ func WithListResultsMethod(n string) Option {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithListByEpochResultsMethod returns a client constructor option that
|
||||
// specifies the "list audit result IDs by epoch" method name.
|
||||
//
|
||||
// Ignores empty value.
|
||||
func WithListByEpochResultsMethod(n string) Option {
|
||||
return func(c *cfg) {
|
||||
if n != "" {
|
||||
c.listByEpochResultsMethod = n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithListByCIDResultsMethod returns a client constructor option that
|
||||
// specifies the "list audit result IDs by epoch and CID" method name.
|
||||
//
|
||||
// Ignores empty value.
|
||||
func WithListByCIDResultsMethod(n string) Option {
|
||||
return func(c *cfg) {
|
||||
if n != "" {
|
||||
c.listByCIDResultsMethod = n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithListByNodeResultsMethod returns a client constructor option that
|
||||
// specifies the "list audit result IDs by epoch, CID, and node key" method name.
|
||||
//
|
||||
// Ignores empty value.
|
||||
func WithListByNodeResultsMethod(n string) Option {
|
||||
return func(c *cfg) {
|
||||
if n != "" {
|
||||
c.listByNodeResultsMethod = n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
51
pkg/morph/client/audit/get_result.go
Normal file
51
pkg/morph/client/audit/get_result.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GetAuditResultArgs groups the arguments
|
||||
// of "get audit result" invocation call.
|
||||
type GetAuditResultArgs struct {
|
||||
id []byte
|
||||
}
|
||||
|
||||
// GetAuditResultValue groups the stack parameters
|
||||
// returned by "get audit result" test invoke.
|
||||
type GetAuditResultValue struct {
|
||||
rawResult []byte
|
||||
}
|
||||
|
||||
// SetID sets audit result ID generated by audit contract.
|
||||
func (g *GetAuditResultArgs) SetID(id []byte) {
|
||||
g.id = id
|
||||
}
|
||||
|
||||
// Result returns audit result structure in binary format.
|
||||
func (v *GetAuditResultValue) Result() []byte {
|
||||
return v.rawResult
|
||||
}
|
||||
|
||||
// GetAuditResult invokes the call of "get audit result" method
|
||||
// of NeoFS Audit contract.
|
||||
func (c *Client) GetAuditResult(args GetAuditResultArgs) (*GetAuditResultValue, error) {
|
||||
prms, err := c.client.TestInvoke(
|
||||
c.getResultMethod,
|
||||
args.id,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.getResultMethod)
|
||||
} else if ln := len(prms); ln != 1 {
|
||||
return nil, errors.Errorf("unexpected stack item count (%s): %d", c.getResultMethod, ln)
|
||||
}
|
||||
|
||||
resultBytes, err := client.BytesFromStackItem(prms[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get byte array from stack item (%s)", c.getResultMethod)
|
||||
}
|
||||
|
||||
return &GetAuditResultValue{
|
||||
rawResult: resultBytes,
|
||||
}, nil
|
||||
}
|
|
@ -1,27 +1,65 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ListResultsArgs groups the arguments
|
||||
// of "list audit results" test invoke call.
|
||||
// of "list all audit result IDs" test invoke call.
|
||||
type ListResultsArgs struct{}
|
||||
|
||||
// ListResultsByEpochArgs groups the arguments
|
||||
// of "list audit result IDs by epoch" test invoke call.
|
||||
type ListResultsByEpochArgs struct {
|
||||
epoch int64
|
||||
}
|
||||
|
||||
// ListResultsByCIDArgs groups the arguments
|
||||
// of "list audit result IDs by epoch and CID" test invoke call.
|
||||
type ListResultsByCIDArgs struct {
|
||||
ListResultsByEpochArgs
|
||||
|
||||
cid []byte
|
||||
}
|
||||
|
||||
// ListResultsByNodeArgs groups the arguments
|
||||
// of "list audit result IDs by epoch, CID, and node key" test invoke call.
|
||||
type ListResultsByNodeArgs struct {
|
||||
ListResultsByCIDArgs
|
||||
|
||||
nodeKey []byte
|
||||
}
|
||||
|
||||
// ListResultsValues groups the stack parameters
|
||||
// returned by "list audit results" test invoke.
|
||||
type ListResultsValues struct {
|
||||
rawResults [][]byte // audit results in a binary format
|
||||
}
|
||||
|
||||
// RawResults returns list of audit results
|
||||
// RawResults returns list of audit result IDs
|
||||
// in a binary format.
|
||||
func (v *ListResultsValues) RawResults() [][]byte {
|
||||
return v.rawResults
|
||||
}
|
||||
|
||||
// ListAuditResults performs the test invoke of "list audit results"
|
||||
// SetEpoch sets epoch of listing audit results.
|
||||
func (v *ListResultsByEpochArgs) SetEpoch(epoch int64) {
|
||||
v.epoch = epoch
|
||||
}
|
||||
|
||||
// SetCID sets container ID of listing audit results.
|
||||
func (v *ListResultsByCIDArgs) SetCID(cid []byte) {
|
||||
v.cid = cid
|
||||
}
|
||||
|
||||
// SetNodeKey sets public key of node that produced listing audit results.
|
||||
func (v *ListResultsByNodeArgs) SetNodeKey(key []byte) {
|
||||
v.nodeKey = key
|
||||
}
|
||||
|
||||
// ListAuditResults performs the test invoke of "list all audit result IDs"
|
||||
// method of NeoFS Audit contract.
|
||||
func (c *Client) ListAuditResults(args ListResultsArgs) (*ListResultsValues, error) {
|
||||
items, err := c.client.TestInvoke(
|
||||
|
@ -29,13 +67,64 @@ func (c *Client) ListAuditResults(args ListResultsArgs) (*ListResultsValues, err
|
|||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.listResultsMethod)
|
||||
} else if ln := len(items); ln != 1 {
|
||||
return nil, errors.Errorf("unexpected stack item count (%s): %d", c.listResultsMethod, ln)
|
||||
}
|
||||
|
||||
items, err = client.ArrayFromStackItem(items[0])
|
||||
return parseAuditResults(items, c.listResultsMethod)
|
||||
}
|
||||
|
||||
// ListAuditResultsByEpoch performs the test invoke of "list audit result IDs
|
||||
// by epoch" method of NeoFS Audit contract.
|
||||
func (c *Client) ListAuditResultsByEpoch(args ListResultsByEpochArgs) (*ListResultsValues, error) {
|
||||
items, err := c.client.TestInvoke(
|
||||
c.listByEpochResultsMethod,
|
||||
args.epoch,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get stack item array from stack item (%s)", c.listResultsMethod)
|
||||
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.listByEpochResultsMethod)
|
||||
}
|
||||
|
||||
return parseAuditResults(items, c.listByEpochResultsMethod)
|
||||
}
|
||||
|
||||
// ListAuditResultsByCID performs the test invoke of "list audit result IDs
|
||||
// by epoch and CID" method of NeoFS Audit contract.
|
||||
func (c *Client) ListAuditResultsByCID(args ListResultsByCIDArgs) (*ListResultsValues, error) {
|
||||
items, err := c.client.TestInvoke(
|
||||
c.listByCIDResultsMethod,
|
||||
args.epoch,
|
||||
args.cid,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.listByCIDResultsMethod)
|
||||
}
|
||||
|
||||
return parseAuditResults(items, c.listByCIDResultsMethod)
|
||||
}
|
||||
|
||||
// ListAuditResultsByNode performs the test invoke of "list audit result IDs
|
||||
// by epoch, CID, and node key" method of NeoFS Audit contract.
|
||||
func (c *Client) ListAuditResultsByNode(args ListResultsByNodeArgs) (*ListResultsValues, error) {
|
||||
items, err := c.client.TestInvoke(
|
||||
c.listByNodeResultsMethod,
|
||||
args.epoch,
|
||||
args.cid,
|
||||
args.nodeKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not perform test invocation (%s)", c.listByNodeResultsMethod)
|
||||
}
|
||||
|
||||
return parseAuditResults(items, c.listByNodeResultsMethod)
|
||||
}
|
||||
|
||||
func parseAuditResults(items []stackitem.Item, method string) (*ListResultsValues, error) {
|
||||
if ln := len(items); ln != 1 {
|
||||
return nil, errors.Errorf("unexpected stack item count (%s): %d", method, ln)
|
||||
}
|
||||
|
||||
items, err := client.ArrayFromStackItem(items[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get stack item array from stack item (%s)", method)
|
||||
}
|
||||
|
||||
res := &ListResultsValues{
|
||||
|
@ -45,7 +134,7 @@ func (c *Client) ListAuditResults(args ListResultsArgs) (*ListResultsValues, err
|
|||
for i := range items {
|
||||
rawRes, err := client.BytesFromStackItem(items[i])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "could not get byte array from stack item (%s)", c.listResultsMethod)
|
||||
return nil, errors.Wrapf(err, "could not get byte array from stack item (%s)", method)
|
||||
}
|
||||
|
||||
res.rawResults = append(res.rawResults, rawRes)
|
||||
|
|
|
@ -2,10 +2,16 @@ package audit
|
|||
|
||||
import (
|
||||
auditAPI "github.com/nspcc-dev/neofs-api-go/pkg/audit"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client/audit"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ResultID is an identity of audit result inside audit contract.
|
||||
type ResultID []byte
|
||||
|
||||
var errUnsupported = errors.New("unsupported structure version")
|
||||
|
||||
// PutAuditResult saves passed audit result structure in NeoFS system
|
||||
// through Audit contract call.
|
||||
//
|
||||
|
@ -24,9 +30,8 @@ func (w *ClientWrapper) PutAuditResult(result *auditAPI.Result) error {
|
|||
PutAuditResult(args)
|
||||
}
|
||||
|
||||
// ListAuditResults returns a list of all audit results in NeoFS system.
|
||||
// The list is composed through Audit contract call.
|
||||
func (w *ClientWrapper) ListAuditResults() ([]*auditAPI.Result, error) {
|
||||
// ListAuditResults returns a list of all audit result IDs inside audit contract.
|
||||
func (w *ClientWrapper) ListAllAuditResultID() ([]ResultID, error) {
|
||||
args := audit.ListResultsArgs{}
|
||||
|
||||
values, err := (*audit.Client)(w).ListAuditResults(args)
|
||||
|
@ -34,17 +39,89 @@ func (w *ClientWrapper) ListAuditResults() ([]*auditAPI.Result, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
rawResults := values.RawResults()
|
||||
result := make([]*auditAPI.Result, 0, len(rawResults))
|
||||
return parseRawResult(values), nil
|
||||
}
|
||||
|
||||
for i := range rawResults {
|
||||
auditRes := auditAPI.NewResult()
|
||||
if err := auditRes.Unmarshal(rawResults[i]); err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal audit result structure")
|
||||
}
|
||||
// ListAuditResultIDByEpoch returns a list of audit result IDs inside audit
|
||||
// contract for specific epoch number.
|
||||
func (w *ClientWrapper) ListAuditResultIDByEpoch(epoch uint64) ([]ResultID, error) {
|
||||
args := audit.ListResultsByEpochArgs{}
|
||||
args.SetEpoch(int64(epoch))
|
||||
|
||||
result = append(result, auditRes)
|
||||
values, err := (*audit.Client)(w).ListAuditResultsByEpoch(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return parseRawResult(values), nil
|
||||
}
|
||||
|
||||
// ListAuditResultIDByCID returns a list of audit result IDs inside audit
|
||||
// contract for specific epoch number and container ID.
|
||||
func (w *ClientWrapper) ListAuditResultIDByCID(epoch uint64, cid *container.ID) ([]ResultID, error) {
|
||||
args := audit.ListResultsByCIDArgs{}
|
||||
args.SetEpoch(int64(epoch))
|
||||
|
||||
if v2 := cid.ToV2(); v2 == nil {
|
||||
return nil, errUnsupported // use other major version if there any
|
||||
} else {
|
||||
args.SetCID(v2.GetValue())
|
||||
}
|
||||
|
||||
values, err := (*audit.Client)(w).ListAuditResultsByCID(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parseRawResult(values), nil
|
||||
}
|
||||
|
||||
// ListAuditResultIDByNode returns a list of audit result IDs inside audit
|
||||
// contract for specific epoch number, container ID and inner ring public key.
|
||||
func (w *ClientWrapper) ListAuditResultIDByNode(epoch uint64, cid *container.ID, key []byte) ([]ResultID, error) {
|
||||
args := audit.ListResultsByNodeArgs{}
|
||||
args.SetEpoch(int64(epoch))
|
||||
args.SetNodeKey(key)
|
||||
|
||||
if v2 := cid.ToV2(); v2 == nil {
|
||||
return nil, errUnsupported // use other major version if there any
|
||||
} else {
|
||||
args.SetCID(v2.GetValue())
|
||||
}
|
||||
|
||||
values, err := (*audit.Client)(w).ListAuditResultsByNode(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parseRawResult(values), nil
|
||||
}
|
||||
|
||||
func parseRawResult(values *audit.ListResultsValues) []ResultID {
|
||||
rawResults := values.RawResults()
|
||||
result := make([]ResultID, 0, len(rawResults))
|
||||
|
||||
for i := range rawResults {
|
||||
result = append(result, rawResults[i])
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAuditResult returns audit result structure stored in audit contract.
|
||||
func (w *ClientWrapper) GetAuditResult(id ResultID) (*auditAPI.Result, error) {
|
||||
args := audit.GetAuditResultArgs{}
|
||||
args.SetID(id)
|
||||
|
||||
value, err := (*audit.Client)(w).GetAuditResult(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auditRes := auditAPI.NewResult()
|
||||
if err := auditRes.Unmarshal(value.Result()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal audit result structure")
|
||||
}
|
||||
|
||||
return auditRes, nil
|
||||
}
|
||||
|
|
|
@ -17,9 +17,10 @@ import (
|
|||
|
||||
func TestAuditResults(t *testing.T) {
|
||||
t.Skip()
|
||||
const epoch = 11
|
||||
|
||||
endpoint := "http://morph_chain.neofs.devenv:30333"
|
||||
sAuditHash := "96a746aa7186f775e5744a6e2c6566dc5c4a57a2"
|
||||
sAuditHash := "cdfb3dab86e6d60e8a143d9e2ecb0b188f3dc2eb"
|
||||
irKeyWIF := "L3o221BojgcCPYgdbXsm6jn7ayTZ72xwREvBHXKknR8VJ3G4WmjB"
|
||||
|
||||
key, err := crypto.WIFDecode(irKeyWIF)
|
||||
|
@ -44,7 +45,7 @@ func TestAuditResults(t *testing.T) {
|
|||
cid.SetSHA256([sha256.Size]byte{1, 2, 3})
|
||||
|
||||
auditRes := auditAPI.NewResult()
|
||||
auditRes.SetAuditEpoch(11)
|
||||
auditRes.SetAuditEpoch(epoch)
|
||||
auditRes.SetPublicKey(pubKey)
|
||||
auditRes.SetContainerID(cid)
|
||||
|
||||
|
@ -52,8 +53,12 @@ func TestAuditResults(t *testing.T) {
|
|||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
list, err := auditClientWrapper.ListAuditResults()
|
||||
list, err := auditClientWrapper.ListAuditResultIDByCID(epoch, cid)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, list, 1)
|
||||
require.Contains(t, list, auditRes)
|
||||
|
||||
savedAuditRes, err := auditClientWrapper.GetAuditResult(list[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, auditRes, savedAuditRes)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue