Add Opus native contract for AI workforce integration

Implement comprehensive AI workforce management infrastructure:

- Operator profiles: Registration (requires Vita), verification,
  supervision via RoleOpusSupervisor (ID 24)

- AI Worker lifecycle: Registration, updates, suspension,
  decommissioning with operator ownership tracking

- Task system: Assignment, progress tracking, completion,
  cancellation, and dispute resolution

- Capability certification: Proficiency levels, certification
  tracking, and supervisor-managed verification

- AI Tribute: Configurable percentage of AI-generated value
  directed to Treasury for societal benefit

- Cross-contract integration:
  - Vita: Operator identity verification
  - Lex: Labor rights enforcement (RightLabor)
  - RoleRegistry: Supervisor role authorization
  - VTS: Registration fees and task payments
  - Treasury: Tribute collection

Contract ID: -22, following Tribute (-21)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Tutus Development 2025-12-20 08:51:48 +00:00
parent 1d96eb7a6e
commit 0e980e7342
8 changed files with 2696 additions and 1 deletions

View File

@ -224,6 +224,10 @@ type Blockchain struct {
lex native.ILex lex native.ILex
eligere native.IEligere eligere native.IEligere
scire native.IScire scire native.IScire
salus native.ISalus
sese native.ISese
tribute native.ITribute
opus native.IOpus
extensible atomic.Value extensible atomic.Value
@ -495,6 +499,22 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger, newN
if err := validateNative(bc.scire, nativeids.Scire, nativenames.Scire, nativehashes.Scire); err != nil { if err := validateNative(bc.scire, nativeids.Scire, nativenames.Scire, nativehashes.Scire); err != nil {
return nil, err return nil, err
} }
bc.salus = bc.contracts.Salus()
if err := validateNative(bc.salus, nativeids.Salus, nativenames.Salus, nativehashes.Salus); err != nil {
return nil, err
}
bc.sese = bc.contracts.Sese()
if err := validateNative(bc.sese, nativeids.Sese, nativenames.Sese, nativehashes.Sese); err != nil {
return nil, err
}
bc.tribute = bc.contracts.Tribute()
if err := validateNative(bc.tribute, nativeids.Tribute, nativenames.Tribute, nativehashes.Tribute); err != nil {
return nil, err
}
bc.opus = bc.contracts.Opus()
if err := validateNative(bc.opus, nativeids.Opus, nativenames.Opus, nativehashes.Opus); err != nil {
return nil, err
}
bc.persistCond = sync.NewCond(&bc.lock) bc.persistCond = sync.NewCond(&bc.lock)
bc.gcBlockTimes, _ = lru.New[uint32, uint64](defaultBlockTimesCache) // Never errors for positive size bc.gcBlockTimes, _ = lru.New[uint32, uint64](defaultBlockTimesCache) // Never errors for positive size

View File

@ -238,6 +238,60 @@ type (
// Address returns the contract's script hash. // Address returns the contract's script hash.
Address() util.Uint160 Address() util.Uint160
} }
// ISalus is an interface required from native Salus contract for
// interaction with Blockchain and other native contracts.
// Salus provides universal healthcare infrastructure.
ISalus interface {
interop.Contract
// GetAccountByOwner returns a healthcare account by owner address.
GetAccountByOwner(d *dao.Simple, owner util.Uint160) (*state.HealthcareAccount, error)
// HasValidAuthorization checks if provider has valid authorization for patient.
HasValidAuthorization(d *dao.Simple, patient util.Uint160, provider util.Uint160, blockHeight uint32) bool
// Address returns the contract's script hash.
Address() util.Uint160
}
// ISese is an interface required from native Sese contract for
// interaction with Blockchain and other native contracts.
// Sese provides life planning infrastructure.
ISese interface {
interop.Contract
// GetAccountByOwner returns a life plan account by owner address.
GetAccountByOwner(d *dao.Simple, owner util.Uint160) (*state.LifePlanAccount, error)
// HasActiveCareer checks if owner has an active career.
HasActiveCareer(d *dao.Simple, owner util.Uint160) bool
// Address returns the contract's script hash.
Address() util.Uint160
}
// ITribute is an interface required from native Tribute contract for
// interaction with Blockchain and other native contracts.
// Tribute provides anti-hoarding economics with velocity tracking.
ITribute interface {
interop.Contract
// GetAccountByOwner returns a velocity account by owner address.
GetAccountByOwner(d *dao.Simple, owner util.Uint160) (*state.VelocityAccount, error)
// GetVelocity returns the current velocity score for an owner.
GetVelocity(d *dao.Simple, owner util.Uint160) uint64
// IsHoarding returns true if owner is hoarding resources.
IsHoarding(d *dao.Simple, owner util.Uint160) bool
// Address returns the contract's script hash.
Address() util.Uint160
}
// IOpus provides AI workforce integration and management.
IOpus interface {
interop.Contract
// GetWorkerByID returns an AI worker by ID.
GetWorkerByID(d *dao.Simple, workerID uint64) (*state.AIWorker, error)
// GetOperatorByOwner returns an operator profile by owner address.
GetOperatorByOwner(d *dao.Simple, owner util.Uint160) (*state.OperatorProfile, error)
// IsWorkerActive returns true if the AI worker is active.
IsWorkerActive(d *dao.Simple, workerID uint64) bool
// Address returns the contract's script hash.
Address() util.Uint160
}
) )
// Contracts is a convenient wrapper around an arbitrary set of native contracts // Contracts is a convenient wrapper around an arbitrary set of native contracts
@ -401,6 +455,30 @@ func (cs *Contracts) Scire() IScire {
return cs.ByName(nativenames.Scire).(IScire) return cs.ByName(nativenames.Scire).(IScire)
} }
// Salus returns native ISalus contract implementation. It panics if
// there's no contract with proper name in cs.
func (cs *Contracts) Salus() ISalus {
return cs.ByName(nativenames.Salus).(ISalus)
}
// Sese returns native ISese contract implementation. It panics if
// there's no contract with proper name in cs.
func (cs *Contracts) Sese() ISese {
return cs.ByName(nativenames.Sese).(ISese)
}
// Tribute returns native ITribute contract implementation. It panics if
// there's no contract with proper name in cs.
func (cs *Contracts) Tribute() ITribute {
return cs.ByName(nativenames.Tribute).(ITribute)
}
// Opus returns native IOpus contract implementation. It panics if
// there's no contract with proper name in cs.
func (cs *Contracts) Opus() IOpus {
return cs.ByName(nativenames.Opus).(IOpus)
}
// NewDefaultContracts returns a new set of default native contracts. // NewDefaultContracts returns a new set of default native contracts.
func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract { func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
mgmt := NewManagement() mgmt := NewManagement()
@ -501,6 +579,37 @@ func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
scire.RoleRegistry = roleRegistry scire.RoleRegistry = roleRegistry
scire.Lex = lex scire.Lex = lex
// Create Salus (Universal Healthcare) contract
salus := newSalus()
salus.NEO = neo
salus.Vita = vita
salus.RoleRegistry = roleRegistry
salus.Lex = lex
// Create Sese (Life Planning) contract
sese := newSese()
sese.NEO = neo
sese.Vita = vita
sese.RoleRegistry = roleRegistry
sese.Lex = lex
// Create Tribute (Anti-Hoarding Economics) contract
tribute := newTribute()
tribute.NEO = neo
tribute.Vita = vita
tribute.VTS = vts
tribute.RoleRegistry = roleRegistry
tribute.Lex = lex
// Create Opus (AI Workforce Integration) contract
opus := newOpus()
opus.NEO = neo
opus.Vita = vita
opus.VTS = vts
opus.RoleRegistry = roleRegistry
opus.Lex = lex
opus.Treasury = treasury
return []interop.Contract{ return []interop.Contract{
mgmt, mgmt,
s, s,
@ -520,5 +629,9 @@ func NewDefaultContracts(cfg config.ProtocolConfiguration) []interop.Contract {
lex, lex,
eligere, eligere,
scire, scire,
salus,
sese,
tribute,
opus,
} }
} }

