tutus-chain/pkg/core/state/opus.go

624 lines
20 KiB
Go

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
}