forked from TrueCloudLab/neoneo-go
native: implement designate contract history retention
Follow neo-project/neo#2007. Fix getDesignatedByRole price along the way.
This commit is contained in:
parent
7121686571
commit
9e781bff47
6 changed files with 174 additions and 49 deletions
|
@ -1297,8 +1297,8 @@ func (bc *Blockchain) verifyTxAttributes(tx *transaction.Transaction) error {
|
||||||
}
|
}
|
||||||
return fmt.Errorf("%w: high priority tx is not signed by committee", ErrInvalidAttribute)
|
return fmt.Errorf("%w: high priority tx is not signed by committee", ErrInvalidAttribute)
|
||||||
case transaction.OracleResponseT:
|
case transaction.OracleResponseT:
|
||||||
h, err := bc.contracts.Oracle.GetScriptHash()
|
h, err := bc.contracts.Oracle.GetScriptHash(bc.dao)
|
||||||
if err != nil {
|
if err != nil || h.Equals(util.Uint160{}) {
|
||||||
return fmt.Errorf("%w: %v", ErrInvalidAttribute, err)
|
return fmt.Errorf("%w: %v", ErrInvalidAttribute, err)
|
||||||
}
|
}
|
||||||
hasOracle := false
|
hasOracle := false
|
||||||
|
|
|
@ -499,7 +499,9 @@ func TestVerifyTx(t *testing.T) {
|
||||||
InvocationScript: testchain.SignCommittee(txSetOracle.GetSignedPart()),
|
InvocationScript: testchain.SignCommittee(txSetOracle.GetSignedPart()),
|
||||||
VerificationScript: testchain.CommitteeVerificationScript(),
|
VerificationScript: testchain.CommitteeVerificationScript(),
|
||||||
}}
|
}}
|
||||||
ic := bc.newInteropContext(trigger.All, bc.dao, nil, txSetOracle)
|
bl := block.New(netmode.UnitTestNet)
|
||||||
|
bl.Index = bc.BlockHeight() + 1
|
||||||
|
ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetOracle)
|
||||||
ic.SpawnVM()
|
ic.SpawnVM()
|
||||||
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
||||||
require.NoError(t, bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, oraclePubs))
|
require.NoError(t, bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, oraclePubs))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package native
|
package native
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -12,8 +13,10 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,8 +26,13 @@ type Designate struct {
|
||||||
NEO *NEO
|
NEO *NEO
|
||||||
|
|
||||||
rolesChangedFlag atomic.Value
|
rolesChangedFlag atomic.Value
|
||||||
oracleNodes atomic.Value
|
oracles atomic.Value
|
||||||
oracleHash atomic.Value
|
}
|
||||||
|
|
||||||
|
type oraclesData struct {
|
||||||
|
nodes keys.PublicKeys
|
||||||
|
addr util.Uint160
|
||||||
|
height uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -46,9 +54,12 @@ const (
|
||||||
|
|
||||||
// Various errors.
|
// Various errors.
|
||||||
var (
|
var (
|
||||||
ErrInvalidRole = errors.New("invalid role")
|
ErrAlreadyDesignated = errors.New("already designated given role at current block")
|
||||||
ErrEmptyNodeList = errors.New("node list is empty")
|
ErrEmptyNodeList = errors.New("node list is empty")
|
||||||
ErrLargeNodeList = errors.New("node list is too large")
|
ErrInvalidIndex = errors.New("invalid index")
|
||||||
|
ErrInvalidRole = errors.New("invalid role")
|
||||||
|
ErrLargeNodeList = errors.New("node list is too large")
|
||||||
|
ErrNoBlock = errors.New("no persisting block in the context")
|
||||||
)
|
)
|
||||||
|
|
||||||
func isValidRole(r Role) bool {
|
func isValidRole(r Role) bool {
|
||||||
|
@ -61,8 +72,9 @@ func newDesignate() *Designate {
|
||||||
s.Manifest.Features = smartcontract.HasStorage
|
s.Manifest.Features = smartcontract.HasStorage
|
||||||
|
|
||||||
desc := newDescriptor("getDesignatedByRole", smartcontract.ArrayType,
|
desc := newDescriptor("getDesignatedByRole", smartcontract.ArrayType,
|
||||||
manifest.NewParameter("role", smartcontract.IntegerType))
|
manifest.NewParameter("role", smartcontract.IntegerType),
|
||||||
md := newMethodAndPrice(s.getDesignatedByRole, 0, smartcontract.AllowStates)
|
manifest.NewParameter("index", smartcontract.IntegerType))
|
||||||
|
md := newMethodAndPrice(s.getDesignatedByRole, 1000000, smartcontract.AllowStates)
|
||||||
s.AddMethod(md, desc, false)
|
s.AddMethod(md, desc, false)
|
||||||
|
|
||||||
desc = newDescriptor("designateAsRole", smartcontract.VoidType,
|
desc = newDescriptor("designateAsRole", smartcontract.VoidType,
|
||||||
|
@ -80,16 +92,6 @@ func newDesignate() *Designate {
|
||||||
|
|
||||||
// Initialize initializes Oracle contract.
|
// Initialize initializes Oracle contract.
|
||||||
func (s *Designate) Initialize(ic *interop.Context) error {
|
func (s *Designate) Initialize(ic *interop.Context) error {
|
||||||
roles := []Role{RoleStateValidator, RoleOracle}
|
|
||||||
for _, r := range roles {
|
|
||||||
si := &state.StorageItem{Value: new(NodeList).Bytes()}
|
|
||||||
if err := ic.DAO.PutStorageItem(s.ContractID, []byte{byte(r)}, si); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.oracleNodes.Store(keys.PublicKeys(nil))
|
|
||||||
s.rolesChangedFlag.Store(true)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,15 +101,17 @@ func (s *Designate) OnPersistEnd(d dao.DAO) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ns NodeList
|
nodeKeys, height, err := s.GetDesignatedByRole(d, RoleOracle, math.MaxUint32)
|
||||||
err := getSerializableFromDAO(s.ContractID, d, []byte{byte(RoleOracle)}, &ns)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.oracleNodes.Store(keys.PublicKeys(ns))
|
od := &oraclesData{
|
||||||
script, _ := smartcontract.CreateMajorityMultiSigRedeemScript(keys.PublicKeys(ns).Copy())
|
nodes: nodeKeys,
|
||||||
s.oracleHash.Store(hash.Hash160(script))
|
addr: oracleHashFromNodes(nodeKeys),
|
||||||
|
height: height,
|
||||||
|
}
|
||||||
|
s.oracles.Store(od)
|
||||||
s.rolesChangedFlag.Store(false)
|
s.rolesChangedFlag.Store(false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -122,7 +126,15 @@ func (s *Designate) getDesignatedByRole(ic *interop.Context, args []stackitem.It
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(ErrInvalidRole)
|
panic(ErrInvalidRole)
|
||||||
}
|
}
|
||||||
pubs, err := s.GetDesignatedByRole(ic.DAO, r)
|
ind, err := args[1].TryInteger()
|
||||||
|
if err != nil || !ind.IsUint64() {
|
||||||
|
panic(ErrInvalidIndex)
|
||||||
|
}
|
||||||
|
index := ind.Uint64()
|
||||||
|
if index > uint64(ic.Chain.BlockHeight()+1) {
|
||||||
|
panic(ErrInvalidIndex)
|
||||||
|
}
|
||||||
|
pubs, _, err := s.GetDesignatedByRole(ic.DAO, r, uint32(index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -134,17 +146,72 @@ func (s *Designate) rolesChanged() bool {
|
||||||
return rc == nil || rc.(bool)
|
return rc == nil || rc.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDesignatedByRole returns nodes for role r.
|
func oracleHashFromNodes(nodes keys.PublicKeys) util.Uint160 {
|
||||||
func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role) (keys.PublicKeys, error) {
|
if len(nodes) == 0 {
|
||||||
|
return util.Uint160{}
|
||||||
|
}
|
||||||
|
script, _ := smartcontract.CreateMajorityMultiSigRedeemScript(nodes.Copy())
|
||||||
|
return hash.Hash160(script)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Designate) getLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, error) {
|
||||||
if !isValidRole(r) {
|
if !isValidRole(r) {
|
||||||
return nil, ErrInvalidRole
|
return util.Uint160{}, ErrInvalidRole
|
||||||
}
|
}
|
||||||
if r == RoleOracle && !s.rolesChanged() {
|
if r == RoleOracle && !s.rolesChanged() {
|
||||||
return s.oracleNodes.Load().(keys.PublicKeys), nil
|
odVal := s.oracles.Load()
|
||||||
|
if odVal != nil {
|
||||||
|
od := odVal.(*oraclesData)
|
||||||
|
return od.addr, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes, _, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
||||||
|
if err != nil {
|
||||||
|
return util.Uint160{}, err
|
||||||
|
}
|
||||||
|
// We only have hashing defined for oracles now.
|
||||||
|
return oracleHashFromNodes(nodes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDesignatedByRole returns nodes for role r.
|
||||||
|
func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.PublicKeys, uint32, error) {
|
||||||
|
if !isValidRole(r) {
|
||||||
|
return nil, 0, ErrInvalidRole
|
||||||
|
}
|
||||||
|
if r == RoleOracle && !s.rolesChanged() {
|
||||||
|
odVal := s.oracles.Load()
|
||||||
|
if odVal != nil {
|
||||||
|
od := odVal.(*oraclesData)
|
||||||
|
if od.height <= index {
|
||||||
|
return od.nodes, od.height, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kvs, err := d.GetStorageItemsWithPrefix(s.ContractID, []byte{byte(r)})
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
var ns NodeList
|
var ns NodeList
|
||||||
err := getSerializableFromDAO(s.ContractID, d, []byte{byte(r)}, &ns)
|
var bestIndex uint32
|
||||||
return keys.PublicKeys(ns), err
|
var resSi *state.StorageItem
|
||||||
|
for k, si := range kvs {
|
||||||
|
if len(k) < 4 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
siInd := binary.BigEndian.Uint32([]byte(k))
|
||||||
|
if (resSi == nil || siInd > bestIndex) && siInd <= index {
|
||||||
|
bestIndex = siInd
|
||||||
|
resSi = si
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if resSi != nil {
|
||||||
|
reader := io.NewBinReaderFromBuf(resSi.Value)
|
||||||
|
ns.DecodeBinary(reader)
|
||||||
|
if reader.Err != nil {
|
||||||
|
return nil, 0, reader.Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys.PublicKeys(ns), bestIndex, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) designateAsRole(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
func (s *Designate) designateAsRole(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
@ -180,11 +247,21 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r Role, pubs keys.Publi
|
||||||
if ok, err := runtime.CheckHashedWitness(ic, h); err != nil || !ok {
|
if ok, err := runtime.CheckHashedWitness(ic, h); err != nil || !ok {
|
||||||
return ErrInvalidWitness
|
return ErrInvalidWitness
|
||||||
}
|
}
|
||||||
|
if ic.Block == nil {
|
||||||
|
return ErrNoBlock
|
||||||
|
}
|
||||||
|
var key = make([]byte, 5)
|
||||||
|
key[0] = byte(r)
|
||||||
|
binary.BigEndian.PutUint32(key[1:], ic.Block.Index+1)
|
||||||
|
|
||||||
|
si := ic.DAO.GetStorageItem(s.ContractID, key)
|
||||||
|
if si != nil {
|
||||||
|
return ErrAlreadyDesignated
|
||||||
|
}
|
||||||
sort.Sort(pubs)
|
sort.Sort(pubs)
|
||||||
s.rolesChangedFlag.Store(true)
|
s.rolesChangedFlag.Store(true)
|
||||||
si := &state.StorageItem{Value: NodeList(pubs).Bytes()}
|
si = &state.StorageItem{Value: NodeList(pubs).Bytes()}
|
||||||
return ic.DAO.PutStorageItem(s.ContractID, []byte{byte(r)}, si)
|
return ic.DAO.PutStorageItem(s.ContractID, key, si)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRole(item stackitem.Item) (Role, bool) {
|
func getRole(item stackitem.Item) (Role, bool) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
|
@ -341,17 +342,14 @@ func (o *Oracle) PutRequestInternal(id uint64, req *state.OracleRequest, d dao.D
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScriptHash returns script hash or oracle nodes.
|
// GetScriptHash returns script hash or oracle nodes.
|
||||||
func (o *Oracle) GetScriptHash() (util.Uint160, error) {
|
func (o *Oracle) GetScriptHash(d dao.DAO) (util.Uint160, error) {
|
||||||
h := o.Desig.oracleHash.Load()
|
return o.Desig.getLastDesignatedHash(d, RoleOracle)
|
||||||
if h == nil {
|
|
||||||
return util.Uint160{}, storage.ErrKeyNotFound
|
|
||||||
}
|
|
||||||
return h.(util.Uint160), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOracleNodes returns public keys of oracle nodes.
|
// GetOracleNodes returns public keys of oracle nodes.
|
||||||
func (o *Oracle) GetOracleNodes(d dao.DAO) (keys.PublicKeys, error) {
|
func (o *Oracle) GetOracleNodes(d dao.DAO) (keys.PublicKeys, error) {
|
||||||
return o.Desig.GetDesignatedByRole(d, RoleOracle)
|
nodes, _, err := o.Desig.GetDesignatedByRole(d, RoleOracle, math.MaxUint32)
|
||||||
|
return nodes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRequestInternal returns request by ID and key under which it is stored.
|
// GetRequestInternal returns request by ID and key under which it is stored.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
"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/emit"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,6 +62,37 @@ func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r native.Role, nodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *Blockchain) getNodesByRole(t *testing.T, ok bool, r native.Role, index uint32, resLen int) {
|
||||||
|
w := io.NewBufBinWriter()
|
||||||
|
emit.AppCallWithOperationAndArgs(w.BinWriter, bc.contracts.Designate.Hash, "getDesignatedByRole", int64(r), int64(index))
|
||||||
|
require.NoError(t, w.Err)
|
||||||
|
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 0)
|
||||||
|
tx.NetworkFee = 10_000_000
|
||||||
|
tx.SystemFee = 10_000_000
|
||||||
|
tx.ValidUntilBlock = 100
|
||||||
|
tx.Signers = []transaction.Signer{
|
||||||
|
{
|
||||||
|
Account: testchain.MultisigScriptHash(),
|
||||||
|
Scopes: transaction.None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
require.NoError(t, signTx(bc, tx))
|
||||||
|
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
|
||||||
|
|
||||||
|
aer, err := bc.GetAppExecResult(tx.Hash())
|
||||||
|
require.NoError(t, err)
|
||||||
|
if ok {
|
||||||
|
require.Equal(t, vm.HaltState, aer.VMState)
|
||||||
|
require.Equal(t, 1, len(aer.Stack))
|
||||||
|
arrItem := aer.Stack[0]
|
||||||
|
require.Equal(t, stackitem.ArrayT, arrItem.Type())
|
||||||
|
arr := arrItem.(*stackitem.Array)
|
||||||
|
require.Equal(t, resLen, arr.Len())
|
||||||
|
} else {
|
||||||
|
require.Equal(t, vm.FaultState, aer.VMState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
defer bc.Close()
|
defer bc.Close()
|
||||||
|
@ -70,6 +103,11 @@ func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
||||||
|
|
||||||
bc.setNodesByRole(t, false, 0xFF, pubs)
|
bc.setNodesByRole(t, false, 0xFF, pubs)
|
||||||
bc.setNodesByRole(t, true, native.RoleOracle, pubs)
|
bc.setNodesByRole(t, true, native.RoleOracle, pubs)
|
||||||
|
index := bc.BlockHeight() + 1
|
||||||
|
bc.getNodesByRole(t, false, 0xFF, 0, 0)
|
||||||
|
bc.getNodesByRole(t, false, native.RoleOracle, 100500, 0)
|
||||||
|
bc.getNodesByRole(t, true, native.RoleOracle, 0, 0) // returns an empty list
|
||||||
|
bc.getNodesByRole(t, true, native.RoleOracle, index, 1) // returns pubs
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDesignate_DesignateAsRole(t *testing.T) {
|
func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
|
@ -78,16 +116,19 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
|
|
||||||
des := bc.contracts.Designate
|
des := bc.contracts.Designate
|
||||||
tx := transaction.New(netmode.UnitTestNet, []byte{}, 0)
|
tx := transaction.New(netmode.UnitTestNet, []byte{}, 0)
|
||||||
ic := bc.newInteropContext(trigger.OnPersist, bc.dao, nil, tx)
|
bl := block.New(netmode.UnitTestNet)
|
||||||
|
bl.Index = bc.BlockHeight() + 1
|
||||||
|
ic := bc.newInteropContext(trigger.OnPersist, bc.dao, bl, tx)
|
||||||
ic.SpawnVM()
|
ic.SpawnVM()
|
||||||
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
||||||
|
|
||||||
pubs, err := des.GetDesignatedByRole(bc.dao, 0xFF)
|
pubs, index, err := des.GetDesignatedByRole(bc.dao, 0xFF, 255)
|
||||||
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
||||||
|
|
||||||
pubs, err = des.GetDesignatedByRole(bc.dao, native.RoleOracle)
|
pubs, index, err = des.GetDesignatedByRole(bc.dao, native.RoleOracle, 255)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0, len(pubs))
|
require.Equal(t, 0, len(pubs))
|
||||||
|
require.Equal(t, uint32(0), index)
|
||||||
|
|
||||||
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{})
|
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{})
|
||||||
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
||||||
|
@ -110,13 +151,15 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
||||||
|
|
||||||
pubs, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, bl.Index+1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
||||||
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
||||||
pubs, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0, len(pubs))
|
require.Equal(t, 0, len(pubs))
|
||||||
|
require.Equal(t, uint32(0), index)
|
||||||
|
|
||||||
// Set another role.
|
// Set another role.
|
||||||
_, err = keys.NewPrivateKey()
|
_, err = keys.NewPrivateKey()
|
||||||
|
@ -126,11 +169,13 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
||||||
|
|
||||||
pubs, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, 255)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
||||||
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
||||||
pubs, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, keys.PublicKeys{pub1}, pubs)
|
require.Equal(t, keys.PublicKeys{pub1}, pubs)
|
||||||
|
require.Equal(t, bl.Index+1, index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"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/state"
|
||||||
|
@ -136,8 +137,10 @@ func TestOracle_Request(t *testing.T) {
|
||||||
pub := priv.PublicKey()
|
pub := priv.PublicKey()
|
||||||
|
|
||||||
tx := transaction.New(netmode.UnitTestNet, []byte{}, 0)
|
tx := transaction.New(netmode.UnitTestNet, []byte{}, 0)
|
||||||
|
bl := block.New(netmode.UnitTestNet)
|
||||||
|
bl.Index = bc.BlockHeight() + 1
|
||||||
setSigner(tx, testchain.CommitteeScriptHash())
|
setSigner(tx, testchain.CommitteeScriptHash())
|
||||||
ic := bc.newInteropContext(trigger.Application, bc.dao, nil, tx)
|
ic := bc.newInteropContext(trigger.Application, bc.dao, bl, tx)
|
||||||
ic.SpawnVM()
|
ic.SpawnVM()
|
||||||
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
||||||
err = bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
err = bc.contracts.Designate.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
||||||
|
|
Loading…
Reference in a new issue