View File

@ -0,0 +1,254 @@
package native_test
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/stretchr/testify/require"
"github.com/tutus-one/tutus-chain/pkg/core/native/nativenames"
"github.com/tutus-one/tutus-chain/pkg/neotest"
"github.com/tutus-one/tutus-chain/pkg/vm/stackitem"
)
func newOpusClient(t *testing.T) *neotest.ContractInvoker {
return newNativeClient(t, nativenames.Opus)
}
// TestOpus_GetConfig tests the getConfig method.
func TestOpus_GetConfig(t *testing.T) {
c := newOpusClient(t)
// Get default config
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
arr, ok := stack[0].Value().([]stackitem.Item)
require.True(t, ok, "expected array result")
require.GreaterOrEqual(t, len(arr), 7) // OpusConfig has 7 fields
}, "getConfig")
}
// TestOpus_GetTotalOperators tests the getTotalOperators method.
func TestOpus_GetTotalOperators(t *testing.T) {
c := newOpusClient(t)
// Initially should be 0
c.Invoke(t, 0, "getTotalOperators")
}
// TestOpus_GetTotalWorkers tests the getTotalWorkers method.
func TestOpus_GetTotalWorkers(t *testing.T) {
c := newOpusClient(t)
// Initially should be 0
c.Invoke(t, 0, "getTotalWorkers")
}
// TestOpus_GetTotalTasks tests the getTotalTasks method.
func TestOpus_GetTotalTasks(t *testing.T) {
c := newOpusClient(t)
// Initially should be 0
c.Invoke(t, 0, "getTotalTasks")
}
// TestOpus_GetTotalCapabilities tests the getTotalCapabilities method.
func TestOpus_GetTotalCapabilities(t *testing.T) {
c := newOpusClient(t)
// Initially should be 0
c.Invoke(t, 0, "getTotalCapabilities")
}
// TestOpus_GetOperator_NonExistent tests getting a non-existent operator.
func TestOpus_GetOperator_NonExistent(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
// Non-existent operator should return null
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
require.Nil(t, stack[0].Value(), "expected null for non-existent operator")
}, "getOperator", acc.ScriptHash())
}
// TestOpus_GetWorker_NonExistent tests getting a non-existent worker.
func TestOpus_GetWorker_NonExistent(t *testing.T) {
c := newOpusClient(t)
// Non-existent worker should return null
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
require.Nil(t, stack[0].Value(), "expected null for non-existent worker")
}, "getWorker", int64(999))
}
// TestOpus_GetTask_NonExistent tests getting a non-existent task.
func TestOpus_GetTask_NonExistent(t *testing.T) {
c := newOpusClient(t)
// Non-existent task should return null
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
require.Nil(t, stack[0].Value(), "expected null for non-existent task")
}, "getTask", int64(999))
}
// TestOpus_GetCapability_NonExistent tests getting a non-existent capability.
func TestOpus_GetCapability_NonExistent(t *testing.T) {
c := newOpusClient(t)
// Non-existent capability should return null
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
require.Nil(t, stack[0].Value(), "expected null for non-existent capability")
}, "getCapability", int64(999))
}
// Note: isWorkerActive and isOperatorVerified methods are not exposed as separate methods.
// Worker/operator status can be checked via getWorker/getOperator.
// TestOpus_GetWorkerCountByOperator_NonExistent tests getting worker count for non-existent operator.
func TestOpus_GetWorkerCountByOperator_NonExistent(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
// Non-existent operator should return 0
c.Invoke(t, 0, "getWorkerCountByOperator", acc.ScriptHash())
}
// TestOpus_RegisterOperator_NoVita tests that registering operator without Vita fails.
func TestOpus_RegisterOperator_NoVita(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
// Should fail - no Vita registered
invoker.InvokeFail(t, "operator must have an active Vita", "registerOperator",
acc.ScriptHash())
}
// TestOpus_VerifyOperator_NotSupervisor tests that non-supervisor cannot verify operator.
func TestOpus_VerifyOperator_NotSupervisor(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
// Should fail - not supervisor
invoker.InvokeFail(t, "caller is not an authorized supervisor", "verifyOperator", acc.ScriptHash())
}
// Note: suspendOperator method is not currently implemented. Operators can be managed
// through their linked Vita status.
// TestOpus_RegisterWorker_NoOperator tests that registering worker without operator fails.
func TestOpus_RegisterWorker_NoOperator(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
modelHash := hash.Sha256([]byte("model")).BytesBE()
// Should fail - no operator registered (registerWorker takes: name, description, workerType, modelHash)
invoker.InvokeFail(t, "operator profile not found", "registerWorker",
"TestWorker", "Test AI Worker", int64(0), modelHash)
}
// TestOpus_SuspendWorker_NotSupervisor tests that non-supervisor cannot suspend worker.
func TestOpus_SuspendWorker_NotSupervisor(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
// Should fail - not supervisor (checked before worker existence)
invoker.InvokeFail(t, "caller is not an authorized supervisor", "suspendWorker", int64(999), "suspension reason")
}
// TestOpus_AssignTask_WorkerNotFound tests that assigning task to non-existent worker fails.
func TestOpus_AssignTask_WorkerNotFound(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
// Should fail - worker not found
invoker.InvokeFail(t, "worker not found", "assignTask",
int64(999), "task-123", "Test Task", int64(1000))
}
// TestOpus_CompleteTask_TaskNotFound tests that completing non-existent task fails.
func TestOpus_CompleteTask_TaskNotFound(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
resultHash := hash.Sha256([]byte("result")).BytesBE()
// Should fail - task not found
invoker.InvokeFail(t, "task not found", "completeTask", int64(999), resultHash, int64(500))
}
// TestOpus_AddCapability_WorkerNotFound tests that adding capability to non-existent worker fails.
func TestOpus_AddCapability_WorkerNotFound(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
acc := e.NewAccount(t)
invoker := c.WithSigners(acc)
// Should fail - worker not found (before checking supervisor)
invoker.InvokeFail(t, "AI worker not found", "addCapability",
int64(999), "language_model", int64(3), "Test certification")
}
// TestOpus_RegisterOperatorWithVita tests operator registration with a valid Vita.
func TestOpus_RegisterOperatorWithVita(t *testing.T) {
c := newOpusClient(t)
e := c.Executor
// Register Vita first
vitaHash := e.NativeHash(t, nativenames.Vita)
acc := e.NewAccount(t)
vitaInvoker := e.NewInvoker(vitaHash, acc)
owner := acc.ScriptHash()
personHash := hash.Sha256(owner.BytesBE()).BytesBE()
isEntity := false
recoveryHash := hash.Sha256([]byte("recovery")).BytesBE()
// Register Vita token
vitaInvoker.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
_, ok := stack[0].Value().([]byte)
require.True(t, ok, "expected ByteArray result")
}, "register", owner.BytesBE(), personHash, isEntity, recoveryHash)
// Now register operator (only takes owner as parameter)
opusInvoker := c.WithSigners(acc)
opusInvoker.Invoke(t, true, "registerOperator", owner.BytesBE())
// Verify operator exists
opusInvoker.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
require.Equal(t, 1, len(stack))
arr, ok := stack[0].Value().([]stackitem.Item)
require.True(t, ok, "expected array result for existing operator")
require.GreaterOrEqual(t, len(arr), 9) // OperatorProfile has 9 fields
}, "getOperator", owner.BytesBE())
// Verify total operators increased
c.Invoke(t, 1, "getTotalOperators")
}

