Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a7d847b
fix: adapt go-ethereum API changes for v1.14.8 upgrade
bysomeone Aug 4, 2026
1bedf91
feat: add legacymimc to preserve zksync/mix MiMC hash compatibility
bysomeone Aug 4, 2026
924de4e
fix: adapt mix/zksync to gnark v0.9.0 and gnark-crypto v0.12.1
bysomeone Aug 4, 2026
f7d2747
feat(mix): add genzkkey tool, update CI to regenerate groth16 keys
bysomeone Aug 4, 2026
6ba3d40
fix(relay): use proto.Equal for BTC header comparison
bysomeone Aug 4, 2026
d89594c
fix(para): disable ForkParaFee in test para nodes via SetFork
bysomeone Aug 4, 2026
c61d6b2
fix(cross2eth): replace secp256k1.Sign with crypto.Sign for CGO=0
bysomeone Aug 4, 2026
83ff857
build(deps): bump chain33 to master with go-ethereum v1.14.8 upgrade
bysomeone Aug 6, 2026
f1a24f6
fix(mix): preserve historical compatibility for CBC and witness formats
bysomeone Aug 6, 2026
1dc942f
fix(zksync): preserve v0.5.3 eddsa key derivation for historical addr…
bysomeone Aug 6, 2026
df34210
fix(mix): add defensive guards per review and remove dead code
bysomeone Aug 6, 2026
c475098
fix(rgbx): CI waits relied on chain33-cli exit codes which are always 0
bysomeone Aug 6, 2026
3851c2b
fix(rgbx): correct CI wait logic per final review
bysomeone Aug 6, 2026
66b98f0
docs: record zksync key derivation fix and groth16 proof re-sync limi…
bysomeone Aug 6, 2026
ed4e38b
fix(mix): add groth16 VK/proof compatibility for old v0.5.2 format
bysomeone Aug 7, 2026
8067616
fix(cross2eth): adapt tests to go-ethereum v1.14.8 simulated backend
bysomeone Aug 7, 2026
46f3bf2
docs: groth16 compatibility implemented, update upgrade notes
bysomeone Aug 7, 2026
02607aa
fix(mix): add ProvingKey compatibility for old v0.5.2 format
bysomeone Aug 7, 2026
c6b9516
test: add legacymimc MiMC compatibility test
bysomeone Aug 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/build_mix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ jobs:
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin

