diff --git a/netmap/netmap_contract.go b/netmap/netmap_contract.go index 3c873e2..8c25e4c 100644 --- a/netmap/netmap_contract.go +++ b/netmap/netmap_contract.go @@ -314,12 +314,13 @@ func UpdateState(state int, publicKey interop.PublicKey) { common.CheckAlphabetWitness(common.AlphabetAddress()) } - switch NodeState(state) { + st := NodeState(state) + switch st { case OfflineState: removeFromNetmap(ctx, publicKey) runtime.Log("remove storage node from the network map") - case MaintenanceState: - updateNetmapState(ctx, publicKey, MaintenanceState) + case MaintenanceState, OnlineState: + updateNetmapState(ctx, publicKey, st) runtime.Log("move storage node to a maintenance state") default: panic("unsupported state") @@ -342,8 +343,8 @@ func UpdateStateIR(state NodeState, publicKey interop.PublicKey) { switch state { case OfflineState: removeFromNetmap(ctx, publicKey) - case MaintenanceState: - updateNetmapState(ctx, publicKey, MaintenanceState) + case MaintenanceState, OnlineState: + updateNetmapState(ctx, publicKey, state) default: panic("unsupported state") } @@ -658,6 +659,9 @@ func removeFromNetmap(ctx storage.Context, key interop.PublicKey) { func updateNetmapState(ctx storage.Context, key interop.PublicKey, state NodeState) { storageKey := append(candidatePrefix, key...) raw := storage.Get(ctx, storageKey).([]byte) + if raw == nil { + panic("peer is missing") + } node := std.Deserialize(raw).(netmapNode) node.state = state storage.Put(ctx, storageKey, std.Serialize(node)) diff --git a/tests/netmap_test.go b/tests/netmap_test.go index 375d0ae..e56ce04 100644 --- a/tests/netmap_test.go +++ b/tests/netmap_test.go @@ -310,9 +310,14 @@ func TestUpdateStateIR(t *testing.T) { cNm := newNetmapInvoker(t) acc := cNm.NewAccount(t) + pub := acc.(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes() + + t.Run("can't move online, need addPeerIR", func(t *testing.T) { + cNm.InvokeFail(t, "peer is missing", "updateStateIR", int64(netmap.OnlineState), pub) + }) + dummyInfo := dummyNodeInfo(acc) cNm.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo.raw) - pub := acc.(neotest.SingleSigner).Account().PrivateKey().PublicKey().Bytes() acc1 := cNm.NewAccount(t) dummyInfo1 := dummyNodeInfo(acc1) @@ -322,9 +327,6 @@ func TestUpdateStateIR(t *testing.T) { cAcc := cNm.WithSigners(acc) 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) { cNm.InvokeFail(t, "unsupported state", "updateStateIR", int64(42), pub) }) @@ -335,14 +337,28 @@ func TestUpdateStateIR(t *testing.T) { cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.OfflineState), pub) checkNetmapCandidates(t, cNm, 1) + checkState := func(expected netmap.NodeState) { + arr := checkNetmapCandidates(t, cNm, 1) + nn := arr[0].Value().([]stackitem.Item) + state, err := nn[1].TryInteger() + require.NoError(t, err) + require.Equal(t, int64(expected), state.Int64()) + } + // Move the second node in the maintenance state. 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()) + t.Run("maintenance -> add peer", func(t *testing.T) { + cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.MaintenanceState), pub1) + checkState(netmap.MaintenanceState) + cNm.Invoke(t, stackitem.Null{}, "addPeerIR", dummyInfo1.raw) + checkState(netmap.OnlineState) + }) + t.Run("maintenance -> online", func(t *testing.T) { + cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.MaintenanceState), pub1) + checkState(netmap.MaintenanceState) + cNm.Invoke(t, stackitem.Null{}, "updateStateIR", int64(netmap.OnlineState), pub1) + checkState(netmap.OnlineState) + }) } func TestUpdateState(t *testing.T) {