View File

@ -45,4 +45,12 @@ var (
Eligere = util.Uint160{0x1, 0x94, 0x73, 0x8e, 0xab, 0x6b, 0xc5, 0xa0, 0xff, 0xab, 0xe0, 0x2a, 0xce, 0xea, 0xd7, 0xb3, 0xa8, 0xe5, 0x7, 0x40} Eligere = util.Uint160{0x1, 0x94, 0x73, 0x8e, 0xab, 0x6b, 0xc5, 0xa0, 0xff, 0xab, 0xe0, 0x2a, 0xce, 0xea, 0xd7, 0xb3, 0xa8, 0xe5, 0x7, 0x40}
// Scire is a hash of native Scire contract. // Scire is a hash of native Scire contract.
Scire = util.Uint160{0x9f, 0x7, 0x16, 0xd4, 0xd6, 0xb8, 0xae, 0x2d, 0x58, 0x42, 0x94, 0xf8, 0x92, 0x62, 0x5d, 0x8e, 0x63, 0xa0, 0xde, 0x3} Scire = util.Uint160{0x9f, 0x7, 0x16, 0xd4, 0xd6, 0xb8, 0xae, 0x2d, 0x58, 0x42, 0x94, 0xf8, 0x92, 0x62, 0x5d, 0x8e, 0x63, 0xa0, 0xde, 0x3}
// Salus is a hash of native Salus contract.
Salus = util.Uint160{0x91, 0x6e, 0x6a, 0xf6, 0x70, 0x7b, 0x91, 0x75, 0x9f, 0xbd, 0xff, 0xdb, 0x25, 0xe6, 0xee, 0xf9, 0x4f, 0x20, 0x88, 0xc8}
// Sese is a hash of native Sese contract.
Sese = util.Uint160{0x16, 0x99, 0x28, 0x39, 0x2, 0xfe, 0x12, 0x60, 0xf3, 0xe, 0x4b, 0x2b, 0xf7, 0x44, 0x19, 0xc4, 0x7d, 0x24, 0xfd, 0x48}
// Tribute is a hash of native Tribute contract.
Tribute = util.Uint160{0x35, 0x9b, 0xbf, 0x51, 0xb5, 0xe3, 0x73, 0x6d, 0x52, 0xad, 0x80, 0xb0, 0x28, 0x4f, 0x22, 0x8f, 0x9, 0xaf, 0x49, 0x1e}
// Opus is a hash of native Opus contract.
Opus = util.Uint160{0xf5, 0x22, 0x73, 0x17, 0x98, 0xab, 0xfc, 0x4d, 0x7c, 0x3a, 0x51, 0x8, 0x47, 0xc7, 0xe5, 0xe4, 0x6, 0x96, 0xb6, 0xfd}
) )

