diff --git a/frostfsid/frostfsid_contract.go b/frostfsid/frostfsid_contract.go index a9cca0e..fd2d446 100644 --- a/frostfsid/frostfsid_contract.go +++ b/frostfsid/frostfsid_contract.go @@ -96,6 +96,7 @@ const ( groupSubjectsKeysPrefix = 'G' groupCounterKey = 'c' namespaceGroupsNamesPrefix = 'm' + addressPrefix = 'A' ) func _deploy(data any, isUpdate bool) { @@ -112,6 +113,27 @@ func _deploy(data any, isUpdate bool) { storage.Put(ctx, adminKey, args.admin) } + if isUpdate { + it := storage.Find(ctx, subjectKeysPrefix, storage.ValuesOnly) + for iterator.Next(it) { + subjectRaw := iterator.Value(it) + subject := std.Deserialize(subjectRaw.([]byte)).(Subject) + address := addressKey(contract.CreateStandardAccount(subject.PrimaryKey)) + if storage.Get(ctx, address) != nil { + panic("frostfsid contract contains duplicate keys") + } + storage.Put(ctx, address, true) + + for i := 0; i < len(subject.AdditionalKeys); i++ { + address = addressKey(contract.CreateStandardAccount(subject.AdditionalKeys[i])) + if storage.Get(ctx, address) != nil { + panic("frostfsid contract contains duplicate keys") + } + storage.Put(ctx, address, true) + } + } + } + storage.Put(ctx, groupCounterKey, 0) storage.Put(ctx, namespaceKey(""), std.Serialize(Namespace{})) @@ -182,6 +204,11 @@ func CreateSubject(ns string, key interop.PublicKey) { panic("key is occupied") } + allAddressKey := addressKey(addr) + if storage.Get(ctx, allAddressKey) != nil { + panic("key is occupied by another additional key") + } + nsKey := namespaceKey(ns) data = storage.Get(ctx, nsKey).([]byte) if data == nil { @@ -197,6 +224,7 @@ func CreateSubject(ns string, key interop.PublicKey) { nsSubjKey := namespaceSubjectKey(ns, addr) storage.Put(ctx, nsSubjKey, []byte{1}) + storage.Put(ctx, allAddressKey, true) runtime.Notify("CreateSubject", interop.Hash160(addr)) } @@ -213,6 +241,11 @@ func AddSubjectKey(addr interop.Hash160, key interop.PublicKey) { panic("incorrect public key length") } + addressKey := addressKey(contract.CreateStandardAccount(key)) + if storage.Get(ctx, addressKey) != nil { + panic("key is occupied") + } + saKey := subjectAdditionalKey(key, addr) data := storage.Get(ctx, saKey).([]byte) if data != nil { @@ -230,6 +263,7 @@ func AddSubjectKey(addr interop.Hash160, key interop.PublicKey) { subject.AdditionalKeys = append(subject.AdditionalKeys, key) storage.Put(ctx, sKey, std.Serialize(subject)) + storage.Put(ctx, addressKey, true) runtime.Notify("AddSubjectKey", addr, key) } @@ -269,6 +303,7 @@ func RemoveSubjectKey(addr interop.Hash160, key interop.PublicKey) { subject.AdditionalKeys = additionalKeys storage.Put(ctx, sKey, std.Serialize(subject)) + storage.Delete(ctx, addressKey(contract.CreateStandardAccount(key))) runtime.Notify("RemoveSubjectKey", addr, key) } @@ -362,6 +397,7 @@ func DeleteSubject(addr interop.Hash160) { for i := 0; i < len(subj.AdditionalKeys); i++ { storage.Delete(ctx, subjectAdditionalKey(subj.AdditionalKeys[i], addr)) + storage.Delete(ctx, addressKey(contract.CreateStandardAccount(subj.AdditionalKeys[i]))) } storage.Delete(ctx, sKey) @@ -1029,3 +1065,7 @@ func idToBytes(itemID int) []byte { zeros := make([]byte, 8-ln) return append(b, zeros...) } + +func addressKey(address []byte) []byte { + return append([]byte{addressPrefix}, address...) +}