Skip to content

fix: adapt to chain33 go-ethereum v1.14.8 upgrade - #1305

Open
bysomeone wants to merge 19 commits into
33cn:masterfrom
bysomeone:fix/chain33-go-ethereum-upgrade
Open

fix: adapt to chain33 go-ethereum v1.14.8 upgrade#1305
bysomeone wants to merge 19 commits into
33cn:masterfrom
bysomeone:fix/chain33-go-ethereum-upgrade

Conversation

@bysomeone

@bysomeone bysomeone commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

chain33 上游升级 go-ethereum 到 v1.14.8,本 PR 适配 plugin 的依赖与 API 变化,并处理升级带来的存量数据兼容问题。

本 PR 基于 33cn/plugin 官方最新 master(已含 ForkEVMFixOverflow 安全修复)。

依赖升级

依赖
chain33 v1.69.1-0.20260508025622-0fa35083839d v1.69.1-0.20260806044231-1edb5ac8d4fd(33cn/chain33 master)
go-ethereum v1.12.0 v1.14.8
gnark v0.5.2 v0.9.0
gnark-crypto v0.10.0 v0.12.1
protobuf v1.31.0 v1.34.2

移除了 replace gnark-crypto => v0.5.3(与 go-ethereum v1.14.8 依赖冲突)。

主要适配

1. go-ethereum API 变化

  • SimulatedBackend.Blockchain() 移除 → 用 Client.HeaderByNumber 替代(cross2eth/x2ethereum ethinterface)
  • secp256k1.Sign (cgo only) → crypto.Sign(5 处签名调用)
  • EVM uint64→int64 溢出防护(ForkEVMFixOverflow,官方 master 已合入,本 PR 基于其之上)

2. gnark v0.9.0 适配

  • Define(curveID, api)Define(api)(5 个电路)
  • frontend.Variable 变为 interface{}Assign()/GetWitnessValue() 移除 → VariableToElement() + 直接赋值
  • twistededwards 路径迁移至 std/algebra/native/twistededwards
  • ScalarMulScalarMultiplication
  • groth16.Prove/Verify 改用 witness.Witness API

3. MiMC 协议兼容

gnark-crypto v0.12.1 将 MiMC constants 从 sha3.Sum256 改为 keccak256,所有 hash 输出变化。新增 plugin/crypto/legacymimc(基于 v0.5.3 的 MiMC 实现):

  • off-chain:legacymimc.NewMiMC(seed)
  • in-circuit:legacymimc.NewCircuitMiMC(api, seed)(保持 Miyaguchi-Preneel 算法)

zksync/mix 全部切换到旧实现,保持链上协议兼容。

4. groth16 密钥重新生成

gnark v0.9.0 的 VK/PK/proof 二进制格式与 v0.5.2 不兼容。新增 mix/cmd/genzkkey

  • CI 实时生成 PK/VK,不再下载旧 tarball
  • testcase.sh 运行时从生成文件读取 VK(groth16.Setup 随机,硬编码 VK 不匹配)

5. Para 链共识修复

chain33 升级引入 ForkParaFee(默认 -1 始终激活),SetAllFork(0) 再加 0,导致 para 链对同步交易收手续费,破坏共识。

  • chain33: 新增 Chain33Config.SetFork() 方法
  • plugin: NewParaNode 初始化后调用 SetFork("ForkParaFee", MaxHeight) 禁用

存量兼容修复

升级改变了多个序列化/派生算法,本 PR 对历史数据做存量兼容:

6. groth16 VK/proof 新旧格式兼容

gnark v0.5.2 → v0.9.0 的 VK/proof 序列化追加 commitments 字段。新增 mix/types/groth16_compat.goReadVerifyingKeyCompatible/ReadProofCompatible):先试新格式,EOF 按旧格式解析(旧格式是新格式前缀,mix/zksync 电路不用 commitment,语义等价)。旧格式 VK/proof 可继续验证,zksnark 6 个旧格式测试已恢复。

7. zksync layer2 key 派生兼容(GenerateKeyCompat)

gnark-crypto v0.5.3 → v0.12.1 修正了 eddsa.GenerateKey 标量反转边界,同一 seed 派生地址变化。新增 zksync/wallet/eddsa_compat.go 复刻 v0.5.3 派生逻辑,恢复历史地址:

  • 钱包签名 / CLI / 测试全部改用兼容派生
  • 原 11 个 skip 的集成测试重新启用并通过

7. mix CBC 解密格式兼容

chain33 CBC 改随机 IV 后,旧格式(ciphertext-only,IV=key[:16])会被误按新格式解析产生静默损坏。decryptDataWithPadinglen%32 精确区分新旧格式(新 %32==16,旧 %32==0)。

8. witness 双格式读取(ReadWitnessCompatible)

