vm: fix unclaimedGas calculation

Fix difference with C#:
```
(base) ekaterinapavlova@MacBook-Air-4 neo-go % curl -X POST
http://seed1t5.neo.org:20332 -H 'Content-Type: application/json' -d '{
  "jsonrpc": "2.0",
  "method": "getapplicationlog",
  "params":
  ["61681ce24dffea5481e9a50b10159b43b7ebfc21967b0b06fee7ff69c7123e3f"],
  "id": 1
}' | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time
  Current
                                 Dload  Upload   Total   Spent    Left
                                 Speed
100   429    0   269  100   160    582    346 --:--:-- --:--:-- --:--:--
   930
{
   "id" : 1,
   "jsonrpc" : "2.0",
   "result" : {
      "executions" : [
         {
            "exception" : null,
            "gasconsumed" : "198754",
            "notifications" : [],
            "stack" : [
               {
                  "type" : "Integer",
                  "value" : "0"
               }
            ],
            "trigger" : "Application",
            "vmstate" : "HALT"
         }
      ],
      "txid" :
      "0x61681ce24dffea5481e9a50b10159b43b7ebfc21967b0b06fee7ff69c7123e3
      f"
   }
}
```
(base) ekaterinapavlova@MacBook-Air-4 neo-go % curl -X POST  https://rpc
.t5.n3.nspcc.ru:20331 -H 'Content-Type: application/json' -d '{
  "jsonrpc": "2.0",
  "method": "getapplicationlog",
  "params":
  ["61681ce24dffea5481e9a50b10159b43b7ebfc21967b0b06fee7ff69c7123e3f"],
  "id": 1
}' | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time
  Current
                                 Dload  Upload   Total   Spent    Left
                                 Speed
100   583  100   423  100   160   1424    538 --:--:-- --:--:-- --:--:--
  1969
{
   "id" : 1,
   "jsonrpc" : "2.0",
   "result" : {
      "executions" : [
         {
            "exception" : "at instruction 120 (SYSCALL): can't calculate
             bonus of height unequal (BlockHeight + 1)",
            "gasconsumed" : "198754",
            "notifications" : [],
            "stack" : [
               {
                  "type" : "Integer",
                  "value" : "4704605"
               },
               {
                  "type" : "ByteString",
                  "value" : "KfYYlDe/fxqqqm1yr7o5XLnQ7uk="
               }
            ],
            "trigger" : "Application",
            "vmstate" : "FAULT"
         }
      ],
      "txid" :
      "0x61681ce24dffea5481e9a50b10159b43b7ebfc21967b0b06fee7ff69c7123e3
      f"
   }
}

```
```
(base) ekaterinapavlova@MacBook-Air-4 neo-go % ./bin/neo-go contract
invokefunction -r https://rpc.t5.n3.nspcc.ru:20331 -w ./testnet_wallet
.json 1e6f88377a6c6bc4f683a5fc61eed5645ec5f123 unclaimedGas
e9eed0b95c39baaf726daaaa1a7fbf379418f629 4704605
Enter account NWtk9HYWsf1njtSzA3XNgwZXRtriACcJ9G password >
Warning: FAULT VM state returned from the RPC node: at instruction 120
(SYSCALL): can't calculate bonus of height unequal (BlockHeight + 1).
Use --force flag to send the transaction anyway.
```

Close #3589

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
Ekaterina Pavlova 2024-09-30 15:21:19 +03:00
parent b1068b1ab9
commit 02727b14b7
2 changed files with 36 additions and 4 deletions

View file

@ -750,18 +750,21 @@ func makeVoterKey(pub []byte, prealloc ...[]byte) []byte {
// CalculateBonus calculates amount of gas generated for holding value NEO from start to end block // CalculateBonus calculates amount of gas generated for holding value NEO from start to end block
// and having voted for active committee member. // and having voted for active committee member.
func (n *NEO) CalculateBonus(ic *interop.Context, acc util.Uint160, end uint32) (*big.Int, error) { func (n *NEO) CalculateBonus(ic *interop.Context, acc util.Uint160, end uint32) (*big.Int, error) {
if ic.Block == nil || end != ic.Block.Index {
return nil, errors.New("can't calculate bonus of height unequal (BlockHeight + 1)")
}
key := makeAccountKey(acc) key := makeAccountKey(acc)
si := ic.DAO.GetStorageItem(n.ID, key) si := ic.DAO.GetStorageItem(n.ID, key)
if si == nil { if si == nil {
return nil, storage.ErrKeyNotFound return big.NewInt(0), nil
} }
st, err := state.NEOBalanceFromBytes(si) st, err := state.NEOBalanceFromBytes(si)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if st.Balance.Sign() == 0 {
return big.NewInt(0), nil
}
if ic.Block == nil || end != ic.Block.Index {
return nil, errors.New("can't calculate bonus of height unequal (BlockHeight + 1)")
}
return n.calculateBonus(ic.DAO, st, end) return n.calculateBonus(ic.DAO, st, end)
} }

View file

@ -776,6 +776,35 @@ func TestNEO_CalculateBonus(t *testing.T) {
}) })
} }
func TestNEO_UnclaimedGas(t *testing.T) {
neoValidatorsInvoker := newNeoValidatorsClient(t)
e := neoValidatorsInvoker.Executor
acc := neoValidatorsInvoker.WithSigners(e.NewAccount(t))
accH := acc.Signers[0].ScriptHash()
t.Run("non-existing account", func(t *testing.T) {
// non-existing account, should return zero unclaimed GAS.
acc.Invoke(t, 0, "unclaimedGas", util.Uint160{}, 1)
})
t.Run("non-zero balance", func(t *testing.T) {
amount := 100
defaultGASPerBlock := 5
neoHolderRewardRatio := 10
rewardDistance := 10
neoValidatorsInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), accH, amount, nil)
for range rewardDistance - 1 {
e.AddNewBlock(t)
}
expectedGas := int64(amount * neoHolderRewardRatio / 100 * defaultGASPerBlock * rewardDistance)
acc.Invoke(t, expectedGas, "unclaimedGas", accH, e.Chain.BlockHeight()+1)
acc.InvokeFail(t, "can't calculate bonus of height unequal (BlockHeight + 1)", "unclaimedGas", accH, e.Chain.BlockHeight())
})
}
func TestNEO_GetCandidates(t *testing.T) { func TestNEO_GetCandidates(t *testing.T) {
neoCommitteeInvoker := newNeoCommitteeClient(t, 100_0000_0000) neoCommitteeInvoker := newNeoCommitteeClient(t, 100_0000_0000)
neoValidatorsInvoker := neoCommitteeInvoker.WithSigners(neoCommitteeInvoker.Validator) neoValidatorsInvoker := neoCommitteeInvoker.WithSigners(neoCommitteeInvoker.Validator)