Merge pull request #2181 from nspcc-dev/states-diff_testnet_289026
core: fix NEO balance state handler
This commit is contained in:
commit
4743d5aacf
7 changed files with 82 additions and 4 deletions
|
@ -28,6 +28,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
|
@ -395,6 +396,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
|
|||
},
|
||||
}
|
||||
require.NoError(t, addNetworkFee(bc, transferTx, acc0))
|
||||
transferTx.SystemFee += 1000000
|
||||
require.NoError(t, acc0.SignTx(testchain.Network(), transferTx))
|
||||
|
||||
b = bc.newBlock(initTx, transferTx)
|
||||
|
@ -415,6 +417,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
|
|||
},
|
||||
}
|
||||
require.NoError(t, addNetworkFee(bc, transferTx, acc0))
|
||||
transferTx.SystemFee += 1000000
|
||||
require.NoError(t, acc0.SignTx(testchain.Network(), transferTx))
|
||||
|
||||
b = bc.newBlock(transferTx)
|
||||
|
@ -603,14 +606,20 @@ func prepareContractMethodInvokeGeneric(chain *Blockchain, sysfee int64,
|
|||
func signTxWithAccounts(chain *Blockchain, tx *transaction.Transaction, accs ...*wallet.Account) {
|
||||
scope := transaction.CalledByEntry
|
||||
for _, acc := range accs {
|
||||
accH, _ := address.StringToUint160(acc.Address)
|
||||
tx.Signers = append(tx.Signers, transaction.Signer{
|
||||
Account: acc.PrivateKey().GetScriptHash(),
|
||||
Account: accH,
|
||||
Scopes: scope,
|
||||
})
|
||||
scope = transaction.Global
|
||||
}
|
||||
size := io.GetVarSize(tx)
|
||||
for _, acc := range accs {
|
||||
if acc.Contract.Deployed {
|
||||
// don't need precise calculation for tests
|
||||
tx.NetworkFee += 1000_0000
|
||||
continue
|
||||
}
|
||||
netFee, sizeDelta := fee.Calculate(chain.GetBaseExecFee(), acc.Contract.Script)
|
||||
size += sizeDelta
|
||||
tx.NetworkFee += netFee
|
||||
|
|
|
@ -442,6 +442,15 @@ func (n *NEO) distributeGas(ic *interop.Context, h util.Uint160, acc *state.NEOB
|
|||
return err
|
||||
}
|
||||
acc.BalanceHeight = ic.Block.Index
|
||||
|
||||
// Must store acc before GAS distribution to fix acc's BalanceHeight value in the storage for
|
||||
// further acc's queries from `onNEP17Payment` if so, see https://github.com/nspcc-dev/neo-go/pull/2181.
|
||||
key := makeAccountKey(h)
|
||||
err = ic.DAO.PutStorageItem(n.ID, key, acc.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to store acc before gas distribution: %w", err)
|
||||
}
|
||||
|
||||
n.GAS.mint(ic, h, gen, true)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -195,6 +195,39 @@ func TestNEO_Vote(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestNEO_RecursiveDistribution is a test for https://github.com/nspcc-dev/neo-go/pull/2181.
|
||||
func TestNEO_RecursiveGASMint(t *testing.T) {
|
||||
bc := newTestChain(t)
|
||||
initBasicChain(t, bc)
|
||||
|
||||
contractHash, err := bc.GetContractScriptHash(1) // deployed rpc/server/testdata/test_contract.go contract
|
||||
require.NoError(t, err)
|
||||
tx := transferTokenFromMultisigAccount(t, bc, contractHash, bc.contracts.GAS.Hash, 2_0000_0000)
|
||||
checkTxHalt(t, bc, tx.Hash())
|
||||
|
||||
// Transfer 10 NEO to test contract, the contract should earn some GAS by owning this NEO.
|
||||
tx = transferTokenFromMultisigAccount(t, bc, contractHash, bc.contracts.NEO.Hash, 10)
|
||||
res, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, res[0].VMState)
|
||||
|
||||
// Add blocks to be able to trigger NEO transfer from contract address to owner
|
||||
// address inside onNEP17Payment (the contract starts NEO transfers from chain height = 100).
|
||||
for i := bc.BlockHeight(); i < 100; i++ {
|
||||
require.NoError(t, bc.AddBlock(bc.newBlock()))
|
||||
}
|
||||
|
||||
// Transfer 1 more NEO to the contract. Transfer will trigger onNEP17Payment. OnNEP17Payment will
|
||||
// trigger transfer of 11 NEO to the contract owner (based on the contract code). 11 NEO Transfer will
|
||||
// trigger GAS distribution. GAS transfer will trigger OnNEP17Payment one more time. The recursion
|
||||
// shouldn't occur here, because contract's balance LastUpdated height has already been updated in
|
||||
// this block.
|
||||
tx = transferTokenFromMultisigAccount(t, bc, contractHash, bc.contracts.NEO.Hash, 1)
|
||||
res, err = bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, vm.HaltState, res[0].VMState, res[0].FaultException)
|
||||
}
|
||||
|
||||
func TestNEO_SetGasPerBlock(t *testing.T) {
|
||||
bc := newTestChain(t)
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ type rpcTestCase struct {
|
|||
check func(t *testing.T, e *executor, result interface{})
|
||||
}
|
||||
|
||||
const testContractHash = "bb6a679438ce0fc6cb0ed1aa85ce83cf96cd3aeb"
|
||||
const deploymentTxHash = "4c631654b04f6a3b25af45082d260b555de4d0eeba6b7697e3a0f18b3f96434f"
|
||||
const testContractHash = "5c9e40a12055c6b9e3f72271c9779958c842135d"
|
||||
const deploymentTxHash = "fefc10d2f7e323282cb50838174b68979b1794c1e5131f2b4737acbc5dde5932"
|
||||
const genesisBlockHash = "0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4"
|
||||
|
||||
const verifyContractHash = "f68822e4ecd93de334bdf1f7c409eda3431bcbd0"
|
||||
|
@ -1650,7 +1650,7 @@ func checkNep17Balances(t *testing.T, e *executor, acc interface{}) {
|
|||
},
|
||||
{
|
||||
Asset: e.chain.UtilityTokenHash(),
|
||||
Amount: "57900879260",
|
||||
Amount: "57898138260",
|
||||
LastUpdated: 15,
|
||||
}},
|
||||
Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(),
|
||||
|
|
25
pkg/rpc/server/testdata/test_contract.go
vendored
25
pkg/rpc/server/testdata/test_contract.go
vendored
|
@ -3,9 +3,12 @@ package testdata
|
|||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/neo"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -13,6 +16,8 @@ const (
|
|||
decimals = 2
|
||||
)
|
||||
|
||||
var owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB")
|
||||
|
||||
func Init() bool {
|
||||
ctx := storage.GetContext()
|
||||
h := runtime.GetExecutingScriptHash()
|
||||
|
@ -22,6 +27,26 @@ func Init() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
||||
curr := runtime.GetExecutingScriptHash()
|
||||
balance := neo.BalanceOf(curr)
|
||||
if ledger.CurrentIndex() >= 100 {
|
||||
ok := neo.Transfer(curr, owner, balance, nil)
|
||||
if !ok {
|
||||
panic("owner transfer failed")
|
||||
}
|
||||
ok = neo.Transfer(curr, owner, 0, nil)
|
||||
if !ok {
|
||||
panic("owner transfer failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify always returns true and is aimed to serve the TestNEO_RecursiveGASMint.
|
||||
func Verify() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
||||
ctx := storage.GetContext()
|
||||
if len(from) != 20 {
|
||||
|
|
2
pkg/rpc/server/testdata/test_contract.yml
vendored
2
pkg/rpc/server/testdata/test_contract.yml
vendored
|
@ -11,4 +11,6 @@ events:
|
|||
- name: amount
|
||||
type: Integer
|
||||
permissions:
|
||||
- hash: ef4073a0f2b305a38ec4050e4d3d28bc40ea63f5
|
||||
methods: ["transfer"]
|
||||
- methods: ["onNEP17Payment"]
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
Loading…
Reference in a new issue