尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Substrate区块链开发框架实战:从节点模板到自定义链的完整指南

发布时间:2026/9/25 9:24:14

资讯中心
01
ARTICLE

Substrate区块链开发框架实战:从节点模板到自定义链的完整指南

Substrate区块链开发框架实战:从节点模板到自定义链的完整指南
1. 从一条命令行说起substrate 到底在解决什么问题第一次接触 substrate 是在一个需要快速验证链上业务逻辑的项目里。当时团队面临一个很现实的问题从零搭一条链光是 P2P 网络、共识、状态存储、交易池这些底层模块就够折腾两三个月业务代码一行没写人已经累趴了。后来有人甩过来一个 substrate 的节点模板改了几行配置一条能出块、能查状态、能发交易的链就跑起来了。那一刻我才真正理解它存在的意义——它不是一条链而是一套用来造链的框架。substrate 是 Parity 团队开源的一套区块链开发框架用 Rust 写成。它的核心价值在于把区块链的通用能力网络通信、共识机制、状态数据库、交易队列、RPC 接口、治理模块等全部封装成可复用的组件开发者只需要专注写自己业务相关的“运行时逻辑”。你可以把它理解成造车时的底盘和动力总成发动机、变速箱、悬挂都给你调好了你要做的是决定这辆车是拉货还是载客内饰怎么设计。它适合谁我梳理了三类人。第一类是想快速验证业务模型的创业者或产品团队不需要从零造轮子几天内就能跑出一条具备完整功能的链来做概念验证。第二类是想深入理解区块链底层原理的开发者substrate 的模块化设计把每个子系统都拆得很清楚读它的源码比读白皮书直观得多。第三类是需要定制化链的企业或组织比如要做联盟链、专用链substrate 允许你自由替换共识、调整出块时间、定制治理规则灵活性远超直接 fork 一条现成的公链。这篇文章我会从整体设计思路讲到具体实操包括环境搭建、运行时开发、节点启动、常见问题排查。不管你是刚听说 substrate 的新手还是已经跑过节点但卡在某个环节的老手应该都能从里面找到能直接用的东西。2. 整体设计思路拆解为什么 substrate 要这么设计2.1 模块化架构背后的取舍逻辑substrate 最核心的设计哲学就是模块化。整个系统被拆成两层外层是节点node负责网络、共识、存储、RPC 这些“脏活累活”内层是运行时runtime负责业务逻辑也就是“这条链到底在干什么”。为什么要这么分我举个实际例子你就明白了。假设你做了一个供应链溯源的链业务逻辑是记录商品从工厂到消费者的流转信息。某天业务方说我们想加一个积分奖励机制消费者扫码验证后给积分。如果链是铁板一块你得改底层代码、重新编译、全网升级风险极大。但在 substrate 里你只需要在 runtime 里加一个 pallet模块编译成新的 Wasm 文件通过链上治理升级即可节点软件本身不用动。这个设计的精妙之处在于runtime 被编译成 WebAssemblyWasm字节码存储在链上。这意味着链的逻辑本身是可以进化的而且升级过程不需要硬分叉。我第一次看到这个机制的时候确实愣了一下——把业务逻辑放在链上用 Wasm 执行节点只负责调度和验证这个思路把“链的升级”从技术问题变成了治理问题。当然这个设计也有代价。Wasm 的执行效率比原生代码低所以 substrate 在关键路径上做了优化比如用原生执行做缓存、只在需要共识的时候才跑 Wasm。另外runtime 的开发门槛比写普通后端高你得理解存储、事件、 extrinsic外部交易这些概念。但总体来说这个取舍是值得的尤其是对于需要长期演进的链来说。2.2 FRAME把模块化做到极致如果说 substrate 的模块化架构是骨架那 FRAMEFramework for Runtime Aggregation of Modularized Entities就是血肉。FRAME 是一套开发 runtime 的框架和库提供了一系列预置的 pallet比如System pallet所有链的基础管理账户、区块、事件、 extrinsic 的索引。Balances pallet代币余额管理转账、冻结、预留。Consensus pallet共识相关的逻辑比如 Aura、BABE、GRANDPA 的接口。Governance pallet链上治理提案、投票、执行。Staking pallet质押和验证人选举。这些 pallet 可以像搭积木一样组合。你要做一条代币链就把 System Balances Consensus Governance 拼起来要做一条 NFT 链就加上 NFT pallet要做跨链消息传递就加上 XCM 相关的 pallet。我个人的经验是不要一上来就想着自己写 pallet。先把官方和社区提供的 pallet 过一遍大概率你要的功能已经有了。比如我做供应链项目的时候本来想自己写一个商品登记的模块后来发现官方有个pallet-uniques可以直接用省了一周的工作量。FRAME 的生态已经相当丰富OpenZeppelin 也有 substrate 版本的合约库很多轮子真的不用重复造。2.3 共识机制的可插拔设计substrate 另一个让我觉得设计得很聪明的地方是共识机制的可插拔。它把共识分成两部分区块生产block authoring和区块最终确认finality。区块生产可以用 Aura轮流出块、BABE基于槽位的出块、或者你自己实现的机制。最终确认可以用 GRANDPA拜占庭容错的最终性工具、或者直接不要最终性比如纯 PoW 链。这种分离设计的好处是你可以根据业务需求灵活组合。举个例子如果你做的是联盟链节点数量少、信任度高可以用 Aura 出块 GRANDPA 最终确认出块时间调到 3 秒甚至 1 秒交易确认速度比很多公链快得多。如果你做的是开放的 PoS 链可以用 BABE GRANDPA让更多节点参与出块。如果你要做一条测试链甚至可以用--dev模式单节点出块秒级确认开发体验极佳。这种灵活性在传统区块链开发里是很难想象的。大多数链的共识是写死的你要改就得硬分叉。substrate 把共识变成了一个可配置项这是它作为“造链框架”的核心竞争力之一。3. 核心细节解析与实操要点3.1 环境搭建Rust 工具链和依赖的坑substrate 用 Rust 开发所以第一步是装 Rust 工具链。这里有几个坑我踩过提前说清楚。首先不要用系统自带的 Rust。Ubuntu 的 apt 源里的 Rust 版本通常很旧substrate 需要比较新的 stable 版本。正确做法是用 rustup 安装curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env rustup update stable其次Wasm 编译目标必须装。substrate 的 runtime 要编译成 Wasm所以需要wasm32-unknown-unknown目标rustup target add wasm32-unknown-unknown第三系统依赖不能少。在 Ubuntu 上需要装这些sudo apt update sudo apt install -y build-essential clang curl git libssl-dev llvm libudev-dev make protobuf-compiler我印象最深的一次踩坑是在一台干净的服务器上编译 substrate 节点模板报了一堆链接错误最后发现是libssl-dev没装。还有一次是protobuf-compiler版本太旧导致编译失败。这些依赖看起来琐碎但缺一个就卡住建议一次性装齐。提示如果你在国内网络环境下拉取 crates.io 的依赖比较慢可以配置镜像源。在~/.cargo/config.toml里加上镜像配置能显著提升下载速度。具体镜像地址可以搜一下最新的可用源。3.2 节点模板最快的上手路径环境准备好之后最快的上手方式是直接用官方提供的节点模板git clone https://github.com/substrate-developer-hub/substrate-node-template cd substrate-node-template cargo build --release第一次编译会比较久我实测在 8 核 16G 的机器上大概 20 到 30 分钟。编译完成后用开发模式启动./target/release/node-template --dev--dev模式会启动一个单节点链自动出块状态存在临时目录重启就重置。这个模式特别适合开发调试你不需要关心网络、共识、存储这些底层东西专注写 runtime 逻辑就行。启动后你会看到类似这样的输出2024-01-15 10:30:00 Substrate Node 2024-01-15 10:30:00 ✌️ version 0.1.0-abc1234-x86_64-linux-gnu 2024-01-15 10:30:00 ❤️ by Substrate DevHub, 2017-2024 2024-01-15 10:30:00 Chain specification: Development 2024-01-15 10:30:00 Node name: nice-unicorn-1234 2024-01-15 10:30:00 Role: AUTHORITY 2024-01-15 10:30:00 Database: RocksDb at /tmp/substrate12345/chains/dev/db 2024-01-15 10:30:00 ⛓ Native runtime: node-template-100 (node-template-1.tx1.au1) 2024-01-15 10:30:00 Initializing Genesis block/state 2024-01-15 10:30:00 Creating empty BABE epoch changes on what appears to be first startup 2024-01-15 10:30:00 Local node identity is: 12D3KooW... 2024-01-15 10:30:00 Operating system: linux 2024-01-15 10:30:00 CPU architecture: x86_64 2024-01-15 10:30:00 Highest known block at #0 2024-01-15 10:30:00 Running JSON-RPC server: addr127.0.0.1:9944 2024-01-15 10:30:06 Starting consensus session on top of parent ... 2024-01-15 10:30:06 Prepared block for proposing at 1 ... 2024-01-15 10:30:06 ✨ Imported #1看到Imported #1就说明链跑起来了。这时候你可以打开 Polkadot.js Apps一个网页版的钱包和区块浏览器连接到ws://127.0.0.1:9944就能看到区块在持续生成也能发交易、查状态。3.3 Runtime 开发从改一个 pallet 开始节点模板跑起来之后下一步就是改 runtime。我建议从修改现有的 pallet 开始而不是一上来就写新的。节点模板里有一个pallet-template里面有一个简单的do_something函数。你可以试着改一下它的逻辑比如加一个计数器每次调用就加一。改完之后重新编译cargo build --release然后重启节点用 Polkadot.js Apps 的 Extrinsics 页面调用这个函数观察状态变化。这里有个关键点runtime 的升级不需要重启节点。在开发模式下你编译出新的 Wasm 之后可以通过sudo调用system.setCode来升级 runtime。这个机制在生产环境里通常配合治理流程使用但在开发阶段你可以直接用它来快速迭代。我个人的经验是runtime 开发最需要注意的是存储设计。substrate 的存储是键值对每个 pallet 有自己的存储前缀。设计存储结构的时候要考虑哪些数据需要上链哪些可以放链下。存储项的读写频率高频读写的项要考虑缓存。存储项的删除逻辑避免状态膨胀。举个例子我做供应链项目的时候商品信息是上链的但商品图片是放 IPFS 的链上只存哈希。这样既保证了数据的可验证性又避免了链上存储被大文件撑爆。3.4 交易生命周期从发起到上链理解 substrate 的交易生命周期对排查问题很有帮助。一笔交易从发起到最终上链大致经过这几个阶段构造交易客户端用私钥签名构造一个 extrinsic。提交到交易池通过 RPC 接口提交交易进入节点的交易池。交易池验证节点检查签名、nonce、余额、手续费等。区块生产出块节点从交易池里挑选交易打包成区块。区块执行runtime 执行区块里的交易更新状态。区块导入区块被其他节点验证并导入最终确认。这个流程里最容易出问题的是第 3 步和第 5 步。第 3 步的常见问题是 nonce 不匹配、余额不足、手续费设置太低。第 5 步的常见问题是 runtime 逻辑报错比如除零、溢出、权限不足。排查的时候我一般先看节点的日志输出。substrate 的日志级别可以通过-l参数调整比如-l runtimedebug可以看到 runtime 执行的详细日志。另外Polkadot.js Apps 的“Chain State”和“Extrinsics”页面也能看到交易的状态和错误信息。4. 实操过程与核心环节实现4.1 从零搭建一条自定义链的完整流程假设我们要做一条简单的“积分链”功能是用户可以注册账户管理员可以给用户发放积分用户可以互相转账积分。我按这个需求走一遍完整流程。第一步准备节点模板git clone https://github.com/substrate-developer-hub/substrate-node-template cd substrate-node-template cargo build --release第二步设计 runtime 的 pallet 组合我们需要这些 palletpallet-system基础必须有。pallet-timestamp时间戳出块需要。pallet-balances代币余额积分可以用它来实现。pallet-sudo管理员权限用于测试。pallet-template自定义逻辑我们改造成积分管理。在runtime/src/lib.rs里这些 pallet 的配置已经大部分就绪我们主要改pallet-template。第三步改造 pallet-template打开pallets/template/src/lib.rs把原来的do_something改成积分发放逻辑#[pallet::call_index(0)] #[pallet::weight(10_000)] pub fn issue_points( origin: OriginForT, account: T::AccountId, amount: u32, ) - DispatchResult { let sender ensure_signed(origin)?; // 检查是否是管理员 ensure!(sender T::Admin::get(), Error::T::NotAdmin); // 发放积分 let current Points::T::get(account); let new_balance current.checked_add(amount).ok_or(Error::T::Overflow)?; Points::T::insert(account, new_balance); Self::deposit_event(Event::PointsIssued { account, amount }); Ok(()) }这里我用了checked_add而不是直接因为 Rust 在 release 模式下溢出是 wrapping 的不会 panic但会导致逻辑错误。用checked_add可以显式处理溢出返回错误。第四步配置存储和事件在 pallet 里定义存储项#[pallet::storage] #[pallet::getter(fn points)] pub type PointsT: Config StorageMap_, Blake2_128Concat, T::AccountId, u32, ValueQuery;定义事件#[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum EventT: Config { PointsIssued { account: T::AccountId, amount: u32 }, }第五步编译和测试cargo build --release ./target/release/node-template --dev启动后用 Polkadot.js Apps 连接到ws://127.0.0.1:9944在 Extrinsics 页面选择template-issuePoints填入账户和金额提交交易。然后在 Chain State 页面查询template.points(account)就能看到积分余额。4.2 参数计算出块时间和区块大小的权衡出块时间和区块大小是两个需要仔细权衡的参数。出块时间太短网络延迟可能导致节点频繁分叉出块时间太长交易确认慢用户体验差。我一般按这个思路来定开发/测试链出块时间 1 到 3 秒区块大小限制放宽方便快速迭代。联盟链出块时间 3 到 6 秒区块大小适中兼顾吞吐和稳定性。公链出块时间 6 到 12 秒区块大小根据网络带宽和节点性能调整。在 substrate 里出块时间由pallet-aura或pallet-babe的配置决定。以 Aura 为例在runtime/src/lib.rs里impl pallet_aura::Config for Runtime { type AuthorityId AuraId; type DisabledValidators (); type MaxAuthorities ConstU32100; type AllowMultipleBlocksPerSlot ConstBoolfalse; }出块时间实际上是由SLOT_DURATION常量控制的pub const MILLISECS_PER_BLOCK: u64 6000; pub const SLOT_DURATION: u64 MILLISECS_PER_BLOCK;改成 3000 就是 3 秒出块。但要注意改这个值之后所有节点的配置都要同步否则会出现时间不一致的问题。区块大小限制在pallet-system的配置里impl frame_system::Config for Runtime { type BlockWeights RuntimeBlockWeights; type BlockLength RuntimeBlockLength; // ... }RuntimeBlockWeights定义了区块的最大权重可以理解为计算量RuntimeBlockLength定义了区块的最大字节数。这两个值需要根据实际业务调整太小会导致交易打包不进去太大可能导致节点处理不过来。4.3 网络配置从单节点到多节点开发模式下是单节点但真实场景需要多节点组网。substrate 的节点启动参数里网络相关的有这几个--chain指定链规格文件可以是dev、local、staging或者自定义的 JSON 文件。--bootnodes指定引导节点新节点通过它加入网络。--portP2P 监听端口默认 30333。--rpc-portRPC 端口默认 9944。--ws-portWebSocket 端口默认 9944新版本可能合并到 rpc-port。--validator标记为验证人节点。--name节点名称方便在日志里识别。启动一个多节点本地测试网可以这样做# 节点 1引导节点 ./target/release/node-template \ --chain local \ --alice \ --port 30333 \ --rpc-port 9944 \ --validator \ --name Alice # 节点 2 ./target/release/node-template \ --chain local \ --bob \ --port 30334 \ --rpc-port 9945 \ --validator \ --bootnodes /ip4/127.0.0.1/tcp/30333/p2p/12D3KooW... \ --name Bob--alice和--bob是预置的测试账户对应的私钥是公开的只能用于测试。生产环境要用自己的密钥通过--keystore或者环境变量配置。注意多节点组网时时间同步很重要。如果节点之间的时钟偏差太大会导致共识失败。建议所有节点都配置 NTP 时间同步。5. 常见问题与排查技巧实录5.1 编译类问题速查编译问题是新手最容易卡住的地方。我整理了一个速查表问题现象可能原因解决方法error: linker cc not found缺少 C 编译器安装build-essentialerror: failed to run custom build command for openssl-sys缺少 OpenSSL 开发库安装libssl-deverror: no matching package named wasm32-unknown-unknown缺少 Wasm 目标rustup target add wasm32-unknown-unknownerror: failed to compile parity-wasmRust 版本太旧rustup update stable编译到一半内存不足机器内存不够增加 swap 或换更大内存的机器error: could not find protoc缺少 protobuf 编译器安装protobuf-compiler我印象最深的一次是编译到 90% 的时候 OOM内存不足被 kill 掉。substrate 编译峰值内存能到 8G 以上如果机器只有 4G 内存基本必挂。解决办法是加 swapsudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile或者用cargo build --release -j 2限制并行编译任务数降低内存峰值。5.2 运行时错误排查Runtime 错误通常表现为交易失败但错误信息可能比较隐晦。我的排查思路是第一步看节点日志。用-l runtimedebug启动节点能看到 runtime 执行的详细日志包括每个 extrinsic 的执行结果和错误码。第二步看 Polkadot.js Apps 的事件。交易失败时事件里会有system.ExtrinsicFailed里面包含错误模块和错误码。比如balances.InsufficientBalance就是余额不足。第三步对照错误定义。每个 pallet 都有自己的Error枚举在源码里能找到对应的错误定义。比如pallet-template里的Error::T::NotAdmin就说明调用者不是管理员。常见的 runtime 错误和原因错误原因解决system.ExtrinsicFailedBadOrigin调用者权限不足检查 origin 和权限逻辑balances.InsufficientBalance余额不足充值或降低金额system.ExtrinsicFailedNonceTooLownonce 重复等待前一笔交易确认system.ExtrinsicFailedPriorityTooLow手续费太低提高 tip 或手续费template.Overflow数值溢出检查计算逻辑用 checked 运算5.3 网络和共识问题多节点组网时常见的问题是节点连不上、不出块、分叉。节点连不上检查--bootnodes的地址是否正确P2P 端口是否开放防火墙是否拦截。可以用telnet或nc测试端口连通性。不出块检查验证人节点是否正常启动密钥是否正确配置时间是否同步。如果只有一个验证人它挂了就没人出块了。分叉通常是网络延迟导致的。如果分叉持续存在可能是共识配置有问题比如出块时间太短、节点时钟偏差太大。GRANDPA 最终确认能解决大部分分叉问题但如果分叉深度超过最终确认的阈值就需要手动干预了。我踩过的一个坑是在本地测试网上两个节点用同一套密钥启动导致双重签名被惩罚机制踢出验证人集合。每个验证人节点必须用独立的密钥这是铁律。5.4 存储和状态问题substrate 的状态存储在 RocksDB 里随着链的运行数据库会越来越大。如果不做清理磁盘很快会被撑爆。几个实用的技巧定期清理旧区块用--pruning参数控制状态保留策略。默认是256保留最近 256 个区块的状态。如果要归档全状态用--pruning archive但磁盘占用会很大。监控数据库大小du -sh /path/to/db可以看数据库大小。如果增长异常快可能是某个 pallet 的存储设计有问题比如无限增长的 StorageMap。状态迁移runtime 升级时如果存储结构变了需要做状态迁移。substrate 提供了on_runtime_upgrade钩子可以在升级时执行迁移逻辑。提示状态迁移是高风险操作一定要在测试网上充分验证。迁移逻辑写错可能导致链的状态损坏无法恢复。6. 工具链与生态哪些轮子可以直接用6.1 开发工具推荐substrate 的生态已经比较成熟有几个工具我几乎每个项目都会用Polkadot.js Apps网页版的区块浏览器和钱包连接节点后可以查状态、发交易、看事件。开发调试必备。subxtRust 写的客户端库可以在 Rust 程序里和 substrate 链交互。适合写自动化测试和链下服务。substrate-api-client另一个 Rust 客户端库功能更底层一些。Zombienet用来启动和管理多节点测试网的工具支持复杂的网络拓扑适合做集成测试。Chainhammer压力测试工具可以测链的 TPS 和延迟。我个人的习惯是开发阶段用 Polkadot.js Apps 做手动测试写集成测试用 subxt压测用 Chainhammer。这套组合基本覆盖了从开发到测试的全流程。6.2 常用 pallet 清单除了官方提供的 pallet社区也有很多高质量的 pallet 可以直接用Pallet功能适用场景pallet-balances代币余额几乎所有链pallet-assets多资产需要发行多种代币的链pallet-uniquesNFT数字收藏品、凭证pallet-identity身份需要实名或认证的场景pallet-democracy治理链上投票、提案pallet-staking质押PoS 链的验证人选举pallet-contracts智能合约需要兼容 Wasm 合约的链pallet-evmEVM 兼容需要跑 Solidity 合约的链pallet-xcm跨链消息需要和其他链交互的场景我特别想提一下pallet-contracts和pallet-evm。如果你想让链支持智能合约这两个 pallet 可以让你省掉大量底层工作。pallet-contracts支持 Wasm 合约pallet-evm支持 Solidity 合约。两者可以同时启用让链同时支持两种合约环境。6.3 从模板到生产还需要做什么节点模板能跑起来和能上生产中间还有不小的距离。我梳理了几个必须做的步骤安全审计runtime 代码要经过专业审计尤其是涉及资产、权限、治理的逻辑。自己写的 pallet 一定要仔细检查边界条件。性能优化开发模式下性能不是问题但生产环境要考虑 TPS、延迟、存储增长。需要做压力测试找出瓶颈。监控告警节点需要监控 CPU、内存、磁盘、网络、出块状态。Prometheus Grafana 是常用组合substrate 节点可以暴露 metrics 接口。灾备恢复验证人节点要有备份密钥要有安全的存储方案。如果节点挂了要能快速恢复。治理配置链上治理的参数提案押金、投票周期、通过阈值要根据实际情况调整。测试网可以宽松一些主网要严格。经济模型如果链有代币经济模型要设计好。通胀率、手续费、质押奖励这些参数直接影响链的长期健康。我个人的体会是从模板到生产工作量至少是开发 runtime 的两倍。很多人低估了运维和治理的复杂度结果链跑起来了但没人用或者出了问题不知道怎么处理。substrate 给了你造链的能力但造出来的链能不能活取决于你对业务和生态的理解。7. 我踩过的那些坑和总结的经验说几个我实际踩过的坑都是文档里不会写的。第一个坑runtime 升级时的存储迁移。有一次我改了一个存储项的类型从u32改成u64编译通过了但升级后链直接起不来。原因是旧数据是u32编码的新代码按u64解码直接 panic。后来我学乖了改存储结构一定要写迁移逻辑在on_runtime_upgrade里把旧数据读出来、转换、写回去。第二个坑Wasm 和原生执行的不一致。substrate 在出块时用原生执行在验证时用 Wasm 执行。如果两者行为不一致会导致区块验证失败。我遇到过一次是因为用了浮点数运算原生和 Wasm 的浮点实现有细微差异。后来我定了个规矩runtime 里不用浮点数所有计算用整数。第三个坑交易池拥堵。有一次做压测交易池瞬间被塞满节点内存暴涨。原因是交易池没有限制大小默认配置下可以无限增长。后来我在节点启动参数里加了--pool-limit和--pool-kbytes限制交易池的大小。第四个坑时间同步。多节点测试网上有一个节点的时钟慢了 30 秒导致它出的块被其他节点拒绝。排查了半天才发现是 NTP 没配好。所有节点必须配置时间同步这是共识正常工作的前提。第五个坑密钥管理。开发阶段用--alice、--bob很方便但生产环境绝对不能用。我见过有人把测试密钥用到生产环境结果资产被转走。生产环境的密钥要用硬件钱包或 KMS 管理绝对不能明文存在节点服务器上。最后分享一个我觉得很实用的技巧用 Zombienet 做集成测试。它可以一键启动一个多节点网络模拟真实的出块、交易、升级场景。我每次改完 runtime都会用 Zombienet 跑一遍集成测试确认没有回归问题再上测试网。这个习惯帮我避免了好几次线上事故。substrate 这个框架入门容易精通难。它的模块化设计让你能快速搭出一条链但要真正用好需要理解它的存储模型、共识机制、治理逻辑、经济模型。我建议新手不要贪多先把节点模板跑起来改一个简单的 pallet发一笔交易看它上链。然后逐步深入理解每一层在做什么。这个过程可能需要几周甚至几个月但一旦打通你会发现造链这件事真的没有想象中那么遥不可及。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。