github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/native/native_test/policy_test.go (about)

     1  package native_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/core/interop"
     8  	"github.com/nspcc-dev/neo-go/pkg/core/native"
     9  	"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
    10  	"github.com/nspcc-dev/neo-go/pkg/core/transaction"
    11  	"github.com/nspcc-dev/neo-go/pkg/io"
    12  	"github.com/nspcc-dev/neo-go/pkg/neotest"
    13  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
    14  	"github.com/nspcc-dev/neo-go/pkg/util"
    15  	"github.com/nspcc-dev/neo-go/pkg/vm/emit"
    16  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
    17  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    18  )
    19  
    20  func newPolicyClient(t *testing.T) *neotest.ContractInvoker {
    21  	return newNativeClient(t, nativenames.Policy)
    22  }
    23  
    24  func TestPolicy_FeePerByte(t *testing.T) {
    25  	testGetSet(t, newPolicyClient(t), "FeePerByte", 1000, 0, 100_000_000)
    26  }
    27  
    28  func TestPolicy_FeePerByteCache(t *testing.T) {
    29  	testGetSetCache(t, newPolicyClient(t), "FeePerByte", 1000)
    30  }
    31  
    32  func TestPolicy_ExecFeeFactor(t *testing.T) {
    33  	testGetSet(t, newPolicyClient(t), "ExecFeeFactor", interop.DefaultBaseExecFee, 1, 1000)
    34  }
    35  
    36  func TestPolicy_ExecFeeFactorCache(t *testing.T) {
    37  	testGetSetCache(t, newPolicyClient(t), "ExecFeeFactor", interop.DefaultBaseExecFee)
    38  }
    39  
    40  func TestPolicy_StoragePrice(t *testing.T) {
    41  	testGetSet(t, newPolicyClient(t), "StoragePrice", native.DefaultStoragePrice, 1, 10000000)
    42  }
    43  
    44  func TestPolicy_StoragePriceCache(t *testing.T) {
    45  	testGetSetCache(t, newPolicyClient(t), "StoragePrice", native.DefaultStoragePrice)
    46  }
    47  
    48  func TestPolicy_AttributeFee(t *testing.T) {
    49  	c := newPolicyClient(t)
    50  	getName := "getAttributeFee"
    51  	setName := "setAttributeFee"
    52  
    53  	randomInvoker := c.WithSigners(c.NewAccount(t))
    54  	committeeInvoker := c.WithSigners(c.Committee)
    55  
    56  	t.Run("set, not signed by committee", func(t *testing.T) {
    57  		randomInvoker.InvokeFail(t, "invalid committee signature", setName, byte(transaction.ConflictsT), 123)
    58  	})
    59  	t.Run("get, unknown attribute", func(t *testing.T) {
    60  		randomInvoker.InvokeFail(t, "invalid attribute type: 84", getName, byte(0x54))
    61  	})
    62  	t.Run("get, default value", func(t *testing.T) {
    63  		randomInvoker.Invoke(t, 0, getName, byte(transaction.ConflictsT))
    64  	})
    65  	t.Run("set, too large value", func(t *testing.T) {
    66  		committeeInvoker.InvokeFail(t, "out of range", setName, byte(transaction.ConflictsT), 10_0000_0001)
    67  	})
    68  	t.Run("set, unknown attribute", func(t *testing.T) {
    69  		committeeInvoker.InvokeFail(t, "invalid attribute type: 84", setName, 0x54, 5)
    70  	})
    71  	t.Run("set, success", func(t *testing.T) {
    72  		// Set and get in the same block.
    73  		txSet := committeeInvoker.PrepareInvoke(t, setName, byte(transaction.ConflictsT), 1)
    74  		txGet := randomInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
    75  		c.AddNewBlock(t, txSet, txGet)
    76  		c.CheckHalt(t, txSet.Hash(), stackitem.Null{})
    77  		c.CheckHalt(t, txGet.Hash(), stackitem.Make(1))
    78  		// Get in the next block.
    79  		randomInvoker.Invoke(t, 1, getName, byte(transaction.ConflictsT))
    80  	})
    81  }
    82  
    83  func TestPolicy_AttributeFeeCache(t *testing.T) {
    84  	c := newPolicyClient(t)
    85  	getName := "getAttributeFee"
    86  	setName := "setAttributeFee"
    87  
    88  	committeeInvoker := c.WithSigners(c.Committee)
    89  
    90  	// Change fee, abort the transaction and check that contract cache wasn't persisted
    91  	// for FAULTed tx at the same block.
    92  	w := io.NewBufBinWriter()
    93  	emit.AppCall(w.BinWriter, committeeInvoker.Hash, setName, callflag.All, byte(transaction.ConflictsT), 5)
    94  	emit.Opcodes(w.BinWriter, opcode.ABORT)
    95  	tx1 := committeeInvoker.PrepareInvocation(t, w.Bytes(), committeeInvoker.Signers)
    96  	tx2 := committeeInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
    97  	committeeInvoker.AddNewBlock(t, tx1, tx2)
    98  	committeeInvoker.CheckFault(t, tx1.Hash(), "ABORT")
    99  	committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(0))
   100  
   101  	// Change fee and check that change is available for the next tx.
   102  	tx1 = committeeInvoker.PrepareInvoke(t, setName, byte(transaction.ConflictsT), 5)
   103  	tx2 = committeeInvoker.PrepareInvoke(t, getName, byte(transaction.ConflictsT))
   104  	committeeInvoker.AddNewBlock(t, tx1, tx2)
   105  	committeeInvoker.CheckHalt(t, tx1.Hash())
   106  	committeeInvoker.CheckHalt(t, tx2.Hash(), stackitem.Make(5))
   107  }
   108  
   109  func TestPolicy_BlockedAccounts(t *testing.T) {
   110  	c := newPolicyClient(t)
   111  	e := c.Executor
   112  	randomInvoker := c.WithSigners(c.NewAccount(t))
   113  	committeeInvoker := c.WithSigners(c.Committee)
   114  	unlucky := util.Uint160{1, 2, 3}
   115  
   116  	t.Run("isBlocked", func(t *testing.T) {
   117  		randomInvoker.Invoke(t, false, "isBlocked", unlucky)
   118  	})
   119  
   120  	t.Run("block-unblock account", func(t *testing.T) {
   121  		committeeInvoker.Invoke(t, true, "blockAccount", unlucky)
   122  		randomInvoker.Invoke(t, true, "isBlocked", unlucky)
   123  		committeeInvoker.Invoke(t, true, "unblockAccount", unlucky)
   124  		randomInvoker.Invoke(t, false, "isBlocked", unlucky)
   125  	})
   126  
   127  	t.Run("double-block", func(t *testing.T) {
   128  		// block
   129  		committeeInvoker.Invoke(t, true, "blockAccount", unlucky)
   130  
   131  		// double-block should fail
   132  		committeeInvoker.Invoke(t, false, "blockAccount", unlucky)
   133  
   134  		// unblock
   135  		committeeInvoker.Invoke(t, true, "unblockAccount", unlucky)
   136  
   137  		// unblock the same account should fail as we don't have it blocked
   138  		committeeInvoker.Invoke(t, false, "unblockAccount", unlucky)
   139  	})
   140  
   141  	t.Run("not signed by committee", func(t *testing.T) {
   142  		randomInvoker.InvokeFail(t, "invalid committee signature", "blockAccount", unlucky)
   143  		randomInvoker.InvokeFail(t, "invalid committee signature", "unblockAccount", unlucky)
   144  	})
   145  
   146  	t.Run("block-unblock contract", func(t *testing.T) {
   147  		committeeInvoker.InvokeFail(t, "cannot block native contract", "blockAccount", c.NativeHash(t, nativenames.Neo))
   148  
   149  		helper := neotest.CompileFile(t, c.CommitteeHash, "./helpers/policyhelper", "./helpers/policyhelper/policyhelper.yml")
   150  		e.DeployContract(t, helper, nil)
   151  		helperInvoker := e.CommitteeInvoker(helper.Hash)
   152  
   153  		helperInvoker.Invoke(t, true, "do")
   154  		committeeInvoker.Invoke(t, true, "blockAccount", helper.Hash)
   155  		helperInvoker.InvokeFail(t, fmt.Sprintf("contract %s is blocked", helper.Hash.StringLE()), "do")
   156  
   157  		committeeInvoker.Invoke(t, true, "unblockAccount", helper.Hash)
   158  		helperInvoker.Invoke(t, true, "do")
   159  	})
   160  }