[#224] netmap: Refactor snapshot processing

Swap keys instead of unmarshaling/marshaling snapshot during `NewEpoch`.

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2022-03-10 13:53:36 +03:00 committed by Alex Vanin
parent f6766a144f
commit 9884f8e68f

View file

@ -35,8 +35,11 @@ const (
notaryDisabledKey = "notary" notaryDisabledKey = "notary"
innerRingKey = "innerring" innerRingKey = "innerring"
snapshot0Key = "snapshotCurrent" // SnapshotCount contains the number of previous snapshots stored by this contract.
snapshot1Key = "snapshotPrevious" // Must be less than 255.
SnapshotCount = 2
snapshotKeyPrefix = "snapshot_"
snapshotCurrentIDKey = "snapshotCurrent"
snapshotEpoch = "snapshotEpoch" snapshotEpoch = "snapshotEpoch"
snapshotBlockKey = "snapshotBlock" snapshotBlockKey = "snapshotBlock"
@ -85,6 +88,15 @@ func _deploy(data interface{}, isUpdate bool) {
if isUpdate { if isUpdate {
common.CheckVersion(args.version) common.CheckVersion(args.version)
data = storage.Get(ctx, "snapshotPrevious")
storage.Put(ctx, snapshotKeyPrefix+"0", data)
data := storage.Get(ctx, "snapshotCurrent")
storage.Put(ctx, snapshotKeyPrefix+"1", data)
storage.Put(ctx, snapshotCurrentIDKey, 1)
return return
} }
@ -96,8 +108,11 @@ func _deploy(data interface{}, isUpdate bool) {
storage.Put(ctx, snapshotEpoch, 0) storage.Put(ctx, snapshotEpoch, 0)
storage.Put(ctx, snapshotBlockKey, 0) storage.Put(ctx, snapshotBlockKey, 0)
common.SetSerialized(ctx, snapshot0Key, []netmapNode{}) prefix := []byte(snapshotKeyPrefix)
common.SetSerialized(ctx, snapshot1Key, []netmapNode{}) for i := 0; i < SnapshotCount; i++ {
common.SetSerialized(ctx, append(prefix, byte(i)), []storageNode{})
}
common.SetSerialized(ctx, snapshotCurrentIDKey, 0)
storage.Put(ctx, balanceContractKey, args.addrBalance) storage.Put(ctx, balanceContractKey, args.addrBalance)
storage.Put(ctx, containerContractKey, args.addrContainer) storage.Put(ctx, containerContractKey, args.addrContainer)
@ -381,7 +396,6 @@ func NewEpoch(epochNum int) {
panic("invalid epoch") // ignore invocations with invalid epoch panic("invalid epoch") // ignore invocations with invalid epoch
} }
data0snapshot := getSnapshot(ctx, snapshot0Key)
dataOnlineState := filterNetmap(ctx, onlineState) dataOnlineState := filterNetmap(ctx, onlineState)
runtime.Log("process new epoch") runtime.Log("process new epoch")
@ -390,11 +404,12 @@ func NewEpoch(epochNum int) {
storage.Put(ctx, snapshotEpoch, epochNum) storage.Put(ctx, snapshotEpoch, epochNum)
storage.Put(ctx, snapshotBlockKey, ledger.CurrentIndex()) storage.Put(ctx, snapshotBlockKey, ledger.CurrentIndex())
// put actual snapshot into previous snapshot id := storage.Get(ctx, snapshotCurrentIDKey).(int)
common.SetSerialized(ctx, snapshot1Key, data0snapshot) id = (id + 1) % SnapshotCount
storage.Put(ctx, snapshotCurrentIDKey, id)
// put netmap into actual snapshot // put netmap into actual snapshot
common.SetSerialized(ctx, snapshot0Key, dataOnlineState) common.SetSerialized(ctx, snapshotKeyPrefix+string([]byte{byte(id)}), dataOnlineState)
// make clean up routines in other contracts // make clean up routines in other contracts
cleanup(ctx, epochNum) cleanup(ctx, epochNum)
@ -419,10 +434,11 @@ func LastEpochBlock() int {
// of current epoch. // of current epoch.
func Netmap() []storageNode { func Netmap() []storageNode {
ctx := storage.GetReadOnlyContext() ctx := storage.GetReadOnlyContext()
return getSnapshot(ctx, snapshot0Key) id := storage.Get(ctx, snapshotCurrentIDKey).(int)
return getSnapshot(ctx, snapshotKeyPrefix+string([]byte{byte(id)}))
} }
// Snapshot method returns list of structures that contain node state // NetmapCandidates method returns list of structures that contain node state
// and byte array of stable marshalled netmap.NodeInfo structure. // and byte array of stable marshalled netmap.NodeInfo structure.
// These structure contain Storage node candidates for next epoch. // These structure contain Storage node candidates for next epoch.
func NetmapCandidates() []netmapNode { func NetmapCandidates() []netmapNode {
@ -437,18 +453,14 @@ func NetmapCandidates() []netmapNode {
// Netmap contract contains only two recent network map snapshot: current and // Netmap contract contains only two recent network map snapshot: current and
// previous epoch. For diff bigger than 1 or less than 0 method throws panic. // previous epoch. For diff bigger than 1 or less than 0 method throws panic.
func Snapshot(diff int) []storageNode { func Snapshot(diff int) []storageNode {
var key string if diff < 0 || SnapshotCount <= diff {
switch diff {
case 0:
key = snapshot0Key
case 1:
key = snapshot1Key
default:
panic("incorrect diff") panic("incorrect diff")
} }
ctx := storage.GetReadOnlyContext() ctx := storage.GetReadOnlyContext()
id := storage.Get(ctx, snapshotCurrentIDKey).(int)
needID := (id - diff + SnapshotCount) % SnapshotCount
key := snapshotKeyPrefix + string([]byte{byte(needID)})
return getSnapshot(ctx, key) return getSnapshot(ctx, key)
} }