2023-04-27 08:25:17 +00:00
|
|
|
package governance
|
|
|
|
|
|
|
|
import (
|
2024-10-21 09:21:01 +00:00
|
|
|
"context"
|
2023-04-27 08:25:17 +00:00
|
|
|
"encoding/binary"
|
|
|
|
"sort"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
|
|
|
|
frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/rolemanagement"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestHandleAlphabetSyncEvent(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
testKeys := generateTestKeys(t)
|
|
|
|
|
|
|
|
es := &testEpochState{
|
|
|
|
epoch: 100,
|
|
|
|
}
|
|
|
|
as := &testAlphabetState{
|
|
|
|
isAlphabet: true,
|
|
|
|
}
|
|
|
|
v := &testVoter{}
|
|
|
|
irf := &testIRFetcher{
|
|
|
|
publicKeys: testKeys.sidechainKeys,
|
|
|
|
}
|
|
|
|
m := &testMorphClient{
|
|
|
|
commiteeKeys: testKeys.sidechainKeys,
|
|
|
|
}
|
|
|
|
mn := &testMainnetClient{
|
|
|
|
alphabetKeys: testKeys.mainnetKeys,
|
|
|
|
}
|
|
|
|
f := &testFrostFSClient{}
|
|
|
|
|
|
|
|
proc, err := New(
|
|
|
|
&Params{
|
2024-01-09 08:37:41 +00:00
|
|
|
Log: test.NewLogger(t),
|
2023-05-18 08:19:08 +00:00
|
|
|
EpochState: es,
|
|
|
|
AlphabetState: as,
|
|
|
|
Voter: v,
|
|
|
|
IRFetcher: irf,
|
|
|
|
MorphClient: m,
|
|
|
|
MainnetClient: mn,
|
|
|
|
FrostFSClient: f,
|
2023-04-27 08:25:17 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
require.NoError(t, err, "failed to create processor")
|
|
|
|
|
|
|
|
ev := Sync{
|
|
|
|
txHash: util.Uint256{100},
|
|
|
|
}
|
|
|
|
|
2024-10-21 09:21:01 +00:00
|
|
|
proc.HandleAlphabetSync(context.Background(), ev)
|
2023-04-27 08:25:17 +00:00
|
|
|
|
|
|
|
for proc.pool.Running() > 0 {
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
}
|
|
|
|
|
|
|
|
require.EqualValues(t, []VoteValidatorPrm{
|
|
|
|
{
|
|
|
|
Validators: testKeys.newAlphabetExp,
|
|
|
|
Hash: &ev.txHash,
|
|
|
|
},
|
|
|
|
}, v.votes, "invalid vote calls")
|
|
|
|
|
2023-05-18 08:19:08 +00:00
|
|
|
var expAlphabetUpdate client.UpdateAlphabetListPrm
|
|
|
|
expAlphabetUpdate.SetHash(ev.txHash)
|
|
|
|
expAlphabetUpdate.SetList(testKeys.newInnerRingExp)
|
|
|
|
require.EqualValues(t, []client.UpdateAlphabetListPrm{expAlphabetUpdate}, m.alphabetUpdates, "invalid alphabet updates")
|
2023-04-27 08:25:17 +00:00
|
|
|
|
2023-05-18 08:19:08 +00:00
|
|
|
var expNotaryUpdate client.UpdateNotaryListPrm
|
|
|
|
expNotaryUpdate.SetHash(ev.txHash)
|
|
|
|
expNotaryUpdate.SetList(testKeys.newAlphabetExp)
|
|
|
|
require.EqualValues(t, []client.UpdateNotaryListPrm{expNotaryUpdate}, m.notaryUpdates, "invalid notary list updates")
|
2023-04-27 08:25:17 +00:00
|
|
|
|
|
|
|
buf := make([]byte, 8)
|
|
|
|
binary.LittleEndian.PutUint64(buf, es.epoch)
|
|
|
|
|
|
|
|
id := append([]byte(alphabetUpdateIDPrefix), buf...)
|
|
|
|
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
|
|
|
|
expFrostFSAlphabetUpd.SetID(id)
|
|
|
|
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
|
|
|
|
|
|
|
|
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestHandleAlphabetDesignateEvent(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
testKeys := generateTestKeys(t)
|
|
|
|
|
|
|
|
es := &testEpochState{
|
|
|
|
epoch: 100,
|
|
|
|
}
|
|
|
|
as := &testAlphabetState{
|
|
|
|
isAlphabet: true,
|
|
|
|
}
|
|
|
|
v := &testVoter{}
|
|
|
|
irf := &testIRFetcher{
|
|
|
|
publicKeys: testKeys.sidechainKeys,
|
|
|
|
}
|
|
|
|
m := &testMorphClient{
|
|
|
|
commiteeKeys: testKeys.sidechainKeys,
|
|
|
|
}
|
|
|
|
mn := &testMainnetClient{
|
|
|
|
alphabetKeys: testKeys.mainnetKeys,
|
|
|
|
}
|
|
|
|
f := &testFrostFSClient{}
|
|
|
|
|
|
|
|
proc, err := New(
|
|
|
|
&Params{
|
2024-01-09 08:37:41 +00:00
|
|
|
Log: test.NewLogger(t),
|
2023-05-18 08:19:08 +00:00
|
|
|
EpochState: es,
|
|
|
|
AlphabetState: as,
|
|
|
|
Voter: v,
|
|
|
|
IRFetcher: irf,
|
|
|
|
MorphClient: m,
|
|
|
|
MainnetClient: mn,
|
|
|
|
FrostFSClient: f,
|
2023-04-27 08:25:17 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
require.NoError(t, err, "failed to create processor")
|
|
|
|
|
|
|
|
ev := rolemanagement.Designate{
|
|
|
|
TxHash: util.Uint256{100},
|
|
|
|
Role: noderoles.NeoFSAlphabet,
|
|
|
|
}
|
|
|
|
|
2024-10-21 09:21:01 +00:00
|
|
|
proc.HandleAlphabetSync(context.Background(), ev)
|
2023-04-27 08:25:17 +00:00
|
|
|
|
|
|
|
for proc.pool.Running() > 0 {
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
}
|
|
|
|
|
|
|
|
require.EqualValues(t, []VoteValidatorPrm{
|
|
|
|
{
|
|
|
|
Validators: testKeys.newAlphabetExp,
|
|
|
|
Hash: &ev.TxHash,
|
|
|
|
},
|
|
|
|
}, v.votes, "invalid vote calls")
|
|
|
|
|
|
|
|
var alpabetUpdExp client.UpdateAlphabetListPrm
|
|
|
|
alpabetUpdExp.SetList(testKeys.newInnerRingExp)
|
|
|
|
alpabetUpdExp.SetHash(ev.TxHash)
|
|
|
|
require.EqualValues(t, []client.UpdateAlphabetListPrm{alpabetUpdExp}, m.alphabetUpdates, "invalid alphabet updates")
|
|
|
|
|
|
|
|
var expNotaryUpdate client.UpdateNotaryListPrm
|
|
|
|
expNotaryUpdate.SetList(testKeys.newAlphabetExp)
|
|
|
|
expNotaryUpdate.SetHash(ev.TxHash)
|
|
|
|
require.EqualValues(t, []client.UpdateNotaryListPrm{expNotaryUpdate}, m.notaryUpdates, "invalid notary list updates")
|
|
|
|
|
|
|
|
buf := make([]byte, 8)
|
|
|
|
binary.LittleEndian.PutUint64(buf, es.epoch)
|
|
|
|
|
|
|
|
id := append([]byte(alphabetUpdateIDPrefix), buf...)
|
|
|
|
var expFrostFSAlphabetUpd frostfscontract.AlphabetUpdatePrm
|
|
|
|
expFrostFSAlphabetUpd.SetID(id)
|
|
|
|
expFrostFSAlphabetUpd.SetPubs(testKeys.newAlphabetExp)
|
|
|
|
|
|
|
|
require.EqualValues(t, []frostfscontract.AlphabetUpdatePrm{expFrostFSAlphabetUpd}, f.updates, "invalid FrostFS alphabet updates")
|
|
|
|
}
|
|
|
|
|
|
|
|
type testKeys struct {
|
|
|
|
sidechainKeys keys.PublicKeys
|
|
|
|
mainnetKeys keys.PublicKeys
|
|
|
|
newAlphabetExp keys.PublicKeys
|
|
|
|
newInnerRingExp keys.PublicKeys
|
|
|
|
}
|
|
|
|
|
|
|
|
func generateTestKeys(t *testing.T) testKeys {
|
|
|
|
for {
|
|
|
|
var result testKeys
|
|
|
|
|
2024-08-30 16:20:55 +00:00
|
|
|
for range 4 {
|
2023-04-27 08:25:17 +00:00
|
|
|
pk, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err, "failed to create private key")
|
|
|
|
result.sidechainKeys = append(result.sidechainKeys, pk.PublicKey())
|
|
|
|
}
|
|
|
|
|
|
|
|
result.mainnetKeys = append(result.mainnetKeys, result.sidechainKeys...)
|
|
|
|
pk, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err, "failed to create private key")
|
|
|
|
result.mainnetKeys = append(result.mainnetKeys, pk.PublicKey())
|
|
|
|
|
|
|
|
result.newAlphabetExp, err = newAlphabetList(result.sidechainKeys, result.mainnetKeys)
|
|
|
|
require.NoError(t, err, "failed to create expected new alphabet")
|
|
|
|
|
|
|
|
if len(result.newAlphabetExp) == 0 {
|
2023-10-31 11:56:55 +00:00
|
|
|
continue // can be happen because of random and sort
|
2023-04-27 08:25:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var irKeys keys.PublicKeys
|
|
|
|
irKeys = append(irKeys, result.sidechainKeys...)
|
|
|
|
result.newInnerRingExp, err = updateInnerRing(irKeys, result.sidechainKeys, result.newAlphabetExp)
|
|
|
|
require.NoError(t, err, "failed to create expected new IR")
|
|
|
|
sort.Sort(result.newInnerRingExp)
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type testEpochState struct {
|
|
|
|
epoch uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *testEpochState) EpochCounter() uint64 {
|
|
|
|
return s.epoch
|
|
|
|
}
|
|
|
|
|
|
|
|
type testAlphabetState struct {
|
|
|
|
isAlphabet bool
|
|
|
|
}
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
func (s *testAlphabetState) IsAlphabet(context.Context) bool {
|
2023-04-27 08:25:17 +00:00
|
|
|
return s.isAlphabet
|
|
|
|
}
|
|
|
|
|
|
|
|
type testVoter struct {
|
|
|
|
votes []VoteValidatorPrm
|
|
|
|
}
|
|
|
|
|
2024-10-21 09:21:01 +00:00
|
|
|
func (v *testVoter) VoteForSidechainValidator(_ context.Context, prm VoteValidatorPrm) error {
|
2023-04-27 08:25:17 +00:00
|
|
|
v.votes = append(v.votes, prm)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type testIRFetcher struct {
|
|
|
|
publicKeys keys.PublicKeys
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) {
|
|
|
|
return f.publicKeys, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type testMorphClient struct {
|
|
|
|
commiteeKeys keys.PublicKeys
|
|
|
|
|
|
|
|
alphabetUpdates []client.UpdateAlphabetListPrm
|
|
|
|
notaryUpdates []client.UpdateNotaryListPrm
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *testMorphClient) Committee() (res keys.PublicKeys, err error) {
|
|
|
|
return c.commiteeKeys, nil
|
|
|
|
}
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
func (c *testMorphClient) UpdateNeoFSAlphabetList(_ context.Context, prm client.UpdateAlphabetListPrm) error {
|
2023-04-27 08:25:17 +00:00
|
|
|
c.alphabetUpdates = append(c.alphabetUpdates, prm)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
func (c *testMorphClient) UpdateNotaryList(_ context.Context, prm client.UpdateNotaryListPrm) error {
|
2023-04-27 08:25:17 +00:00
|
|
|
c.notaryUpdates = append(c.notaryUpdates, prm)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type testMainnetClient struct {
|
|
|
|
alphabetKeys keys.PublicKeys
|
|
|
|
designateHash util.Uint160
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *testMainnetClient) NeoFSAlphabetList() (res keys.PublicKeys, err error) {
|
|
|
|
return c.alphabetKeys, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *testMainnetClient) GetDesignateHash() util.Uint160 {
|
|
|
|
return c.designateHash
|
|
|
|
}
|
|
|
|
|
|
|
|
type testFrostFSClient struct {
|
|
|
|
updates []frostfscontract.AlphabetUpdatePrm
|
|
|
|
}
|
|
|
|
|
2024-10-21 13:27:28 +00:00
|
|
|
func (c *testFrostFSClient) AlphabetUpdate(_ context.Context, p frostfscontract.AlphabetUpdatePrm) error {
|
2023-04-27 08:25:17 +00:00
|
|
|
c.updates = append(c.updates, p)
|
|
|
|
return nil
|
|
|
|
}
|