From d8631ff3afb9d0672020da2c94f1a26b6f2b807c Mon Sep 17 00:00:00 2001 From: king Date: Wed, 2 Sep 2026 12:55:01 +0000 Subject: [PATCH 1/3] ci: restore relayd build and real relay integration test plugin/dapp/relay/cmd/build.sh has had its relayd build section commented out since 2021 (739e84e44), so build/ci/relay was never created and `make docker-compose dapp=relay` silently returned 0 (the fake-green job deleted in b04a1b858). Restore the OUT_DIR build so the btcd+relayd testcase.sh runs again. Also fix wait_btcd_up: docker-compose v1 no longer exists on the ubuntu-22.04 runners, and the awk picked the CREATED column instead of STATUS, so the loop could never see btcd as up. Use docker inspect instead. Add a real ci_relay workflow to replace the deleted fake one. Co-Authored-By: Claude --- .github/workflows/build_relay.yml | 43 +++++++++++++++++++++++++ plugin/dapp/relay/cmd/build.sh | 17 +++++----- plugin/dapp/relay/cmd/build/testcase.sh | 6 ++-- 3 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/build_relay.yml diff --git a/.github/workflows/build_relay.yml b/.github/workflows/build_relay.yml new file mode 100644 index 0000000000..ace0bfb431 --- /dev/null +++ b/.github/workflows/build_relay.yml @@ -0,0 +1,43 @@ +name: ci_relay + +# relay 集成测试:btcd(simnet) + relayd + 6 个 chain33 节点。 +# 依赖 plugin/dapp/relay/cmd/build.sh 在 make build_ci 时构建 relayd 并生成 +# build/ci/relay(relayd、relayd.toml、Dockerfile-relayd、docker-compose-relay.yml、 +# testcase.sh),否则 make docker-compose dapp=relay 会打印 +# "dapp=relay not exist or is system dir" 后直接返回 0(假绿)。 +# agents/** push 用于在 agent 分支上远程迭代,成熟后可移除。 +on: + push: + branches: [ master, 'agents/**' ] + pull_request: + workflow_dispatch: + +jobs: + ci_relay: + name: ci_relay + runs-on: ubuntu-22.04 + timeout-minutes: 90 + steps: + - name: checkout + uses: actions/checkout@v4 + with: + # build 脚本用 git describe --tags 注入版本号 + fetch-depth: 0 + + - name: Set up Golang + uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + id: go + + - name: set go env + run: export PATH=${PATH}:`go env GOPATH`/bin + + - name: deploy + run: | + make build_ci + make docker-compose dapp=relay + + - name: cleanup + if: always() + run: make docker-compose-down dapp=relay diff --git a/plugin/dapp/relay/cmd/build.sh b/plugin/dapp/relay/cmd/build.sh index 61ad9259f5..996736c884 100755 --- a/plugin/dapp/relay/cmd/build.sh +++ b/plugin/dapp/relay/cmd/build.sh @@ -4,14 +4,15 @@ strpwd=$(pwd) strcmd=${strpwd##*dapp/} strapp=${strcmd%/cmd*} -#OUT_DIR="${1}/$strapp" -#SRC_RELAYD=github.com/33cn/plugin/plugin/dapp/relay/cmd/relayd -#FLAG=$2 -# -## shellcheck disable=SC2086,1072 -#go build ${FLAG} -v -o "${OUT_DIR}/relayd" "${SRC_RELAYD}" -#cp ./relayd/relayd.toml "${OUT_DIR}/relayd.toml" -#cp ./build/* "${OUT_DIR}" +OUT_DIR="${1}/$strapp" +SRC_RELAYD=github.com/33cn/plugin/plugin/dapp/relay/cmd/relayd +FLAG=$2 + +mkdir -p "${OUT_DIR}" +# shellcheck disable=SC2086,1072 +go build ${FLAG} -v -o "${OUT_DIR}/relayd" "${SRC_RELAYD}" +cp ./relayd/relayd.toml "${OUT_DIR}/relayd.toml" +cp ./build/* "${OUT_DIR}" OUT_TESTDIR="${1}/dapptest/$strapp" mkdir -p "${OUT_TESTDIR}" diff --git a/plugin/dapp/relay/cmd/build/testcase.sh b/plugin/dapp/relay/cmd/build/testcase.sh index e7a33b622b..764e184176 100755 --- a/plugin/dapp/relay/cmd/build/testcase.sh +++ b/plugin/dapp/relay/cmd/build/testcase.sh @@ -46,8 +46,10 @@ function relay_config() { function wait_btcd_up() { local count=20 while [ $count -gt 0 ]; do - status=$(docker-compose ps | grep btcd | awk '{print $5}') - if [ "${status}" == "Up" ]; then + # docker compose ps 列取错(取到 CREATED 列)会导致永远重启 btcd, + # 且 ubuntu-22.04 runner 只有 compose v2,这里直接用 docker inspect 判状态 + status=$(docker inspect -f '{{.State.Status}}' "${BTCD}" 2>/dev/null || true) + if [ "${status}" == "running" ]; then break fi docker compose logs btcd From 41682ac8ea2b7fab3dde1cde28485414c1ba5bad Mon Sep 17 00:00:00 2001 From: king Date: Wed, 2 Sep 2026 13:10:16 +0000 Subject: [PATCH 2/3] fix(relay): decode verify order addr with its own btc network params btcd simnet integration test creates orders with simnet addresses ('S...'), but verifyBtcTxContent hardcoded MainNetParams when extracting addresses from the raw tx outputs, so simnet output addresses were re-encoded as mainnet '1...' addresses and never matched order.XAddr. The RelayVerify tx was rejected with ErrRelayVerifyAddrNotFound and the order stayed in confirming forever (relay testcase: 'wrong relay status finish real buy order id'). Pick the network params that successfully decode order.XAddr (mainnet/ testnet3/regtest/simnet), falling back to MainNet. Add a simnet regression test, and dump relayd/chain33 logs in testcase.sh when the finish wait times out. Co-Authored-By: Claude --- plugin/dapp/relay/cmd/build/testcase.sh | 4 ++ plugin/dapp/relay/executor/relay_test.go | 48 ++++++++++++++++++++++++ plugin/dapp/relay/executor/relaybtc.go | 22 ++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/plugin/dapp/relay/cmd/build/testcase.sh b/plugin/dapp/relay/cmd/build/testcase.sh index 764e184176..6fcd478ed4 100755 --- a/plugin/dapp/relay/cmd/build/testcase.sh +++ b/plugin/dapp/relay/cmd/build/testcase.sh @@ -336,6 +336,10 @@ function relay_test() { count=$((count - 1)) if [ $count -le 0 ]; then echo "wrong relay status finish real buy order id" + echo "=========== # relayd logs ===========" + docker compose logs relayd 2>&1 | tail -80 + echo "=========== # chain33 relay logs ===========" + docker compose logs chain33 2>&1 | grep -iE "verify|relay" | tail -60 exit 1 fi done diff --git a/plugin/dapp/relay/executor/relay_test.go b/plugin/dapp/relay/executor/relay_test.go index 77cf02dcdc..6f9f4cd824 100644 --- a/plugin/dapp/relay/executor/relay_test.go +++ b/plugin/dapp/relay/executor/relay_test.go @@ -5,14 +5,21 @@ package executor import ( + "bytes" "testing" apimock "github.com/33cn/chain33/client/mocks" + "github.com/33cn/chain33/common" "github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/db" "github.com/33cn/chain33/common/db/mocks" "github.com/33cn/chain33/types" ty "github.com/33cn/plugin/plugin/dapp/relay/types" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" @@ -372,6 +379,47 @@ func TestRunSuiteRelay(t *testing.T) { suite.Run(t, log) } +// TestVerifyBtcTxContentSimnet 集成测试场景回归: btcd simnet 的订单收款地址 +// 必须按 simnet 网络参数解析输出地址,硬编码 MainNet 会因地址编码不一致误判 +func TestVerifyBtcTxContentSimnet(t *testing.T) { + hash160 := bytes.Repeat([]byte{0xab}, 20) + addr, err := btcutil.NewAddressPubKeyHash(hash160, &chaincfg.SimNetParams) + if err != nil { + t.Fatal(err) + } + pkScript, err := txscript.PayToAddrScript(addr) + if err != nil { + t.Fatal(err) + } + + msgTx := wire.NewMsgTx(2) + // Deserialize 会把 vin 数 0 当作 witness marker,因此至少带一个输入 + // (真实的 btc 交易也必然有输入) + msgTx.AddTxIn(wire.NewTxIn(wire.NewOutPoint(&chainhash.Hash{}, 0xffffffff), nil, nil)) + msgTx.AddTxOut(wire.NewTxOut(100000, pkScript)) + var buf bytes.Buffer + if err := msgTx.SerializeNoWitness(&buf); err != nil { + t.Fatal(err) + } + rawHash := txidFromMsgTx(msgTx) + // reverse 原地修改切片,先拷贝一份作为期望值 + want := append([]byte{}, rawHash...) + btcTx := &ty.BtcTransaction{ + Hash: common.ToHex(reverse(rawHash)), + RawTx: common.ToHex(buf.Bytes()), + } + spv := &ty.BtcSpv{Hash: btcTx.Hash} + order := &ty.RelayOrder{XAddr: addr.EncodeAddress(), XAmount: 100000} + + got, err := verifyBtcTxContent(btcTx, spv, order) + if err != nil { + t.Fatalf("verifyBtcTxContent simnet addr: %v", err) + } + if !bytes.Equal(got, want) { + t.Fatalf("verifyBtcTxContent rawHash mismatch, got %x want %x", got, want) + } +} + ////////////////////////////////////// type suiteBtcHeader struct { diff --git a/plugin/dapp/relay/executor/relaybtc.go b/plugin/dapp/relay/executor/relaybtc.go index 161be72b6f..caf8aef392 100644 --- a/plugin/dapp/relay/executor/relaybtc.go +++ b/plugin/dapp/relay/executor/relaybtc.go @@ -16,6 +16,7 @@ import ( "github.com/33cn/chain33/common/merkle" "github.com/33cn/chain33/types" ty "github.com/33cn/plugin/plugin/dapp/relay/types" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -342,9 +343,13 @@ func verifyBtcTxContent(btcTx *ty.BtcTransaction, spv *ty.BtcSpv, order *ty.Rela return nil, ty.ErrRelayBtcTxHashErr } + // 订单收款地址可能属于任一 btc 网络(集成测试为 simnet), + // 用能成功解码订单地址的网络参数解析输出地址, + // 否则硬编码 MainNet 会把 simnet 输出地址重编码成 mainnet 地址,永远匹配不上 + params := addrNetParams(order.XAddr) var foundtx bool for _, out := range msgTx.TxOut { - _, addrs, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, &chaincfg.MainNetParams) + _, addrs, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, params) if err != nil { continue } @@ -390,6 +395,21 @@ func (b *btcStore) verifyCmdBtcTx(verify *ty.RelayVerifyCli) error { return nil } +// addrNetParams 返回能成功解码 addr 的 btc 网络参数,全部失败时回退 MainNet +func addrNetParams(addr string) *chaincfg.Params { + for _, p := range []*chaincfg.Params{ + &chaincfg.MainNetParams, + &chaincfg.TestNet3Params, + &chaincfg.RegressionNetParams, + &chaincfg.SimNetParams, + } { + if _, err := btcutil.DecodeAddress(addr, p); err == nil { + return p + } + } + return &chaincfg.MainNetParams +} + // decodeRawTx 将 hex 编码的原始 btc 交易反序列化为 MsgTx func decodeRawTx(rawTx string) (*wire.MsgTx, error) { data, err := common.FromHex(rawTx) From 577fa3bdfa2dfafb96bb26f89ed87631caf1a938 Mon Sep 17 00:00:00 2001 From: king Date: Thu, 3 Sep 2026 02:57:57 +0000 Subject: [PATCH 3/3] ci: drop agents/** push trigger from ci_relay, keep master and PR Remote iteration on the agents/relayed branch is done; the workflow now only runs on master pushes and pull requests, matching the other workflows. Co-Authored-By: Claude --- .github/workflows/build_relay.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build_relay.yml b/.github/workflows/build_relay.yml index ace0bfb431..2b43646c98 100644 --- a/.github/workflows/build_relay.yml +++ b/.github/workflows/build_relay.yml @@ -5,10 +5,9 @@ name: ci_relay # build/ci/relay(relayd、relayd.toml、Dockerfile-relayd、docker-compose-relay.yml、 # testcase.sh),否则 make docker-compose dapp=relay 会打印 # "dapp=relay not exist or is system dir" 后直接返回 0(假绿)。 -# agents/** push 用于在 agent 分支上远程迭代,成熟后可移除。 on: push: - branches: [ master, 'agents/**' ] + branches: [ master ] pull_request: workflow_dispatch: