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 }