forked from TrueCloudLab/frostfs-node
333 lines
8.4 KiB
Go
333 lines
8.4 KiB
Go
package container
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"encoding/hex"
|
|
"testing"
|
|
"time"
|
|
|
|
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
|
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid"
|
|
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
|
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
|
|
"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/network/payload"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestPutEvent(t *testing.T) {
|
|
t.Parallel()
|
|
nst := &testNetworkState{
|
|
homHashDisabled: true,
|
|
epoch: 100,
|
|
}
|
|
mc := &testMorphClient{}
|
|
|
|
proc, err := New(&Params{
|
|
Log: test.NewLogger(t, true),
|
|
PoolSize: 2,
|
|
AlphabetState: &testAlphabetState{isAlphabet: true},
|
|
FrostFSIDClient: &testIDClient{},
|
|
NetworkState: nst,
|
|
ContainerClient: &testContainerClient{},
|
|
MorphClient: mc,
|
|
})
|
|
require.NoError(t, err, "failed to create processor")
|
|
|
|
p, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
var usr user.ID
|
|
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
|
|
|
var pp netmap.PlacementPolicy
|
|
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
|
|
|
var cnr containerSDK.Container
|
|
cnr.Init()
|
|
cnr.SetOwner(usr)
|
|
cnr.SetPlacementPolicy(pp)
|
|
cnr.SetBasicACL(acl.Private)
|
|
containerSDK.DisableHomomorphicHashing(&cnr)
|
|
|
|
nr := &payload.P2PNotaryRequest{
|
|
MainTransaction: &transaction.Transaction{},
|
|
}
|
|
|
|
event := &testPutEvent{
|
|
cnr: &cnr,
|
|
pk: p,
|
|
st: nil,
|
|
nr: nr,
|
|
}
|
|
|
|
proc.handlePut(event)
|
|
|
|
for proc.pool.Running() > 0 {
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
|
|
}
|
|
|
|
func TestDeleteEvent(t *testing.T) {
|
|
t.Parallel()
|
|
nst := &testNetworkState{
|
|
homHashDisabled: true,
|
|
epoch: 100,
|
|
}
|
|
cc := &testContainerClient{
|
|
get: make(map[string]*containercore.Container),
|
|
}
|
|
|
|
p, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
|
|
idc := &testIDClient{
|
|
publicKeys: []*keys.PublicKey{
|
|
p.PublicKey(),
|
|
},
|
|
}
|
|
mc := &testMorphClient{}
|
|
|
|
proc, err := New(&Params{
|
|
Log: test.NewLogger(t, true),
|
|
PoolSize: 2,
|
|
AlphabetState: &testAlphabetState{isAlphabet: true},
|
|
FrostFSIDClient: idc,
|
|
NetworkState: nst,
|
|
ContainerClient: cc,
|
|
MorphClient: mc,
|
|
})
|
|
require.NoError(t, err, "failed to create processor")
|
|
|
|
var usr user.ID
|
|
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
|
|
|
var pp netmap.PlacementPolicy
|
|
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
|
|
|
var cnr containerSDK.Container
|
|
cnr.Init()
|
|
cnr.SetOwner(usr)
|
|
cnr.SetPlacementPolicy(pp)
|
|
cnr.SetBasicACL(acl.Private)
|
|
containerSDK.DisableHomomorphicHashing(&cnr)
|
|
|
|
var cid cid.ID
|
|
containerSDK.CalculateID(&cid, cnr)
|
|
cidBin := make([]byte, 32)
|
|
cid.Encode(cidBin)
|
|
|
|
nr := &payload.P2PNotaryRequest{
|
|
MainTransaction: &transaction.Transaction{},
|
|
}
|
|
|
|
ev := containerEvent.Delete{
|
|
ContainerIDValue: cidBin,
|
|
SignatureValue: p.Sign(cidBin),
|
|
NotaryRequestValue: nr,
|
|
}
|
|
|
|
var signature frostfscrypto.Signature
|
|
signer := frostfsecdsa.Signer(p.PrivateKey)
|
|
require.NoError(t, signature.Calculate(signer, ev.ContainerID()), "failed to calculate signature")
|
|
cc.get[hex.EncodeToString(ev.ContainerID())] = &containercore.Container{
|
|
Value: cnr,
|
|
Signature: signature,
|
|
}
|
|
|
|
proc.handleDelete(ev)
|
|
|
|
for proc.pool.Running() > 0 {
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
var expectedDelete cntClient.DeletePrm
|
|
expectedDelete.SetCID(ev.ContainerID())
|
|
expectedDelete.SetSignature(ev.Signature())
|
|
|
|
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
|
|
}
|
|
|
|
func TestSetEACLEvent(t *testing.T) {
|
|
t.Parallel()
|
|
nst := &testNetworkState{
|
|
homHashDisabled: true,
|
|
epoch: 100,
|
|
}
|
|
cc := &testContainerClient{
|
|
get: make(map[string]*containercore.Container),
|
|
}
|
|
mc := &testMorphClient{}
|
|
|
|
proc, err := New(&Params{
|
|
Log: test.NewLogger(t, true),
|
|
PoolSize: 2,
|
|
AlphabetState: &testAlphabetState{isAlphabet: true},
|
|
FrostFSIDClient: &testIDClient{},
|
|
NetworkState: nst,
|
|
ContainerClient: cc,
|
|
MorphClient: mc,
|
|
})
|
|
require.NoError(t, err, "failed to create processor")
|
|
|
|
p, err := keys.NewPrivateKey()
|
|
require.NoError(t, err)
|
|
|
|
var usr user.ID
|
|
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
|
|
|
|
var pp netmap.PlacementPolicy
|
|
pp.AddReplicas(netmap.ReplicaDescriptor{})
|
|
|
|
var cnr containerSDK.Container
|
|
cnr.Init()
|
|
cnr.SetOwner(usr)
|
|
cnr.SetPlacementPolicy(pp)
|
|
cnr.SetBasicACL(acl.PrivateExtended)
|
|
containerSDK.DisableHomomorphicHashing(&cnr)
|
|
|
|
var cid cid.ID
|
|
containerSDK.CalculateID(&cid, cnr)
|
|
cidBytes := make([]byte, 32)
|
|
cid.Encode(cidBytes)
|
|
|
|
var signature frostfscrypto.Signature
|
|
signer := frostfsecdsa.Signer(p.PrivateKey)
|
|
require.NoError(t, signature.Calculate(signer, cidBytes), "failed to calculate signature")
|
|
|
|
cc.get[hex.EncodeToString(cidBytes)] = &containercore.Container{
|
|
Value: cnr,
|
|
Signature: signature,
|
|
}
|
|
|
|
table := eacl.NewTable()
|
|
table.SetCID(cid)
|
|
table.SetVersion(version.Current())
|
|
|
|
r := &eacl.Record{}
|
|
r.AddObjectContainerIDFilter(eacl.MatchStringEqual, cid)
|
|
|
|
table.AddRecord(r)
|
|
|
|
nr := &payload.P2PNotaryRequest{
|
|
MainTransaction: &transaction.Transaction{},
|
|
}
|
|
event := containerEvent.SetEACL{
|
|
TableValue: table.ToV2().StableMarshal(nil),
|
|
PublicKeyValue: p.PublicKey().Bytes(),
|
|
SignatureValue: p.Sign(table.ToV2().StableMarshal(nil)),
|
|
NotaryRequestValue: nr,
|
|
}
|
|
|
|
proc.handleSetEACL(event)
|
|
|
|
for proc.pool.Running() > 0 {
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
var expectedPutEACL cntClient.PutEACLPrm
|
|
expectedPutEACL.SetTable(table.ToV2().StableMarshal(nil))
|
|
expectedPutEACL.SetKey(p.PublicKey().Bytes())
|
|
expectedPutEACL.SetSignature(p.Sign(table.ToV2().StableMarshal(nil)))
|
|
|
|
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
|
|
}
|
|
|
|
type testAlphabetState struct {
|
|
isAlphabet bool
|
|
}
|
|
|
|
func (s *testAlphabetState) IsAlphabet() bool {
|
|
return s.isAlphabet
|
|
}
|
|
|
|
type testNetworkState struct {
|
|
homHashDisabled bool
|
|
epoch uint64
|
|
}
|
|
|
|
func (s *testNetworkState) HomomorphicHashDisabled() (bool, error) {
|
|
return s.homHashDisabled, nil
|
|
}
|
|
|
|
func (s *testNetworkState) Epoch() (uint64, error) {
|
|
return s.epoch, nil
|
|
}
|
|
|
|
type testContainerClient struct {
|
|
contractAddress util.Uint160
|
|
get map[string]*containercore.Container
|
|
}
|
|
|
|
func (c *testContainerClient) ContractAddress() util.Uint160 {
|
|
return c.contractAddress
|
|
}
|
|
|
|
func (c *testContainerClient) Get(cid []byte) (*containercore.Container, error) {
|
|
key := hex.EncodeToString(cid)
|
|
if cont, found := c.get[key]; found {
|
|
return cont, nil
|
|
}
|
|
return nil, new(apistatus.ContainerNotFound)
|
|
}
|
|
|
|
type testIDClient struct {
|
|
publicKeys keys.PublicKeys
|
|
}
|
|
|
|
func (c *testIDClient) AccountKeys(p frostfsid.AccountKeysPrm) (keys.PublicKeys, error) {
|
|
return c.publicKeys, nil
|
|
}
|
|
|
|
var _ putEvent = &testPutEvent{}
|
|
|
|
type testPutEvent struct {
|
|
cnr *containerSDK.Container
|
|
pk *keys.PrivateKey
|
|
st []byte
|
|
nr *payload.P2PNotaryRequest
|
|
}
|
|
|
|
func (e *testPutEvent) MorphEvent() {}
|
|
|
|
func (e *testPutEvent) Container() []byte {
|
|
return e.cnr.Marshal()
|
|
}
|
|
|
|
func (e *testPutEvent) PublicKey() []byte {
|
|
return e.pk.PublicKey().Bytes()
|
|
}
|
|
|
|
func (e *testPutEvent) Signature() []byte {
|
|
return e.pk.Sign(e.cnr.Marshal())
|
|
}
|
|
|
|
func (e *testPutEvent) SessionToken() []byte {
|
|
return e.st
|
|
}
|
|
func (e *testPutEvent) NotaryRequest() *payload.P2PNotaryRequest {
|
|
return e.nr
|
|
}
|
|
|
|
type testMorphClient struct {
|
|
transactions []*transaction.Transaction
|
|
}
|
|
|
|
func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error {
|
|
c.transactions = append(c.transactions, mainTx)
|
|
return nil
|
|
}
|