tutus-chain/pkg/tutustest/roles.go

227 lines
7.1 KiB
Go

package tutustest
import (
"testing"
"github.com/tutus-one/tutus-chain/pkg/core/native/nativenames"
"github.com/tutus-one/tutus-chain/pkg/util"
"github.com/tutus-one/tutus-chain/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
// Standard role IDs matching role_registry.go and role_registry_domain.go
const (
// Basic roles
RoleAdmin uint64 = 1
RoleValidator uint64 = 2
RoleNotary uint64 = 3
RoleOracle uint64 = 4
RoleStateRoot uint64 = 5
RoleNeoFSInner uint64 = 6
RoleNeoFSOuter uint64 = 7
RoleP2PNotary uint64 = 8
// Government service roles
RoleEducator uint64 = 20
RoleHealthProvider uint64 = 21
RoleLifeCoach uint64 = 22
RoleTributeAdmin uint64 = 23
RoleOpusSupervisor uint64 = 24
RolePalamAuditor uint64 = 25
RolePalamJudge uint64 = 26
RoleBridgeOperator uint64 = 27
RoleInvestmentMgr uint64 = 28
RoleJudge uint64 = 29
// Domain committee roles (CRIT-002)
RoleCommitteeLegal uint64 = 100
RoleCommitteeHealth uint64 = 101
RoleCommitteeEducation uint64 = 102
RoleCommitteeEconomy uint64 = 103
RoleCommitteeIdentity uint64 = 104
RoleCommitteeGovernance uint64 = 105
)
// RoleHelper provides utilities for testing RoleRegistry operations.
type RoleHelper struct {
*Executor
t testing.TB
RoleReg *ContractInvoker
Designate *ContractInvoker
}
// NewRoleHelper creates a helper for testing role-based operations.
func NewRoleHelper(t testing.TB, e *Executor) *RoleHelper {
return &RoleHelper{
Executor: e,
t: t,
RoleReg: e.CommitteeInvoker(e.NativeHash(t, nativenames.RoleRegistry)),
Designate: e.CommitteeInvoker(e.NativeHash(t, nativenames.Designation)),
}
}
// GrantRole grants a role to an account (requires committee authority).
func (r *RoleHelper) GrantRole(account util.Uint160, roleID uint64) {
r.RoleReg.Invoke(r.t, true, "grantRole", account, roleID)
}
// RevokeRole revokes a role from an account (requires committee authority).
func (r *RoleHelper) RevokeRole(account util.Uint160, roleID uint64) {
r.RoleReg.Invoke(r.t, true, "revokeRole", account, roleID)
}
// HasRole checks if an account has a specific role.
func (r *RoleHelper) HasRole(account util.Uint160, roleID uint64) bool {
var hasRole bool
r.RoleReg.InvokeAndCheck(r.t, func(t testing.TB, stack []stackitem.Item) {
hasRole = stack[0].Value().(bool)
}, "hasRole", account, roleID)
return hasRole
}
// RequireRole asserts that an account has a specific role.
func (r *RoleHelper) RequireRole(account util.Uint160, roleID uint64) {
require.True(r.t, r.HasRole(account, roleID), "account should have role %d", roleID)
}
// RequireNoRole asserts that an account does not have a specific role.
func (r *RoleHelper) RequireNoRole(account util.Uint160, roleID uint64) {
require.False(r.t, r.HasRole(account, roleID), "account should not have role %d", roleID)
}
// GetRoleMembers returns all members with a specific role.
func (r *RoleHelper) GetRoleMembers(roleID uint64) []util.Uint160 {
var members []util.Uint160
r.RoleReg.InvokeAndCheck(r.t, func(t testing.TB, stack []stackitem.Item) {
arr, ok := stack[0].Value().([]stackitem.Item)
if !ok {
return
}
for _, item := range arr {
bs, err := item.TryBytes()
require.NoError(t, err)
members = append(members, util.Uint160(bs))
}
}, "getRoleMembers", roleID)
return members
}
// SetupEducator grants the Educator role to an account.
func (r *RoleHelper) SetupEducator(account util.Uint160) {
r.GrantRole(account, RoleEducator)
}
// SetupHealthProvider grants the HealthProvider role to an account.
func (r *RoleHelper) SetupHealthProvider(account util.Uint160) {
r.GrantRole(account, RoleHealthProvider)
}
// SetupJudge grants the Judge role to an account.
func (r *RoleHelper) SetupJudge(account util.Uint160) {
r.GrantRole(account, RoleJudge)
}
// SetupLifeCoach grants the LifeCoach role to an account.
func (r *RoleHelper) SetupLifeCoach(account util.Uint160) {
r.GrantRole(account, RoleLifeCoach)
}
// SetupTributeAdmin grants the TributeAdmin role to an account.
func (r *RoleHelper) SetupTributeAdmin(account util.Uint160) {
r.GrantRole(account, RoleTributeAdmin)
}
// SetupOpusSupervisor grants the OpusSupervisor role to an account.
func (r *RoleHelper) SetupOpusSupervisor(account util.Uint160) {
r.GrantRole(account, RoleOpusSupervisor)
}
// SetupPalamAuditor grants the PalamAuditor role to an account.
func (r *RoleHelper) SetupPalamAuditor(account util.Uint160) {
r.GrantRole(account, RolePalamAuditor)
}
// SetupPalamJudge grants the PalamJudge role to an account.
func (r *RoleHelper) SetupPalamJudge(account util.Uint160) {
r.GrantRole(account, RolePalamJudge)
}
// SetupBridgeOperator grants the BridgeOperator role to an account.
func (r *RoleHelper) SetupBridgeOperator(account util.Uint160) {
r.GrantRole(account, RoleBridgeOperator)
}
// SetupInvestmentManager grants the InvestmentManager role to an account.
func (r *RoleHelper) SetupInvestmentManager(account util.Uint160) {
r.GrantRole(account, RoleInvestmentMgr)
}
// SetupDomainCommittee grants a domain committee role to an account.
func (r *RoleHelper) SetupDomainCommittee(account util.Uint160, domain string) {
var roleID uint64
switch domain {
case "legal":
roleID = RoleCommitteeLegal
case "health":
roleID = RoleCommitteeHealth
case "education":
roleID = RoleCommitteeEducation
case "economy":
roleID = RoleCommitteeEconomy
case "identity":
roleID = RoleCommitteeIdentity
case "governance":
roleID = RoleCommitteeGovernance
default:
require.Fail(r.t, "unknown domain: %s", domain)
}
r.GrantRole(account, roleID)
}
// RoleScenario represents a test scenario with role assignments.
type RoleScenario struct {
helper *RoleHelper
accounts map[string]SingleSigner
roles map[string][]uint64
}
// NewRoleScenario creates a new role scenario builder.
func (r *RoleHelper) NewScenario() *RoleScenario {
return &RoleScenario{
helper: r,
accounts: make(map[string]SingleSigner),
roles: make(map[string][]uint64),
}
}
// WithAccount adds a named account to the scenario.
func (s *RoleScenario) WithAccount(name string, acc SingleSigner) *RoleScenario {
s.accounts[name] = acc
return s
}
// WithRole assigns a role to a named account.
func (s *RoleScenario) WithRole(accountName string, roleID uint64) *RoleScenario {
s.roles[accountName] = append(s.roles[accountName], roleID)
return s
}
// Setup executes all role assignments in the scenario.
func (s *RoleScenario) Setup() map[string]SingleSigner {
for name, roles := range s.roles {
acc, ok := s.accounts[name]
require.True(s.helper.t, ok, "account %s not found", name)
for _, roleID := range roles {
s.helper.GrantRole(acc.ScriptHash(), roleID)
}
}
return s.accounts
}
// Get returns a named account from the scenario.
func (s *RoleScenario) Get(name string) SingleSigner {
acc, ok := s.accounts[name]
require.True(s.helper.t, ok, "account %s not found", name)
return acc
}