Source Code

;; model-training-rewards - Clarity 4
;; Rewards distribution for ML model training contributions

(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-REWARD-NOT-FOUND (err u101))
(define-constant ERR-ALREADY-CLAIMED (err u102))
(define-constant ERR-INSUFFICIENT-FUNDS (err u103))

(define-map training-contributions uint
  {
    contributor: principal,
    model-id: uint,
    data-samples-provided: uint,
    quality-score: uint,
    contribution-timestamp: uint,
    reward-amount: uint,
    is-claimed: bool
  }
)

(define-map contributor-stats principal
  {
    total-contributions: uint,
    total-rewards-earned: uint,
    total-rewards-claimed: uint,
    average-quality-score: uint,
    reputation-score: uint
  }
)

(define-map reward-pools uint
  {
    model-id: uint,
    total-pool: uint,
    distributed-amount: uint,
    minimum-quality: uint,
    is-active: bool
  }
)

(define-map milestone-rewards uint
  {
    milestone-name: (string-utf8 100),
    threshold: uint,
    reward-multiplier: uint,
    achieved-by: (list 10 principal)
  }
)

(define-data-var contribution-counter uint u0)
(define-data-var pool-counter uint u0)
(define-data-var milestone-counter uint u0)
(define-data-var base-reward-per-sample uint u100)

(define-public (record-contribution
    (model-id uint)
    (data-samples uint)
    (quality-score uint))
  (let ((contribution-id (+ (var-get contribution-counter) u1))
        (reward (calculate-reward data-samples quality-score)))
    (map-set training-contributions contribution-id
      {
        contributor: tx-sender,
        model-id: model-id,
        data-samples-provided: data-samples,
        quality-score: quality-score,
        contribution-timestamp: stacks-block-time,
        reward-amount: reward,
        is-claimed: false
      })
    (update-contributor-stats tx-sender data-samples quality-score reward)
    (var-set contribution-counter contribution-id)
    (ok contribution-id)))

(define-public (claim-reward (contribution-id uint))
  (let ((contribution (unwrap! (map-get? training-contributions contribution-id) ERR-REWARD-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get contributor contribution)) ERR-NOT-AUTHORIZED)
    (asserts! (not (get is-claimed contribution)) ERR-ALREADY-CLAIMED)
    (map-set training-contributions contribution-id
      (merge contribution { is-claimed: true }))
    (try! (update-claimed-stats tx-sender (get reward-amount contribution)))
    (ok (get reward-amount contribution))))

(define-public (create-reward-pool
    (model-id uint)
    (total-pool uint)
    (minimum-quality uint))
  (let ((pool-id (+ (var-get pool-counter) u1)))
    (map-set reward-pools pool-id
      {
        model-id: model-id,
        total-pool: total-pool,
        distributed-amount: u0,
        minimum-quality: minimum-quality,
        is-active: true
      })
    (var-set pool-counter pool-id)
    (ok pool-id)))

(define-public (create-milestone
    (milestone-name (string-utf8 100))
    (threshold uint)
    (multiplier uint))
  (let ((milestone-id (+ (var-get milestone-counter) u1)))
    (map-set milestone-rewards milestone-id
      {
        milestone-name: milestone-name,
        threshold: threshold,
        reward-multiplier: multiplier,
        achieved-by: (list)
      })
    (var-set milestone-counter milestone-id)
    (ok milestone-id)))

(define-private (calculate-reward (samples uint) (quality uint))
  (let ((base (* samples (var-get base-reward-per-sample)))
        (quality-bonus (/ (* base quality) u100)))
    (+ base quality-bonus)))

(define-private (update-contributor-stats (contributor principal) (samples uint) (quality uint) (reward uint))
  (let ((stats (default-to
                 { total-contributions: u0, total-rewards-earned: u0, total-rewards-claimed: u0, average-quality-score: u0, reputation-score: u50 }
                 (map-get? contributor-stats contributor)))
        (new-total (+ (get total-contributions stats) u1))
        (new-avg-quality (/ (+ (* (get average-quality-score stats) (get total-contributions stats)) quality) new-total)))
    (map-set contributor-stats contributor
      {
        total-contributions: new-total,
        total-rewards-earned: (+ (get total-rewards-earned stats) reward),
        total-rewards-claimed: (get total-rewards-claimed stats),
        average-quality-score: new-avg-quality,
        reputation-score: (+ (get reputation-score stats) u1)
      })
    true))

(define-private (update-claimed-stats (contributor principal) (amount uint))
  (let ((stats (unwrap! (map-get? contributor-stats contributor) ERR-NOT-AUTHORIZED)))
    (map-set contributor-stats contributor
      (merge stats { total-rewards-claimed: (+ (get total-rewards-claimed stats) amount) }))
    (ok true)))

(define-read-only (get-contribution (contribution-id uint))
  (ok (map-get? training-contributions contribution-id)))

(define-read-only (get-contributor-stats (contributor principal))
  (ok (map-get? contributor-stats contributor)))

(define-read-only (get-reward-pool (pool-id uint))
  (ok (map-get? reward-pools pool-id)))

(define-read-only (get-milestone (milestone-id uint))
  (ok (map-get? milestone-rewards milestone-id)))

(define-read-only (validate-principal (p principal))
  (principal-destruct? p))

(define-read-only (format-contribution-id (contribution-id uint))
  (ok (int-to-ascii contribution-id)))

(define-read-only (parse-contribution-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (15)

FunctionAccessArgs
record-contributionpublicmodel-id: uint, data-samples: uint, quality-score: uint
claim-rewardpubliccontribution-id: uint
create-reward-poolpublicmodel-id: uint, total-pool: uint, minimum-quality: uint
create-milestonepublicmilestone-name: (string-utf8 100
calculate-rewardprivatesamples: uint, quality: uint
update-contributor-statsprivatecontributor: principal, samples: uint, quality: uint, reward: uint
update-claimed-statsprivatecontributor: principal, amount: uint
get-contributionread-onlycontribution-id: uint
get-contributor-statsread-onlycontributor: principal
get-reward-poolread-onlypool-id: uint
get-milestoneread-onlymilestone-id: uint
validate-principalread-onlyp: principal
format-contribution-idread-onlycontribution-id: uint
parse-contribution-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only