package state import ( "errors" "fmt" "math/big" "github.com/tutus-one/tutus-chain/pkg/util" "github.com/tutus-one/tutus-chain/pkg/vm/stackitem" ) // LifePlanAccountStatus represents the status of a life planning account. type LifePlanAccountStatus uint8 const ( // LifePlanAccountActive indicates an active account. LifePlanAccountActive LifePlanAccountStatus = 0 // LifePlanAccountSuspended indicates a suspended account. LifePlanAccountSuspended LifePlanAccountStatus = 1 // LifePlanAccountClosed indicates a closed account. LifePlanAccountClosed LifePlanAccountStatus = 2 ) // CareerCycleStatus represents the status of a career cycle. type CareerCycleStatus uint8 const ( // CareerCycleActive indicates an active career. CareerCycleActive CareerCycleStatus = 0 // CareerCycleCompleted indicates a completed career. CareerCycleCompleted CareerCycleStatus = 1 // CareerCycleTransitioning indicates transitioning to new career. CareerCycleTransitioning CareerCycleStatus = 2 ) // SabbaticalStatus represents the status of a sabbatical. type SabbaticalStatus uint8 const ( // SabbaticalPlanned indicates a planned sabbatical. SabbaticalPlanned SabbaticalStatus = 0 // SabbaticalActive indicates an active sabbatical. SabbaticalActive SabbaticalStatus = 1 // SabbaticalCompleted indicates a completed sabbatical. SabbaticalCompleted SabbaticalStatus = 2 // SabbaticalCancelled indicates a cancelled sabbatical. SabbaticalCancelled SabbaticalStatus = 3 ) // SabbaticalPurpose represents the purpose of a sabbatical. type SabbaticalPurpose uint8 const ( // SabbaticalPurposeEducation for education and learning. SabbaticalPurposeEducation SabbaticalPurpose = 0 // SabbaticalPurposeHealth for health and recovery. SabbaticalPurposeHealth SabbaticalPurpose = 1 // SabbaticalPurposeFamily for family care. SabbaticalPurposeFamily SabbaticalPurpose = 2 // SabbaticalPurposeExploration for personal exploration. SabbaticalPurposeExploration SabbaticalPurpose = 3 // SabbaticalPurposeTransition for career transition. SabbaticalPurposeTransition SabbaticalPurpose = 4 // SabbaticalPurposeVolunteer for volunteering. SabbaticalPurposeVolunteer SabbaticalPurpose = 5 ) // MilestoneType represents the type of life milestone. type MilestoneType uint8 const ( // MilestoneCareerStart for starting a career. MilestoneCareerStart MilestoneType = 0 // MilestoneCareerEnd for ending a career. MilestoneCareerEnd MilestoneType = 1 // MilestoneEducation for educational achievements. MilestoneEducation MilestoneType = 2 // MilestoneFamily for family events. MilestoneFamily MilestoneType = 3 // MilestoneHealth for health milestones. MilestoneHealth MilestoneType = 4 // MilestoneFinancial for financial goals. MilestoneFinancial MilestoneType = 5 // MilestonePersonal for personal achievements. MilestonePersonal MilestoneType = 6 ) // GoalStatus represents the status of a life goal. type GoalStatus uint8 const ( // GoalStatusPlanned indicates a planned goal. GoalStatusPlanned GoalStatus = 0 // GoalStatusInProgress indicates an in-progress goal. GoalStatusInProgress GoalStatus = 1 // GoalStatusCompleted indicates a completed goal. GoalStatusCompleted GoalStatus = 2 // GoalStatusAbandoned indicates an abandoned goal. GoalStatusAbandoned GoalStatus = 3 ) // LifePlanAccount represents a citizen's life planning account. type LifePlanAccount struct { VitaID uint64 // Owner's Vita token ID Owner util.Uint160 // Owner's address TotalContributions uint64 // Lifetime contributions EmployerContributions uint64 // Employer contributions GovernmentContributions uint64 // Government matching CurrentBalance uint64 // Current account balance SabbaticalCredits uint64 // Available sabbatical credits LongevityMultiplier uint32 // Age-based benefit multiplier (basis points) CurrentCareerCycleID uint64 // Active career cycle ID TotalCareerCycles uint32 // Number of career cycles TotalSabbaticals uint32 // Number of sabbaticals taken Status LifePlanAccountStatus // Account status CreatedAt uint32 // Block height when created UpdatedAt uint32 // Block height of last update } // ToStackItem implements stackitem.Convertible interface. func (a *LifePlanAccount) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(a.VitaID))), stackitem.NewByteArray(a.Owner.BytesBE()), stackitem.NewBigInteger(big.NewInt(int64(a.TotalContributions))), stackitem.NewBigInteger(big.NewInt(int64(a.EmployerContributions))), stackitem.NewBigInteger(big.NewInt(int64(a.GovernmentContributions))), stackitem.NewBigInteger(big.NewInt(int64(a.CurrentBalance))), stackitem.NewBigInteger(big.NewInt(int64(a.SabbaticalCredits))), stackitem.NewBigInteger(big.NewInt(int64(a.LongevityMultiplier))), stackitem.NewBigInteger(big.NewInt(int64(a.CurrentCareerCycleID))), stackitem.NewBigInteger(big.NewInt(int64(a.TotalCareerCycles))), stackitem.NewBigInteger(big.NewInt(int64(a.TotalSabbaticals))), stackitem.NewBigInteger(big.NewInt(int64(a.Status))), stackitem.NewBigInteger(big.NewInt(int64(a.CreatedAt))), stackitem.NewBigInteger(big.NewInt(int64(a.UpdatedAt))), }), nil } // FromStackItem implements stackitem.Convertible interface. func (a *LifePlanAccount) FromStackItem(item stackitem.Item) error { items, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not a struct") } if len(items) != 14 { return fmt.Errorf("wrong number of elements: expected 14, got %d", len(items)) } vitaID, err := items[0].TryInteger() if err != nil { return fmt.Errorf("invalid vitaID: %w", err) } a.VitaID = vitaID.Uint64() owner, err := items[1].TryBytes() if err != nil { return fmt.Errorf("invalid owner: %w", err) } a.Owner, err = util.Uint160DecodeBytesBE(owner) if err != nil { return fmt.Errorf("invalid owner address: %w", err) } totalContributions, err := items[2].TryInteger() if err != nil { return fmt.Errorf("invalid totalContributions: %w", err) } a.TotalContributions = totalContributions.Uint64() employerContributions, err := items[3].TryInteger() if err != nil { return fmt.Errorf("invalid employerContributions: %w", err) } a.EmployerContributions = employerContributions.Uint64() governmentContributions, err := items[4].TryInteger() if err != nil { return fmt.Errorf("invalid governmentContributions: %w", err) } a.GovernmentContributions = governmentContributions.Uint64() currentBalance, err := items[5].TryInteger() if err != nil { return fmt.Errorf("invalid currentBalance: %w", err) } a.CurrentBalance = currentBalance.Uint64() sabbaticalCredits, err := items[6].TryInteger() if err != nil { return fmt.Errorf("invalid sabbaticalCredits: %w", err) } a.SabbaticalCredits = sabbaticalCredits.Uint64() longevityMultiplier, err := items[7].TryInteger() if err != nil { return fmt.Errorf("invalid longevityMultiplier: %w", err) } a.LongevityMultiplier = uint32(longevityMultiplier.Uint64()) currentCareerCycleID, err := items[8].TryInteger() if err != nil { return fmt.Errorf("invalid currentCareerCycleID: %w", err) } a.CurrentCareerCycleID = currentCareerCycleID.Uint64() totalCareerCycles, err := items[9].TryInteger() if err != nil { return fmt.Errorf("invalid totalCareerCycles: %w", err) } a.TotalCareerCycles = uint32(totalCareerCycles.Uint64()) totalSabbaticals, err := items[10].TryInteger() if err != nil { return fmt.Errorf("invalid totalSabbaticals: %w", err) } a.TotalSabbaticals = uint32(totalSabbaticals.Uint64()) status, err := items[11].TryInteger() if err != nil { return fmt.Errorf("invalid status: %w", err) } a.Status = LifePlanAccountStatus(status.Uint64()) createdAt, err := items[12].TryInteger() if err != nil { return fmt.Errorf("invalid createdAt: %w", err) } a.CreatedAt = uint32(createdAt.Uint64()) updatedAt, err := items[13].TryInteger() if err != nil { return fmt.Errorf("invalid updatedAt: %w", err) } a.UpdatedAt = uint32(updatedAt.Uint64()) return nil } // CareerCycle represents a career phase in a person's life. type CareerCycle struct { ID uint64 // Unique career cycle ID VitaID uint64 // Owner's Vita ID Owner util.Uint160 // Owner's address CareerField string // Industry/profession StartedAt uint32 // Block height when started EndedAt uint32 // Block height when ended (0 = active) ContributionTotal uint64 // Total contributions in this cycle TransitionReason string // Why career ended Status CareerCycleStatus // Career status } // ToStackItem implements stackitem.Convertible interface. func (c *CareerCycle) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(c.ID))), stackitem.NewBigInteger(big.NewInt(int64(c.VitaID))), stackitem.NewByteArray(c.Owner.BytesBE()), stackitem.NewByteArray([]byte(c.CareerField)), stackitem.NewBigInteger(big.NewInt(int64(c.StartedAt))), stackitem.NewBigInteger(big.NewInt(int64(c.EndedAt))), stackitem.NewBigInteger(big.NewInt(int64(c.ContributionTotal))), stackitem.NewByteArray([]byte(c.TransitionReason)), stackitem.NewBigInteger(big.NewInt(int64(c.Status))), }), nil } // FromStackItem implements stackitem.Convertible interface. func (c *CareerCycle) 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() vitaID, err := items[1].TryInteger() if err != nil { return fmt.Errorf("invalid vitaID: %w", err) } c.VitaID = vitaID.Uint64() owner, err := items[2].TryBytes() if err != nil { return fmt.Errorf("invalid owner: %w", err) } c.Owner, err = util.Uint160DecodeBytesBE(owner) if err != nil { return fmt.Errorf("invalid owner address: %w", err) } careerField, err := items[3].TryBytes() if err != nil { return fmt.Errorf("invalid careerField: %w", err) } c.CareerField = string(careerField) startedAt, err := items[4].TryInteger() if err != nil { return fmt.Errorf("invalid startedAt: %w", err) } c.StartedAt = uint32(startedAt.Uint64()) endedAt, err := items[5].TryInteger() if err != nil { return fmt.Errorf("invalid endedAt: %w", err) } c.EndedAt = uint32(endedAt.Uint64()) contributionTotal, err := items[6].TryInteger() if err != nil { return fmt.Errorf("invalid contributionTotal: %w", err) } c.ContributionTotal = contributionTotal.Uint64() transitionReason, err := items[7].TryBytes() if err != nil { return fmt.Errorf("invalid transitionReason: %w", err) } c.TransitionReason = string(transitionReason) status, err := items[8].TryInteger() if err != nil { return fmt.Errorf("invalid status: %w", err) } c.Status = CareerCycleStatus(status.Uint64()) return nil } // Sabbatical represents a career break. type Sabbatical struct { ID uint64 // Unique sabbatical ID VitaID uint64 // Owner's Vita ID Owner util.Uint160 // Owner's address Purpose SabbaticalPurpose // Purpose of sabbatical Description string // Description of plans StartedAt uint32 // Block height when started Duration uint32 // Planned duration in blocks EndedAt uint32 // Block height when ended (0 = ongoing) FundingUsed uint64 // Credits spent during sabbatical Outcome string // Sabbatical results Status SabbaticalStatus // Sabbatical status } // ToStackItem implements stackitem.Convertible interface. func (s *Sabbatical) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(s.ID))), stackitem.NewBigInteger(big.NewInt(int64(s.VitaID))), stackitem.NewByteArray(s.Owner.BytesBE()), stackitem.NewBigInteger(big.NewInt(int64(s.Purpose))), stackitem.NewByteArray([]byte(s.Description)), stackitem.NewBigInteger(big.NewInt(int64(s.StartedAt))), stackitem.NewBigInteger(big.NewInt(int64(s.Duration))), stackitem.NewBigInteger(big.NewInt(int64(s.EndedAt))), stackitem.NewBigInteger(big.NewInt(int64(s.FundingUsed))), stackitem.NewByteArray([]byte(s.Outcome)), stackitem.NewBigInteger(big.NewInt(int64(s.Status))), }), nil } // FromStackItem implements stackitem.Convertible interface. func (s *Sabbatical) FromStackItem(item stackitem.Item) error { items, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not a struct") } if len(items) != 11 { return fmt.Errorf("wrong number of elements: expected 11, got %d", len(items)) } id, err := items[0].TryInteger() if err != nil { return fmt.Errorf("invalid id: %w", err) } s.ID = id.Uint64() vitaID, err := items[1].TryInteger() if err != nil { return fmt.Errorf("invalid vitaID: %w", err) } s.VitaID = vitaID.Uint64() owner, err := items[2].TryBytes() if err != nil { return fmt.Errorf("invalid owner: %w", err) } s.Owner, err = util.Uint160DecodeBytesBE(owner) if err != nil { return fmt.Errorf("invalid owner address: %w", err) } purpose, err := items[3].TryInteger() if err != nil { return fmt.Errorf("invalid purpose: %w", err) } s.Purpose = SabbaticalPurpose(purpose.Uint64()) description, err := items[4].TryBytes() if err != nil { return fmt.Errorf("invalid description: %w", err) } s.Description = string(description) startedAt, err := items[5].TryInteger() if err != nil { return fmt.Errorf("invalid startedAt: %w", err) } s.StartedAt = uint32(startedAt.Uint64()) duration, err := items[6].TryInteger() if err != nil { return fmt.Errorf("invalid duration: %w", err) } s.Duration = uint32(duration.Uint64()) endedAt, err := items[7].TryInteger() if err != nil { return fmt.Errorf("invalid endedAt: %w", err) } s.EndedAt = uint32(endedAt.Uint64()) fundingUsed, err := items[8].TryInteger() if err != nil { return fmt.Errorf("invalid fundingUsed: %w", err) } s.FundingUsed = fundingUsed.Uint64() outcome, err := items[9].TryBytes() if err != nil { return fmt.Errorf("invalid outcome: %w", err) } s.Outcome = string(outcome) status, err := items[10].TryInteger() if err != nil { return fmt.Errorf("invalid status: %w", err) } s.Status = SabbaticalStatus(status.Uint64()) return nil } // LifeMilestone represents a significant life event. type LifeMilestone struct { ID uint64 // Unique milestone ID VitaID uint64 // Owner's Vita ID Owner util.Uint160 // Owner's address MilestoneType MilestoneType // Type of milestone Title string // Milestone title Description string // Milestone description ContentHash util.Uint256 // Hash of supporting documentation AchievedAt uint32 // Block height when achieved IsVerified bool // Whether milestone is verified } // ToStackItem implements stackitem.Convertible interface. func (m *LifeMilestone) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(m.ID))), stackitem.NewBigInteger(big.NewInt(int64(m.VitaID))), stackitem.NewByteArray(m.Owner.BytesBE()), stackitem.NewBigInteger(big.NewInt(int64(m.MilestoneType))), stackitem.NewByteArray([]byte(m.Title)), stackitem.NewByteArray([]byte(m.Description)), stackitem.NewByteArray(m.ContentHash.BytesBE()), stackitem.NewBigInteger(big.NewInt(int64(m.AchievedAt))), stackitem.NewBool(m.IsVerified), }), nil } // FromStackItem implements stackitem.Convertible interface. func (m *LifeMilestone) 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) } m.ID = id.Uint64() vitaID, err := items[1].TryInteger() if err != nil { return fmt.Errorf("invalid vitaID: %w", err) } m.VitaID = vitaID.Uint64() owner, err := items[2].TryBytes() if err != nil { return fmt.Errorf("invalid owner: %w", err) } m.Owner, err = util.Uint160DecodeBytesBE(owner) if err != nil { return fmt.Errorf("invalid owner address: %w", err) } milestoneType, err := items[3].TryInteger() if err != nil { return fmt.Errorf("invalid milestoneType: %w", err) } m.MilestoneType = MilestoneType(milestoneType.Uint64()) title, err := items[4].TryBytes() if err != nil { return fmt.Errorf("invalid title: %w", err) } m.Title = string(title) description, err := items[5].TryBytes() if err != nil { return fmt.Errorf("invalid description: %w", err) } m.Description = string(description) contentHash, err := items[6].TryBytes() if err != nil { return fmt.Errorf("invalid contentHash: %w", err) } m.ContentHash, err = util.Uint256DecodeBytesBE(contentHash) if err != nil { return fmt.Errorf("invalid contentHash value: %w", err) } achievedAt, err := items[7].TryInteger() if err != nil { return fmt.Errorf("invalid achievedAt: %w", err) } m.AchievedAt = uint32(achievedAt.Uint64()) isVerified, err := items[8].TryBool() if err != nil { return fmt.Errorf("invalid isVerified: %w", err) } m.IsVerified = isVerified return nil } // LifeGoal represents a future life goal. type LifeGoal struct { ID uint64 // Unique goal ID VitaID uint64 // Owner's Vita ID Owner util.Uint160 // Owner's address Title string // Goal title Description string // Goal description TargetBlock uint32 // Target block height for completion Progress uint32 // Progress percentage (0-10000 basis points) Status GoalStatus // Goal status CreatedAt uint32 // Block height when created CompletedAt uint32 // Block height when completed (0 = incomplete) } // ToStackItem implements stackitem.Convertible interface. func (g *LifeGoal) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(g.ID))), stackitem.NewBigInteger(big.NewInt(int64(g.VitaID))), stackitem.NewByteArray(g.Owner.BytesBE()), stackitem.NewByteArray([]byte(g.Title)), stackitem.NewByteArray([]byte(g.Description)), stackitem.NewBigInteger(big.NewInt(int64(g.TargetBlock))), stackitem.NewBigInteger(big.NewInt(int64(g.Progress))), stackitem.NewBigInteger(big.NewInt(int64(g.Status))), stackitem.NewBigInteger(big.NewInt(int64(g.CreatedAt))), stackitem.NewBigInteger(big.NewInt(int64(g.CompletedAt))), }), nil } // FromStackItem implements stackitem.Convertible interface. func (g *LifeGoal) FromStackItem(item stackitem.Item) error { items, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not a struct") } if len(items) != 10 { return fmt.Errorf("wrong number of elements: expected 10, got %d", len(items)) } id, err := items[0].TryInteger() if err != nil { return fmt.Errorf("invalid id: %w", err) } g.ID = id.Uint64() vitaID, err := items[1].TryInteger() if err != nil { return fmt.Errorf("invalid vitaID: %w", err) } g.VitaID = vitaID.Uint64() owner, err := items[2].TryBytes() if err != nil { return fmt.Errorf("invalid owner: %w", err) } g.Owner, err = util.Uint160DecodeBytesBE(owner) if err != nil { return fmt.Errorf("invalid owner address: %w", err) } title, err := items[3].TryBytes() if err != nil { return fmt.Errorf("invalid title: %w", err) } g.Title = string(title) description, err := items[4].TryBytes() if err != nil { return fmt.Errorf("invalid description: %w", err) } g.Description = string(description) targetBlock, err := items[5].TryInteger() if err != nil { return fmt.Errorf("invalid targetBlock: %w", err) } g.TargetBlock = uint32(targetBlock.Uint64()) progress, err := items[6].TryInteger() if err != nil { return fmt.Errorf("invalid progress: %w", err) } g.Progress = uint32(progress.Uint64()) status, err := items[7].TryInteger() if err != nil { return fmt.Errorf("invalid status: %w", err) } g.Status = GoalStatus(status.Uint64()) createdAt, err := items[8].TryInteger() if err != nil { return fmt.Errorf("invalid createdAt: %w", err) } g.CreatedAt = uint32(createdAt.Uint64()) completedAt, err := items[9].TryInteger() if err != nil { return fmt.Errorf("invalid completedAt: %w", err) } g.CompletedAt = uint32(completedAt.Uint64()) return nil } // SeseConfig represents configurable parameters for the Sese contract. type SeseConfig struct { DefaultSabbaticalCredits uint64 // Default sabbatical credits per year MinSabbaticalDuration uint32 // Minimum sabbatical duration in blocks MaxSabbaticalDuration uint32 // Maximum sabbatical duration in blocks GovernmentMatchPercent uint32 // Government matching percentage (basis points) LongevityBonusPercent uint32 // Longevity bonus percentage (basis points per year) } // ToStackItem implements stackitem.Convertible interface. func (c *SeseConfig) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ stackitem.NewBigInteger(big.NewInt(int64(c.DefaultSabbaticalCredits))), stackitem.NewBigInteger(big.NewInt(int64(c.MinSabbaticalDuration))), stackitem.NewBigInteger(big.NewInt(int64(c.MaxSabbaticalDuration))), stackitem.NewBigInteger(big.NewInt(int64(c.GovernmentMatchPercent))), stackitem.NewBigInteger(big.NewInt(int64(c.LongevityBonusPercent))), }), nil } // FromStackItem implements stackitem.Convertible interface. func (c *SeseConfig) FromStackItem(item stackitem.Item) error { items, ok := item.Value().([]stackitem.Item) if !ok { return errors.New("not a struct") } if len(items) != 5 { return fmt.Errorf("wrong number of elements: expected 5, got %d", len(items)) } defaultCredits, err := items[0].TryInteger() if err != nil { return fmt.Errorf("invalid defaultSabbaticalCredits: %w", err) } c.DefaultSabbaticalCredits = defaultCredits.Uint64() minDuration, err := items[1].TryInteger() if err != nil { return fmt.Errorf("invalid minSabbaticalDuration: %w", err) } c.MinSabbaticalDuration = uint32(minDuration.Uint64()) maxDuration, err := items[2].TryInteger() if err != nil { return fmt.Errorf("invalid maxSabbaticalDuration: %w", err) } c.MaxSabbaticalDuration = uint32(maxDuration.Uint64()) govMatch, err := items[3].TryInteger() if err != nil { return fmt.Errorf("invalid governmentMatchPercent: %w", err) } c.GovernmentMatchPercent = uint32(govMatch.Uint64()) longevityBonus, err := items[4].TryInteger() if err != nil { return fmt.Errorf("invalid longevityBonusPercent: %w", err) } c.LongevityBonusPercent = uint32(longevityBonus.Uint64()) return nil }