Skip to main content

难点:Legacy 和 Native SegWit

下面给你一套可直接拿去面试的素材:一个问题表述 + STAR 回答 + 追问时的技术点。内容和你仓库里的实现是对得上的(bitcoinLegacy / P2PKH 脚本 / 手写 SegWit 测试等)。


面试问题(你可以这样抛给面试官)

「在钱包或区块链项目里,有没有遇到过协议层突然改需求、而且你之前自己手写了一套实现,必须紧急兼容旧格式的情况?具体难点是什么?」

或更短:

「Bitcoin 地址有 Legacy 和 Native SegWit 两套,你是怎么处理兼容和交易构造一致性的?」


STAR 回答(约 1.5~2 分钟,建议背骨架自己发挥)

Situation(背景)

我们做 MPC 钱包的 Bitcoin 模块时,我一开始按 Native SegWit(P2WPKH,bc1... 做的:地址派生和 UTXO 选币、锁定脚本、签名输入 里有一部分是自己手写的,没有全走 Trust Wallet Core 的现成路径。测试也是按 bc1 + witness 脚本走的。

大概 10 月初,TL 突然说:公司对接的上游/旧钱包体系不支持 Native SegWit,历史资产和对手方地址都是 Legacy(P2PKH,1...,要加急切到 Legacy,不能等下个版本。

Task(任务)

在很短时间内做到三件事一致:

  1. 展示地址(创建钱包、MPC 公钥派生)→ 1...
  2. 链上 UTXO / 收款 和实际脚本类型一致 → P2PKH
  3. 签名构造 不能还按 SegWit 的 witness 逻辑走

难点在于:不是改一个 if,而是整条链路都要从「我手写的 SegWit」切到「Legacy + P2PKH」,而且当时代码里已经混了两套 API。

Action(行动)

  1. 先对齐「单一事实来源」
    统一派生路径 m/44'/0'/0'/0/0,但地址生成显式用 Trust Wallet 的 derivation: .bitcoinLegacy,保证和旧钱包同一套 1 开头地址。

  2. 交易侧改锁定脚本
    Bitcoin 签名不再用 witness 的 0x00 0x14 + hash 那套,而是 BitcoinScript.buildPayToPublicKeyHash(纯 P2PKH);注释里也区分了:P2PKH 不需要 redeem script,SegWit 才走另一套。

  3. 排查「看起来改对了但仍失败」
    卡得最久的是:地址是一种格式、UTXO 脚本是另一种。例如有的地方 AnyAddress(coin: .bitcoin) 默认出 bc1,钱包展示却是 1 开头——选币或签名时对不上 scriptPubKey。我把 WalletService、TransactionService、UTXO 准备 三条路径全部改成 Legacy 一致,并在 MPC 派生地址处同样走 bitcoinLegacy

  4. 验证策略
    用同一私钥对比:Legacy 地址、公钥 hash、锁定脚本 hex;再和旧钱包导出的 1 地址做交叉验证,避免只测「能生成地址」不测「能花币」。

Result(结果)

在加急窗口内完成了 Legacy 全链路:创建/导入/MPC 派生地址、UTXO 构造、签名都与上游旧钱包对齐;后续若再支持 SegWit,也清楚要在地址 API、script、签名输入三处同时切换,不能单改 UI 地址。

收尾一句(体现反思)

这件事让我意识到:Bitcoin 的难不在「生成两个字符串」,而在 地址类型 = 锁定脚本 = 签名 witness 结构 必须三位一体;手写一层时,需求变更的成本会特别高,所以后来同类逻辑更倾向于在 WalletCore 上封一层、少手写脚本细节。


面试官追问时,可说的「技术亮点」(30 秒版)

你可以怎么说
两种格式本质同一公钥,bc1 vs 1编码和 script 类型不同,不是换了个字符串
Legacy 脚本OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
SegWit 脚本OP_0 <20-byte-key-hash>,签名走 witness,fee 模型不同
你踩的坑地址用 Legacy,UTXO 仍按 SegWit 填 → 签名失败或选不到币
工程手段强制 bitcoinLegacy + P2PKH buildPayToPublicKeyHash,全链路 grep 对齐

若对方懂 Trust Wallet,可以补一句:

「我们最终在 Swift 层用 AnyAddress(..., derivation: .bitcoinLegacy)getAddressDerivation(coin: .bitcoin, derivation: .bitcoinLegacy) 与交易里的 P2PKH 脚本保持一致。」


可选:更「故事感」的开场(10 秒)

「有一次 10 月 1 号前后,TL 说公司不能用 bc1,旧钱包只认 1 开头,要我几天内从我自己手写的 SegWit 交易链路切到 Legacy。最难的不是查文档,而是发现代码里已经半套 Legacy、半套 SegWit,导致联调时地址对、签名错。」


建议避免的表述

  • 别说「Bitcoin 有两种地址随便选一个」——要说 script 类型必须一致
  • 别说「我全用 Trust Wallet 就没问题」——你的亮点恰恰是 手写 SegWit 后被迫理解脚本层
  • 时间可以说「国庆前后 / 10 月初加急」,不必咬死「10 月 1 日当天发需求」,除非 HR 会核对。

如果你愿意,我可以再帮你压一版 英文 60 秒 elevator pitch,或改成「系统设计题:如何同时支持 Legacy + SegWit」的标准答案。