106 lines
5.0 KiB
Go
106 lines
5.0 KiB
Go
// Package chain 定义可信数据空间(联盟链)的客户端抽象。
|
|
// MVP 提供内存 mock 实现,使业务逻辑可在无真实 ChainMaker 网络时开发与测试;
|
|
// 后续以 ChainMaker Go SDK 实现替换,接口不变。
|
|
// 对应需求:需求16(智能合约方法)、需求3/4(签发与验真)、需求14(权限)。
|
|
package chain
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/tcs-iptv/tcs/internal/model"
|
|
)
|
|
|
|
// Role 调用方角色,用于合约级权限控制(需求14)。
|
|
type Role string
|
|
|
|
const (
|
|
RoleRegulator Role = "regulator" // 监管主体:唯一可 issueMA / 下架
|
|
RoleReviewer Role = "reviewer" // 审核主体(CSPS/媒资库)
|
|
RoleCP Role = "cp" // 内容提供商
|
|
RoleOperator Role = "operator" // 运营商
|
|
)
|
|
|
|
// 错误定义。
|
|
var (
|
|
ErrPermissionDenied = errors.New("chain: permission denied")
|
|
ErrMANotIssued = errors.New("chain: MA not issued")
|
|
ErrMAAlreadyIssued = errors.New("chain: MA already issued (1:1 binding immutable)")
|
|
ErrHashExists = errors.New("chain: content hash already exists")
|
|
ErrNotFound = errors.New("chain: not found")
|
|
)
|
|
|
|
// IssueRequest 签发 MA 码并强绑定哈希包。
|
|
type IssueRequest struct {
|
|
CCCode string
|
|
ContentTwinID string
|
|
MerkleRoot string
|
|
FileHash string
|
|
PerceptualHash string
|
|
Episodes []model.EpisodeHash // 集级哈希(分集内容)
|
|
Content model.Content
|
|
}
|
|
|
|
// VerifyResult 哈希验真结果(需求4-AC4)。
|
|
type VerifyResult struct {
|
|
Valid bool `json:"valid"`
|
|
CCCode string `json:"ma_code"`
|
|
BoundHash string `json:"bound_hash"`
|
|
SubmittedHash string `json:"submitted_hash"`
|
|
Match bool `json:"match"`
|
|
Version string `json:"version"`
|
|
}
|
|
|
|
// MappingsResult 映射查询结果(需求11/17)。
|
|
type MappingsResult struct {
|
|
CCCode string `json:"ma_code"`
|
|
Mappings []model.Mapping `json:"mappings"`
|
|
CDNEndpoints []string `json:"cdn_endpoints"`
|
|
}
|
|
|
|
// Client 是可信数据空间的统一访问接口。
|
|
// 业务服务只依赖此接口,不感知底层是 mock 还是 ChainMaker。
|
|
type Client interface {
|
|
// IssueMA 签发 MA 码并与哈希包 1:1 强绑定(仅监管主体)。
|
|
IssueMA(role Role, req IssueRequest) (txID string, err error)
|
|
// RegisterHashBinding 追加哈希绑定(如转码版,建立父子关系)。
|
|
RegisterHashBinding(role Role, b model.HashBinding) (txID string, err error)
|
|
// RegisterMapping 注册三方编码映射(MA 必须已签发)。
|
|
RegisterMapping(role Role, m model.Mapping) (txID string, err error)
|
|
// VerifyHash 按 MA 码校验提交哈希是否与绑定哈希一致。
|
|
VerifyHash(ccCode, fileHash string) (VerifyResult, error)
|
|
// VerifyEpisodeHash 按 MA 码+集号校验该集哈希。
|
|
VerifyEpisodeHash(ccCode string, episode int, fileHash string) (VerifyResult, error)
|
|
// ListEpisodes 返回某 MA 码下的全部集级哈希绑定。
|
|
ListEpisodes(ccCode string) ([]model.HashBinding, error)
|
|
// HashExists 判断内容哈希是否已存在(防换壳重发)。
|
|
HashExists(fileHash string) (ccCode string, exists bool)
|
|
// QueryContent 查询内容主记录。
|
|
QueryContent(ccCode string) (model.Content, error)
|
|
// ListContents 按状态列出内容(空状态返回全部)。
|
|
ListContents(status string) ([]model.Content, error)
|
|
// QueryMappings 查询 MA 码绑定的全部三方映射与 CDN 端点。
|
|
QueryMappings(ccCode string) (MappingsResult, error)
|
|
// RecordVersionChange 记录版本变更(绑定断裂触发重审)。
|
|
RecordVersionChange(vc model.VersionChange) (txID string, err error)
|
|
// Revoke 下架(仅监管主体),返回受影响的映射。
|
|
Revoke(role Role, ccCode, reason string) (MappingsResult, error)
|
|
// RevokeEpisode 集级下架(仅监管主体):只下架指定集,整剧其他集不受影响。
|
|
RevokeEpisode(role Role, ccCode string, episode int, reason string) error
|
|
// Restore 恢复上架整剧(仅监管主体):下架状态恢复为流通中。
|
|
Restore(role Role, ccCode string) error
|
|
// RestoreEpisode 恢复上架指定集(仅监管主体)。
|
|
RestoreEpisode(role Role, ccCode string, episode int) error
|
|
// SetContentStatus 更新内容状态。
|
|
SetContentStatus(ccCode, status string) error
|
|
// QueryByHash 根据内容哈希反查标识信息及映射关系。
|
|
QueryByHash(fileHash string) (model.ContentQueryResult, error)
|
|
// QueryByProvincialCode 根据省级内容编码(CP MediaID)反查标识信息。
|
|
QueryByProvincialCode(provincialCode string) (model.ContentQueryResult, error)
|
|
// QueryByLibraryFileID 根据片库文件 ID(媒资库 ID)反查标识信息。
|
|
QueryByLibraryFileID(libraryFileID string) (model.ContentQueryResult, error)
|
|
// MergeMA 将多个 MA 码合并为一个主 MA 码(仅监管主体)。
|
|
MergeMA(role Role, req model.MergeRequest) (model.MergeResult, error)
|
|
// SplitMA 将一个 MA 码拆分为多个独立 MA 码(仅监管主体)。
|
|
SplitMA(role Role, req model.SplitRequest) (model.SplitResult, error)
|
|
}
|