feat(chain): ChainMaker 真实链接入脚手架(build tag 隔离)+ 契约测试

- internal/chain/chainmaker.go [//go:build chainmaker]: ChainMakerClient 适配器骨架,
  实现 chain.Client 全部方法到合约 Invoke/Query,按角色证书做链上鉴权,错误映射回标准错误
- internal/chain/chainmaker_stub.go [//go:build !chainmaker]: 占位构造函数,
  保证默认构建不依赖 SDK、主工程始终可编译
- contracts/tcs_registry/registry.go: 补齐合约方法
  RegisterHashBinding/VerifyEpisodeHash/ListEpisodes/HashExists/RecordVersionChange/
  RevokeEpisode/Restore/RestoreEpisode/SetContentStatus/QueryMappings/ListContents
  并增加集级哈希/映射/版本计数索引 KV 设计
- config: TCS_CHAIN_BACKEND=memory|pg|chainmaker + TCS_CHAINMAKER_SDK_CONF 开关
- cmd/api-svc: newChain 按 backend 选择,chainmaker 失败逐级降级 pg 到内存
- internal/chain/conformance_test.go: chain.Client 契约测试套件,双实现共用
  MemoryChain 默认跑;PersistentChain 经 TCS_TEST_PG_DSN;ChainMaker 经 -tags 与 env
- 验证: 默认 build/vet/test 全绿;MemoryChain 与 PersistentChain 契约套件均通过,行为一致
This commit is contained in:
selfrelease
2026-06-14 20:47:21 +08:00
parent 8a9ea6b40b
commit 166f460d57
9 changed files with 875 additions and 49 deletions
+29 -11
View File
@@ -37,18 +37,36 @@ func newAllocationStore(db *sql.DB) macode.AllocationStore {
return macode.NewMemoryStore()
}
// newChain 优先使用 PostgreSQL 持久化链(写穿 + 启动水合),不可用时回退纯内存。
func newChain(db *sql.DB) chain.Client {
if db != nil {
if pc, err := chain.NewPersistentChain(db); err == nil {
log.Printf("chain: 使用 PostgreSQL 持久化链(写穿+水合,重启不丢数据)")
return pc
} else {
log.Printf("chain: PG 持久化链初始化失败(%v),回退内存链", err)
// newChain 按配置选择链后端:
// - chainmaker:真实链(需 -tags chainmaker 构建并配置 SDK),失败回退 pg/内存
// - pg:PG 持久化链(写穿+水合,重启不丢数据)
// - memory:纯内存(仅开发)
//
// PG 不可用时自动降级到内存。
func newChain(backend, sdkConf string, db *sql.DB) chain.Client {
switch backend {
case "chainmaker":
cm, err := chain.NewChainMakerClient(sdkConf, db)
if err == nil {
log.Printf("chain: 使用 ChainMaker 真实链后端")
return cm
}
log.Printf("chain: ChainMaker 后端不可用(%v),降级", err)
fallthrough
case "pg":
if db != nil {
if pc, err := chain.NewPersistentChain(db); err == nil {
log.Printf("chain: 使用 PostgreSQL 持久化链(写穿+水合,重启不丢数据)")
return pc
} else {
log.Printf("chain: PG 持久化链初始化失败(%v),回退内存链", err)
}
}
fallthrough
default:
log.Printf("chain: 使用内存链(仅开发用,重启丢数据)")
return chain.NewMemoryChain()
}
log.Printf("chain: 使用内存链(仅开发用,重启丢数据)")
return chain.NewMemoryChain()
}
func main() {
@@ -56,7 +74,7 @@ func main() {
// 装配依赖:共享一个 PG 连接给链持久化与号段存储
db := openDB(cfg.PostgresDSN)
ch := newChain(db)
ch := newChain(cfg.ChainBackend, cfg.ChainMakerSDKConf, db)
gen := macode.NewGenerator(newAllocationStore(db))
// 示例号段(生产由与发码机构对接后配置)
// 机构节点 6101 = 陕西(管理方:陕西IPTV运营公司);行业节点 8531 = IPTV视听内容