Skip to content

Voting to NULL ("unvoting") in NEO doesn't clear LastGasPerVote #2894

@roman-khimov

Description

@roman-khimov

Describe the bug
When some NEO owner removes his previously casted vote completely (that is he calls vote(acc, null)) the old LastGasPerVote value is kept in the account state. It won't be used in any way since VoteTo is null, but it still takes up some storage space.

Not critical, but would be nice to fix in 3.7.

Expected behavior
Clear LastGasPerVote when voting for null.

Current behavior

if (voteTo != null && voteTo != state_account.VoteTo)
{
StorageKey voterRewardKey = CreateStorageKey(Prefix_VoterRewardPerCommittee).Add(voteTo);
var latestGasPerVote = engine.Snapshot.TryGet(voterRewardKey) ?? BigInteger.Zero;
state_account.LastGasPerVote = latestGasPerVote;
}
ECPoint from = state_account.VoteTo;
state_account.VoteTo = voteTo;

(Optional) Additional context
Discovered accidentally with the master version of NeoGo, it had a state diff relative to released 3.6:

block 41660: value mismatch for key +////xTrvgat3qG/w8hQoD/I4MgUz6rygA==: QQQhAS8hA7yiAAAhAA== vs QQQhAS8hA7yiAAAhB+POSWfBCAE=

NeoGo tried to save an account state of

00000000  41 04 21 01 2f 21 03 bc  a2 00 00 21 00           |A.!./!.....!.|

while C# node has

00000000  41 04 21 01 2f 21 03 bc  a2 00 00 21 07 e3 ce 49  |A.!./!.....!...I|
00000010  67 c1 08 01                                       |g...|

(notice zero 21 00 vs value stored in 21 07 ... in the end)

But it's not because NeoGo has the "proper" behavior described above, it's just that it loses LastGasPerVote accidentally during deserialization of non-voting account (see nspcc-dev/neo-go#3122 fix). So both nodes can be improved.

Related to #2841.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions