2021-12-03 15:51:46 +00:00
|
|
|
package native_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
2022-04-19 11:35:19 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
2021-12-03 15:51:46 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
2022-04-19 11:35:19 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
2021-12-03 15:51:46 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
2022-04-19 11:35:19 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
2021-12-03 15:51:46 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func newDesignateClient(t *testing.T) *neotest.ContractInvoker {
|
|
|
|
return newNativeClient(t, nativenames.Designation)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDesignate_DesignateAsRole(t *testing.T) {
|
|
|
|
c := newDesignateClient(t)
|
|
|
|
e := c.Executor
|
|
|
|
designateInvoker := c.WithSigners(c.Committee)
|
|
|
|
|
|
|
|
priv, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pubs := keys.PublicKeys{priv.PublicKey()}
|
|
|
|
|
|
|
|
setNodesByRole(t, designateInvoker, false, 0xFF, pubs)
|
|
|
|
setNodesByRole(t, designateInvoker, true, noderoles.Oracle, pubs)
|
|
|
|
index := e.Chain.BlockHeight() + 1
|
|
|
|
checkNodeRoles(t, designateInvoker, false, 0xFF, 0, nil)
|
|
|
|
checkNodeRoles(t, designateInvoker, false, noderoles.Oracle, 100500, nil)
|
|
|
|
checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, 0, keys.PublicKeys{}) // returns an empty list
|
|
|
|
checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, index, pubs) // returns pubs
|
|
|
|
|
|
|
|
priv1, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pubs = keys.PublicKeys{priv1.PublicKey()}
|
|
|
|
setNodesByRole(t, designateInvoker, true, noderoles.StateValidator, pubs)
|
|
|
|
checkNodeRoles(t, designateInvoker, true, noderoles.StateValidator, e.Chain.BlockHeight()+1, pubs)
|
|
|
|
|
|
|
|
t.Run("neofs", func(t *testing.T) {
|
|
|
|
priv, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pubs = keys.PublicKeys{priv.PublicKey()}
|
|
|
|
setNodesByRole(t, designateInvoker, true, noderoles.NeoFSAlphabet, pubs)
|
|
|
|
checkNodeRoles(t, designateInvoker, true, noderoles.NeoFSAlphabet, e.Chain.BlockHeight()+1, pubs)
|
|
|
|
})
|
|
|
|
}
|
2022-04-19 11:35:19 +00:00
|
|
|
|
|
|
|
type dummyOracle struct {
|
|
|
|
updateNodes func(k keys.PublicKeys)
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddRequests processes new requests.
|
|
|
|
func (o *dummyOracle) AddRequests(map[uint64]*state.OracleRequest) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveRequests removes already processed requests.
|
|
|
|
func (o *dummyOracle) RemoveRequests([]uint64) {
|
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateOracleNodes updates oracle nodes.
|
|
|
|
func (o *dummyOracle) UpdateOracleNodes(k keys.PublicKeys) {
|
|
|
|
if o.updateNodes != nil {
|
|
|
|
o.updateNodes(k)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdateNativeContract updates oracle contract native script and hash.
|
|
|
|
func (o *dummyOracle) UpdateNativeContract([]byte, []byte, util.Uint160, int) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start runs oracle module.
|
|
|
|
func (o *dummyOracle) Start() {
|
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shutdown shutdowns oracle module.
|
|
|
|
func (o *dummyOracle) Shutdown() {
|
|
|
|
panic("TODO")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDesignate_Cache(t *testing.T) {
|
|
|
|
c := newDesignateClient(t)
|
|
|
|
e := c.Executor
|
|
|
|
designateInvoker := c.WithSigners(c.Committee)
|
|
|
|
r := int64(noderoles.Oracle)
|
|
|
|
var (
|
|
|
|
updatedNodes keys.PublicKeys
|
|
|
|
updateCalled bool
|
|
|
|
)
|
|
|
|
oracleServ := &dummyOracle{
|
|
|
|
updateNodes: func(k keys.PublicKeys) {
|
|
|
|
updatedNodes = k
|
|
|
|
updateCalled = true
|
|
|
|
},
|
|
|
|
}
|
|
|
|
privGood, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
2023-04-03 10:34:24 +00:00
|
|
|
pubsGood := []any{privGood.PublicKey().Bytes()}
|
2022-04-19 11:35:19 +00:00
|
|
|
|
|
|
|
privBad, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
2023-04-03 10:34:24 +00:00
|
|
|
pubsBad := []any{privBad.PublicKey().Bytes()}
|
2022-04-19 11:35:19 +00:00
|
|
|
|
|
|
|
// Firstly, designate good Oracle node and check that OracleService callback was called during PostPersist.
|
|
|
|
e.Chain.SetOracle(oracleServ)
|
|
|
|
txDesignateGood := designateInvoker.PrepareInvoke(t, "designateAsRole", r, pubsGood)
|
|
|
|
e.AddNewBlock(t, txDesignateGood)
|
|
|
|
e.CheckHalt(t, txDesignateGood.Hash(), stackitem.Null{})
|
|
|
|
require.True(t, updateCalled)
|
|
|
|
require.Equal(t, keys.PublicKeys{privGood.PublicKey()}, updatedNodes)
|
|
|
|
updatedNodes = nil
|
|
|
|
updateCalled = false
|
|
|
|
|
|
|
|
// Check designated node in a separate block.
|
|
|
|
checkNodeRoles(t, designateInvoker, true, noderoles.Oracle, e.Chain.BlockHeight()+1, keys.PublicKeys{privGood.PublicKey()})
|
|
|
|
|
|
|
|
// Designate privBad as oracle node and abort the transaction. Designation cache changes
|
|
|
|
// shouldn't be persisted to the contract and no notification should be sent.
|
|
|
|
w := io.NewBufBinWriter()
|
|
|
|
emit.AppCall(w.BinWriter, designateInvoker.Hash, "designateAsRole", callflag.All, int64(r), pubsBad)
|
|
|
|
emit.Opcodes(w.BinWriter, opcode.ABORT)
|
|
|
|
require.NoError(t, w.Err)
|
|
|
|
script := w.Bytes()
|
|
|
|
|
|
|
|
designateInvoker.InvokeScriptCheckFAULT(t, script, designateInvoker.Signers, "ABORT")
|
|
|
|
require.Nil(t, updatedNodes)
|
|
|
|
require.False(t, updateCalled)
|
|
|
|
}
|