View File

@ -43,4 +43,12 @@ const (
Eligere int32 = -17 Eligere int32 = -17
// Scire is an ID of native Scire contract. // Scire is an ID of native Scire contract.
Scire int32 = -18 Scire int32 = -18
// Salus is an ID of native Salus contract.
Salus int32 = -19
// Sese is an ID of native Sese contract.
Sese int32 = -20
// Tribute is an ID of native Tribute contract.
Tribute int32 = -21
// Opus is an ID of native Opus contract.
Opus int32 = -22
) )

View File

@ -20,6 +20,10 @@ const (
Lex = "Lex" Lex = "Lex"
Eligere = "Eligere" Eligere = "Eligere"
Scire = "Scire" Scire = "Scire"
Salus = "Salus"
Sese = "Sese"
Tribute = "Tribute"
Opus = "Opus"
) )
// All contains the list of all native contract names ordered by the contract ID. // All contains the list of all native contract names ordered by the contract ID.
@ -42,6 +46,10 @@ var All = []string{
Lex, Lex,
Eligere, Eligere,
Scire, Scire,
Salus,
Sese,
Tribute,
Opus,
} }
// IsValid checks if the name is a valid native contract's name. // IsValid checks if the name is a valid native contract's name.
@ -63,5 +71,9 @@ func IsValid(name string) bool {
name == Federation || name == Federation ||
name == Lex || name == Lex ||
name == Eligere || name == Eligere ||
name == Scire name == Scire ||
name == Salus ||
name == Sese ||
name == Tribute ||
name == Opus
} }

1657
pkg/core/native/opus.go Normal file

File diff suppressed because it is too large Load Diff

623
pkg/core/state/opus.go Normal file
View File

