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 }