- name: download zk key file
- name: generate zk key file
run: |
pwd&&cd ./plugin/dapp/mix/cmd/
wget https://github.com/mdj33/gnark/blob/main/chain33key.tar.gz?raw=true -O chain33key.tar.gz
tar -xzvf chain33key.tar.gz
cp chain33key/* ./gnark/
cd ./plugin/dapp/mix/cmd/
# groth16 PK/VK 与 gnark 版本绑定;链上已按 gnark v0.9.0 生成密钥,
# 此处实时生成保证密钥与代码一致(旧 v0.5.2 密钥无法被 v0.9.0 读取)
go run ./genzkkey ./gnark/
cd -
- name: deploy
run: |
make build_ci
make docker-compose dapp=mix
make docker-compose-down dapp=mix
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ build: depends

build_ci: depends ## Build the binary file for CI (Linux/amd64|arm64 when not on Linux, for Docker)
@if [ "$$(uname)" = "Linux" ]; then \
go build $(BUILD_FLAGS) -v -o $(CLI) $(SRC_CLI) && \
go build $(BUILD_FLAGS) -v -o $(APP); \
CGO_ENABLED=1 go build $(BUILD_FLAGS) -v -o $(CLI) $(SRC_CLI) && \
CGO_ENABLED=1 go build $(BUILD_FLAGS) -v -o $(APP); \
else \
CGO_ENABLED=0 GOOS=linux GOARCH=$$(go env GOARCH) go build $(BUILD_FLAGS) -v -o $(CLI) $(SRC_CLI) && \
CGO_ENABLED=0 GOOS=linux GOARCH=$$(go env GOARCH) go build $(BUILD_FLAGS) -v -o $(APP); \
Expand Down
2 changes: 2 additions & 0 deletions chain33.fork.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ForkFormatAddressKey=0
ForkCheckEthTxSort=0
ForkProxyExec=0
ForkMaxTxFeeV1=0
ForkAccountBlacklist=-1
ForkParaFee=-1
ForkEthAddressFormat=0

[fork.sub.none]
Expand Down
3 changes: 3 additions & 0 deletions chain33.para.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Title="user.p.para."
DisableForkCheck=true
TestNet=false
CoinSymbol="para"
EnableParaFork=true
Expand Down Expand Up @@ -324,6 +325,8 @@ ForkFormatAddressKey=0
ForkCheckEthTxSort=0
ForkProxyExec=0
ForkMaxTxFeeV1=0
ForkAccountBlacklist=-1
ForkParaFee=-1
ForkEthAddressFormat=0

[fork.sub.none]
Expand Down
1 change: 1 addition & 0 deletions chain33.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Title="chain33"
DisableForkCheck=true
TestNet=true
FixTime=false
version="6.3.0"
Expand Down
198 changes: 198 additions & 0 deletions docs/chain33-go-ethereum-v1.14.8-upgrade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# chain33 go-ethereum v1.14.8 升级适配

## 背景

chain33 上游将 `go-ethereum` 从 v1.12.0 升级到 v1.14.8,plugin 需同步升级并适配。

## 依赖变化

| 依赖 | 旧版本 | 新版本 | 影响 |
|------|--------|--------|------|
| `github.com/33cn/chain33` | v1.69.1-0.20260508 | 3f8f145b | 主依赖 |
| `github.com/ethereum/go-ethereum` | v1.12.0 | v1.14.8 | 核心升级 |
| `github.com/consensys/gnark` | v0.5.2 | v0.9.0 | zksync/mix 电路 |
| `github.com/consensys/gnark-crypto` | v0.10.0 (replace v0.5.3) | v0.12.1 | zksync/mix 哈希与签名 |
| `github.com/BurntSushi/toml` | v1.2.1 | v1.3.2 | 间接 |

移除了 `replace github.com/consensys/gnark-crypto => v0.5.3`,该 replace 会强制降级 gnark-crypto 至旧版,与 go-ethereum v1.14.8 依赖冲突。

## 适配内容

### 1. go-ethereum API 变化

`SimulatedBackend.Blockchain()` 在 v1.14 移除,改为内嵌 `simulated.Client`:

- `plugin/dapp/cross2eth/ebrelayer/relayer/ethereum/ethinterface/ethinterface.go`
- `plugin/dapp/x2ethereum/ebrelayer/ethinterface/ethinterface.go`

```go
// 旧
return sim.Blockchain().CurrentBlock(), nil
// 新
return sim.Client.HeaderByNumber(ctx, number)
```

#### 1.1 `crypto/secp256k1.Sign` → `crypto.Sign`(CGO=0 兼容)

go-ethereum v1.14.8 的 `crypto/secp256k1` 包带 `//go:build cgo` tag,`CGO_ENABLED=0` 下不可用。跨链签名全部改为 go-ethereum 跨平台入口 `crypto.Sign(hash []byte, key *ecdsa.PrivateKey)`:

- `cross2eth/ebrelayer/utils/signature.go: prefixMessage`
- `x2ethereum/ebrelayer/ethtxs/utils.go: prefixMessage`
- `cross2eth/ebrelayer/relayer/chain33/tx.go: safeTransfer`(Gnosis Safe 多签)
- `cross2eth/boss4x/chain33/offline/multisignTransfer.go`
- `bridgevmxgo/boss4x/chain33/offline/multisignTransfer.go`

```go
// 旧:libsecp256k1(仅 cgo)
sig, err := secp256k1.Sign(hash, math.PaddedBigBytes(key.D, 32))
// 新:跨平台,签名格式字节级一致
sig, err := crypto.Sign(hash, key)
```

> **兼容性已实测验证**:同一私钥+消息,`crypto.Sign` 与旧 `secp256k1.Sign`(libsecp256k1)输出**逐字节相同**;且 `crypto.Sign` 在 `CGO_ENABLED=0/1` 两种构建下输出一致。`sig[64] += 27`(recovery id 0/1 → 27/28,Gnosis Safe / ecrecover 格式)不受影响。多签节点 cgo/non-cgo 混跑不会产生不同签名。

### 2. gnark-crypto API 变化

#### 2.1 `fr.Element.SetString` 返回 2 值

```go
// 旧
f.SetString(s).Bytes()
// 新
elem, _ := f.SetString(s)
elem.Bytes()
```

受影响:`zksync/wallet/utils.go`、`zksync/executor/zkproofutil.go`

#### 2.2 `eddsa.GenerateKey` 返回指针

`eddsa.GenerateKey` 从返回 `PrivateKey` 值改为 `*PrivateKey`。所有接收 `eddsa.PrivateKey` 的函数签名改为 `*eddsa.PrivateKey`:

- `zksync/wallet/zksyncbizpolicy.go: SignTx`
- `zksync/commands/l2txs/utils.go: SignTxInEddsa`
- `zksync/executor/exec_test.go: SignTxInEddsa`

#### 2.3 `bn254.PointAffine.ScalarMul` 改名

`ScalarMul` → `ScalarMultiplication`(mix/types/util.go)

### 3. gnark API 变化

#### 3.1 电路 Define 签名

```go
// 旧
func (circuit *X) Define(curveID ecc.ID, api frontend.API) error
// 新
func (circuit *X) Define(api frontend.API) error
```

受影响:mix 5 个电路 + zksync `commitProofCircuit`

#### 3.2 `frontend.Variable` 变为 `interface{}`

`Assign()` 和 `GetWitnessValue()` 移除:

```go
// 旧
input.Amount.Assign(v)
input.Amount.GetWitnessValue(ecc.BN254)
// 新
input.Amount = v
mixTy.VariableToElement(input.Amount)
```

mix 新增 `VariableToElement` helper(types/util.go)将 Variable 值转回 `fr.Element`。

#### 3.3 电路内 mimc 移路径

`gnark/std/algebra/twistededwards` → `gnark/std/algebra/native/twistededwards`,`NewEdCurve` 签名变化。

#### 3.4 groth16 编译/验证 API

```go
// 旧
frontend.Compile(ecc.BN254, backend.GROTH16, circuit) // frontend.CompiledConstraintSystem
groth16.Prove(ccs, pk, circuit)
groth16.ReadAndVerify(proof, vk, buf)
witness.WritePublicTo(buf, ecc.BN254, circuit)
// 新
frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, circuit) // constraint.ConstraintSystem
w, _ := frontend.NewWitness(circuit, field)
groth16.Prove(ccs, pk, w)
pubW, _ := w.Public(); pubW.WriteTo(buf)
groth16.Verify(proof, vk, pubW)
```

### 4. MiMC 哈希兼容(重点)

#### 问题

gnark-crypto v0.5.3 → v0.12.1 的 MiMC round constants 推导算法变化:

| 版本 | 推导算法 | seed |
|------|----------|------|
| v0.5.3 | `sha3.Sum256(seed)` | 自定义 |
| v0.12.1 | `keccak256("seed")` | 硬编码 "seed" |

SHA3-256 与 Keccak-256 是不同的哈希函数,round constants 完全不同,导致所有 MiMC 输出变化。

若 zksync/mix 链上已有数据(note hash、merkle root、zk proof),新哈希无法验证旧数据,**协议断裂**。

#### 解决方案:`plugin/crypto/legacymimc`

保留旧版 MiMC 实现(基于 gnark-crypto v0.5.3 源码,sha3.Sum256 推导,支持自定义 seed):

- `legacymimc.NewMiMC(seed)` — off-chain 哈希
- `legacymimc.NewCircuitMiMC(api, seed)` — 电路内哈希(gnark frontend.API)

zksync/mix 全部切换到 legacymimc,保持旧哈希语义:

| dapp | off-chain | in-circuit |
|------|-----------|------------|
| zksync | `legacymimc.NewMiMC(ZkMimcHashSeed="seed")` | — |
| mix | `legacymimc.NewMiMC(MimcHashSeed)` | `legacymimc.NewCircuitMiMC(api, MimcHashSeed)` |

**待办**:后续可通过 dapp fork(如 `ForkMiMCHash`)在分叉高度后切换到新哈希。

#### 5. chain33 CBC 随机 IV 影响

chain33 的 `b70757355 fix: CBC 随机 IV` 将 `CBCEncrypterPrivkey` 改为随机 IV,返回 `IV(16)+ciphertext` 格式。但其 `CBCDecrypterPrivkey` 新格式仅对 **32 字节明文**生效(钱包私钥场景),mix 加密数据明文更大导致解密回退旧格式而失败。

**适配**:`mix/wallet/cryptokey.go:decryptDataWithPading` 自行按新格式(IV+ciphertext)解密,并回退兼容旧格式。

#### 6. zksync key 派生链变化

chain33 升级后,zksync 的 `SetPubKey` 校验(`mimc(pubkey.X || pubkey.Y)`)与 deposit 时硬编码的 `Chain33Addr` 不再匹配。复现确认当前派生结果与历史测试数据(`2b8a...`)不同,root cause 为跨链 key 派生链(secp256k1 → `GetLayer2PrivateKeySeed` → `eddsa.GenerateKey`)的深层变化。

**影响**:gnark-crypto v0.5.3 → v0.12.1 修正了 `eddsa.GenerateKey` 的标量反转边界(`j=sizeFr` → `sizeFr-1`),导致同一 seed 派生出的 layer2 地址变化。已通过 `zksync/wallet/eddsa_compat.go` 的 `GenerateKeyCompat`(复刻 v0.5.3 派生逻辑)恢复历史地址兼容,原 11 个集成测试(TestTransfer/TestWithdraw/TestWithdrawNFT/TestTransfer2New/TestTree2contract/TestContract2Tree/TestMintNFT/TestProxyExit/TestProxyExitFaid/TestTransferNFT/TestNFTMisc)已重新启用并通过。若主网 zksync 已有用户数据,使用兼容派生后地址与历史一致,无需迁移。

#### 7. groth16 序列化格式兼容

gnark v0.5.2 → v0.9.0 的 groth16 VK/PK/proof 二进制序列化格式变化(v0.9.0 追加 commitments 相关字段)。已实现**新旧格式兼容读取**:

- `mix/types/groth16_compat.go`:`ReadVerifyingKeyCompatible` / `ReadProofCompatible`
- v0.5.2 旧格式(VK bellman 主部分、proof `Ar|Bs|Krs`)与新 v0.9.0 格式均可读取
- 旧格式是新格式的前缀(去掉 commitments 段);mix/zksync 电路不使用 gnark commitment 特性,新旧 proof **语义等价**
- `mix/executor/zksnark` 的 6 个旧格式 VK/proof 验证测试已恢复(不再 skip)
- 链上已部署的旧格式 VK/proof **无需重置**,可继续验证;新格式同样正常

**安全性**:mix/zksync 电路不使用 commitment,新旧 proof 均不含 commitment(仅序列化格式差异),验证走标准 groth16,无安全影响。

## 编译与测试状态

- 全项目编译通过
- zksync 测试通过(key 派生已通过 `GenerateKeyCompat` 兼容)
- mix 测试通过(含 zksnark 旧格式 VK/proof 验证)
- cross2eth 合约测试通过(`Pending` 查询语义适配 simulated backend)
- `cross2eth/contracts/gnosis/bsctest` 与 `chain33test` 为历史遗留(main 缺失),与本次升级无关

## 待办

- [ ] 通过 dapp fork 切换 MiMC 到新哈希(`ForkMiMCHash`)

## 溯源参考

- 攻击分析:`docs/security/evm-uint64-overflow-attack-analysis.md`
- 本次升级 commit:fix/chain33-go-ethereum-upgrade
Loading
Loading