forked from TrueCloudLab/neoneo-go
Merge pull request #1855 from nspcc-dev/rpc/getDesignatedByRole
rpc: add (*Client).GetDesignatedByRole method
This commit is contained in:
commit
57c3ecd135
18 changed files with 184 additions and 91 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"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/native/noderoles"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/crypto"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/crypto"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/gas"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/gas"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
|
||||||
|
@ -69,10 +70,10 @@ func TestContractParameterTypes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRoleManagementRole(t *testing.T) {
|
func TestRoleManagementRole(t *testing.T) {
|
||||||
require.EqualValues(t, native.RoleOracle, roles.Oracle)
|
require.EqualValues(t, noderoles.Oracle, roles.Oracle)
|
||||||
require.EqualValues(t, native.RoleStateValidator, roles.StateValidator)
|
require.EqualValues(t, noderoles.StateValidator, roles.StateValidator)
|
||||||
require.EqualValues(t, native.RoleNeoFSAlphabet, roles.NeoFSAlphabet)
|
require.EqualValues(t, noderoles.NeoFSAlphabet, roles.NeoFSAlphabet)
|
||||||
require.EqualValues(t, native.RoleP2PNotary, roles.P2PNotary)
|
require.EqualValues(t, noderoles.P2PNotary, roles.P2PNotary)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNameServiceRecordType(t *testing.T) {
|
func TestNameServiceRecordType(t *testing.T) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||||
"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/native/noderoles"
|
||||||
"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/core/stateroot"
|
"github.com/nspcc-dev/neo-go/pkg/core/stateroot"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
|
@ -791,11 +792,11 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error
|
||||||
|
|
||||||
func (bc *Blockchain) updateExtensibleWhitelist(height uint32) error {
|
func (bc *Blockchain) updateExtensibleWhitelist(height uint32) error {
|
||||||
updateCommittee := native.ShouldUpdateCommittee(height, bc)
|
updateCommittee := native.ShouldUpdateCommittee(height, bc)
|
||||||
oracles, oh, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, native.RoleOracle, height)
|
oracles, oh, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.Oracle, height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stateVals, sh, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, native.RoleStateValidator, height)
|
stateVals, sh, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.StateValidator, height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -814,7 +815,7 @@ func (bc *Blockchain) updateExtensibleWhitelist(height uint32) error {
|
||||||
bc.updateExtensibleList(&newList, bc.contracts.NEO.GetNextBlockValidatorsInternal())
|
bc.updateExtensibleList(&newList, bc.contracts.NEO.GetNextBlockValidatorsInternal())
|
||||||
|
|
||||||
if len(oracles) > 0 {
|
if len(oracles) > 0 {
|
||||||
h, err := bc.contracts.Designate.GetLastDesignatedHash(bc.dao, native.RoleOracle)
|
h, err := bc.contracts.Designate.GetLastDesignatedHash(bc.dao, noderoles.Oracle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -823,7 +824,7 @@ func (bc *Blockchain) updateExtensibleWhitelist(height uint32) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(stateVals) > 0 {
|
if len(stateVals) > 0 {
|
||||||
h, err := bc.contracts.Designate.GetLastDesignatedHash(bc.dao, native.RoleStateValidator)
|
h, err := bc.contracts.Designate.GetLastDesignatedHash(bc.dao, noderoles.StateValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"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/mempool"
|
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||||
"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/native/nativeprices"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -596,7 +598,7 @@ func TestVerifyTx(t *testing.T) {
|
||||||
ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetOracle)
|
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, noderoles.Oracle, oraclePubs))
|
||||||
_, err = ic.DAO.Persist()
|
_, err = ic.DAO.Persist()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -807,7 +809,7 @@ func TestVerifyTx(t *testing.T) {
|
||||||
ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetNotary)
|
ic := bc.newInteropContext(trigger.All, bc.dao, bl, txSetNotary)
|
||||||
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.RoleP2PNotary, keys.PublicKeys{notary.PrivateKey().PublicKey()}))
|
require.NoError(t, bc.contracts.Designate.DesignateAsRole(ic, noderoles.P2PNotary, keys.PublicKeys{notary.PrivateKey().PublicKey()}))
|
||||||
_, err = ic.DAO.Persist()
|
_, err = ic.DAO.Persist()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
getNotaryAssistedTx := func(signaturesCount uint8, serviceFee int64) *transaction.Transaction {
|
getNotaryAssistedTx := func(signaturesCount uint8, serviceFee int64) *transaction.Transaction {
|
||||||
|
@ -1030,7 +1032,7 @@ func TestVerifyTx(t *testing.T) {
|
||||||
fee.Opcode(bc.GetBaseExecFee(), // Notary verification script
|
fee.Opcode(bc.GetBaseExecFee(), // Notary verification script
|
||||||
opcode.PUSHDATA1, opcode.RET, // invocation script
|
opcode.PUSHDATA1, opcode.RET, // invocation script
|
||||||
opcode.PUSH0, opcode.SYSCALL, opcode.RET) + // Neo.Native.Call
|
opcode.PUSH0, opcode.SYSCALL, opcode.RET) + // Neo.Native.Call
|
||||||
native.NotaryVerificationPrice*bc.GetBaseExecFee() // Notary witness verification price
|
nativeprices.NotaryVerificationPrice*bc.GetBaseExecFee() // Notary witness verification price
|
||||||
tx.Scripts = []transaction.Witness{
|
tx.Scripts = []transaction.Witness{
|
||||||
{
|
{
|
||||||
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, make([]byte, 64, 64)...),
|
InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, make([]byte, 64, 64)...),
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
|
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||||
"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/native/noderoles"
|
||||||
"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/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -472,7 +473,7 @@ func initBasicChain(t *testing.T, bc *Blockchain) {
|
||||||
ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json"))
|
ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NoError(t, ntr.Accounts[0].Decrypt("one"))
|
require.NoError(t, ntr.Accounts[0].Decrypt("one"))
|
||||||
bc.setNodesByRole(t, true, native.RoleP2PNotary, keys.PublicKeys{ntr.Accounts[0].PrivateKey().PublicKey()})
|
bc.setNodesByRole(t, true, noderoles.P2PNotary, keys.PublicKeys{ntr.Accounts[0].PrivateKey().PublicKey()})
|
||||||
t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes()))
|
t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes()))
|
||||||
|
|
||||||
// Push verification contract with arguments into the chain.
|
// Push verification contract with arguments into the chain.
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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"
|
||||||
|
@ -58,17 +59,6 @@ const (
|
||||||
maxNodeCount = 32
|
maxNodeCount = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// Role represents type of participant.
|
|
||||||
type Role byte
|
|
||||||
|
|
||||||
// Role enumeration.
|
|
||||||
const (
|
|
||||||
RoleStateValidator Role = 4
|
|
||||||
RoleOracle Role = 8
|
|
||||||
RoleNeoFSAlphabet Role = 16
|
|
||||||
RoleP2PNotary Role = 128
|
|
||||||
)
|
|
||||||
|
|
||||||
// Various errors.
|
// Various errors.
|
||||||
var (
|
var (
|
||||||
ErrAlreadyDesignated = errors.New("already designated given role at current block")
|
ErrAlreadyDesignated = errors.New("already designated given role at current block")
|
||||||
|
@ -79,9 +69,9 @@ var (
|
||||||
ErrNoBlock = errors.New("no persisting block in the context")
|
ErrNoBlock = errors.New("no persisting block in the context")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Designate) isValidRole(r Role) bool {
|
func (s *Designate) isValidRole(r noderoles.Role) bool {
|
||||||
return r == RoleOracle || r == RoleStateValidator ||
|
return r == noderoles.Oracle || r == noderoles.StateValidator ||
|
||||||
r == RoleNeoFSAlphabet || (s.p2pSigExtensionsEnabled && r == RoleP2PNotary)
|
r == noderoles.NeoFSAlphabet || (s.p2pSigExtensionsEnabled && r == noderoles.P2PNotary)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDesignate(p2pSigExtensionsEnabled bool) *Designate {
|
func newDesignate(p2pSigExtensionsEnabled bool) *Designate {
|
||||||
|
@ -120,17 +110,17 @@ func (s *Designate) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.updateCachedRoleData(&s.oracles, ic.DAO, RoleOracle); err != nil {
|
if err := s.updateCachedRoleData(&s.oracles, ic.DAO, noderoles.Oracle); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.updateCachedRoleData(&s.stateVals, ic.DAO, RoleStateValidator); err != nil {
|
if err := s.updateCachedRoleData(&s.stateVals, ic.DAO, noderoles.StateValidator); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.updateCachedRoleData(&s.neofsAlphabet, ic.DAO, RoleNeoFSAlphabet); err != nil {
|
if err := s.updateCachedRoleData(&s.neofsAlphabet, ic.DAO, noderoles.NeoFSAlphabet); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if s.p2pSigExtensionsEnabled {
|
if s.p2pSigExtensionsEnabled {
|
||||||
if err := s.updateCachedRoleData(&s.notaries, ic.DAO, RoleP2PNotary); err != nil {
|
if err := s.updateCachedRoleData(&s.notaries, ic.DAO, noderoles.P2PNotary); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,13 +159,13 @@ func (s *Designate) rolesChanged() bool {
|
||||||
return rc == nil || rc.(bool)
|
return rc == nil || rc.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) hashFromNodes(r Role, nodes keys.PublicKeys) util.Uint160 {
|
func (s *Designate) hashFromNodes(r noderoles.Role, nodes keys.PublicKeys) util.Uint160 {
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
return util.Uint160{}
|
return util.Uint160{}
|
||||||
}
|
}
|
||||||
var script []byte
|
var script []byte
|
||||||
switch r {
|
switch r {
|
||||||
case RoleP2PNotary:
|
case noderoles.P2PNotary:
|
||||||
script, _ = smartcontract.CreateMultiSigRedeemScript(1, nodes.Copy())
|
script, _ = smartcontract.CreateMultiSigRedeemScript(1, nodes.Copy())
|
||||||
default:
|
default:
|
||||||
script, _ = smartcontract.CreateDefaultMultiSigRedeemScript(nodes.Copy())
|
script, _ = smartcontract.CreateDefaultMultiSigRedeemScript(nodes.Copy())
|
||||||
|
@ -183,7 +173,7 @@ func (s *Designate) hashFromNodes(r Role, nodes keys.PublicKeys) util.Uint160 {
|
||||||
return hash.Hash160(script)
|
return hash.Hash160(script)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) updateCachedRoleData(v *atomic.Value, d dao.DAO, r Role) error {
|
func (s *Designate) updateCachedRoleData(v *atomic.Value, d dao.DAO, r noderoles.Role) error {
|
||||||
nodeKeys, height, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
nodeKeys, height, err := s.GetDesignatedByRole(d, r, math.MaxUint32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -194,15 +184,15 @@ func (s *Designate) updateCachedRoleData(v *atomic.Value, d dao.DAO, r Role) err
|
||||||
height: height,
|
height: height,
|
||||||
})
|
})
|
||||||
switch r {
|
switch r {
|
||||||
case RoleOracle:
|
case noderoles.Oracle:
|
||||||
if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil {
|
if orc, _ := s.OracleService.Load().(services.Oracle); orc != nil {
|
||||||
orc.UpdateOracleNodes(nodeKeys.Copy())
|
orc.UpdateOracleNodes(nodeKeys.Copy())
|
||||||
}
|
}
|
||||||
case RoleP2PNotary:
|
case noderoles.P2PNotary:
|
||||||
if ntr, _ := s.NotaryService.Load().(services.Notary); ntr != nil {
|
if ntr, _ := s.NotaryService.Load().(services.Notary); ntr != nil {
|
||||||
ntr.UpdateNotaryNodes(nodeKeys.Copy())
|
ntr.UpdateNotaryNodes(nodeKeys.Copy())
|
||||||
}
|
}
|
||||||
case RoleStateValidator:
|
case noderoles.StateValidator:
|
||||||
if s.StateRootService != nil {
|
if s.StateRootService != nil {
|
||||||
s.StateRootService.UpdateStateValidators(height, nodeKeys.Copy())
|
s.StateRootService.UpdateStateValidators(height, nodeKeys.Copy())
|
||||||
}
|
}
|
||||||
|
@ -210,16 +200,16 @@ func (s *Designate) updateCachedRoleData(v *atomic.Value, d dao.DAO, r Role) err
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) getCachedRoleData(r Role) *roleData {
|
func (s *Designate) getCachedRoleData(r noderoles.Role) *roleData {
|
||||||
var val interface{}
|
var val interface{}
|
||||||
switch r {
|
switch r {
|
||||||
case RoleOracle:
|
case noderoles.Oracle:
|
||||||
val = s.oracles.Load()
|
val = s.oracles.Load()
|
||||||
case RoleStateValidator:
|
case noderoles.StateValidator:
|
||||||
val = s.stateVals.Load()
|
val = s.stateVals.Load()
|
||||||
case RoleNeoFSAlphabet:
|
case noderoles.NeoFSAlphabet:
|
||||||
val = s.neofsAlphabet.Load()
|
val = s.neofsAlphabet.Load()
|
||||||
case RoleP2PNotary:
|
case noderoles.P2PNotary:
|
||||||
val = s.notaries.Load()
|
val = s.notaries.Load()
|
||||||
}
|
}
|
||||||
if val != nil {
|
if val != nil {
|
||||||
|
@ -229,7 +219,7 @@ func (s *Designate) getCachedRoleData(r Role) *roleData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLastDesignatedHash returns last designated hash of a given role.
|
// GetLastDesignatedHash returns last designated hash of a given role.
|
||||||
func (s *Designate) GetLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, error) {
|
func (s *Designate) GetLastDesignatedHash(d dao.DAO, r noderoles.Role) (util.Uint160, error) {
|
||||||
if !s.isValidRole(r) {
|
if !s.isValidRole(r) {
|
||||||
return util.Uint160{}, ErrInvalidRole
|
return util.Uint160{}, ErrInvalidRole
|
||||||
}
|
}
|
||||||
|
@ -247,7 +237,7 @@ func (s *Designate) GetLastDesignatedHash(d dao.DAO, r Role) (util.Uint160, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDesignatedByRole returns nodes for role r.
|
// GetDesignatedByRole returns nodes for role r.
|
||||||
func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.PublicKeys, uint32, error) {
|
func (s *Designate) GetDesignatedByRole(d dao.DAO, r noderoles.Role, index uint32) (keys.PublicKeys, uint32, error) {
|
||||||
if !s.isValidRole(r) {
|
if !s.isValidRole(r) {
|
||||||
return nil, 0, ErrInvalidRole
|
return nil, 0, ErrInvalidRole
|
||||||
}
|
}
|
||||||
|
@ -301,7 +291,7 @@ func (s *Designate) designateAsRole(ic *interop.Context, args []stackitem.Item)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DesignateAsRole sets nodes for role r.
|
// DesignateAsRole sets nodes for role r.
|
||||||
func (s *Designate) DesignateAsRole(ic *interop.Context, r Role, pubs keys.PublicKeys) error {
|
func (s *Designate) DesignateAsRole(ic *interop.Context, r noderoles.Role, pubs keys.PublicKeys) error {
|
||||||
length := len(pubs)
|
length := len(pubs)
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return ErrEmptyNodeList
|
return ErrEmptyNodeList
|
||||||
|
@ -332,7 +322,7 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r Role, pubs keys.Publi
|
||||||
return ic.DAO.PutStorageItem(s.ID, key, NodeList(pubs).Bytes())
|
return ic.DAO.PutStorageItem(s.ID, key, NodeList(pubs).Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) getRole(item stackitem.Item) (Role, bool) {
|
func (s *Designate) getRole(item stackitem.Item) (noderoles.Role, bool) {
|
||||||
bi, err := item.TryInteger()
|
bi, err := item.TryInteger()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, false
|
return 0, false
|
||||||
|
@ -341,5 +331,5 @@ func (s *Designate) getRole(item stackitem.Item) (Role, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
u := bi.Uint64()
|
u := bi.Uint64()
|
||||||
return Role(u), u <= math.MaxUint8 && s.isValidRole(Role(u))
|
return noderoles.Role(u), u <= math.MaxUint8 && s.isValidRole(noderoles.Role(u))
|
||||||
}
|
}
|
||||||
|
|
4
pkg/core/native/nativeprices/prices.go
Normal file
4
pkg/core/native/nativeprices/prices.go
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package nativeprices
|
||||||
|
|
||||||
|
// NotaryVerificationPrice is the price of `verify` native Notary method.
|
||||||
|
const NotaryVerificationPrice = 1 << 15
|
12
pkg/core/native/noderoles/roles.go
Normal file
12
pkg/core/native/noderoles/roles.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package noderoles
|
||||||
|
|
||||||
|
// Role represents type of participant.
|
||||||
|
type Role byte
|
||||||
|
|
||||||
|
// Role enumeration.
|
||||||
|
const (
|
||||||
|
StateValidator Role = 4
|
||||||
|
Oracle Role = 8
|
||||||
|
NeoFSAlphabet Role = 16
|
||||||
|
P2PNotary Role = 128
|
||||||
|
)
|
|
@ -12,6 +12,8 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativeprices"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -40,9 +42,6 @@ type Notary struct {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
notaryContractID = reservedContractID - 1
|
notaryContractID = reservedContractID - 1
|
||||||
// NotaryVerificationPrice is the price of `verify` Notary method.
|
|
||||||
NotaryVerificationPrice = 1 << 15
|
|
||||||
|
|
||||||
// prefixDeposit is a prefix for storing Notary deposits.
|
// prefixDeposit is a prefix for storing Notary deposits.
|
||||||
prefixDeposit = 1
|
prefixDeposit = 1
|
||||||
defaultDepositDeltaTill = 5760
|
defaultDepositDeltaTill = 5760
|
||||||
|
@ -87,7 +86,7 @@ func newNotary() *Notary {
|
||||||
|
|
||||||
desc = newDescriptor("verify", smartcontract.BoolType,
|
desc = newDescriptor("verify", smartcontract.BoolType,
|
||||||
manifest.NewParameter("signature", smartcontract.SignatureType))
|
manifest.NewParameter("signature", smartcontract.SignatureType))
|
||||||
md = newMethodAndPrice(n.verify, NotaryVerificationPrice, callflag.ReadStates)
|
md = newMethodAndPrice(n.verify, nativeprices.NotaryVerificationPrice, callflag.ReadStates)
|
||||||
n.AddMethod(md, desc)
|
n.AddMethod(md, desc)
|
||||||
|
|
||||||
desc = newDescriptor("getMaxNotValidBeforeDelta", smartcontract.IntegerType)
|
desc = newDescriptor("getMaxNotValidBeforeDelta", smartcontract.IntegerType)
|
||||||
|
@ -370,7 +369,7 @@ func (n *Notary) verify(ic *interop.Context, args []stackitem.Item) stackitem.It
|
||||||
|
|
||||||
// GetNotaryNodes returns public keys of notary nodes.
|
// GetNotaryNodes returns public keys of notary nodes.
|
||||||
func (n *Notary) GetNotaryNodes(d dao.DAO) (keys.PublicKeys, error) {
|
func (n *Notary) GetNotaryNodes(d dao.DAO) (keys.PublicKeys, error) {
|
||||||
nodes, _, err := n.Desig.GetDesignatedByRole(d, RoleP2PNotary, math.MaxUint32)
|
nodes, _, err := n.Desig.GetDesignatedByRole(d, noderoles.P2PNotary, math.MaxUint32)
|
||||||
return nodes, err
|
return nodes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||||
"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/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -410,12 +411,12 @@ 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(d dao.DAO) (util.Uint160, error) {
|
func (o *Oracle) GetScriptHash(d dao.DAO) (util.Uint160, error) {
|
||||||
return o.Desig.GetLastDesignatedHash(d, RoleOracle)
|
return o.Desig.GetLastDesignatedHash(d, noderoles.Oracle)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
nodes, _, err := o.Desig.GetDesignatedByRole(d, RoleOracle, math.MaxUint32)
|
nodes, _, err := o.Desig.GetDesignatedByRole(d, noderoles.Oracle, math.MaxUint32)
|
||||||
return nodes, err
|
return nodes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"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/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/native/noderoles"
|
||||||
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
@ -20,7 +21,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r native.Role, nodes keys.PublicKeys) {
|
func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r noderoles.Role, nodes keys.PublicKeys) {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
for _, pub := range nodes {
|
for _, pub := range nodes {
|
||||||
emit.Bytes(w.BinWriter, pub.Bytes())
|
emit.Bytes(w.BinWriter, pub.Bytes())
|
||||||
|
@ -63,7 +64,7 @@ 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) {
|
func (bc *Blockchain) getNodesByRole(t *testing.T, ok bool, r noderoles.Role, index uint32, resLen int) {
|
||||||
res, err := invokeContractMethod(bc, 10_000_000, bc.contracts.Designate.Hash, "getDesignatedByRole", int64(r), int64(index))
|
res, err := invokeContractMethod(bc, 10_000_000, bc.contracts.Designate.Hash, "getDesignatedByRole", int64(r), int64(index))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -86,25 +87,25 @@ func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
||||||
pubs := keys.PublicKeys{priv.PublicKey()}
|
pubs := keys.PublicKeys{priv.PublicKey()}
|
||||||
|
|
||||||
bc.setNodesByRole(t, false, 0xFF, pubs)
|
bc.setNodesByRole(t, false, 0xFF, pubs)
|
||||||
bc.setNodesByRole(t, true, native.RoleOracle, pubs)
|
bc.setNodesByRole(t, true, noderoles.Oracle, pubs)
|
||||||
index := bc.BlockHeight() + 1
|
index := bc.BlockHeight() + 1
|
||||||
bc.getNodesByRole(t, false, 0xFF, 0, 0)
|
bc.getNodesByRole(t, false, 0xFF, 0, 0)
|
||||||
bc.getNodesByRole(t, false, native.RoleOracle, 100500, 0)
|
bc.getNodesByRole(t, false, noderoles.Oracle, 100500, 0)
|
||||||
bc.getNodesByRole(t, true, native.RoleOracle, 0, 0) // returns an empty list
|
bc.getNodesByRole(t, true, noderoles.Oracle, 0, 0) // returns an empty list
|
||||||
bc.getNodesByRole(t, true, native.RoleOracle, index, 1) // returns pubs
|
bc.getNodesByRole(t, true, noderoles.Oracle, index, 1) // returns pubs
|
||||||
|
|
||||||
priv1, err := keys.NewPrivateKey()
|
priv1, err := keys.NewPrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
pubs = keys.PublicKeys{priv1.PublicKey()}
|
pubs = keys.PublicKeys{priv1.PublicKey()}
|
||||||
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
bc.setNodesByRole(t, true, noderoles.StateValidator, pubs)
|
||||||
bc.getNodesByRole(t, true, native.RoleStateValidator, bc.BlockHeight()+1, 1)
|
bc.getNodesByRole(t, true, noderoles.StateValidator, bc.BlockHeight()+1, 1)
|
||||||
|
|
||||||
t.Run("neofs", func(t *testing.T) {
|
t.Run("neofs", func(t *testing.T) {
|
||||||
priv, err := keys.NewPrivateKey()
|
priv, err := keys.NewPrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
pubs = keys.PublicKeys{priv.PublicKey()}
|
pubs = keys.PublicKeys{priv.PublicKey()}
|
||||||
bc.setNodesByRole(t, true, native.RoleNeoFSAlphabet, pubs)
|
bc.setNodesByRole(t, true, noderoles.NeoFSAlphabet, pubs)
|
||||||
bc.getNodesByRole(t, true, native.RoleNeoFSAlphabet, bc.BlockHeight()+1, 1)
|
bc.getNodesByRole(t, true, noderoles.NeoFSAlphabet, bc.BlockHeight()+1, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -123,15 +124,15 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
pubs, index, err := des.GetDesignatedByRole(bc.dao, 0xFF, 255)
|
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, index, err = des.GetDesignatedByRole(bc.dao, native.RoleOracle, 255)
|
pubs, index, err = des.GetDesignatedByRole(bc.dao, noderoles.Oracle, 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)
|
require.Equal(t, uint32(0), index)
|
||||||
|
|
||||||
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{})
|
err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{})
|
||||||
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
||||||
|
|
||||||
err = des.DesignateAsRole(ic, native.RoleOracle, make(keys.PublicKeys, 32+1))
|
err = des.DesignateAsRole(ic, noderoles.Oracle, make(keys.PublicKeys, 32+1))
|
||||||
require.True(t, errors.Is(err, native.ErrLargeNodeList), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrLargeNodeList), "got: %v", err)
|
||||||
|
|
||||||
priv, err := keys.NewPrivateKey()
|
priv, err := keys.NewPrivateKey()
|
||||||
|
@ -141,19 +142,19 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
err = des.DesignateAsRole(ic, 0xFF, keys.PublicKeys{pub})
|
err = des.DesignateAsRole(ic, 0xFF, keys.PublicKeys{pub})
|
||||||
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
||||||
|
|
||||||
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{pub})
|
||||||
require.True(t, errors.Is(err, native.ErrInvalidWitness), "got: %v", err)
|
require.True(t, errors.Is(err, native.ErrInvalidWitness), "got: %v", err)
|
||||||
|
|
||||||
setSigner(tx, testchain.CommitteeScriptHash())
|
setSigner(tx, testchain.CommitteeScriptHash())
|
||||||
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
err = des.DesignateAsRole(ic, noderoles.Oracle, keys.PublicKeys{pub})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, bl.Index+1)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.Oracle, 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)
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.StateValidator, 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)
|
require.Equal(t, uint32(0), index)
|
||||||
|
@ -162,29 +163,29 @@ func TestDesignate_DesignateAsRole(t *testing.T) {
|
||||||
_, err = keys.NewPrivateKey()
|
_, err = keys.NewPrivateKey()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
pub1 := priv.PublicKey()
|
pub1 := priv.PublicKey()
|
||||||
err = des.DesignateAsRole(ic, native.RoleStateValidator, keys.PublicKeys{pub1})
|
err = des.DesignateAsRole(ic, noderoles.StateValidator, keys.PublicKeys{pub1})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, 255)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.Oracle, 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)
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.StateValidator, 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)
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
||||||
// Set P2PNotary role.
|
// Set P2PNotary role.
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleP2PNotary, 255)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.P2PNotary, 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)
|
require.Equal(t, uint32(0), index)
|
||||||
|
|
||||||
err = des.DesignateAsRole(ic, native.RoleP2PNotary, keys.PublicKeys{pub1})
|
err = des.DesignateAsRole(ic, noderoles.P2PNotary, keys.PublicKeys{pub1})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleP2PNotary, 255)
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, noderoles.P2PNotary, 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)
|
require.Equal(t, bl.Index+1, index)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/internal/testchain"
|
"github.com/nspcc-dev/neo-go/internal/testchain"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||||
|
@ -261,7 +261,7 @@ func TestNotaryNodesReward(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
notaryNodesPublicKeys[i] = notaryNodes[i].PublicKey()
|
notaryNodesPublicKeys[i] = notaryNodes[i].PublicKey()
|
||||||
}
|
}
|
||||||
chain.setNodesByRole(t, true, native.RoleP2PNotary, notaryNodesPublicKeys)
|
chain.setNodesByRole(t, true, noderoles.P2PNotary, notaryNodesPublicKeys)
|
||||||
for _, notaryNode := range notaryNodesPublicKeys {
|
for _, notaryNode := range notaryNodesPublicKeys {
|
||||||
checkBalanceOf(t, chain, notaryNode.GetScriptHash(), 0)
|
checkBalanceOf(t, chain, notaryNode.GetScriptHash(), 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"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/native/noderoles"
|
||||||
"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/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
@ -154,7 +155,7 @@ func TestOracle_Request(t *testing.T) {
|
||||||
ic := bc.newInteropContext(trigger.Application, bc.dao, bl, 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, noderoles.Oracle, keys.PublicKeys{pub})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0)
|
tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0)
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
|
"github.com/nspcc-dev/neo-go/pkg/core/blockchainer"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/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"
|
||||||
|
@ -104,7 +104,7 @@ func TestNotary(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
notaryNodes := keys.PublicKeys{acc1.PrivateKey().PublicKey(), acc2.PrivateKey().PublicKey()}
|
notaryNodes := keys.PublicKeys{acc1.PrivateKey().PublicKey(), acc2.PrivateKey().PublicKey()}
|
||||||
bc.setNodesByRole(t, true, native.RoleP2PNotary, notaryNodes)
|
bc.setNodesByRole(t, true, noderoles.P2PNotary, notaryNodes)
|
||||||
|
|
||||||
createFallbackTx := func(requester *wallet.Account, mainTx *transaction.Transaction, nvbIncrement ...uint32) *transaction.Transaction {
|
createFallbackTx := func(requester *wallet.Account, mainTx *transaction.Transaction, nvbIncrement ...uint32) *transaction.Transaction {
|
||||||
fallback := transaction.New(testchain.Network(), []byte{byte(opcode.RET)}, 2000_0000)
|
fallback := transaction.New(testchain.Network(), []byte{byte(opcode.RET)}, 2000_0000)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"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/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/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"
|
||||||
|
@ -120,7 +120,7 @@ func TestOracle(t *testing.T) {
|
||||||
acc2, orc2, m2, ch2 := getTestOracle(t, bc, "./testdata/oracle2.json", "two")
|
acc2, orc2, m2, ch2 := getTestOracle(t, bc, "./testdata/oracle2.json", "two")
|
||||||
oracleNodes := keys.PublicKeys{acc1.PrivateKey().PublicKey(), acc2.PrivateKey().PublicKey()}
|
oracleNodes := keys.PublicKeys{acc1.PrivateKey().PublicKey(), acc2.PrivateKey().PublicKey()}
|
||||||
// Must be set in native contract for tx verification.
|
// Must be set in native contract for tx verification.
|
||||||
bc.setNodesByRole(t, true, native.RoleOracle, oracleNodes)
|
bc.setNodesByRole(t, true, noderoles.Oracle, oracleNodes)
|
||||||
orc1.UpdateOracleNodes(oracleNodes.Copy())
|
orc1.UpdateOracleNodes(oracleNodes.Copy())
|
||||||
orc2.UpdateOracleNodes(oracleNodes.Copy())
|
orc2.UpdateOracleNodes(oracleNodes.Copy())
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ func TestOracleFull(t *testing.T) {
|
||||||
go orc.Run()
|
go orc.Run()
|
||||||
t.Cleanup(orc.Shutdown)
|
t.Cleanup(orc.Shutdown)
|
||||||
|
|
||||||
bc.setNodesByRole(t, true, native.RoleOracle, keys.PublicKeys{acc.PrivateKey().PublicKey()})
|
bc.setNodesByRole(t, true, noderoles.Oracle, keys.PublicKeys{acc.PrivateKey().PublicKey()})
|
||||||
putOracleRequest(t, cs.Hash, bc, "http://get.1234", new(string), "handle", []byte{}, 10_000_000)
|
putOracleRequest(t, cs.Hash, bc, "http://get.1234", new(string), "handle", []byte{}, 10_000_000)
|
||||||
|
|
||||||
require.Eventually(t, func() bool { return mp.Count() == 1 },
|
require.Eventually(t, func() bool { return mp.Count() == 1 },
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
|
@ -73,7 +73,7 @@ func TestStateRoot(t *testing.T) {
|
||||||
bc := newTestChain(t)
|
bc := newTestChain(t)
|
||||||
|
|
||||||
h, pubs, accs := newMajorityMultisigWithGAS(t, 2)
|
h, pubs, accs := newMajorityMultisigWithGAS(t, 2)
|
||||||
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
bc.setNodesByRole(t, true, noderoles.StateValidator, pubs)
|
||||||
updateIndex := bc.BlockHeight()
|
updateIndex := bc.BlockHeight()
|
||||||
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ func TestStateRootInitNonZeroHeight(t *testing.T) {
|
||||||
var root util.Uint256
|
var root util.Uint256
|
||||||
t.Run("init", func(t *testing.T) { // this is in a separate test to do proper cleanup
|
t.Run("init", func(t *testing.T) { // this is in a separate test to do proper cleanup
|
||||||
bc := newTestChainWithCustomCfgAndStore(t, st, nil)
|
bc := newTestChainWithCustomCfgAndStore(t, st, nil)
|
||||||
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
bc.setNodesByRole(t, true, noderoles.StateValidator, pubs)
|
||||||
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
||||||
|
|
||||||
_, err := persistBlock(bc)
|
_, err := persistBlock(bc)
|
||||||
|
@ -210,7 +210,7 @@ func TestStateRootFull(t *testing.T) {
|
||||||
lastValidated.Store(ep)
|
lastValidated.Store(ep)
|
||||||
})
|
})
|
||||||
|
|
||||||
bc.setNodesByRole(t, true, native.RoleStateValidator, pubs)
|
bc.setNodesByRole(t, true, noderoles.StateValidator, pubs)
|
||||||
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
transferTokenFromMultisigAccount(t, bc, h, bc.contracts.GAS.Hash, 1_0000_0000)
|
||||||
require.Eventually(t, func() bool { return lastHeight.Load() == 2 }, time.Second, time.Millisecond)
|
require.Eventually(t, func() bool { return lastHeight.Load() == 2 }, time.Second, time.Millisecond)
|
||||||
checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 2, 1)
|
checkVoteBroadcasted(t, bc, lastValidated.Load().(*payload.Extensible), 2, 1)
|
||||||
|
@ -247,7 +247,7 @@ func checkVoteBroadcasted(t *testing.T, bc *Blockchain, p *payload.Extensible,
|
||||||
require.Equal(t, height, vote.Height)
|
require.Equal(t, height, vote.Height)
|
||||||
require.Equal(t, int32(valIndex), vote.ValidatorIndex)
|
require.Equal(t, int32(valIndex), vote.ValidatorIndex)
|
||||||
|
|
||||||
pubs, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, native.RoleStateValidator, bc.BlockHeight())
|
pubs, _, err := bc.contracts.Designate.GetDesignatedByRole(bc.dao, noderoles.StateValidator, bc.BlockHeight())
|
||||||
require.True(t, len(pubs) > int(valIndex))
|
require.True(t, len(pubs) > int(valIndex))
|
||||||
require.True(t, pubs[valIndex].Verify(vote.Signature, r.GetSignedHash().BytesBE()))
|
require.True(t, pubs[valIndex].Verify(vote.Signature, r.GetSignedHash().BytesBE()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,14 @@ package client
|
||||||
// Various non-policy things from native contracts.
|
// Various non-policy things from native contracts.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/elliptic"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetOraclePrice invokes `getPrice` method on a native Oracle contract.
|
// GetOraclePrice invokes `getPrice` method on a native Oracle contract.
|
||||||
|
@ -34,3 +39,54 @@ func (c *Client) GetGasPerBlock() (int64, error) {
|
||||||
}
|
}
|
||||||
return c.invokeNativeGetMethod(neoHash, "getGasPerBlock")
|
return c.invokeNativeGetMethod(neoHash, "getGasPerBlock")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDesignatedByRole invokes `getDesignatedByRole` method on a native RoleManagement contract.
|
||||||
|
func (c *Client) GetDesignatedByRole(role noderoles.Role, index uint32) (keys.PublicKeys, error) {
|
||||||
|
rmHash, err := c.GetNativeContractHash(nativenames.Designation)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get native RoleManagement hash: %w", err)
|
||||||
|
}
|
||||||
|
result, err := c.InvokeFunction(rmHash, "getDesignatedByRole", []smartcontract.Parameter{
|
||||||
|
{
|
||||||
|
Type: smartcontract.IntegerType,
|
||||||
|
Value: int64(role),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: smartcontract.IntegerType,
|
||||||
|
Value: int64(index),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = getInvocationError(result)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("`getDesignatedByRole`: %w", err)
|
||||||
|
}
|
||||||
|
return topPublicKeysFromStack(result.Stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// topPublicKeysFromStack returns the top array of public keys from stack.
|
||||||
|
func topPublicKeysFromStack(st []stackitem.Item) (keys.PublicKeys, error) {
|
||||||
|
index := len(st) - 1 // top stack element is last in the array
|
||||||
|
var (
|
||||||
|
pks keys.PublicKeys
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
items, ok := st[index].Value().([]stackitem.Item)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid stack item type: %s", st[index].Type())
|
||||||
|
}
|
||||||
|
pks = make(keys.PublicKeys, len(items))
|
||||||
|
for i, item := range items {
|
||||||
|
val, ok := item.Value().([]byte)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid array element #%d: %s", i, item.Type())
|
||||||
|
}
|
||||||
|
pks[i], err = keys.NewPublicKeyFromBytes(val, elliptic.P256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pks, nil
|
||||||
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
"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/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativeprices"
|
||||||
"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/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"
|
||||||
|
@ -693,7 +693,7 @@ func (c *Client) CalculateNotaryFee(nKeys uint8) (int64, error) {
|
||||||
fee.Opcode(baseExecFee, // Notary node witness
|
fee.Opcode(baseExecFee, // Notary node witness
|
||||||
opcode.PUSHDATA1, opcode.RET, // invocation script
|
opcode.PUSHDATA1, opcode.RET, // invocation script
|
||||||
opcode.PUSH0, opcode.SYSCALL, opcode.RET) + // System.Contract.CallNative
|
opcode.PUSH0, opcode.SYSCALL, opcode.RET) + // System.Contract.CallNative
|
||||||
native.NotaryVerificationPrice*baseExecFee + // Notary witness verification price
|
nativeprices.NotaryVerificationPrice*baseExecFee + // Notary witness verification price
|
||||||
feePerByte*int64(io.GetVarSize(make([]byte, 66))) + // invocation script per-byte fee
|
feePerByte*int64(io.GetVarSize(make([]byte, 66))) + // invocation script per-byte fee
|
||||||
feePerByte*int64(io.GetVarSize([]byte{})), // verification script per-byte fee
|
feePerByte*int64(io.GetVarSize([]byte{})), // verification script per-byte fee
|
||||||
nil
|
nil
|
||||||
|
|
|
@ -2,6 +2,7 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/elliptic"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
"github.com/nspcc-dev/neo-go/internal/testserdes"
|
||||||
"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/block"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||||
"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/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
@ -476,6 +478,28 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"getDesignatedByRole": {
|
||||||
|
{
|
||||||
|
name: "positive",
|
||||||
|
invoke: func(c *Client) (interface{}, error) {
|
||||||
|
return c.GetDesignatedByRole(noderoles.P2PNotary, 10)
|
||||||
|
},
|
||||||
|
serverResponse: `{"id" : 1,"result" : {"stack" : [{"value" : [{"type":"ByteString","value":"Aw0WkQoDc8WqpG18xPMTEgfHO6gRTVtMN0Mw6zw06fzl"},{"type":"ByteString","value":"A+bmJ9wIaj96Ygr+uQQvQ0AaUrQmj2b3AGnztAOkU3/L"}],"type" : "Array"}],"exception" : null,"script" : "ERQSwB8ME2dldERlc2lnbmF0ZWRCeVJvbGUMFOKV45FUTBeK2U8D7E3N/3hTTs9JQWJ9W1I=","gasconsumed" : "2028150","state" : "HALT"}, "jsonrpc" : "2.0"}`,
|
||||||
|
result: func(c *Client) interface{} {
|
||||||
|
pk1Bytes, _ := base64.StdEncoding.DecodeString("Aw0WkQoDc8WqpG18xPMTEgfHO6gRTVtMN0Mw6zw06fzl")
|
||||||
|
pk1, err := keys.NewPublicKeyFromBytes(pk1Bytes, elliptic.P256())
|
||||||
|
if err != nil {
|
||||||
|
panic("invalid pub key #1 bytes")
|
||||||
|
}
|
||||||
|
pk2Bytes, _ := base64.StdEncoding.DecodeString("A+bmJ9wIaj96Ygr+uQQvQ0AaUrQmj2b3AGnztAOkU3/L")
|
||||||
|
pk2, err := keys.NewPublicKeyFromBytes(pk2Bytes, elliptic.P256())
|
||||||
|
if err != nil {
|
||||||
|
panic("invalid pub key #2 bytes")
|
||||||
|
}
|
||||||
|
return keys.PublicKeys{pk1, pk2}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"getMaxNotValidBeforeDelta": {
|
"getMaxNotValidBeforeDelta": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
|
|
Loading…
Reference in a new issue