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

     1  package native_test
     2  
     3  import (
     4  	"sort"
     5  	"testing"
     6  
     7  	"github.com/nspcc-dev/neo-go/pkg/config"
     8  	"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
     9  	"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
    10  	"github.com/nspcc-dev/neo-go/pkg/core/state"
    11  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    12  	"github.com/nspcc-dev/neo-go/pkg/io"
    13  	"github.com/nspcc-dev/neo-go/pkg/neotest"
    14  	"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
    15  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
    16  	"github.com/nspcc-dev/neo-go/pkg/util"
    17  	"github.com/nspcc-dev/neo-go/pkg/vm/emit"
    18  	"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
    19  	"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
    20  	"github.com/stretchr/testify/require"
    21  )
    22  
    23  func newDesignateClient(t *testing.T) *neotest.ContractInvoker {
    24  	return newNativeClient(t, nativenames.Designation)
    25  }
    26  
    27  func TestDesignate_DesignateAsRole(t *testing.T) {
    28  	c := newDesignateClient(t)
    29  	e := c.Executor
    30  	designateInvoker := c.WithSigners(c.Committee)
    31  
    32  	priv, err := keys.NewPrivateKey()
    33  	require.NoError(t, err)
    34  	pubs := keys.PublicKeys{priv.PublicKey()}
    35  
    36  	setNodesByRole(t, designateInvoker, false, 0xFF, pubs)
    37  	setNodesByRole(t, designateInvoker, true, noderoles.Oracle, pubs)
    38  	index := e.Chain.BlockHeight() + 1
    39  	checkNodeRoles(t, designateInvoker, false, 0xFF, 0, nil)
    40  	checkNodeRoles(t, designateInvoker, false, noderoles.Oracle, 100500, nil)
    41  	checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, 0, keys.PublicKeys{}) // returns an empty list
    42  	checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, index, pubs)          // returns pubs
    43  
    44  	priv1, err := keys.NewPrivateKey()
    45  	require.NoError(t, err)
    46  	pubs = keys.PublicKeys{priv1.PublicKey()}
    47  	setNodesByRole(t, designateInvoker, true, noderoles.StateValidator, pubs)
    48  	checkNodeRoles(t, designateInvoker, true, noderoles.StateValidator, e.Chain.BlockHeight()+1, pubs)
    49  
    50  	t.Run("neofs", func(t *testing.T) {
    51  		priv, err := keys.NewPrivateKey()
    52  		require.NoError(t, err)
    53  		pubs = keys.PublicKeys{priv.PublicKey()}
    54  		setNodesByRole(t, designateInvoker, true, noderoles.NeoFSAlphabet, pubs)
    55  		checkNodeRoles(t, designateInvoker, true, noderoles.NeoFSAlphabet, e.Chain.BlockHeight()+1, pubs)
    56  	})
    57  }
    58  
    59  type dummyOracle struct {
    60  	updateNodes func(k keys.PublicKeys)
    61  }
    62  
    63  // AddRequests processes new requests.
    64  func (o *dummyOracle) AddRequests(map[uint64]*state.OracleRequest) {
    65  }
    66  
    67  // RemoveRequests removes already processed requests.
    68  func (o *dummyOracle) RemoveRequests([]uint64) {
    69  	panic("TODO")
    70  }
    71  
    72  // UpdateOracleNodes updates oracle nodes.
    73  func (o *dummyOracle) UpdateOracleNodes(k keys.PublicKeys) {
    74  	if o.updateNodes != nil {
    75  		o.updateNodes(k)
    76  		return
    77  	}
    78  	panic("TODO")
    79  }
    80  
    81  // UpdateNativeContract updates oracle contract native script and hash.
    82  func (o *dummyOracle) UpdateNativeContract([]byte, []byte, util.Uint160, int) {
    83  }
    84  
    85  // Start runs oracle module.
    86  func (o *dummyOracle) Start() {
    87  	panic("TODO")
    88  }
    89  
    90  // Shutdown shutdowns oracle module.
    91  func (o *dummyOracle) Shutdown() {
    92  	panic("TODO")
    93  }
    94  
    95  func TestDesignate_Cache(t *testing.T) {
    96  	c := newDesignateClient(t)
    97  	e := c.Executor
    98  	designateInvoker := c.WithSigners(c.Committee)
    99  	r := int64(noderoles.Oracle)
   100  	var (
   101  		updatedNodes keys.PublicKeys
   102  		updateCalled bool
   103  	)
   104  	oracleServ := &dummyOracle{
   105  		updateNodes: func(k keys.PublicKeys) {
   106  			updatedNodes = k
   107  			updateCalled = true
   108  		},
   109  	}
   110  	privGood, err := keys.NewPrivateKey()
   111  	require.NoError(t, err)
   112  	pubsGood := []any{privGood.PublicKey().Bytes()}
   113  
   114  	privBad, err := keys.NewPrivateKey()
   115  	require.NoError(t, err)
   116  	pubsBad := []any{privBad.PublicKey().Bytes()}
   117  
   118  	// Firstly, designate good Oracle node and check that OracleService callback was called during PostPersist.
   119  	e.Chain.SetOracle(oracleServ)
   120  	txDesignateGood := designateInvoker.PrepareInvoke(t, "designateAsRole", r, pubsGood)
   121  	e.AddNewBlock(t, txDesignateGood)
   122  	e.CheckHalt(t, txDesignateGood.Hash(), stackitem.Null{})
   123  	require.True(t, updateCalled)
   124  	require.Equal(t, keys.PublicKeys{privGood.PublicKey()}, updatedNodes)
   125  	updatedNodes = nil
   126  	updateCalled = false
   127  
   128  	// Check designated node in a separate block.
   129  	checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, e.Chain.BlockHeight()+1, keys.PublicKeys{privGood.PublicKey()})
   130  
   131  	// Designate privBad as oracle node and abort the transaction. Designation cache changes
   132  	// shouldn't be persisted to the contract and no notification should be sent.
   133  	w := io.NewBufBinWriter()
   134  	emit.AppCall(w.BinWriter, designateInvoker.Hash, "designateAsRole", callflag.All, int64(r), pubsBad)
   135  	emit.Opcodes(w.BinWriter, opcode.ABORT)
   136  	require.NoError(t, w.Err)
   137  	script := w.Bytes()
   138  
   139  	designateInvoker.InvokeScriptCheckFAULT(t, script, designateInvoker.Signers, "ABORT")
   140  	require.Nil(t, updatedNodes)
   141  	require.False(t, updateCalled)
   142  }
   143  
   144  func TestDesignate_GenesisRolesExtension(t *testing.T) {
   145  	pk1, err := keys.NewPrivateKey()
   146  	require.NoError(t, err)
   147  	pk2, err := keys.NewPrivateKey()
   148  	require.NoError(t, err)
   149  	pubs := keys.PublicKeys{pk1.PublicKey(), pk2.PublicKey()}
   150  
   151  	bc, acc := chain.NewSingleWithCustomConfig(t, func(blockchain *config.Blockchain) {
   152  		blockchain.Genesis.Roles = map[noderoles.Role]keys.PublicKeys{
   153  			noderoles.StateValidator: pubs,
   154  		}
   155  	})
   156  	e := neotest.NewExecutor(t, bc, acc, acc)
   157  	c := e.CommitteeInvoker(e.NativeHash(t, nativenames.Designation))
   158  
   159  	// Check designated node in a separate block.
   160  	sort.Sort(pubs)
   161  	checkNodeRoles(t, c, true, noderoles.StateValidator, e.Chain.BlockHeight()+1, pubs)
   162  }