gnark v0.5.2([uint32(n)][elems]%32==4)与 v0.9.0(%32==12)witness 格式不兼容。新增 ReadWitnessCompatiblelen%32 识别并解析两种格式,接入 mix Verify/ConstructCircuitPubInput/zksync verifyProof,使链上存量 pubInput 可继续验证。

9. cross2eth 测试适配

simulated backend v1.14.8 的 Pending 查询行为变化,测试改 Pending:false + NewOracleClaimCommit(模拟确认时序),TestBridgeBankUnlock/TestBridgeBankSedondUnlockErc20 已恢复。

10. rgbx CI 稳定性修复

chain33-cli RPC 失败时退出码恒为 0,导致 rgbx CI 的 wait/tx 等待"假通过",产生偶发失败(DKG timeout、restart 恢复 pending 查询)。改用 jq 校验输出内容(而非退出码)判断就绪/交易确认,并加长 DKG 等待。

其他修复

  • relay BTC 测试: assert.Equalproto.Equal(protobuf v1.34.2 新增 sizeCache 字段)
  • 386 架构: 5 个 gnark 测试文件加 //go:build !386(gnark v0.9.0 32-bit 未对齐 atomic panic)
  • ci_mix: make build_ci 确保 Docker 使用最新编译的二进制

chain33 侧改动

已合并到 chain33 master:

  • 798621305 fix(wallet): CBCDecrypterPrivkey 支持 64-byte ed25519 密钥及随机 IV
  • 528b6ef7d fix(ethrpc): checkIPWhitelist 通配符 "*" 处理
  • 1edb5ac8d feat: 新增 Chain33Config.SetFork() 公开方法

另有独立 PR 待合并:

  • 33cn/chain33#1373 fix(cli): RPC 失败时退出码非 0,供脚本感知失败(rgbx CI 已先用 jq 校验绕过,不阻塞本 PR)

CI 状态

Job 状态
GitHub Actions (16 项) ✅ 全部通过
Jenkins ci-plugin ⏳ GitHub token 过期,需管理员更新(见 PR 评论)

部署说明

  • groth16 兼容: 旧 v0.5.2 VK/proof 已通过兼容 reader 支持,历史数据无需重置(详见升级文档)
  • MiMC: 已用 legacymimc 保持哈希兼容(旧算法,历史数据不变);如需切换到 gnark v0.12.1 新哈希(keccak 版),需后续新增 dapp fork 控制切换高度(当前未实现)

🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com

@bysomeone
bysomeone force-pushed the fix/chain33-go-ethereum-upgrade branch 2 times, most recently from ab1747e to 623b15d Compare August 6, 2026 04:58
@bysomeone

Copy link
Copy Markdown
Collaborator Author

ci-plugin (Jenkins) 无法运行说明

本 PR 的 ci-plugin(Jenkins CI)GitHub token(33cntoken)过期而无法触发/扫描,需要 33cn 管理员更新 Jenkins 的 GitHub token 后才能恢复。

  • 影响:PR 页面的 Jenkins 检查(ci-plugin)一直无法运行
  • 其余 CI 状态:GitHub Actions 16 项 + AppVeyor 均已通过 ✅
  • 待办:33cn 管理员在 Jenkins credentials 中更新 GitHub token(33cntoken),或临时改用有效 token 后重新触发

GitHub Actions 全部绿灯,本 PR 的功能与测试验证完整。

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 14.94662% with 239 lines in your changes missing coverage. Please review.
✅ Project coverage is 28.83%. Comparing base (0d0e378) to head (1d7b629).
⚠️ Report is 127 commits behind head on master.

Files with missing lines Patch % Lines
plugin/crypto/legacymimc/mimc.go 0.00% 72 Missing ⚠️
plugin/dapp/mix/cmd/genzkkey/main.go 0.00% 44 Missing ⚠️
plugin/crypto/legacymimc/circuit.go 0.00% 30 Missing ⚠️
plugin/dapp/evm/executor/vm/runtime/token.go 0.00% 19 Missing ⚠️
plugin/dapp/zksync/executor/zkproof.go 0.00% 17 Missing ⚠️
plugin/dapp/evm/executor/vm/runtime/evm.go 18.75% 12 Missing and 1 partial ⚠️
plugin/dapp/zksync/executor/zkproofutil.go 0.00% 10 Missing ⚠️
plugin/dapp/evm/executor/vm/state/statedb.go 50.00% 7 Missing ⚠️
plugin/dapp/mix/executor/zksnark/verify.go 50.00% 1 Missing and 3 partials ⚠️
plugin/dapp/zksync/wallet/eddsa_compat.go 86.20% 2 Missing and 2 partials ⚠️
... and 9 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master    #1305       +/-   ##
===========================================
- Coverage   48.37%   28.83%   -19.54%     
===========================================
  Files         223      382      +159     
  Lines       42519    73407    +30888     
