Linera EVM 桥部署实操指南:基于 Docker 镜像在真实网络完成 EVM↔Linera Bridge 全流程部署

发布时间:2026/9/10 11:55:28
Linera EVM 桥部署实操指南:基于 Docker 镜像在真实网络完成 EVM↔Linera Bridge 全流程部署 Linera EVM 桥部署实操指南基于 Docker 镜像在真实网络完成 EVM↔Linera Bridge 全流程部署【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol导读本文是 Linera 协议仓库中 linera-bridge/deploy/README.mdBridge deployment runbook的完整实操指南讲解如何在真实的 EVM 网络Base、Ethereum 等与真实的 Linera 网络之间通过仓库预构建的 Docker 镜像以一段段可直接复制粘贴的命令完成整条跨链桥的搭建。读完本文你将掌握跨链桥各组件LightClient、FungibleBridge、wrapped-fungible、evm-bridge的严格创建顺序与依赖关系、三个 Docker 镜像包装函数docker-foundry / docker-linera / docker-linera-bridge的用法、从发起桥链、发布应用、跨链注册到生成 relayer 环境文件的完整 10 步流程以及 relayer 的启动、治理角色与安全注意事项。所有关键命令均以当前仓库源码为事实依据。部署一座桥 ≠ 运行这座桥。本 runbook 负责部署provisioning部署合约、创建应用、完成注册并产出一个 relayer 环境文件。之后的运维operating请参见 docker/README.testnet.md。一次部署会得到什么一座桥横跨两条链各部件之间存在严格的创建顺序——后面的步骤消费前面步骤的输出。整体依赖关系如下Linera faucet ──init-light-client──▶ committee args ( pause-guardian, proposer) │ EVM: LightClient ◀───────────────────────┘ Token (reuse existing ERC-20, or deploy LineraToken) Linera: request bridge chain ──▶ chain id owner wrapped-fungible app ──▶ WRAPPED_APP_ID (needs token, chain ids) evm-bridge app ──▶ BRIDGE_APP_ID (needs WRAPPED_APP_ID) EVM: FungibleBridge ◀── LightClient chain id token app ids governance │ Linera: register on both sides ◀──────────┘ (wrapped: authorize bridge; evm-bridge: record FungibleBridge addr)每一步产出的制品如下侧制品说明EVMLightClient验证 Linera 证书创世委员会来自 faucetEVMERC-20 token复用一个已有 token或新部署一个LineraTokenEVMFungibleBridge锁定存入的 ERC-20在验证过的BurnEvent上释放Linerabridge chain由 relayer 拥有并驱动的一条链Linerawrapped-fungibleapp铸造/销毁包装代币Lineraevm-bridgeapp验证 EVM 存款证明协调铸造/销毁桥的代币方向EVM 侧deposit()把发送者的 ERC-20锁入桥合约同时 Linera 侧 evm-bridge 应用铸造包装代币Linera 侧销毁包装代币后桥合约把等量 ERC-20释放给目标地址。因此桥自身不持有“自有浮存”每笔提款都有对应的历史存款背书。三个 Docker 镜像所有步骤都在三个镜像之一中运行通过一层薄薄的 shell 包装函数粘贴一次即可调用包装函数镜像构建自提供docker-foundryfoundry-jqDockerfile.foundryforge、cast、jqdocker-lineralinera-testDockerfile--target runtimelinera客户端/lineradocker-linera-bridgelinera-bridgeDockerfile.bridgelinera-bridgeCLI三个镜像的构建配方都在仓库 docker 目录docker/Dockerfile.foundry 基于ghcr.io/foundry-rs/foundry:stable仅额外安装jq因此forge script的部署广播结果可以由jq就地解析docker/Dockerfile.bridge 采用三段式chef/planner/builder runtime构建运行时阶段只装入linera-bridge二进制、bridge-entrypoint.sh和必要系统包入口为bridge-entrypoint.sh默认命令CMD [serve]docker/bridge-entrypoint.sh 会读取RPC_URL、EVM_BRIDGE_ADDRESS、LINERA_BRIDGE_APP、LINERA_FUNGIBLE_APP、EVM_PRIVATE_KEY、LINERA_BRIDGE_CHAIN_ID、LINERA_BRIDGE_CHAIN_OWNER等必需环境变量把它们拼成linera-bridge serve --rpc-url... --evm-bridge-address...形式的长参数并执行LINERA_WALLET/LINERA_KEYSTORE/LINERA_STORAGE则由 clap 直接通过env ...读取无需显式传参。linera-bridgeCLI 的子命令在 linera-bridge/src/main.rs 中定义init-light-client查询 faucet 生成 LightClient 构造参数、generate-deposit-proof为指定 EVM 交易生成存款证明与serverelay 服务relayfeature 下启用。前置条件在承载部署的主机上Docker仓库目录需要被共享进容器home 目录下的路径默认满足下面的$OUT必须位于仓库内部不能放/tmp否则/shared卷挂载在容器内为空。仓库需带子模块检出forge才能编译合约git submodule update --init --recursive对应的子模块位于 linera-bridge/src/solidity/lib 下含 forge-std 与 openzeppelin-contracts。从仓库根目录一次性构建三个镜像和 Wasm 模块make -C linera-bridge build-all该目标定义在 linera-bridge/Makefile先经build-wasm依赖构建 4 个.wasm模块再依次构建linera-test--target runtime、debug 模式、scylladbfeature、linera-bridge与foundry-jq。构建 Wasm 需要一个带wasm32-unknown-unknowntarget 的 Rust 工具链rustup target add wasm32-unknown-unknown——这是本 runbook 假设的唯一宿主机工具链。验证模块存在ls examples/target/wasm32-unknown-unknown/release/wrapped_fungible_{contract,service}.wasm \ linera-bridge/contracts/evm-bridge/target/wasm32-unknown-unknown/release/evm_bridge_{contract,service}.wasm目标网络上有一个持有资金的 EVM 账户支付合约部署费用以及后续 relayer 的addBlockgas。提前决定并持有的治理地址EVM 地址PAUSE_GUARDIAN、PROPOSER、CANCELLER详见治理角色。可访问目标 EVM RPC 与 Linera faucet。与Linera 网络运营方协调把 EVM RPC 主机名加入 HTTP 白名单见 HTTP 白名单——否则存款会失败。请从仓库根目录、在同一个 shell 会话中运行下面每一条命令包装函数与被复制前进的export都存在于该会话中。准备环境变量与包装函数先填入本次部署的取值再粘贴包装函数与辅助函数。# ── Per-deployment configuration ── export NETWORKbase-sepolia export RPC_URLhttps://sepolia.base.org # target EVM JSON-RPC export FAUCET_URLhttps://faucet.your-linera-net # faucet of the Linera network you bridge to export EVM_PRIVATE_KEY0x... # funded deployer key # Governance roles (EVM addresses you control) export PAUSE_GUARDIAN0x... export PROPOSER0x... export CANCELLER0x... export TIMELOCK_DELAY172800 # FungibleBridge timelock, seconds (e.g. 48h) # RPC the Linera validators use for EVM finality (must be allow-listed; defaults to RPC_URL) export EVM_RPC_ENDPOINT_FOR_LINERA${EVM_RPC_ENDPOINT_FOR_LINERA:-$RPC_URL} # Output dir — holds the bridge-chain wallet. BACK THIS UP. Must be under the repo. export OUT$PWD/linera-bridge/deploy/out/$NETWORK mkdir -p $OUT/wallet# ── Wrappers (paste once) ── # forge / cast / jq. Its entrypoint is sh -c, so the command is one string; # $RPC_URL and $EVM_PRIVATE_KEY are expanded INSIDE the container (forwarded via -e). docker-foundry() { docker run --rm \ -e RPC_URL -e EVM_PRIVATE_KEY \ -e LIGHT_CLIENT_ARGS_JSON_FILE \ -e TOKEN_ADDRESS \ -v $PWD/linera-bridge/src/solidity:/contracts \ -v $OUT:/shared \ -w /contracts \ foundry-jq $* } # linera client. Wallet/keystore/storage persist in $OUT/wallet across calls. # Wasm modules are reachable under /repo. docker-linera() { docker run --rm \ -e LINERA_WALLET/data/wallet.json \ -e LINERA_KEYSTORE/data/keystore.json \ -e LINERA_STORAGErocksdb:/data/client.db \ -v $OUT/wallet:/data \ -v $PWD:/repo \ linera-test /linera $ } # linera-bridge CLI (its image entrypoint is the relayer; override it). docker-linera-bridge() { docker run --rm \ -v $OUT:/shared \ --entrypoint linera-bridge \ linera-bridge $ } # Extract a deployed address from a forge broadcast file by contract name: # deployed_addr ScriptFile.s.sol ContractName deployed_addr() { docker-foundry jq -r .transactions[]|select(.contractName\$2\)|.contractAddress broadcast/$1/$EVM_CHAIN_ID/run-latest.json } # Convert a 0x EVM address to the JSON byte array the Linera apps expect. addr_to_bytes() { local h${1#0x} out i for (( i0; i${#h}; i2 )); do out$out,$(( 16#${h:$i:2} )); done echo [${out#,}] }然后探测 EVM 链 ID后续步骤与 broadcast 路径都要用到export EVM_CHAIN_ID$(docker-foundry cast chain-id --rpc-url $RPC_URL) echo EVM chain id: $EVM_CHAIN_ID说明docker-foundry的入口是sh -c所以整个命令是一个字符串$RPC_URL、$EVM_PRIVATE_KEY等变量是在容器内部展开的通过-e转发进去。deployed_addr依赖 broadcast 文件的固定路径broadcast/脚本/chainId/run-latest.json链 ID 目录由此处的$EVM_CHAIN_ID决定而合约名匹配用jq过滤.transactions[] | select(.contractName...)。addr_to_bytes把0x十六进制地址逐字节转成 Linera 应用期望的 JSON 字节数组。第 1 步生成委员会参数Linera → LightClient 构造 JSON查询 faucet把LightClient的创世构造参数验证者地址、权重、admin 链、epoch、以及 pause-guardian/proposer 角色写入$OUT/light-client-args.jsondocker-linera-bridge init-light-client \ --faucet-url $FAUCET_URL \ --output /shared/light-client-args.json \ --pause-guardian $PAUSE_GUARDIAN \ --proposer $PROPOSER从源码看这个子命令linera-bridge/src/main.rs会向 faucet POST 一条 GraphQL 查询{ currentCommittee { validators } currentEpoch genesisConfig }用validator_evm_address把每个验证者的公钥推导成 EVM 地址从genesisConfig中找出ChainOrigin::Root(0)的 admin 链 ID最终产出包含validators、weights、admin_chain_id、epoch、pause_guardian、proposer的 JSON 文件。生成参数时请使用你信任的 faucet因为 LightClient 在创世时是“信任式”接收委员会信息的。第 2 步部署 LightClientEVMexport LIGHT_CLIENT_ARGS_JSON_FILE/shared/light-client-args.json docker-foundry forge script script/DeployLightClient.s.sol \ --rpc-url $RPC_URL --private-key $EVM_PRIVATE_KEY --broadcast export LIGHT_CLIENT_ADDRESS$(deployed_addr DeployLightClient.s.sol LightClient) echo LightClient: $LIGHT_CLIENT_ADDRESS部署脚本 DeployLightClient.s.sol 用 forge-std 的vm.readFile读取LIGHT_CLIENT_ARGS_JSON_FILE指向的 JSON该路径必须在 foundry.toml 的fs_permissions白名单内——/shared已列入解析出验证者地址数组与uint64权重数组校验二者等长调用new LightClient(validators, weights, adminChainId, epoch, pauseGuardian, proposer)并在部署后断言adminChainId()与期望一致。若要在区块浏览器上验证合约可在forge命令后追加--verify --etherscan-api-key $KEY --verifier-url $URL参见各网络注意事项。第 3 步确定 ERC-20 tokenEVM复用已有 ERC-20最常见的情况——设置其地址然后直接从合约读取decimals()保证包装应用与它不会产生小数位漂移export TOKEN_ADDRESS0x... # existing ERC-20 on THIS network export TOKEN_DECIMALS$(docker-foundry cast call $TOKEN_ADDRESS decimals()(uint8) --rpc-url $RPC_URL) echo Token $TOKEN_ADDRESS has $TOKEN_DECIMALS decimals一定要在当前网络上核验该地址确有代码——主网地址或 EOA在这里会返回0x而 relayer 后续对它的decimals()查询会直接中止docker-foundry cast code $TOKEN_ADDRESS --rpc-url $RPC_URL | head -c 12; echo # 0x → not a contract here, stop…或部署全新的LineraToken——此时由你选择新 token 的小数位同一个值同时喂给 token 与包装应用保证二者匹配。这些TOKEN_*变量只有DeployLineraToken读取所以只在这一步显式传-e而不是塞进共享包装函数export TOKEN_NAMELineraToken TOKEN_SYMBOLLIN TOKEN_DECIMALS18 \ TOKEN_SUPPLY1000000000000000000000 docker run --rm \ -v $PWD/linera-bridge/src/solidity:/contracts -w /contracts \ -e RPC_URL -e EVM_PRIVATE_KEY \ -e TOKEN_NAME -e TOKEN_SYMBOL -e TOKEN_DECIMALS -e TOKEN_SUPPLY \ foundry-jq forge script script/DeployLineraToken.s.sol \ --rpc-url $RPC_URL --private-key $EVM_PRIVATE_KEY --broadcast export TOKEN_ADDRESS$(deployed_addr DeployLineraToken.s.sol LineraToken) echo Token: $TOKEN_ADDRESS ($TOKEN_DECIMALS decimals)第 4 步申请桥链Lineradocker-linera wallet init --faucet $FAUCET_URL docker-linera wallet request-chain --faucet $FAUCET_URL --set-default--set-default让新链成为钱包默认链这样下面两步publish-and-create它们没有--chain-id参数就自动指向它。从request-chain输出中复制64 位十六进制 chain id第一行与0x…owner第二行export BRIDGE_CHAIN_ID64-hex chain id export BRIDGE_CHAIN_OWNER0x64-hex owner第 5 步发布 wrapped-fungible 应用Lineradocker-linera sync || true docker-linera process-inbox || true export WRAPPED_PARAMS{\ticker_symbol\:\$TICKER_SYMBOL\,\decimals\:$TOKEN_DECIMALS,\mint_chain_id\:\$BRIDGE_CHAIN_ID\,\evm_token_address\:$(addr_to_bytes $TOKEN_ADDRESS),\evm_source_chain_id\:$EVM_CHAIN_ID} docker-linera publish-and-create \ /repo/examples/target/wasm32-unknown-unknown/release/wrapped_fungible_contract.wasm \ /repo/examples/target/wasm32-unknown-unknown/release/wrapped_fungible_service.wasm \ --json-parameters $WRAPPED_PARAMS \ --json-argument {accounts:{}}复制打印出的 64 位十六进制应用 IDexport WRAPPED_APP_ID64-hex app idWRAPPED_PARAMS中通过addr_to_bytes把 EVM token 地址编码为字节数组并带上 EVM 源链 ID——这两个字段让 wrapped-fungible 应用与某条具体 EVM 链上的具体 token 绑定。第 6 步发布 evm-bridge 应用Lineradocker-linera sync || true docker-linera process-inbox || true export BRIDGE_PARAMS{\source_chain_id\:$EVM_CHAIN_ID,\token_address\:$(addr_to_bytes $TOKEN_ADDRESS),\bridge_chain_id\:\$BRIDGE_CHAIN_ID\,\fungible_app_id\:\$WRAPPED_APP_ID\} export BRIDGE_ARG{\rpc_endpoint\:\\} # Fill in with EVM endpoint when Linera network is allowed to query it docker-linera publish-and-create \ /repo/linera-bridge/contracts/evm-bridge/target/wasm32-unknown-unknown/release/evm_bridge_contract.wasm \ /repo/linera-bridge/contracts/evm-bridge/target/wasm32-unknown-unknown/release/evm_bridge_service.wasm \ --json-parameters $BRIDGE_PARAMS \ --json-argument $BRIDGE_ARG \ --required-application-ids $WRAPPED_APP_ID复制打印出的 64 位十六进制应用 IDexport BRIDGE_APP_ID64-hex app id注意--required-application-ids $WRAPPED_APP_IDevm-bridge 应用显式声明依赖 wrapped-fungible 应用两个应用的发布必须按此顺序执行。BRIDGE_ARG中的rpc_endpoint先留空待 Linera 网络允许查询该 EVM 端点后再填入这也是 HTTP 白名单 提到的前提。第 7 步部署 FungibleBridgeEVM这是唯一不走docker-foundry包装函数的一步构造函数入参以显式-e传入并且应用 ID / 链 ID 需要补上 Linera 侧值没有的0x前缀docker run --rm \ -v $PWD/linera-bridge/src/solidity:/contracts -w /contracts \ -e RPC_URL -e EVM_PRIVATE_KEY \ -e LIGHT_CLIENT$LIGHT_CLIENT_ADDRESS \ -e TOKEN_ADDRESS$TOKEN_ADDRESS \ -e BRIDGE_CHAIN_ID0x$BRIDGE_CHAIN_ID \ -e FUNGIBLE_APP_ID0x$WRAPPED_APP_ID \ -e BRIDGE_APP_ID0x$BRIDGE_APP_ID \ -e PAUSE_GUARDIAN -e PROPOSER -e CANCELLER -e TIMELOCK_DELAY \ foundry-jq forge script script/DeployFungibleBridge.s.sol \ --rpc-url $RPC_URL --private-key $EVM_PRIVATE_KEY --broadcast export BRIDGE_ADDRESS$(deployed_addr DeployFungibleBridge.s.sol FungibleBridge) echo FungibleBridge: $BRIDGE_ADDRESS部署脚本 DeployFungibleBridge.s.sol 会先部署一个FungibleBurnEventDecoderV1用于解码当前 BurnEvent 模式的初始解码器后续 schema 变更通过setDecoder替换再以lightClient、chainId、token、fungibleAppId、bridgeAppId、decoder、pauseGuardian、proposer、canceller、timelockDelay十个参数构造FungibleBridge并做部署后断言lightClient 与 decoder 地址回读一致。因此治理地址与 timelock 在部署时就被固化进合约请使用你控制的地址最好是多签。第 8 步两侧交叉注册Linera在 wrapped 应用上授权桥再在 evm-bridge 应用中记录 FungibleBridge 地址。两个操作都运行在桥链上。操作字节是 BCS 变体标签 负载08evm-bridge app id表示RegisterAuthorizedCaller02 20 字节 EVM 地址表示RegisterFungibleBridge。# wrapped-fungible: RegisterAuthorizedCaller(evm-bridge app id) docker-linera execute-operation \ --application-id $WRAPPED_APP_ID \ --operation 08$BRIDGE_APP_ID \ --chain-id $BRIDGE_CHAIN_ID # evm-bridge: RegisterFungibleBridge(FungibleBridge address) export BRIDGE_ADDR_HEX$(echo ${BRIDGE_ADDRESS#0x} | tr A-Z a-z) docker-linera execute-operation \ --application-id $BRIDGE_APP_ID \ --operation 02$BRIDGE_ADDR_HEX \ --chain-id $BRIDGE_CHAIN_ID这两项注册都是set-once的对已注册的桥再次执行会在应用层报错——这是预期行为。从安全设计看见 linera-bridge/README.md 的 Security analysis这两项注册均受访问控制且不可被抢先注册front-runLinera 侧要求链 owner 的认证签名EVM 侧registerFungibleApplicationId仅限部署者。第 9 步可选给测试账户注资以试桥不要预先给 FungibleBridge 注资。它不持有自有浮存——它是被存款 1:1 抵押的deposit()把发送者的 ERC-20 锁入桥_safeTransferFrom(msg.sender, address(this), …)同时 evm-bridge 应用在 Linera 侧铸造包装代币Linera 侧销毁后正好把锁定量释放回去_safeTransfer(target, …)。因此每笔提款都有对应的历史存款背书——桥上没有需要“打底”的东西。你真正需要的是一个持有 ERC-20 的 EVM 账户来做第一笔存款复用 token如 Base Sepolia USDC从 token 自己的 faucet如 Circle 的 Base Sepolia USDC faucet领取测试币到你将要发起桥接的账户。全新LineraToken部署者持有全部供给——转一些给测试账户export RECIPIENT0x... # the account youll deposit from export SEED_AMOUNT100000000000000000000 # 100 LIN at 18 decimals docker run --rm -e RPC_URL -e EVM_PRIVATE_KEY foundry-jq \ cast send $TOKEN_ADDRESS transfer(address,uint256) $RECIPIENT $SEED_AMOUNT \ --rpc-url \$RPC_URL --private-key \$EVM_PRIVATE_KEY第 10 步生成 relayer 环境文件# Deploy block seeds the relayers start block (hex → decimal). RAW_BLOCK$(docker-foundry jq -r .receipts[0].blockNumber broadcast/DeployFungibleBridge.s.sol/$EVM_CHAIN_ID/run-latest.json) export MONITOR_START_BLOCK$(( RAW_BLOCK )) cat $OUT/relayer.env EOF # Relayer env for the $NETWORK bridge deployment. # Wallet paths are CONTAINER paths: bind-mount the host $OUT/wallet at /data. # EVM_PRIVATE_KEY is intentionally NOT written here — supply it separately. RPC_URL$RPC_URL FAUCET_URL$FAUCET_URL EVM_BRIDGE_ADDRESS$BRIDGE_ADDRESS LINERA_BRIDGE_APP$BRIDGE_APP_ID LINERA_FUNGIBLE_APP$WRAPPED_APP_ID LINERA_BRIDGE_CHAIN_ID$BRIDGE_CHAIN_ID LINERA_BRIDGE_CHAIN_OWNER$BRIDGE_CHAIN_OWNER LINERA_WALLET/data/wallet.json LINERA_KEYSTORE/data/keystore.json LINERA_STORAGErocksdb:/data/client.db MONITOR_SCAN_INTERVAL30 MONITOR_START_BLOCK$MONITOR_START_BLOCK MAX_RETRIES10 # eth_getLogs chunk size — match your RPCs max getLogs range. 2000 works with the # public Base Sepolia RPC; raise it for providers that allow larger ranges. Alchemys # free tier caps at 10 (impractical) — use the public RPC or a paid plan. MAX_LOG_BLOCK_RANGE10 PORT3001 EOF echo Wrote $OUT/relayer.env cat $OUT/relayer.env这份relayer.env与 docker/Dockerfile.bridge 中声明的环境变量一一对应RPC_URL等为必需项PORT、MONITOR_SCAN_INTERVAL、MONITOR_START_BLOCK、MAX_RETRIES、MAX_LOG_BLOCK_RANGE以及各缓存大小BLOB_CACHE_SIZE、CONFIRMED_BLOCK_CACHE_SIZE、CERTIFICATE_CACHE_SIZE等均有默认值默认MAX_LOG_BLOCK_RANGE2000可在 linera-bridge/src/main.rs 的--max-log-block-range参数中看到其语义单次eth_getLogs查询的最大区块跨度受 RPC 提供方范围上限约束。LINERA_BRIDGE_CHAIN_ID与LINERA_BRIDGE_CHAIN_OWNER是linera-bridge serve的参数见 main.rs。部署结果一览输出位置LightClient(EVM)$LIGHT_CLIENT_ADDRESSFungibleBridge(EVM)$BRIDGE_ADDRESSToken (EVM)$TOKEN_ADDRESSevm-bridge(Linera)$BRIDGE_APP_IDwrapped-fungible(Linera)$WRAPPED_APP_ID桥链 id / owner$BRIDGE_CHAIN_ID/$BRIDGE_CHAIN_OWNER桥链钱包$OUT/wallet/—务必备份Relayer 环境文件$OUT/relayer.env运行 relayer同一个linera-bridge镜像负责运行 relayer。它直接消费relayer.env从/data绑定挂载读取桥链钱包EVM_PRIVATE_KEY从环境取刻意不写进relayer.env。不需要 GCP 或 compose 栈——只需docker rundocker run -d --name linera-relay \ --env-file $OUT/relayer.env \ -e EVM_PRIVATE_KEY \ -v $OUT/wallet:/data \ -p 3001:3001 \ linera-bridge镜像入口会根据这些环境变量拼出linera-bridge serve命令relayer.env已把LINERA_WALLET/LINERA_KEYSTORE/LINERA_STORAGE指向/data/...-p与它的PORT3001对应bridge-entrypoint.sh中会用${RPC_URL:?...}形式强校验必需变量未设置直接报错退出。检查它是否起来并同时在扫描两条链docker logs -f linera-relay # follow startup curl -sI http://127.0.0.1:3001/health | head -1 # HTTP/1.1 200 OK curl -s http://127.0.0.1:3001/metrics | grep ^linera_bridge_ | head停止并删除docker rm -f linera-relay重跑上面的docker run即可重启——钱包与 relay 状态持久化在$OUT/wallet/。relayer 在 EVM 侧签名addBlock交易因此EVM_PRIVATE_KEY账户必须在目标网络持有 gas。如果linera_bridge_evm_balance_wei指标偏低充值即可无需重启。在 VM 上把 relayer 作为长期服务运维GCP Secret Manager 管密钥、Prometheus 告警、备份等参见 docker/README.testnet.md。另外 linera-bridge/Makefile 也提供了make -C linera-bridge relayer-up目标它会在启动前强制校验RPC_URL、EVM_BRIDGE_ADDRESS、LINERA_BRIDGE_APP、LINERA_FUNGIBLE_APP、EVM_PRIVATE_KEY五个必需变量缺少任一即报错并打印用法。治理角色PAUSE_GUARDIAN—— 可以在LightClient/桥侧紧急暂停区块注册治理角色不能动用资金。PROPOSER—— 把关LightClient上的委员会-epoch 维护expireEpochsBelow并在FungibleBridge上提出 timelock 变更。CANCELLER—— 可取消FungibleBridge上待执行的 timelock 变更必须与 proposer 不同。TIMELOCK_DELAY—— 已入队的FungibleBridge治理变更在真正执行前必须等待的秒数。请使用你控制的地址理想情况下是多签。它们在部署时被固化进合约第 2、7 步。各网络注意事项网络EVM RPC浏览器验证 URLBase Sepoliahttps://sepolia.base.orghttps://api-sepolia.basescan.org/apiEthereum Sepolia一个 Sepolia RPChttps://api-sepolia.etherscan.io/apiBase / Ethereum 主网一个主网 RPCbasescan/etherscan 的…/api主网几乎总是复用已有 ERC-20第 3 步第一种选项。桥不需要注入流动性——它由存款抵押见第 9 步。若要验证合约在forge命令后追加--verify --etherscan-api-key KEY --verifier-url URL。这些验证端点在 foundry.toml 的[rpc_endpoints]/[etherscan]段中也有对应配置键值从环境变量读取不落盘。HTTP 白名单evm-bridge应用验证 EVM 存款最终性的方式是从 Linera 验证者内部调用配置的 RPC 端点EVM_RPC_ENDPOINT_FOR_LINERA。该主机名必须在验证者的 HTTP 请求白名单中否则存款会以UnauthorizedHttpRequest失败该错误类型定义于 linera-execution/src/lib.rs由执行层在请求未被授权时抛出。上线前请先与网络运营方协调。安全说明部署者在创世时是被信任的。LightClient的构造函数无条件接收创世委员会此后委员会变更必须通过认证过的CreateCommittee证书。请从你信任的 faucet 生成参数。注册是 set-once第 8 步且受访问控制——没有链 ownerLinera 侧或部署者EVM 侧的密钥注册无法被抢先执行。保护好$OUT/。它持有桥链钱包。丢失钱包 失去对桥链的控制无恢复手段——重新部署意味着一条全新的桥。该目录已被 gitignore请安全备份。本 runbook 全程不会把密钥落盘。EVM_PRIVATE_KEY从你的 shell 环境转发进容器从不写入relayer.env。把它排除在 shell 历史之外是你的责任例如用read -rs EVM_PRIVATE_KEY。补充一点桥本身的安全边界详见 linera-bridge/README.md 的 Security analysiswrapped-fungible 的Mint操作要求调用方必须是已注册的 evm-bridge 应用authenticated_caller_id必须匹配参数中的bridge_app_id桥链 owner 也不能直接铸造FungibleBridge._onBlock只处理内嵌在已认证 Linera 区块证书中的BurnEvent且Microchain拒绝重复区块提交因此 EVM 侧释放必然对应 Linera 侧的真实销毁。唯一的“全量沦陷”场景是 Linera 验证者法定人数按权重 2/3被攻破——这是 BFT 协议的固有信任假设与桥本身无关。故障排查症状可能原因处理容器内/shared为空$OUT不在 Docker 共享路径下把$OUT放在仓库内不要/tmpcannot reach EVM RPCRPC_URL错误 / 网络不通docker-foundry cast chain-id --rpc-url $RPC_URL自检forge读不到参数文件委员会参数不在/shared重跑第 1 步LIGHT_CLIENT_ARGS_JSON_FILE/shared/light-client-args.jsonvm.readFile权限拒绝路径超出fs_permissions参数文件必须在/shared下已在 foundry.toml 白名单publish-and-create失败 / 找不到 Wasm模块未构建make -C linera-bridge build-wasm检查前置条件里的lsdeployed_addr打印为空$EVM_CHAIN_ID或合约名错误确认$EVM_CHAIN_IDbroadcast 目录是broadcast/脚本/chainId/存款失败UnauthorizedHttpRequestRPC 主机未加入白名单见 HTTP 白名单Relayereth_getLogs ... exceeds max block range/ 10 区块限制RPC 限制getLogs范围把relayer.env中MAX_LOG_BLOCK_RANGE降到 ≤ RPC 上限公共 Base Sepolia 为 2000并重启Alchemy 免费层10不实用——改用公共 RPC 或付费套餐延伸阅读桥的整体架构、证书验证原理与安全分析linera-bridge/README.mdrelayer 长期运维Secret Manager、告警、备份docker/README.testnet.md本地演示Docker Anvil 本地验证者 前端examples/bridge-demo/README.md构建入口与常用目标make -C linera-bridge build-all、build-wasm、relayer-up见 linera-bridge/Makefile【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考