neo-go/pkg/core/native_policy_test.go
2020-08-14 12:08:57 +03:00

253 lines
8.1 KiB
Go

package core
import (
"math/big"
"sort"
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
func TestMaxTransactionsPerBlock(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
t.Run("get, internal method", func(t *testing.T) {
n := chain.contracts.Policy.GetMaxTransactionsPerBlockInternal(chain.dao)
require.Equal(t, 512, int(n))
})
t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getMaxTransactionsPerBlock")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(512)))
require.NoError(t, chain.persist())
})
t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxTransactionsPerBlock", bigint.ToBytes(big.NewInt(1024)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
n := chain.contracts.Policy.GetMaxTransactionsPerBlockInternal(chain.dao)
require.Equal(t, 1024, int(n))
})
}
func TestMaxBlockSize(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
t.Run("get, internal method", func(t *testing.T) {
n := chain.contracts.Policy.GetMaxBlockSizeInternal(chain.dao)
require.Equal(t, 1024*256, int(n))
})
t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getMaxBlockSize")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(1024*256)))
require.NoError(t, chain.persist())
})
t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxBlockSize", bigint.ToBytes(big.NewInt(102400)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
res, err = invokeNativePolicyMethod(chain, "getMaxBlockSize")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(102400)))
require.NoError(t, chain.persist())
})
}
func TestFeePerByte(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
t.Run("get, internal method", func(t *testing.T) {
n := chain.contracts.Policy.GetFeePerByteInternal(chain.dao)
require.Equal(t, 1000, int(n))
})
t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getFeePerByte")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(1000)))
require.NoError(t, chain.persist())
})
t.Run("set", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setFeePerByte", bigint.ToBytes(big.NewInt(1024)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
n := chain.contracts.Policy.GetFeePerByteInternal(chain.dao)
require.Equal(t, 1024, int(n))
})
}
func TestBlockSystemFee(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
t.Run("get, internal method", func(t *testing.T) {
n := chain.contracts.Policy.GetMaxBlockSystemFeeInternal(chain.dao)
require.Equal(t, 9000*native.GASFactor, int(n))
})
t.Run("get", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getMaxBlockSystemFee")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(9000*native.GASFactor)))
require.NoError(t, chain.persist())
})
t.Run("set, too low fee", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxBlockSystemFee", bigint.ToBytes(big.NewInt(4007600)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(false))
})
t.Run("set, success", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "setMaxBlockSystemFee", bigint.ToBytes(big.NewInt(100000000)))
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
res, err = invokeNativePolicyMethod(chain, "getMaxBlockSystemFee")
require.NoError(t, err)
checkResult(t, res, stackitem.NewBigInteger(big.NewInt(100000000)))
require.NoError(t, chain.persist())
})
}
func TestBlockedAccounts(t *testing.T) {
chain := newTestChain(t)
defer chain.Close()
account := util.Uint160{1, 2, 3}
t.Run("get, internal method", func(t *testing.T) {
accounts, err := chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err)
require.Equal(t, native.BlockedAccounts{}, accounts)
})
t.Run("get, contract method", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "getBlockedAccounts")
require.NoError(t, err)
checkResult(t, res, stackitem.NewArray([]stackitem.Item{}))
require.NoError(t, chain.persist())
})
t.Run("block-unblock account", func(t *testing.T) {
res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
accounts, err := chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err)
require.Equal(t, native.BlockedAccounts{account}, accounts)
require.NoError(t, chain.persist())
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
accounts, err = chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err)
require.Equal(t, native.BlockedAccounts{}, accounts)
require.NoError(t, chain.persist())
})
t.Run("double-block", func(t *testing.T) {
// block
res, err := invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
// double-block should fail
res, err = invokeNativePolicyMethod(chain, "blockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(false))
require.NoError(t, chain.persist())
// unblock
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
// unblock the same account should fail as we don't have it blocked
res, err = invokeNativePolicyMethod(chain, "unblockAccount", account.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(false))
require.NoError(t, chain.persist())
})
t.Run("sorted", func(t *testing.T) {
accounts := []util.Uint160{
{2, 3, 4},
{4, 5, 6},
{3, 4, 5},
{1, 2, 3},
}
for _, acc := range accounts {
res, err := invokeNativePolicyMethod(chain, "blockAccount", acc.BytesBE())
require.NoError(t, err)
checkResult(t, res, stackitem.NewBool(true))
require.NoError(t, chain.persist())
}
sort.Slice(accounts, func(i, j int) bool {
return accounts[i].Less(accounts[j])
})
actual, err := chain.contracts.Policy.GetBlockedAccountsInternal(chain.dao)
require.NoError(t, err)
require.Equal(t, native.BlockedAccounts(accounts), actual)
})
}
func invokeNativePolicyMethod(chain *Blockchain, method string, args ...interface{}) (*state.AppExecResult, error) {
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, chain.contracts.Policy.Metadata().Hash, method, args...)
if w.Err != nil {
return nil, w.Err
}
script := w.Bytes()
tx := transaction.New(chain.GetConfig().Magic, script, 10000000)
validUntil := chain.blockHeight + 1
tx.ValidUntilBlock = validUntil
addSigners(tx)
err := signTx(chain, tx)
if err != nil {
return nil, err
}
b := chain.newBlock(tx)
err = chain.AddBlock(b)
if err != nil {
return nil, err
}
res, err := chain.GetAppExecResult(tx.Hash())
if err != nil {
return nil, err
}
return res, nil
}
func checkResult(t *testing.T, result *state.AppExecResult, expected stackitem.Item) {
require.Equal(t, vm.HaltState, result.VMState)
require.Equal(t, 1, len(result.Stack))
require.Equal(t, expected, result.Stack[0])
}