===========================================
+ Hits        20568    21166      +598     
- Misses      20058    50265    +30207     
- Partials     1893     1976       +83     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

bysomeone and others added 19 commits August 7, 2026 15:09
- Replace secp256k1.Sign with crypto.Sign (5 call sites)
- SimulatedBackend.Blockchain() → Client.HeaderByNumber
- Update Makefile: remove -i flag, force CGO_ENABLED=1
- Add DisableForkCheck/ForkAccountBlacklist/ForkParaFee to CI configs

Co-Authored-By: Claude <noreply@anthropic.com>
gnark-crypto v0.12.1 changed MiMC constants from sha3.Sum256 to
keccak256, breaking all existing chain data (note hashes, merkle
roots, zk proofs). legacymimc uses the old constants and preserves
gnark v0.5.2 Miyaguchi-Preneel algorithm for in-circuit use.

Co-Authored-By: Claude <noreply@anthropic.com>
mix circuits:
- Define(curveID, api) → Define(api)
- frontend.Variable is interface{}, Assign() → direct assignment
- GetWitnessValue() → VariableToElement()
- mimc.NewMiMC → legacymimc.NewCircuitMiMC
- twistededwards path: std/algebra → std/algebra/native
- ScalarMulFixedBase/ScalarMulNonFixedBase → ScalarMul
- AddGeneric → Add
- Groth16 Prove/Verify use witness.Witness API

mix wallet:
- CBC decryption adapted for chain33 random IV format
- Mimc hash → legacymimc

zksync:
- Mimc hash → legacymimc for proof compatibility

Co-Authored-By: Claude <noreply@anthropic.com>
gnark v0.9.0 PK/VK binary format is incompatible with v0.5.2.
Add genzkkey to compile circuits and generate fresh keys.
CI now generates keys at build time instead of downloading old tarball.
testcase.sh reads VK from generated files (groth16.Setup is random).

Also add make build_ci before docker-compose to ensure Docker uses
freshly compiled binaries.

Co-Authored-By: Claude <noreply@anthropic.com>
protobuf v1.34.2 adds internal sizeCache field that breaks
assert.Equal comparison. Use proto.Equal instead.

Co-Authored-By: Claude <noreply@anthropic.com>
chain33 ForkParaFee defaults to -1 (always active). Test mode
SetAllFork(0) activates it, causing para chain to charge fees on
synced blocks which breaks consensus.

Fix: call SetFork("ForkParaFee", MaxHeight) after para node init.

Requires chain33 5b2b6d28c for Chain33Config.SetFork API.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
chain33 PR merged; drop the temporary bysomeone/chain33 replace and
use upstream master (v1.69.1-0.20260806044231-1edb5ac8d):
- go-ethereum v1.14.8 upgrade
- Chain33Config.SetFork() programmatic fork override (1edb5ac8d)
- ethrpc checkIPWhitelist '*' wildcard (528b6ef7d)
- CBCDecrypterPrivkey 64-byte ed25519 key support (798621305)

Co-Authored-By: Claude <noreply@anthropic.com>
- decryptDataWithPading: disambiguate new (IV16+ciphertext, len%32==16) vs
  legacy (ciphertext-only, len%32==0) CBC formats by length; previously the
  legacy blob was mis-parsed as new format producing silent corrupted plaintext
- add ReadWitnessCompatible: parse both gnark v0.5.2 ([uint32(n)][n*32B],
  len%32==4) and v0.9.0 (len%32==12) witness pubInput formats so on-chain
  legacy pubInput remains verifiable
- wire ReadWitnessCompatible into zksnark Verify and ConstructCircuitPubInput
- tests cover new+legacy CBC round-trip and both witness formats

Co-Authored-By: Claude <noreply@anthropic.com>
…esses

gnark-crypto v0.5.3->v0.12.1 fixed eddsa.GenerateKey scalar byte-reversal
boundary (j=sizeFr -> j=sizeFr-1), changing keypair derivation for the same
seed. zksync layer2 addresses (mimc(pubkey)) were already persisted on-chain
under the v0.5.3 derivation, so after the upgrade SetPubKey validation would
fail and historical users could no longer operate.

Add GenerateKeyCompat that replicates the v0.5.3 scalar construction and
builds the v0.12.1 PrivateKey via SetBytes (Sign/Verify are identical across
versions). Replace all eddsa.GenerateKey call sites (wallet signing, CLI,
tests) and re-enable the 11 previously skipped integration tests.
verifyProof now reads pubInput through mix.ReadWitnessCompatible.

Co-Authored-By: Claude <noreply@anthropic.com>
- ReadWitnessCompatible: reject input that is neither old (%32==4) nor
  new (%32==12) witness format with a clear error, instead of silently
  forwarding to ReadFrom
- decryptDataWithPading: guard empty and non-16-aligned input to avoid
  panics on crafted data (pre-existing gap)
