forked from TrueCloudLab/frostfs-contract
container: Add DeletionInfo() method
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
2b1fa53b67
commit
c6a7820363
3 changed files with 57 additions and 1 deletions
|
@ -2,6 +2,7 @@ name: "Container"
|
|||
safemethods:
|
||||
- "count"
|
||||
- "containersOf"
|
||||
- "deletionInfo"
|
||||
- "eACL"
|
||||
- "get"
|
||||
- "getContainerSize"
|
||||
|
|
|
@ -64,6 +64,7 @@ const (
|
|||
estimateKeyPrefix = "cnr"
|
||||
containerKeyPrefix = 'x'
|
||||
ownerKeyPrefix = 'o'
|
||||
graveKeyPrefix = 'g'
|
||||
estimatePostfixSize = 10
|
||||
// CleanupDelta contains the number of the last epochs for which container estimations are present.
|
||||
CleanupDelta = 3
|
||||
|
@ -337,6 +338,25 @@ func Delete(containerID []byte, signature interop.Signature, publicKey interop.P
|
|||
runtime.Notify("DeleteSuccess", containerID)
|
||||
}
|
||||
|
||||
type DelInfo struct {
|
||||
Owner interop.Hash160
|
||||
Epoch int
|
||||
}
|
||||
|
||||
// DeletionInfo method returns container deletion info.
|
||||
// If the container had never existed, NotFoundError is throwed.
|
||||
// It can be used to check whether non-existing container was indeed deleted
|
||||
// or does not yet exist at some height.
|
||||
func DeletionInfo(containerID []byte) DelInfo {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
graveKey := append([]byte{graveKeyPrefix}, containerID...)
|
||||
data := storage.Get(ctx, graveKey).([]byte)
|
||||
if data == nil {
|
||||
panic(NotFoundError)
|
||||
}
|
||||
return std.Deserialize(data).(DelInfo)
|
||||
}
|
||||
|
||||
// Get method returns a structure that contains a stable marshaled Container structure,
|
||||
// the signature, the public key of the container creator and a stable marshaled SessionToken
|
||||
// structure if it was provided.
|
||||
|
@ -596,6 +616,9 @@ func addContainer(ctx storage.Context, id, owner []byte, container Container) {
|
|||
|
||||
idKey := append([]byte{containerKeyPrefix}, id...)
|
||||
common.SetSerialized(ctx, idKey, container)
|
||||
|
||||
graveKey := append([]byte{graveKeyPrefix}, id...)
|
||||
storage.Delete(ctx, graveKey)
|
||||
}
|
||||
|
||||
func removeContainer(ctx storage.Context, id []byte, owner []byte) {
|
||||
|
@ -604,6 +627,14 @@ func removeContainer(ctx storage.Context, id []byte, owner []byte) {
|
|||
storage.Delete(ctx, containerListKey)
|
||||
|
||||
storage.Delete(ctx, append([]byte{containerKeyPrefix}, id...))
|
||||
|
||||
graveKey := append([]byte{graveKeyPrefix}, id...)
|
||||
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
|
||||
epoch := contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int)
|
||||
common.SetSerialized(ctx, graveKey, DelInfo{
|
||||
Owner: owner,
|
||||
Epoch: epoch,
|
||||
})
|
||||
}
|
||||
|
||||
func getAllContainers(ctx storage.Context) [][]byte {
|
||||
|
|
|
@ -243,19 +243,43 @@ func addContainer(t *testing.T, c, cBal *neotest.ContractInvoker) (neotest.Signe
|
|||
}
|
||||
|
||||
func TestContainerDelete(t *testing.T) {
|
||||
c, cBal, _ := newContainerInvoker(t)
|
||||
c, cBal, cNm := newContainerInvoker(t)
|
||||
|
||||
acc, cnt := addContainer(t, c, cBal)
|
||||
cAcc := c.WithSigners(acc)
|
||||
cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "delete",
|
||||
cnt.id[:], cnt.sig, cnt.pub, cnt.token)
|
||||
|
||||
newDelInfo := func(acc neotest.Signer, epoch int64) *stackitem.Struct {
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewBuffer([]byte(signerToOwner(acc))),
|
||||
stackitem.NewBigInteger(big.NewInt(epoch)),
|
||||
})
|
||||
}
|
||||
|
||||
c.InvokeFail(t, container.NotFoundError, "deletionInfo", cnt.id[:])
|
||||
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.pub, cnt.token)
|
||||
c.Invoke(t, newDelInfo(acc, 0), "deletionInfo", cnt.id[:])
|
||||
|
||||
t.Run("multi-epoch", func(t *testing.T) {
|
||||
cNm.Invoke(t, stackitem.Null{}, "newEpoch", 1)
|
||||
|
||||
t.Run("epoch tick does not change deletion info", func(t *testing.T) {
|
||||
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.pub, cnt.token)
|
||||
c.Invoke(t, newDelInfo(acc, 0), "deletionInfo", cnt.id[:])
|
||||
})
|
||||
|
||||
acc1, cnt1 := addContainer(t, c, cBal)
|
||||
c.Invoke(t, stackitem.Null{}, "delete", cnt1.id[:], cnt1.sig, cnt1.pub, cnt1.token)
|
||||
c.Invoke(t, newDelInfo(acc, 0), "deletionInfo", cnt.id[:])
|
||||
c.Invoke(t, newDelInfo(acc1, 1), "deletionInfo", cnt1.id[:])
|
||||
})
|
||||
|
||||
t.Run("missing container", func(t *testing.T) {
|
||||
id := cnt.id
|
||||
id[0] ^= 0xFF
|
||||
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.pub, cnt.token)
|
||||
c.InvokeFail(t, container.NotFoundError, "deletionInfo", id[:])
|
||||
})
|
||||
|
||||
c.InvokeFail(t, container.NotFoundError, "get", cnt.id[:])
|
||||
|
|
Loading…
Reference in a new issue