[#42] container: Make GAS costs more predictable in Delete()

Persisting a transaction is done in 2 stages:
1. TestInvoke
2. Sign and send to the network.
3. At some point the tx is persisted.
Some time passes between 1 and 3, this could lead to different GAS
costs. It is a known issue for container delete: different epoch can
have different size in bytes and thus different cost to store.
Here we introduce fixed-length encoding for integers, so that the
problem can be avoided.

Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
Evgenii Stratonikov 2023-10-05 15:01:30 +03:00
parent 1ebeff7f6f
commit 6212b5bf72
2 changed files with 13 additions and 5 deletions

View file

@ -343,6 +343,11 @@ type DelInfo struct {
Epoch int Epoch int
} }
type delInfo struct {
Owner []byte
Epoch []byte
}
// DeletionInfo method returns container deletion info. // DeletionInfo method returns container deletion info.
// If the container had never existed, NotFoundError is throwed. // If the container had never existed, NotFoundError is throwed.
// It can be used to check whether non-existing container was indeed deleted // It can be used to check whether non-existing container was indeed deleted
@ -354,7 +359,12 @@ func DeletionInfo(containerID []byte) DelInfo {
if data == nil { if data == nil {
panic(NotFoundError) panic(NotFoundError)
} }
return std.Deserialize(data).(DelInfo)
d := std.Deserialize(data).(delInfo)
return DelInfo{
Owner: d.Owner,
Epoch: common.FromFixedWidth64(d.Epoch),
}
} }
// Get method returns a structure that contains a stable marshaled Container structure, // Get method returns a structure that contains a stable marshaled Container structure,
@ -631,9 +641,9 @@ func removeContainer(ctx storage.Context, id []byte, owner []byte) {
graveKey := append([]byte{graveKeyPrefix}, id...) graveKey := append([]byte{graveKeyPrefix}, id...)
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160) netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
epoch := contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int) epoch := contract.Call(netmapContractAddr, "epoch", contract.ReadOnly).(int)
common.SetSerialized(ctx, graveKey, DelInfo{ common.SetSerialized(ctx, graveKey, delInfo{
Owner: owner, Owner: owner,
Epoch: epoch, Epoch: common.ToFixedWidth64(epoch),
}) })
} }

View file

@ -283,8 +283,6 @@ func TestContainerDelete(t *testing.T) {
}) })
t.Run("gas costs are the same for different epochs", func(t *testing.T) { t.Run("gas costs are the same for different epochs", func(t *testing.T) {
t.Skip()
_, cnt2 := addContainer(t, c, cBal) _, cnt2 := addContainer(t, c, cBal)
args := []interface{}{cnt2.id[:], cnt2.sig, cnt2.pub, cnt2.token} args := []interface{}{cnt2.id[:], cnt2.sig, cnt2.pub, cnt2.token}