@ -0,0 +1,623 @@
package state
import (
"errors"
"fmt"
"math/big"
"github.com/tutus-one/tutus-chain/pkg/util"
"github.com/tutus-one/tutus-chain/pkg/vm/stackitem"
)
// AIWorkerStatus represents the status of an AI worker.
type AIWorkerStatus uint8
const (
// AIWorkerActive indicates an active AI worker.
AIWorkerActive AIWorkerStatus = 0
// AIWorkerSuspended indicates a suspended AI worker.
AIWorkerSuspended AIWorkerStatus = 1
// AIWorkerDecommissioned indicates a decommissioned AI worker.
AIWorkerDecommissioned AIWorkerStatus = 2
)
// TaskStatus represents the status of an AI task.
type TaskStatus uint8
const (
// TaskAssigned indicates a task has been assigned.
TaskAssigned TaskStatus = 0
// TaskInProgress indicates a task is being worked on.
TaskInProgress TaskStatus = 1
// TaskCompleted indicates a task was completed successfully.
TaskCompleted TaskStatus = 2
// TaskFailed indicates a task failed.
TaskFailed TaskStatus = 3
// TaskCancelled indicates a task was cancelled.
TaskCancelled TaskStatus = 4
)
// CapabilityLevel represents the proficiency level of an AI capability.
type CapabilityLevel uint8
const (
// CapabilityBasic represents basic proficiency.
CapabilityBasic CapabilityLevel = 0
// CapabilityStandard represents standard proficiency.
CapabilityStandard CapabilityLevel = 1
// CapabilityAdvanced represents advanced proficiency.
CapabilityAdvanced CapabilityLevel = 2
// CapabilityExpert represents expert proficiency.
CapabilityExpert CapabilityLevel = 3
)
// WorkerType represents the type of AI worker.
type WorkerType uint8
const (
// WorkerTypeGeneral represents a general-purpose AI.
WorkerTypeGeneral WorkerType = 0
// WorkerTypeSpecialized represents a domain-specialized AI.
WorkerTypeSpecialized WorkerType = 1
// WorkerTypeAutonomous represents a fully autonomous AI agent.
WorkerTypeAutonomous WorkerType = 2
// WorkerTypeAssistive represents an AI that assists humans.
WorkerTypeAssistive WorkerType = 3
)
// AIWorker represents a registered AI worker in the Opus system.
type AIWorker struct {
ID uint64 // Unique AI worker ID
Name string // Human-readable name
Description string // Description of capabilities
OperatorVitaID uint64 // Vita ID of the human/org operator
Operator util.Uint160 // Operator's address
WorkerType WorkerType // Type of AI worker
ModelHash util.Uint256 // Hash of the AI model/system
TributeRate uint32 // Tribute rate in basis points (e.g., 5000 = 50%)
TotalTasksAssigned uint64 // Total tasks assigned
TotalTasksCompleted uint64 // Total tasks completed
TotalValueGenerated uint64 // Total value generated (in VTS)
TotalTributePaid uint64 // Total tribute paid to society
Status AIWorkerStatus // Worker status
RegisteredAt uint32 // Block height when registered
UpdatedAt uint32 // Block height of last update
}
// ToStackItem implements stackitem.Convertible interface.
func (w *AIWorker) ToStackItem() (stackitem.Item, error) {
return stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(w.ID))),
stackitem.NewByteArray([]byte(w.Name)),
stackitem.NewByteArray([]byte(w.Description)),
stackitem.NewBigInteger(big.NewInt(int64(w.OperatorVitaID))),
stackitem.NewByteArray(w.Operator.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(w.WorkerType))),
stackitem.NewByteArray(w.ModelHash.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(w.TributeRate))),
stackitem.NewBigInteger(big.NewInt(int64(w.TotalTasksAssigned))),
stackitem.NewBigInteger(big.NewInt(int64(w.TotalTasksCompleted))),
stackitem.NewBigInteger(big.NewInt(int64(w.TotalValueGenerated))),
stackitem.NewBigInteger(big.NewInt(int64(w.TotalTributePaid))),
stackitem.NewBigInteger(big.NewInt(int64(w.Status))),
stackitem.NewBigInteger(big.NewInt(int64(w.RegisteredAt))),
stackitem.NewBigInteger(big.NewInt(int64(w.UpdatedAt))),
}), nil
}
// FromStackItem implements stackitem.Convertible interface.
func (w *AIWorker) FromStackItem(item stackitem.Item) error {
items, ok := item.Value().([]stackitem.Item)
if !ok {
return errors.New("not a struct")
}
if len(items) != 15 {
return fmt.Errorf("wrong number of elements: expected 15, got %d", len(items))
}
id, err := items[0].TryInteger()
if err != nil {
return fmt.Errorf("invalid id: %w", err)
}
w.ID = id.Uint64()
name, err := items[1].TryBytes()
if err != nil {
return fmt.Errorf("invalid name: %w", err)
}
w.Name = string(name)
description, err := items[2].TryBytes()
if err != nil {
return fmt.Errorf("invalid description: %w", err)
}
w.Description = string(description)
operatorVitaID, err := items[3].TryInteger()
if err != nil {
return fmt.Errorf("invalid operatorVitaID: %w", err)
}
w.OperatorVitaID = operatorVitaID.Uint64()
operator, err := items[4].TryBytes()
if err != nil {
return fmt.Errorf("invalid operator: %w", err)
}
w.Operator, err = util.Uint160DecodeBytesBE(operator)
if err != nil {
return fmt.Errorf("invalid operator address: %w", err)
}
workerType, err := items[5].TryInteger()
if err != nil {
return fmt.Errorf("invalid workerType: %w", err)
}
w.WorkerType = WorkerType(workerType.Uint64())
modelHash, err := items[6].TryBytes()
if err != nil {
return fmt.Errorf("invalid modelHash: %w", err)
}
w.ModelHash, err = util.Uint256DecodeBytesBE(modelHash)
if err != nil {
return fmt.Errorf("invalid modelHash value: %w", err)
}
tributeRate, err := items[7].TryInteger()
if err != nil {
return fmt.Errorf("invalid tributeRate: %w", err)
}
w.TributeRate = uint32(tributeRate.Uint64())
tasksAssigned, err := items[8].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalTasksAssigned: %w", err)
}
w.TotalTasksAssigned = tasksAssigned.Uint64()
tasksCompleted, err := items[9].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalTasksCompleted: %w", err)
}
w.TotalTasksCompleted = tasksCompleted.Uint64()
valueGenerated, err := items[10].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalValueGenerated: %w", err)
}
w.TotalValueGenerated = valueGenerated.Uint64()
tributePaid, err := items[11].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalTributePaid: %w", err)
}
w.TotalTributePaid = tributePaid.Uint64()
status, err := items[12].TryInteger()
if err != nil {
return fmt.Errorf("invalid status: %w", err)
}
w.Status = AIWorkerStatus(status.Uint64())
registeredAt, err := items[13].TryInteger()
if err != nil {
return fmt.Errorf("invalid registeredAt: %w", err)
}
w.RegisteredAt = uint32(registeredAt.Uint64())
updatedAt, err := items[14].TryInteger()
if err != nil {
return fmt.Errorf("invalid updatedAt: %w", err)
}
w.UpdatedAt = uint32(updatedAt.Uint64())
return nil
}
// AITask represents a task assigned to an AI worker.
type AITask struct {
ID uint64 // Unique task ID
WorkerID uint64 // AI worker ID
RequesterVitaID uint64 // Vita ID of the requester (0 = system task)
Requester util.Uint160 // Requester's address
TaskType string // Type/category of task
Description string // Task description
ValueOffered uint64 // VTS value offered for task
ValueCompleted uint64 // Actual value upon completion
TributePaid uint64 // Tribute paid from this task
ResultHash util.Uint256 // Hash of task result/output
Status TaskStatus // Task status
AssignedAt uint32 // Block height when assigned
CompletedAt uint32 // Block height when completed (0 = incomplete)
}
// ToStackItem implements stackitem.Convertible interface.
func (t *AITask) ToStackItem() (stackitem.Item, error) {
return stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(t.ID))),
stackitem.NewBigInteger(big.NewInt(int64(t.WorkerID))),
stackitem.NewBigInteger(big.NewInt(int64(t.RequesterVitaID))),
stackitem.NewByteArray(t.Requester.BytesBE()),
stackitem.NewByteArray([]byte(t.TaskType)),
stackitem.NewByteArray([]byte(t.Description)),
stackitem.NewBigInteger(big.NewInt(int64(t.ValueOffered))),
stackitem.NewBigInteger(big.NewInt(int64(t.ValueCompleted))),
stackitem.NewBigInteger(big.NewInt(int64(t.TributePaid))),
stackitem.NewByteArray(t.ResultHash.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(t.Status))),
stackitem.NewBigInteger(big.NewInt(int64(t.AssignedAt))),
stackitem.NewBigInteger(big.NewInt(int64(t.CompletedAt))),
}), nil
}
// FromStackItem implements stackitem.Convertible interface.
func (t *AITask) FromStackItem(item stackitem.Item) error {
items, ok := item.Value().([]stackitem.Item)
if !ok {
return errors.New("not a struct")
}
if len(items) != 13 {
return fmt.Errorf("wrong number of elements: expected 13, got %d", len(items))
}
id, err := items[0].TryInteger()
if err != nil {
return fmt.Errorf("invalid id: %w", err)
}
t.ID = id.Uint64()
workerID, err := items[1].TryInteger()
if err != nil {
return fmt.Errorf("invalid workerID: %w", err)
}
t.WorkerID = workerID.Uint64()
requesterVitaID, err := items[2].TryInteger()
if err != nil {
return fmt.Errorf("invalid requesterVitaID: %w", err)
}
t.RequesterVitaID = requesterVitaID.Uint64()
requester, err := items[3].TryBytes()
if err != nil {
return fmt.Errorf("invalid requester: %w", err)
}
t.Requester, err = util.Uint160DecodeBytesBE(requester)
if err != nil {
return fmt.Errorf("invalid requester address: %w", err)
}
taskType, err := items[4].TryBytes()
if err != nil {
return fmt.Errorf("invalid taskType: %w", err)
}
t.TaskType = string(taskType)
description, err := items[5].TryBytes()
if err != nil {
return fmt.Errorf("invalid description: %w", err)
}
t.Description = string(description)
valueOffered, err := items[6].TryInteger()
if err != nil {
return fmt.Errorf("invalid valueOffered: %w", err)
}
t.ValueOffered = valueOffered.Uint64()
valueCompleted, err := items[7].TryInteger()
if err != nil {
return fmt.Errorf("invalid valueCompleted: %w", err)
}
t.ValueCompleted = valueCompleted.Uint64()
tributePaid, err := items[8].TryInteger()
if err != nil {
return fmt.Errorf("invalid tributePaid: %w", err)
}
t.TributePaid = tributePaid.Uint64()
resultHash, err := items[9].TryBytes()
if err != nil {
return fmt.Errorf("invalid resultHash: %w", err)
}
t.ResultHash, err = util.Uint256DecodeBytesBE(resultHash)
if err != nil {
return fmt.Errorf("invalid resultHash value: %w", err)
}
status, err := items[10].TryInteger()
if err != nil {
return fmt.Errorf("invalid status: %w", err)
}
t.Status = TaskStatus(status.Uint64())
assignedAt, err := items[11].TryInteger()
if err != nil {
return fmt.Errorf("invalid assignedAt: %w", err)
}
t.AssignedAt = uint32(assignedAt.Uint64())
completedAt, err := items[12].TryInteger()
if err != nil {
return fmt.Errorf("invalid completedAt: %w", err)
}
t.CompletedAt = uint32(completedAt.Uint64())
return nil
}
// AICapability represents a certified capability of an AI worker.
type AICapability struct {
ID uint64 // Unique capability ID
WorkerID uint64 // AI worker ID
Name string // Capability name
Category string // Capability category
Level CapabilityLevel // Proficiency level
CertifiedBy util.Uint160 // Certifier's address
CertifiedAt uint32 // Block height when certified
ExpiresAt uint32 // Expiration block (0 = never)
IsVerified bool // Whether capability is verified
}
// ToStackItem implements stackitem.Convertible interface.
func (c *AICapability) ToStackItem() (stackitem.Item, error) {
return stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(c.ID))),
stackitem.NewBigInteger(big.NewInt(int64(c.WorkerID))),
stackitem.NewByteArray([]byte(c.Name)),
stackitem.NewByteArray([]byte(c.Category)),
stackitem.NewBigInteger(big.NewInt(int64(c.Level))),
stackitem.NewByteArray(c.CertifiedBy.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(c.CertifiedAt))),
stackitem.NewBigInteger(big.NewInt(int64(c.ExpiresAt))),
stackitem.NewBool(c.IsVerified),
}), nil
}
// FromStackItem implements stackitem.Convertible interface.
func (c *AICapability) FromStackItem(item stackitem.Item) error {
items, ok := item.Value().([]stackitem.Item)
if !ok {
return errors.New("not a struct")
}
if len(items) != 9 {
return fmt.Errorf("wrong number of elements: expected 9, got %d", len(items))
}
id, err := items[0].TryInteger()
if err != nil {
return fmt.Errorf("invalid id: %w", err)
}
c.ID = id.Uint64()
workerID, err := items[1].TryInteger()
if err != nil {
return fmt.Errorf("invalid workerID: %w", err)
}
c.WorkerID = workerID.Uint64()
name, err := items[2].TryBytes()
if err != nil {
return fmt.Errorf("invalid name: %w", err)
}
c.Name = string(name)
category, err := items[3].TryBytes()
if err != nil {
return fmt.Errorf("invalid category: %w", err)
}
c.Category = string(category)
level, err := items[4].TryInteger()
if err != nil {
return fmt.Errorf("invalid level: %w", err)
}
c.Level = CapabilityLevel(level.Uint64())
certifiedBy, err := items[5].TryBytes()
if err != nil {
return fmt.Errorf("invalid certifiedBy: %w", err)
}
c.CertifiedBy, err = util.Uint160DecodeBytesBE(certifiedBy)
if err != nil {
return fmt.Errorf("invalid certifiedBy address: %w", err)
}
certifiedAt, err := items[6].TryInteger()
if err != nil {
return fmt.Errorf("invalid certifiedAt: %w", err)
}
c.CertifiedAt = uint32(certifiedAt.Uint64())
expiresAt, err := items[7].TryInteger()
if err != nil {
return fmt.Errorf("invalid expiresAt: %w", err)
}
c.ExpiresAt = uint32(expiresAt.Uint64())
isVerified, err := items[8].TryBool()
if err != nil {
return fmt.Errorf("invalid isVerified: %w", err)
}
c.IsVerified = isVerified
return nil
}
// OperatorProfile represents an AI operator's profile (human/org that deploys AI).
type OperatorProfile struct {
VitaID uint64 // Operator's Vita ID
Owner util.Uint160 // Operator's address
TotalWorkersOwned uint64 // Number of AI workers owned
TotalTributePaid uint64 // Total tribute paid by all workers
TotalValueGenerated uint64 // Total value generated by all workers
ReputationScore uint32 // Reputation score (0-10000 basis points)
IsVerified bool // Whether operator is verified
CreatedAt uint32 // Block height when created
UpdatedAt uint32 // Block height of last update
}
// ToStackItem implements stackitem.Convertible interface.
func (p *OperatorProfile) ToStackItem() (stackitem.Item, error) {
return stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(p.VitaID))),
stackitem.NewByteArray(p.Owner.BytesBE()),
stackitem.NewBigInteger(big.NewInt(int64(p.TotalWorkersOwned))),
stackitem.NewBigInteger(big.NewInt(int64(p.TotalTributePaid))),
stackitem.NewBigInteger(big.NewInt(int64(p.TotalValueGenerated))),
stackitem.NewBigInteger(big.NewInt(int64(p.ReputationScore))),
stackitem.NewBool(p.IsVerified),
stackitem.NewBigInteger(big.NewInt(int64(p.CreatedAt))),
stackitem.NewBigInteger(big.NewInt(int64(p.UpdatedAt))),
}), nil
}
// FromStackItem implements stackitem.Convertible interface.
func (p *OperatorProfile) FromStackItem(item stackitem.Item) error {
items, ok := item.Value().([]stackitem.Item)
if !ok {
return errors.New("not a struct")
}
if len(items) != 9 {
return fmt.Errorf("wrong number of elements: expected 9, got %d", len(items))
}
vitaID, err := items[0].TryInteger()
if err != nil {
return fmt.Errorf("invalid vitaID: %w", err)
}
p.VitaID = vitaID.Uint64()
owner, err := items[1].TryBytes()
if err != nil {
return fmt.Errorf("invalid owner: %w", err)
}
p.Owner, err = util.Uint160DecodeBytesBE(owner)
if err != nil {
return fmt.Errorf("invalid owner address: %w", err)
}
totalWorkers, err := items[2].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalWorkersOwned: %w", err)
}
p.TotalWorkersOwned = totalWorkers.Uint64()
tributePaid, err := items[3].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalTributePaid: %w", err)
}
p.TotalTributePaid = tributePaid.Uint64()
valueGenerated, err := items[4].TryInteger()
if err != nil {
return fmt.Errorf("invalid totalValueGenerated: %w", err)
}
p.TotalValueGenerated = valueGenerated.Uint64()
reputationScore, err := items[5].TryInteger()
if err != nil {
return fmt.Errorf("invalid reputationScore: %w", err)
}
p.ReputationScore = uint32(reputationScore.Uint64())
isVerified, err := items[6].TryBool()
if err != nil {
return fmt.Errorf("invalid isVerified: %w", err)
}
p.IsVerified = isVerified
createdAt, err := items[7].TryInteger()
if err != nil {
return fmt.Errorf("invalid createdAt: %w", err)
}
p.CreatedAt = uint32(createdAt.Uint64())
updatedAt, err := items[8].TryInteger()
if err != nil {
return fmt.Errorf("invalid updatedAt: %w", err)
}
p.UpdatedAt = uint32(updatedAt.Uint64())
return nil
}
// OpusConfig represents configurable parameters for the Opus contract.
type OpusConfig struct {
MinTributeRate uint32 // Minimum tribute rate (basis points)
MaxTributeRate uint32 // Maximum tribute rate (basis points)
DefaultTributeRate uint32 // Default tribute rate for new workers
RegistrationFee uint64 // VTS fee to register an AI worker
TaskCompletionMinimum uint64 // Minimum value for task completion
VerificationRequired bool // Whether operator verification is required
MaxWorkersPerOperator uint64 // Maximum AI workers per operator (0 = unlimited)
}
// ToStackItem implements stackitem.Convertible interface.
func (c *OpusConfig) ToStackItem() (stackitem.Item, error) {
return stackitem.NewStruct([]stackitem.Item{
stackitem.NewBigInteger(big.NewInt(int64(c.MinTributeRate))),
stackitem.NewBigInteger(big.NewInt(int64(c.MaxTributeRate))),
stackitem.NewBigInteger(big.NewInt(int64(c.DefaultTributeRate))),
stackitem.NewBigInteger(big.NewInt(int64(c.RegistrationFee))),
stackitem.NewBigInteger(big.NewInt(int64(c.TaskCompletionMinimum))),
stackitem.NewBool(c.VerificationRequired),
stackitem.NewBigInteger(big.NewInt(int64(c.MaxWorkersPerOperator))),
}), nil
}
// FromStackItem implements stackitem.Convertible interface.
func (c *OpusConfig) FromStackItem(item stackitem.Item) error {
items, ok := item.Value().([]stackitem.Item)
if !ok {
return errors.New("not a struct")
}
if len(items) != 7 {
return fmt.Errorf("wrong number of elements: expected 7, got %d", len(items))
}
minRate, err := items[0].TryInteger()
if err != nil {
return fmt.Errorf("invalid minTributeRate: %w", err)
}
c.MinTributeRate = uint32(minRate.Uint64())
maxRate, err := items[1].TryInteger()
if err != nil {
return fmt.Errorf("invalid maxTributeRate: %w", err)
}
c.MaxTributeRate = uint32(maxRate.Uint64())
defaultRate, err := items[2].TryInteger()
if err != nil {
return fmt.Errorf("invalid defaultTributeRate: %w", err)
}
c.DefaultTributeRate = uint32(defaultRate.Uint64())
regFee, err := items[3].TryInteger()
if err != nil {
return fmt.Errorf("invalid registrationFee: %w", err)
}
c.RegistrationFee = regFee.Uint64()
taskMin, err := items[4].TryInteger()
if err != nil {
return fmt.Errorf("invalid taskCompletionMinimum: %w", err)
}
c.TaskCompletionMinimum = taskMin.Uint64()
verificationReq, err := items[5].TryBool()
if err != nil {
return fmt.Errorf("invalid verificationRequired: %w", err)
}
c.VerificationRequired = verificationReq
maxWorkers, err := items[6].TryInteger()
if err != nil {
return fmt.Errorf("invalid maxWorkersPerOperator: %w", err)
}
c.MaxWorkersPerOperator = maxWorkers.Uint64()
return nil
}