[#269] netmap: Support Maintenance node state

Signed-off-by: Evgenii Stratonikov <evgeniy@morphbits.ru>
This commit is contained in:
Evgenii Stratonikov 2022-09-20 10:42:36 +03:00 committed by fyrchik
parent 2d0101033b
commit cb684994fc
2 changed files with 37 additions and 7 deletions

View file

@ -56,6 +56,7 @@ const (
_ NodeState = iota _ NodeState = iota
OnlineState OnlineState
OfflineState OfflineState
MaintenanceState
) )
var ( var (
@ -317,6 +318,9 @@ func UpdateState(state int, publicKey interop.PublicKey) {
case OfflineState: case OfflineState:
removeFromNetmap(ctx, publicKey) removeFromNetmap(ctx, publicKey)
runtime.Log("remove storage node from the network map") runtime.Log("remove storage node from the network map")
case MaintenanceState:
updateNetmapState(ctx, publicKey, MaintenanceState)
runtime.Log("move storage node to a maintenance state")
default: default:
panic("unsupported state") panic("unsupported state")
} }
@ -338,6 +342,8 @@ func UpdateStateIR(state NodeState, publicKey interop.PublicKey) {
switch state { switch state {
case OfflineState: case OfflineState:
removeFromNetmap(ctx, publicKey) removeFromNetmap(ctx, publicKey)
case MaintenanceState:
updateNetmapState(ctx, publicKey, MaintenanceState)
default: default:
panic("unsupported state") panic("unsupported state")
} }
@ -649,6 +655,14 @@ func removeFromNetmap(ctx storage.Context, key interop.PublicKey) {
storage.Delete(ctx, storageKey) storage.Delete(ctx, storageKey)
} }
func updateNetmapState(ctx storage.Context, key interop.PublicKey, state NodeState) {
storageKey := append(candidatePrefix, key...)
raw := storage.Get(ctx, storageKey).([]byte)
node := std.Deserialize(raw).(netmapNode)
node.state = state
storage.Put(ctx, storageKey, std.Serialize(node))
}
func filterNetmap(ctx storage.Context, st NodeState) []storageNode { func filterNetmap(ctx storage.Context, st NodeState) []storageNode {
var ( var (
netmap = getNetmapNodes(ctx) netmap = getNetmapNodes(ctx)

View file

@ -312,22 +312,37 @@ func TestUpdateStateIR(t *testing.T) {
acc := cNm.NewAccount(t) acc := cNm.NewAccount(t)
dummyInfo := dummyNodeInfo(acc) dummyInfo := dummyNodeInfo(acc)
cNm.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo.raw) cNm.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo.raw)
pub := acc.(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes() pub := acc.(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes()
acc1 := cNm.NewAccount(t)
dummyInfo1 := dummyNodeInfo(acc1)
cNm.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo1.raw)
t.Run("must be signed by the alphabet", func(t *testing.T) { t.Run("must be signed by the alphabet", func(t *testing.T) {
cAcc := cNm.WithSigners(acc) cAcc := cNm.WithSigners(acc)
cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "updateStateIR", int64(2), pub) cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "updateStateIR", int64(netmap.OfflineState), pub)
})
t.Run("can't move online", func(t *testing.T) {
cNm.InvokeFail(t, "unsupported state", "updateStateIR", int64(netmap.OnlineState), pub)
}) })
t.Run("invalid state", func(t *testing.T) { t.Run("invalid state", func(t *testing.T) {
cNm.InvokeFail(t, "unsupported state", "updateStateIR", int64(42), pub) cNm.InvokeFail(t, "unsupported state", "updateStateIR", int64(42), pub)
}) })
checkNetmapCandidates(t, cNm, 2)
// Move the first node offline.
cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.OfflineState), pub)
checkNetmapCandidates(t, cNm, 1) checkNetmapCandidates(t, cNm, 1)
t.Run("good", func(t *testing.T) {
cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(2), pub) // Move the second node in the maintenance state.
checkNetmapCandidates(t, cNm, 0) pub1 := acc1.(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes()
}) cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.MaintenanceState), pub1)
arr := checkNetmapCandidates(t, cNm, 1)
nn := arr[0].Value().([]stackitem.Item)
state, err := nn[1].TryInteger()
require.NoError(t, err)
require.Equal(t, int64(netmap.MaintenanceState), state.Int64())
} }
func TestUpdateState(t *testing.T) { func TestUpdateState(t *testing.T) {
@ -365,7 +380,7 @@ func TestUpdateState(t *testing.T) {
checkNetmapCandidates(t, cNm, 0) checkNetmapCandidates(t, cNm, 0)
} }
func checkNetmapCandidates(t *testing.T, c *neotest.ContractInvoker, size int) { func checkNetmapCandidates(t *testing.T, c *neotest.ContractInvoker, size int) []stackitem.Item {
s, err := c.TestInvoke(t, "netmapCandidates") s, err := c.TestInvoke(t, "netmapCandidates")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, s.Len()) require.Equal(t, 1, s.Len())
@ -373,4 +388,5 @@ func checkNetmapCandidates(t *testing.T, c *neotest.ContractInvoker, size int) {
arr, ok := s.Pop().Value().([]stackitem.Item) arr, ok := s.Pop().Value().([]stackitem.Item)
require.True(t, ok) require.True(t, ok)
require.Equal(t, size, len(arr)) require.Equal(t, size, len(arr))
return arr
} }