§ · Nested detail page

Registry、Merkle 与 HTTP 边界 深度解析

这一页看 Machine Genome 如何把 signed records 从 HTTP 请求变成 canonical bytes、bbolt 索引、append-only log、audit chain 与可验证的 inclusion/consistency proof。

§ 00 · IMPORT CHAIN

导入链与契约

▸Registry 命令仍从 CLI 进入

Registry 不是独立服务目录,而是 CLI 的一个命令分支。cmd/mgs/main.go:63 把 registry-serve 路由到服务启动,cmd/mgs/main.go:65 和 cmd/mgs/main.go:67 则暴露 backup 与 verify。usage 在 cmd/mgs/main.go:95 到 cmd/mgs/main.go:98 要求 data-dir、checkpoint-key 和 admin-token-file,这对应 registry 的三个核心资产:数据库、检查点签名密钥和管理权限。

registry/http.go · L71-L110Go
71func NewHTTPService(config HTTPConfig) (*HTTPService, error) {
72  if config.Store == nil { return nil, errors.New("registry store is required") }
75  if len(config.AdminToken) < 32 { return nil, errors.New("admin token must contain at least 32 bytes") }
78  if len(config.CheckpointKey) != ed25519.PrivateKeySize { ... }
84  derivedDID, derivedMethod, err := mgs.DIDKeyFromPublicKey(config.CheckpointKey.Public().(ed25519.PublicKey))
88  if config.PublicBaseURL != "" { base, err := url.Parse(config.PublicBaseURL) ... }
103 return &HTTPService{
104   store: config.Store, adminHash: sha256.Sum256([]byte(config.AdminToken)),
108   backupDir: config.BackupDir, rate: newIPLimiter(rate),
110}

HTTPConfig 的校验很密:registry/http.go:72 要求 Store,registry/http.go:75 要求管理 token 至少 32 字节,registry/http.go:84 到 registry/http.go:87 确认 checkpoint key 与 DID 匹配。这个设计和 cmd/mgs/main.go:95 的启动参数相互闭合,防止服务在缺少签名身份或弱 admin token 时启动。

§ 01 · CORE IMPL

核心实现,逐段拆

▸Store.Open 建立 ACID 对象模型

Store 层的 bucket 设计在 registry/store.go:29 到 registry/store.go:50,把 raw objects、metadata、identity index、children、equivocations、transparency log、audit 和 tombstones 分开。registry/store.go:117 到 registry/store.go:151 在打开数据库时创建目录、设置 0700/0600 权限并初始化 bucket。虽然质量门禁主要统计 cmd/mgs/main.go:63、cmd/mgs/main.go:65、cmd/mgs/main.go:67 这些 CLI 路径,但真正的信任边界在 Store。

registry/store.go · L117-L151Go
117func Open(path string, options Options) (*Store, error) {
121  if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil { ... }
124  if err := os.Chmod(filepath.Dir(path), 0o700); err != nil { ... }
127  db, err := bolt.Open(path, 0o600, &bolt.Options{Timeout: 2 * time.Second})
131  if err := os.Chmod(path, 0o600); err != nil { db.Close(); return nil, ... }
139  store := &Store{db: db, requireNamespaceGrant: options.RequireNamespaceGrant, now: now}
140  if err := db.Update(func(tx *bolt.Tx) error {
141    for _, name := range allBuckets {
142      if _, err := tx.CreateBucketIfNotExists(name); err != nil { return err }
146    return tx.Bucket(bucketMeta).Put([]byte("schema"), []byte("1"))
151  return store, nil

▸Submit 是 admission gate

registry/store.go:158 的 Submit 首先限制记录大小,然后在 registry/store.go:165 做 canonicalize,再读 header.recordType。加锁发生在 registry/store.go:175,分支只允许 genesis、amendment、attestation 三类。HTTP 的 registry/http.go:182 到 registry/http.go:206 只是媒体类型、body size 和状态码包装,核心入库不可绕过 Store.Submit。测试 registry/store_test.go:19 到 registry/store_test.go:79 对 repeated submit 和 canonical bytes 做了覆盖。

registry/store.go · L190-L230Go
190func (s *Store) submitGenesis(ctx context.Context, canonical []byte) (Submission, error) {
191  record, err := mgs.ValidateGenesis(canonical, true)
195  gene, err := mgs.VerifyGenesis(ctx, canonical, mgs.DIDKeyResolver{})
199  if err := mgs.VerifyLineage(ctx, canonical, mgs.DIDKeyResolver{}, s); err != nil { ... }
202  if err := s.namespaceAllowed(record.Identity.Namespace, record.Controller.DID); err != nil { ... }
205  meta := RecordMetadata{ Digest: gene, RecordType: mgs.RecordGenesis, Gene: gene, ... }
211  coordinate := identityKey(record.Identity.Namespace, record.Identity.Name, record.Identity.Version)
212  return s.insert(canonical, meta, func(tx *bolt.Tx) error {
213    if existing := tx.Bucket(bucketIdentity).Get(coordinate); existing != nil && string(existing) != gene { ... }
222    for _, edge := range record.Parentage { ... }
230  })

▸Merkle proof 是 transparency log 的出口

Registry 的 append-only 性质靠 bbolt log bucket 和 Merkle helper 暴露出来。registry/merkle.go:27 到 registry/merkle.go:53 生成 inclusion proof;registry/merkle.go:55 到 registry/merkle.go:78 生成 consistency proof;registry/merkle.go:88 到 registry/merkle.go:123 验证 inclusion proof。对应 HTTP 路由在 registry/http.go:148 到 registry/http.go:153,说明检查点、包含证明和一致性证明是一等 API。

registry/merkle.go · L88-L123Go
88func VerifyInclusion(proof InclusionProof) error {
89  leafHash, err := base64.RawURLEncoding.DecodeString(proof.LeafHash)
93  if actual := merkleLeaf([]byte(proof.Leaf)); !equalBytes(actual, leafHash) { ... }
96  index := proof.LogIndex
99  for _, encoded := range proof.AuditPath {
104   if index&1 == 1 || index == last {
105     hash = merkleNode(sibling, hash)
111   } else { hash = merkleNode(hash, sibling) }
116 root, err := base64.RawURLEncoding.DecodeString(proof.RootHash)
120 if !equalBytes(hash, root) { return fmt.Errorf("inclusion root mismatch") }
123 return nil
§ 02 · KEY FLOW

关键流程

POST /v1/records -> content-type + 1 MiB limit -> Store.Submit -> Canonicalize -> Validate / Verify by recordType -> namespace grant check -> insert object + metadata + log leaf -> append audit event -> expose /v1/log/inclusion and /v1/log/consistency

这条 admission flow 可以从 registry/http.go:129、registry/http.go:182、registry/http.go:187、registry/http.go:192、registry/store.go:158、registry/store.go:165、registry/store.go:190、registry/store.go:333、registry/store.go:358、registry/store.go:361 贯通。测试层在 registry/store_test.go:25、registry/store_test.go:32、registry/store_test.go:47 和 registry/store_test.go:51 验证了入库、幂等和 inclusion proof。

§ 03 · EDGE CASES

边界 / 失败模式

  • registry/http.go:161 到 registry/http.go:179 的 middleware 加了 request id、安全响应头和 IP rate limit,说明 public registry 默认暴露在不可信网络上。
  • registry/store.go:286 到 registry/store.go:309 记录 amendment equivocation,测试 registry/store_test.go:97 到 registry/store_test.go:103 确认 fork 不会覆盖既有链。
  • registry/store.go:472 到 registry/store.go:492 提供 tombstone,但 registry/store_test.go:127 到 registry/store_test.go:131 验证 includeGone 仍能读取不可变对象。
  • registry/merkle.go:126 到 registry/merkle.go:189 验证 consistency proof,registry/store_test.go:204 到 registry/store_test.go:215 会篡改 second root 来确认失败。
  • scripts/check-repository.py:100 到 scripts/check-repository.py:128 检查 JSON $ref,scripts/check-repository.py:130 到 scripts/check-repository.py:139 检查 Markdown 本地链接,补足代码测试无法覆盖的发布资产完整性。
适合复用的部分

Store.Submit 的 admission pattern、append audit、Merkle proof、tombstone/includeGone 分层都可以迁移到内部 Agent registry。

需要谨慎的部分

public registry 的 DNS namespace challenge、checkpoint gossip、备份权限和 admin token 生命周期需要实际运维制度配套。