- migrate TestDepositSetVal to ReadWitnessCompatible (covers legacy-format
  pubInput end-to-end) and remove now-unused Witness.LimitReadFrom

Co-Authored-By: Claude <noreply@anthropic.com>
chain33-cli RPC commands print errors to stderr but exit 0 on failure
(jsonclient Run/RunExt return without os.Exit; cobra Run handlers don't
propagate errors). rgbx readiness/tx waits that checked the exit code
therefore always passed immediately, even when node RPC was not listening,
causing flaky CI failures (DKG timeout, restart recovery pending query).

- wait_cli_ready: block last_header exit code -> validate JSON output via jq '.height != null'
- tx_wait: tx query_hash exit code -> validate '.txs | length > 0'
- wait_auto_dkg_commit: getCross rc==0 -> validate '.tssAddress != ""', widen 60s->120s
- ensure_btc_crosschain_prerequisite: getCross rc!=0 -> validate output
- wait_no_withdraw_pending_for_user / scenario_restart_recovery: guard empty
  values from failed queries (listPend polled until it returns a number)

Co-Authored-By: Claude <noreply@anthropic.com>
- tx_wait: GetTxByHashes returns {"txs":[null]} for not-yet-mined tx, so
  '.txs? | length > 0' passed immediately; filter out null entries:
  '.txs? | map(select(. != null)) | length > 0'
- scenario_restart_recovery / wait_no_withdraw_pending_for_user: under
  set -e + pipefail a failed jq in command substitution aborts the script
  on the first poll instead of retrying; add '||' fallback so polling can
  retry until the rgbx query is ready

Co-Authored-By: Claude <noreply@anthropic.com>
…tation

- zksync SetPubKey section: key derivation is now fixed via GenerateKeyCompat
  (was t.Skip); historical addresses preserved, 11 tests re-enabled
- groth16 section: old v0.5.2 proof bytes cannot be re-read by v0.9.0
  (missing Commitments fields), so a fresh full re-sync of chains with
  historical mix/zksync txs fails; deployment must choose snapshot-based
  sync or mix/zksync dapp reset

Co-Authored-By: Claude <noreply@anthropic.com>
gnark v0.5.2->v0.9.0 appends commitments fields to groth16 VK/proof
serialization. Old format is a prefix of the new format; mix/zksync
circuits don't use the commitment feature, so the two are semantically
equivalent.

Add ReadVerifyingKeyCompatible/ReadProofCompatible (mix/types/groth16_compat.go):
- try v0.9.0 standard ReadFrom first (new format unchanged)
- on EOF fall back to parsing the old bellman main part with empty
  commitments, then Precompute() so Verify works
- wire into zksnark.Verify; re-enable 6 previously skipped old-format
  VK/proof verification tests
- new tests cover new format, old format, and truncated-invalid input

Co-Authored-By: Claude <noreply@anthropic.com>
- bind.CallOpts{Pending:true} contract queries behave differently in
  v1.14.8 simulated backend (pending state no longer reflects the latest
  submitted tx), so BalanceOf under pending returned 0. Switch to
  Pending:false and Commit after Oracle.NewOracleClaim before querying,
  matching the on-chain confirm-then-read sequence.
- re-enable TestBridgeBankUnlock and TestBridgeBankSedondUnlockErc20

Co-Authored-By: Claude <noreply@anthropic.com>
- groth16 section: old v0.5.2 VK/proof now readable via
  ReadVerifyingKeyCompatible/ReadProofCompatible; no snapshot-sync or
  dapp-reset deployment requirement
- zksync key derivation: fixed via GenerateKeyCompat (tests re-enabled)
- cross2eth: simulated backend pending-query adaptation

Co-Authored-By: Claude <noreply@anthropic.com>
Completes the seamless-upgrade story: old PK (v0.5.2) can now be read by
new code so mix wallet can keep generating proofs with the existing key
without redeploying VK/PK.

- ReadProvingKeyCompatible (groth16_compat.go): try v0.9.0 ReadFrom, fall
  back to manual old-format parse (Domain + main part, empty CommitmentKeys)
- wire into mix wallet getZkProofKeys (all proof flows inherit compat)
- tests: new PK prove+verify, old PK prove+old VK verify (seamless
  scenario), truncated-invalid rejected

Co-Authored-By: Claude <noreply@anthropic.com>
Verify legacymimc produces byte-identical MiMC hashes to gnark-crypto
v0.5.3 (the historical protocol implementation). Test vectors generated
independently from v0.5.3 with the mix MimcHashSeed.

Co-Authored-By: Claude <noreply@anthropic.com>
@bysomeone
bysomeone force-pushed the fix/chain33-go-ethereum-upgrade branch from 4352293 to c6b9516 Compare August 7, 2026 07:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant