区块链应用与工程实践:从数字资产、交易所到 BaaS、供应链与 Tinychain

区块链真正进入工程实践后,问题很快就从“区块如何连接、共识如何工作”扩展到资产如何表示、交易所如何记账、钱包如何管理多条链、链上数据如何索引、身份和供应链怎样接入,以及一个最小区块链节点究竟由哪些模块组成。本文从数字资产出发,逐步串联交易平台、钱包服务、BaaS、数字身份、供应链和 Tinychain 实现,形成一套从业务应用到基础设施、再回到底层节点设计的完整区块链工程视角。

从“区块链能记账”走向“区块链能承载什么”

理解区块链应用时,一个很容易出现的误区,是把注意力始终放在区块、哈希、PoW、P2P 网络这些底层技术上。

这些当然重要,但真正进入业务世界之后,更重要的问题会变成:

  • 账本上究竟记录什么?
  • 记录的对象是货币、资产、身份,还是供应链事件?
  • 资产交换是在链上完成,还是在链下完成?
  • 哪些数据必须全网共识,哪些数据根本不应该上链?
  • 谁持有私钥?
  • 谁负责把现实世界的信息转换成链上的可信事实?
  • 一个互联网系统如何稳定地接入多条区块链?
  • 当吞吐量、隐私和监管要求与“完全去中心化”发生冲突时,应该怎么取舍?

这也是区块链从底层协议向应用基础设施发展的关键一步。

本文涉及的原始技术背景主要形成于 2018 年前后的区块链生态,因此 EOS、NEO、NEP-5、EtherDelta、早期 0x 等项目名称更适合作为理解当时设计思想的历史案例,而不是今天直接照搬的技术选型清单。真正值得保留下来的,是它们背后的几个长期问题:资产如何表达、账本如何分层、链上和链下如何协同、私钥如何管理,以及多主体之间究竟需要什么样的信任模型。

从数字货币到数字资产

比特币最先让区块链的“价值传输”能力被大规模看见,但数字货币并不是区块链能够表达的全部内容。

更一般地说,当一个对象可以在数字系统中被唯一标识、确定所有权或者控制权,并按照一套规则进行转移时,它就具备了成为数字资产的基础。

原生资产和资产数字化不是一回事

讨论数字资产时,最好先区分两个概念。

**原生数字资产(Native Digital Asset)**从诞生开始就存在于数字协议之中。比特币就是最典型的例子:BTC 的发行、所有权、转移和验证规则全部由比特币网络定义,它不存在一个必须在链外找到的“BTC 实物”。

另一种情况是把现实世界中的资产表示到链上,例如房产、提单、债权、艺术品、会员权益等。此时链上的 Token 更准确地说,是某种资产凭证、权利主张或者数字表示

这两者的差别非常重要:

1
2
3
4
5
6
7
8
9
原生数字资产
资产本身 = 协议中的状态

现实资产数字化
链上 Token / 凭证

指向某项链外权利或资产

还需要登记机构、托管方、法律关系或其他外部机制保证对应关系

区块链可以证明“某个 Token 从 A 转移给了 B”,但它无法凭空证明现实世界中的一颗钻石是真是假,也无法自动证明某栋房产在法律上属于谁。

上链解决的是登记、流转和可验证性问题,不会自动解决现实资产本身的鉴真问题。

这条边界贯穿数字资产、数字身份和供应链三个领域。

原生数字货币与锚定型数字货币

从经济关系上,可以把早期数字货币粗略分成两类。

类型 核心特征 价值来源
原生数字货币 不直接锚定某种链外资产 网络规则、稀缺性和社会共识
锚定型数字货币 与法币或其他资产建立兑换/储备关系 储备资产、发行机制和承兑能力

比特币属于前者,而早期的 Tether、bitCNY 等,则体现了第二种思路。

锚定型数字货币试图解决的是一个很现实的问题:原生加密资产价格波动很大,而商业支付、结算和计价更需要稳定的价值尺度。

因此,从系统设计角度看,稳定资产通常承担的并不是“重新发明一个比特币”的角色,而是承担:

  • 计价单位;
  • 交易媒介;
  • 清算媒介;
  • 不同数字资产之间的流动性桥梁。

Token 是数字资产的一种可编程表达

智能合约让资产不再只是数据库中的一个余额字段,而可以携带可执行规则。

从生态角色来看,可以把 Token 粗略分成三类。

基础设施型 Token

这类 Token 与底层网络本身直接相关,例如支付 Gas、参与网络治理、抵押或者获得某些基础设施使用权。

早期以太坊的 Ether、NEO、EOS 等经常被放在这一类别中讨论。

它们同时可能具有货币属性,因为它们往往也是底层生态中最通用的交换媒介。

金融型 Token

金融型 Token 的重点不是提供底层计算能力,而是为资产提供:

  • 流动性;
  • 计价;
  • 结算;
  • 抵押;
  • 交易场所中的某些权益。

稳定资产以及早期交易平台发行的 Token 都曾被归入这一范围。

需要注意,“在经济属性上接近证券”并不意味着法律上天然就是或不是证券。Token 的法律属性取决于具体发行方式、权利结构和司法辖区,不能仅靠技术形式判断。

商业垂直生态 Token

还有一种思路,是围绕具体商业网络建立数字权益,例如:

  • 游戏;
  • 内容社区;
  • 会员体系;
  • 数字版权;
  • 某个产业协作网络。

它希望 Token 不只是积分,而成为连接生产者、消费者、平台和合作伙伴的价值媒介。

这种设计真正困难的部分通常不在于“写一个 ERC-20 合约”,而在于:

为什么这个生态需要一个可自由转移、可编程的资产,而不是普通数据库积分?

如果这个问题回答不了,Token 很容易只是给传统积分换了一个区块链外壳。

三类 Token 的依赖关系

早期生态中有一个很有启发性的判断:

1
2
3
4
5
商业垂直生态型 Token

├─────────────┐
↓ ↓
基础设施型 Token ← 金融型 Token

商业应用通常需要底层链提供安全、共识和结算能力;金融型 Token 同样依赖基础设施;商业生态有时还会进一步依赖稳定资产或者其他金融 Token 完成计价和结算。

因此往往呈现一种反向关系:

1
2
3
4
5
流动性:
基础设施型 > 金融型 > 垂直商业型

种类数量:
垂直商业型 > 金融型 > 基础设施型

这并不是严格的经济学定律,更适合把它理解为一种生态结构判断:底层基础设施少而通用,上层应用多而垂直。

数字资产交易所到底在做什么

区块链资产如果不能交换,就很难形成流动性。

因此数字资产交易平台逐渐成为区块链世界与传统互联网、金融系统接触最深的基础设施之一。

但很多人第一次使用中心化交易所时,会产生一个非常典型的误解:

我在交易所里买了 1 BTC,是不是区块链立刻产生了一笔 Bitcoin Transaction?

通常不是。

理解交易所,必须先分清金融交易 Trade区块链交易 Transaction

场内交易和场外交易

交易方式首先可以分成两大类。

**场内交易(Exchange Trading)**由交易场所聚合买卖双方,参与者提交订单,再由撮合系统按照规则成交。

交易场所通常会参与:

  • 订单管理;
  • 撮合;
  • 结算;
  • 资产托管;
  • 行情发布;
  • 风险控制。

**场外交易(OTC)**则更强调买卖双方直接形成交易对手关系,交易平台可能主要提供报价、担保、撮合或者信息服务。

中心化数字资产交易所主要采用前一种模式。

传统证券交易体系和数字资产交易所的区别

传统证券体系通常存在这样的角色链:

flowchart LR
    U[投资者] --> B[证券公司 / 券商]
    B --> E[证券交易所]
    E --> C[登记结算机构]
    C --> B
    B --> U
    R[监管机构] --> E
    R --> B

普通投资者通常不会直接连接证券交易所,而是通过券商完成开户、委托和查询;资金、证券登记、撮合等职责被多个机构拆分。

早期数字资产交易所则明显更加扁平:

flowchart LR
    U1[用户 A] --> EX[数字资产交易所]
    U2[用户 B] --> EX
    U3[用户 C] --> EX

    EX --> BTC[Bitcoin]
    EX --> ETH[Ethereum]
    EX --> OTHER[其他区块链]

交易所自己往往同时承担:

  • 用户账户;
  • 数字资产托管;
  • 内部账本;
  • 撮合;
  • 结算;
  • 钱包;
  • 充提币;
  • 行情;
  • KYC;
  • 风控。

这也是中心化交易所效率很高,但风险高度集中的原因。

中心化、半中心化和去中心化

从哪些模块被放到链上,可以把交易平台粗略理解成三个方向。

模式 撮合 资产托管/结算 特征
中心化交易所 链下 交易所托管,链下内部结算 性能高、体验好,但平台风险集中
混合/半中心化 链下 链上或用户自行托管 在性能与资产控制之间折中
去中心化交易 链上或去中心化协议 链上 降低托管风险,但受到链性能、流动性和交互成本约束

2018 年曾经用 0x、Kyber Network、EtherDelta、BitShares 等项目说明这些方向。今天具体协议已经发生很大变化,但这种按撮合和结算分别判断中心化程度的方法依然很有价值。

所谓“去中心化交易所”也不是一个开关。

真正应该问的是:

1
2
3
4
5
6
7
8
订单保存在哪里?
价格发现在哪里?
撮合在哪里?
资产由谁保管?
签名在哪里完成?
结算在哪里完成?
行情由谁生产?
前端和 RPC 又由谁提供?

一个系统完全可能在某些层去中心化,而在其他层保持中心化。

中心化交易所最关键的设计:两套账本

数字资产交易所与普通互联网交易系统最大的不同之一,就是它同时面对两种账本:

1
2
3
4
5
6
7
8
区块链账本
Bitcoin
Ethereum
...
↕ 充值 / 提现
交易所内部账本

用户账户

这两套账本彼此独立。

Trade 和 Transaction 不是同一个“交易”

在交易所内部:

1
2
3
4
5
6
7
8
9
用户下单

订单进入 Order Book

撮合成功

生成 Trade

修改内部持仓

整个过程可以完全不产生任何区块链 Transaction。

只有当资产真正从交易所控制的链上地址流入或者流出时,才需要区块链交易。

所以:

1
2
3
4
5
Trade
= 金融市场中的成交

Transaction
= 区块链账本中的状态转移

这是理解中心化交易所的第一原则。

用户余额实际上是交易所的内部负债

假设用户向交易所充值 1 BTC。

链上看到的是:

1
2
3
用户链上地址
↓ 1 BTC
交易所控制的地址

当交易所确认到账以后,内部数据库可能记录:

1
2
3
user_id = 10001
asset = BTC
balance = 1.00000000

此时用户页面上显示的“1 BTC”已经不是一个独立属于该用户的链上 UTXO,而是交易所内部账本对用户的负债记录。

所以中心化托管模型本质上是:

1
2
3
交易所链上资产

所有用户内部负债总和

如果两者严重不一致,平台就会出现偿付风险。

这也是为什么中心化交易所的安全不仅仅是“数据库别丢”,还包括:

  • 链上储备;
  • 内部账务;
  • 钱包私钥;
  • 提现权限;
  • 运营流程;
  • 风控;
  • 审计。

交易所的四大后端系统

一个较完整的中心化交易平台,至少可以拆成四个主要系统。

flowchart LR
    C[Web / App / API Client] --> W[Web 业务系统]
    C --> WS[行情 WebSocket]

    W --> M[交易撮合系统]
    W --> A[资金管理系统]
    W --> O[运营后台]

    M --> DB[(交易与订单存储)]
    A --> LEDGER[(持仓 / 内部账本)]
    A --> WG[Wallet Gateway]

    WG --> BTC[Bitcoin Node]
    WG --> ETH[Ethereum Node]
    WG --> OTHER[Other Chains]

    O --> A
    O --> W

Web 业务系统

面向用户,负责:

  • 注册和登录;
  • 账户管理;
  • API;
  • KYC;
  • 2FA;
  • 安全策略;
  • 订单入口;
  • 行情展示;
  • 通知。

它与常规互联网业务系统非常接近,重点是可扩展性和安全性。

撮合系统

这是交易平台的计算核心。

它需要处理:

  • 买单簿;
  • 卖单簿;
  • 价格优先;
  • 时间优先;
  • 部分成交;
  • 完全成交;
  • 撤单;
  • 成交事件。

撮合引擎追求的是:

确定性、低延迟、高吞吐和可重放。

早期架构资料经常使用 Redis 等内存系统来表达“撮合不能频繁访问磁盘”的思想。真正进入生产环境后,更重要的不是某一个中间件名称,而是确保订单进入撮合核心以后拥有严格的顺序,并能通过日志或者事件流恢复状态。

运营后台

运营系统不是简单的“管理页面”。

它往往负责:

  • KYC 审核;
  • 提现审核;
  • 风控处置;
  • 币种维护;
  • 钱包状态;
  • 手续费配置;
  • 用户冻结;
  • 账务核对;
  • 异常告警;
  • 运营数据。

交易所发展到一定规模以后,运营后台通常会成为安全边界的一部分,因此需要比普通管理后台更严格的网络隔离、权限模型和操作审计。

资金管理系统

资金管理系统才是数字资产交易平台与普通互联网交易系统区别最大的地方。

它至少包括:

1
2
3
4
资金管理
├── 法币支付/结算
├── 用户内部持仓账本
└── 数字货币钱包服务

这里既要维护内部余额,又要处理真正的区块链资产。

一笔交易为什么通常不上链

假设 A 希望用 BTC 买入某种资产 X。

业务过程可以简化成:

sequenceDiagram
    participant A as 用户 A
    participant W as Web 系统
    participant L as 资金账本
    participant M as 撮合引擎
    participant B as 用户 B

    A->>W: 提交 X/BTC 买单
    W->>L: 冻结 A 的 BTC
    W->>M: Buy Order

    B->>W: 提交 X/BTC 卖单
    W->>L: 冻结 B 的 X
    W->>M: Sell Order

    M->>M: 撮合
    M-->>W: Trade

    W->>L: A: BTC↓ X↑
    W->>L: B: X↓ BTC↑

这里发生的是内部账本变化。

没有任何链上 Transaction。

原始案例随后使用“某用户再把资产提到外部钱包”解释链上流程,其中角色和提取币种存在前后表述不完全一致的问题。真正需要掌握的是核心机制:只有当任一用户将内部余额兑换为真正的链上控制权时,交易所才需要发起链上 Transaction。

提币过程

sequenceDiagram
    participant U as 用户
    participant W as Web/API
    participant R as 风控/运营
    participant L as 内部账本
    participant WG as Wallet Service
    participant BC as Blockchain

    U->>W: 提币请求
    W->>R: 风控 / KYC / 2FA 检查
    R->>L: 冻结可提余额
    R->>WG: 创建提币任务
    WG->>BC: 构造、签名并广播 Transaction
    BC-->>WG: txid
    WG-->>W: Broadcasting

    BC-->>WG: 区块确认
    WG->>L: 完成账务扣减
    WG-->>W: Completed

这才会真正改变区块链状态。

充值过程

充值过程刚好相反:

sequenceDiagram
    participant U as 用户钱包
    participant BC as Blockchain
    participant S as Block Scanner
    participant L as 内部账本
    participant W as Web

    U->>BC: 转账到交易所充值地址
    BC-->>S: 新区块
    S->>S: 解析 Transaction
    S->>S: 匹配充值地址

    loop 等待规定确认数
        BC-->>S: 新区块
    end

    S->>L: 增加用户内部余额
    L-->>W: 余额可用

早期交易所实践经常把这种策略概括成“宽进严出”:充值更多依赖自动扫块,提现则需要更严格的风控和安全审批。

为什么钱包服务不能只是“跑一个全节点”

如果应用规模很小,直接调用 Bitcoin Core、Ethereum Client 等节点 RPC 就可以完成很多工作。

但交易平台一旦拥有大量用户,问题马上出现。

全节点首先是共识网络节点,并不是为百万级业务查询优化的数据库。

例如业务系统可能频繁查询:

1
2
3
4
5
6
这个地址有没有充值?
这笔交易确认了多少个块?
某个区块是否发生重组?
用户所有历史充值是什么?
某个币种当前同步高度是多少?
最近是否出现异常大额交易?

如果全部直接压向钱包节点,性能、稳定性和风险控制都会变得困难。

因此出现了非常重要的一层基础设施:Block Scanner / Blockchain Indexer。

数字钱包到底可以怎么分类

钱包这个词本身非常容易产生歧义。

它既可能表示一个手机 App,也可能表示一套私钥服务,还可能表示完整区块链节点。

可以从几个不同维度理解。

按客户端形态

1
2
3
4
Mobile
PC
Web / Cloud
Hardware

很多所谓“在线钱包”的客户端实际上只是代理,真正的私钥和钱包服务运行在服务器端。

按币种

1
2
单币种钱包
多币种钱包

多币种又可以继续分:

1
2
3
4
5
同一条链上的多个 Token
例如 Ethereum + ERC-20

多条异构链
例如 Bitcoin + Ethereum + ...

第二种明显更加复杂,因为不同链在:

  • 地址模型;
  • 交易模型;
  • Gas/Fee;
  • 确认机制;
  • 分叉;
  • RPC;
  • 签名算法

上可能完全不同。

按私钥控制权

早期资料中有时使用 On-chain Wallet 和 Off-chain Wallet 描述私钥是否由平台托管。

为了避免与“链上交易/链下交易”混淆,今天更容易理解的叫法是:

1
2
3
4
5
6
7
Non-custodial Wallet
非托管钱包
用户控制私钥

Custodial Wallet
托管钱包
平台控制私钥

这是钱包设计中比 UI 形态更重要的区别。

Whoever controls the private key controls the asset.

钱包真正保护的并不是“币”,而是能够授权资产转移的私钥或者签名能力

单签、多签与多人审批

还可以按照控制策略划分:

1
2
3
Single Signature
Multi-Signature
M-of-N Approval

对于企业资金管理,只依赖单个人的一把私钥往往风险过高。

因此生产系统还会进一步考虑:

  • 多签;
  • HSM;
  • MPC;
  • 多级审批;
  • 冷热分层;
  • 限额;
  • 操作审计。

这些具体实现不断演进,但背后的目标没有变化:避免单点私钥失窃直接导致全部资产丢失。

Block Scan:把区块链变成业务可以查询的数据库

全节点通常使用自己的嵌入式存储,例如 LevelDB、Berkeley DB 或其他数据库,但这些结构是为了节点自身运行而设计的。

业务系统真正需要的是:

1
2
3
SELECT ...
FROM transactions
WHERE address = ?

这就是扫块技术存在的原因。

扫块的基本过程

flowchart LR
    N[Full Node] --> RPC[JSON-RPC]
    RPC --> S[Block Scanner]

    S --> B[(block)]
    S --> T[(transaction)]
    S --> I[(input)]
    S --> O[(output)]
    S --> A[(address/index)]

    B --> API[Query API]
    T --> API
    I --> API
    O --> API

    API --> EX[交易所]
    API --> BE[区块浏览器]
    API --> APP[业务系统]

扫描器从某个区块高度开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
height = 0

getblock(height)

解析 Header

解析 Transactions

解析 Input / Output

写入结构化数据库

height++

以 UTXO 类型区块链为例,可以建立这样的关系:

1
2
3
4
5
6
7
8
block
│ block_height

transaction
│ tx_hash
├───────────┐
↓ ↓
tx_input tx_output

一个简化的关系型设计可以是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CREATE TABLE block (
height BIGINT PRIMARY KEY,
hash CHAR(64) NOT NULL,
previous_block_hash CHAR(64),
merkle_root CHAR(64),
timestamp BIGINT,
tx_count INT
);

CREATE TABLE tx (
id BIGINT PRIMARY KEY,
block_height BIGINT,
hash CHAR(64) NOT NULL
);

CREATE TABLE tx_output (
id BIGINT PRIMARY KEY,
tx_id BIGINT,
output_index BIGINT,
value BIGINT,
address VARCHAR(128),
asset VARCHAR(64)
);

CREATE TABLE tx_input (
id BIGINT PRIMARY KEY,
tx_id BIGINT,
prev_tx_id BIGINT,
prev_out_index BIGINT
);

真正困难的地方并不是“解析 JSON”,而是:

索引数据库必须正确处理链重组。

为什么 Reorg 是扫块系统的核心问题

假设本地已经同步:

1
1000 -> 1001A -> 1002A

随后节点发现网络最终接受的是:

1
1000 -> 1001B -> 1002B -> 1003B

那么 1001A1002A 就变成孤立分支。

索引器不能继续假装它们仍然属于主链。

因此至少需要保存:

1
2
3
4
height
hash
previous_hash
canonical / orphan 状态

处理方式可以是:

  • 将孤块移动到 fork 表;
  • 在原表上标记 canonical=false
  • 回滚受影响的派生状态;
  • 从共同祖先重新同步。

所以生产级区块索引系统本质上不是简单 ETL,而是一个能够理解区块链最终性和重组的状态同步系统

区块浏览器其实就是扫块服务的一个产品形态

区块浏览器看起来是一个 Web 页面,实际上核心结构并不神秘:

1
2
3
4
5
6
7
8
9
全节点

Block Scanner

结构化数据库

Query API

Web UI

用户输入:

1
2
3
Block Hash
Transaction Hash
Address

系统就能够查询:

  • 交易是否已经进入区块;
  • 当前确认数;
  • 输入输出;
  • 资产变化;
  • 区块高度;
  • 时间;
  • 链上活动统计。

所以从工程角度看,区块浏览器也是一种区块链数据服务

它的重要性在于把原本适合节点程序处理的数据,变成普通互联网系统能够消费的数据。

Wallet Service:为业务系统统一多条链

当系统只支持一条链时,业务系统直接调用节点 RPC 尚可接受。

当币种越来越多时,如果业务系统分别理解:

1
2
3
4
5
Bitcoin RPC
Ethereum RPC
Chain A RPC
Chain B RPC
...

架构很快就会失控。

因此更合理的方式是增加钱包服务层。

flowchart LR
    EX[交易平台] --> API[统一 Wallet API]

    API --> M[Monitoring]
    API --> ADAPTER[Wallet Adapter Layer]
    API --> DB[(区块索引库)]
    DB --> BK[(Backup)]

    ADAPTER --> BTC[BTC Adapter]
    ADAPTER --> ETH[ETH Adapter]
    ADAPTER --> X[Other Adapter]

    BTC --> BN[Bitcoin Node]
    ETH --> EN[Ethereum Node]
    X --> XN[Other Node]

    BN --> BC1[Bitcoin Network]
    EN --> BC2[Ethereum Network]
    XN --> BC3[Other Network]

上层业务最好看到统一接口,例如:

1
2
3
4
5
6
7
8
createAddress()
getBalance()
getTransaction()
getBlockHeight()
estimateFee()
createWithdrawal()
broadcast()
getConfirmations()

而不同链的复杂性由 Adapter 层吸收。

这样才能把:

区块链协议差异

转化成:

普通后端服务接口差异。

BaaS:把区块链变成可以集成的基础服务

沿着 Wallet Service 再往上抽象,自然会出现 Blockchain as a Service(BaaS)。

可以用一个很简单的类比理解:

1
2
3
4
5
6
7
8
IaaS
提供计算、存储、网络资源

PaaS
提供数据库、消息、缓存等应用基础能力

BaaS
提供节点、交易、区块、身份、资产等区块链能力

为什么 BaaS 更像 PaaS

一个业务系统希望支持区块链支付,如果没有 BaaS,可能需要自己完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
下载完整节点

同步全部区块

持续运维节点

处理升级/分叉

自行扫块

建设查询数据库

建设交易广播 API

建设监控系统

而真正的业务需求可能只是:

1
2
3
4
5
6
7
POST /transactions

GET /transactions/{txid}

GET /addresses/{address}

GET /blocks/{height}

这正是 PaaS 思路最擅长解决的问题:把复杂基础设施封装成稳定服务。

一套 BaaS 可以提供什么

从公链集成角度,可以把它拆成:

flowchart TB
    APP[业务应用]

    APP --> API[BaaS API Layer]

    API --> QUERY[区块 / 交易查询]
    API --> BROADCAST[交易广播]
    API --> VERIFY[交易验证]
    API --> ID[身份 / 凭证服务]
    API --> ASSET[数字资产服务]

    QUERY --> IDX[(Blockchain Index)]
    BROADCAST --> NODE[Node Cluster]
    VERIFY --> NODE
    NODE --> BC[Blockchain Network]

最核心的能力通常包括:

  • 节点托管;
  • 区块查询;
  • Transaction 查询;
  • 广播;
  • 确认数跟踪;
  • 地址服务;
  • 多链 Adapter;
  • 索引;
  • 监控;
  • 身份验证;
  • 某些数字资产能力。

BaaS 和联盟链平台不要混为一谈

早期资料中还区分过一种“BTaaS”思路:

1
2
3
4
5
BaaS
更强调使用已有公链服务

BTaaS / DLT Platform
更强调帮助企业部署自己的联盟链

这种命名并不是今天所有厂商都遵循的行业标准,但背后的架构区别非常值得保留:

1
2
3
使用开放网络已有的共识和资产
vs
自己组织参与者建立许可网络

选择哪种方式,最终仍然取决于信任边界。

BaaS 真正难的不是“启动 Docker”

真正棘手的是两个问题。

系统级私钥安全

一旦服务可以代表用户或者企业签名,它就直接控制真实资产。

因此必须明确:

1
2
3
4
5
6
7
8
谁能调用签名?
谁能导出私钥?
签名机是否联网?
是否支持审批?
是否可以审计?
单次/单日限额是多少?
密钥如何备份?
故障后如何恢复?

区块链服务必须稳定且可观察

区块链节点可能遇到:

  • 同步落后;
  • 节点宕机;
  • 网络隔离;
  • 链重组;
  • 软件升级;
  • 硬分叉;
  • RPC 异常;
  • Peer 数量异常。

因此 BaaS 不能只提供“一个 RPC 地址”。

它还应该具备:

1
2
3
4
5
6
7
Health Check
Height Lag Monitor
Peer Monitor
Fork/Reorg Detection
RPC Failover
Alerting
Audit Log

这也是为什么区块链真正成为企业基础设施以后,会越来越像传统分布式系统工程。

从互联网账号走向数字身份

区块链还有一个很自然的应用方向:身份。

比特币给出的启发是:

链上的资产不会凭空存在,它一定归属于某个能够提供有效签名的地址。

那么进一步的问题就是:

能不能让一个密码学身份不仅代表地址,还承载人与各种客观事实之间的关系?

身份不是身份证

身份证、护照、驾照都只是凭证。

真正的“身份”实际上分散存在于大量机构中:

1
2
3
4
5
6
7
8
公安系统
医院
银行
学校
社交平台
电商平台
政府机构
...

它们记录:

  • 出生;
  • 教育;
  • 就医;
  • 出入境;
  • 消费;
  • 社交;
  • 工作;
    -资产。

从这个角度看,身份可以抽象成:

与某个主体有关的一系列可验证事实和历史事件的集合。

身份技术经历了怎样的变化

可以把身份表达方式粗略看成三个阶段。

印章和实物身份

玉玺、印章、虎符,本质上都是利用某种难以复制的实物标识证明身份。

它能够表达的信息非常有限。

卡片型身份

身份证、驾照、护照、银行卡把更多身份属性写入凭证。

但问题仍然明显:

1
2
3
4
医院有医院的数据
银行有银行的数据
学校有学校的数据
出入境有出入境的数据

身份片段彼此割裂。

互联网身份

互联网平台开始将大量身份片段聚合。

OAuth、SSO、互联网实名认证等机制降低了重复认证成本,但也产生了新的集中化问题:

1
2
3
4
5
用户身份

大型身份提供者

大量第三方服务

一个平台一旦掌握:

  • 身份;
  • 社交;
  • 消费;
  • 行为;
  • 授权记录;

就会成为非常强的中心节点。

互联网身份的问题

可以归纳成三类。

身份并不真正由用户控制

账号能被:

  • 封禁;
  • 删除;
  • 撤销;
  • 修改权限。

用户通常只有平台账户的使用权,而不是身份基础设施本身的控制权。

数据安全与隐私问题

中心数据库成为天然的高价值攻击目标。

风险包括:

  • 泄漏;
  • 非授权使用;
  • 篡改;
  • 账号接管;
  • 身份冒用。

身份数据所有权和互操作问题

不同系统使用不同账户。

1
2
3
应用 A 注册一次
应用 B 再注册一次
应用 C 再做一次实名认证

每个平台都创建了一份新的身份副本。

于是形成:

1
2
Identity Silos
身份孤岛

区块链数字身份真正需要解决的是验证和授权

区块链身份如果只做“把身份证哈希写到链上”,价值非常有限。

一个完整身份体系至少需要处理两个基本动作。

Verification:验证

证明某项声明确实由可信主体签发。

例如:

1
2
3
某学校
↓ 签名
“此人获得某学位”

验证者不需要直接向学校数据库发起查询,也可以通过签名关系判断凭证是否有效。

Authorization:授权

身份所有者需要能够决定:

1
2
3
4
谁可以读取什么?
可以读取多久?
能否继续传播?
是否可以撤销?

区块链账户体系中的公私钥结构天然适合表达授权关系。

在今天的技术语境中,这类思想经常会落到 DID(Decentralized Identifier)和 Verifiable Credentials(可验证凭证)一类体系中。

但真正设计时必须坚持一个原则:

个人完整身份数据不应该因为使用区块链就全部公开上链。

链上更适合存:

  • 标识;
  • 公钥关系;
  • 凭证摘要;
  • 状态;
  • 撤销信息;
  • 必要证明。

大量个人原始数据仍然应保留在链外。

区块链不会自动证明“上链内容是真的”

这和供应链的物理世界问题完全一样。

例如:

1
2
某人声称:
“我毕业于 X 大学”

把这句话写入区块链,只能证明:

某个时刻确实有人把这句话写进去了。

真正让它具有可信度的是:

1
2
3
X 大学
↓ 使用可验证身份签名
凭证

因此第三方机构并不会因为区块链出现而消失。

变化的是:

过去用户每次都必须向中心机构实时查询;未来可以由机构签发可独立验证的凭证。

数字身份仍然面临三个硬问题

隐私边界

不可篡改和隐私天然存在张力。

个人敏感信息一旦明文永久写入公共账本,几乎无法真正删除。

数据规模

身份历史可以极其庞大。

区块链显然不适合保存:

1
2
3
4
所有医疗文件
全部照片
全部聊天记录
完整视频

因此必须采用链上证明、链外数据的分层方式。

与既有身份体系兼容

现实世界已经存在:

  • 身份证;
  • 护照;
  • 企业账号;
  • 银行身份;
  • OAuth;
  • 各类证书。

区块链身份不可能一夜之间替换这些体系。

真正可行的路径往往是逐步把既有身份转换成可验证声明

供应链为什么经常被认为适合区块链

供应链名字里虽然也有一个“链”,实际上它更像一张网络。

flowchart LR
    R1[原材料供应商] --> S1[一级供应商]
    R2[原材料供应商] --> S1
    S1 --> M[制造商]
    M --> W[批发商]
    W --> D1[经销商]
    W --> D2[经销商]
    D1 --> C1[消费者]
    D2 --> C2[消费者]

越复杂的产品,背后的参与企业通常越多。

而真正困难的不是画出网络,而是让这些彼此独立甚至互相竞争的组织共同维护一致事实。

供应链中的三条“流”

供应链管理最核心的三个对象分别是:

1
2
3
物流
信息流
资金流

大致关系是:

flowchart LR
    S[供应商] -->|物流| M[制造商]
    M -->|物流| D[分销商]
    D -->|物流| C[消费者]

    C -->|资金流| D
    D -->|资金流| M
    M -->|资金流| S

    S <-.信息流.-> M
    M <-.信息流.-> D
    D <-.信息流.-> C

物流通常向需求侧移动,资金流反方向返回,信息则需要整个网络共享。

问题是现实中这三条流长期由不同系统负责:

1
2
3
资金流 -> 银行 / 支付体系
信息流 -> ERP / SCM / EDI
物流 -> 物流公司 / 仓储 / IoT

数据因此容易被切割。

传统供应链的几个典型问题

核心企业控制范围有限

供应链可能有很多层:

1
2
3
4
5
6
7
核心企业

一级供应商

二级供应商

三级供应商

核心企业往往只能可靠看到最接近自己的几个层级。

数据可能不一致

参与者有自己的数据库、Excel、甚至纸质文件。

一个订单可能在多个系统中分别拥有一份状态。

信息存在篡改动机

上下游企业并不天然利益一致。

如果数据影响:

  • 付款;
  • 绩效;
  • 库存责任;
  • 质量责任;

参与者就可能存在修改数据的经济动机。

需求信息逐级失真

需求变化经过多个节点向供应侧传播时,可能出现明显放大。

这会进一步导致:

  • 错误排产;
  • 过量库存;
  • 缺货;
  • 资金占用。

供应链金融为什么更需要可信数据

供应链金融(Supply Chain Finance,SCF)的核心问题仍然是金融风险。

例如供应商拥有一笔核心企业应付账款:

1
2
3
供应商
↓ 应收账款
核心企业

如果银行确信:

1
2
3
4
订单是真实的
货物确实发出了
验收已经发生
应收账款没有重复融资

就更容易根据这笔资产提供融资。

所以供应链金融真正稀缺的并不仅仅是资金,而是:

可信、连续、可以审计的供应链事实。

区块链能够提供的是多主体共同确认的共享记录。

它不会消灭信用风险,但可以让风险判断依赖的数据更加透明。

区块链在供应链中最容易从物流切入

信息流已经有 ERP 和 SCM,资金流已经有银行体系。

物流反而是大量主体天然都需要看到的对象。

例如一个跨境集装箱可能经过:

1
2
3
4
5
6
7
8
9
10
11
12
13
托运方

货运代理

仓储

港口

海关

航运公司

目的港

如果出了问题,经常会出现:

1
2
“不是我这里的问题”
“交付给下一个环节以后就不知道了”

共享账本至少能够记录:

1
2
3
4
5
什么时候

把什么货物
交给了谁
状态是什么

这对追责和审计非常重要。

区块链不能直接感知现实世界

这也是所有所谓“区块链溯源”方案最应该明确的边界。

假设传感器报告:

1
2
3
4
{
"container": "C-10086",
"temperature": 3.2
}

区块链可以保证这条数据一旦写入以后不容易被修改。

但它不能自动证明:

1
2
3
4
传感器没有坏
传感器没有被替换
提交数据的人没有造假
设备确实装在那个集装箱里

因此完整方案还需要:

1
2
3
4
5
6
IoT
硬件身份
设备认证
可信数据采集
人员流程
审计

区块链只是其中的共享可信记录层

DLT:用联盟链重构供应链协作

供应链通常存在明确的企业参与者。

因此早期项目非常自然地采用 Distributed Ledger Technology(DLT)或者联盟链。

例如:

flowchart LR
    S[托运方] <--> F[货运中介]
    F <--> C[航运公司]
    C <--> B[银行]
    B <--> S

    DLT[(联盟账本)]
    S --- DLT
    F --- DLT
    C --- DLT
    B --- DLT

参与者不是匿名加入,而是通过许可成为网络成员。

自建 DLT

行业核心企业可以自己组织网络。

1
2
3
4
航运公司
银行
货运代理
大型托运企业

分别运行节点。

这样做最大的优势是:

  • 权限清晰;
  • 可控;
  • 数据可以只对指定成员开放;
  • 容易结合现有业务系统。

但这里并没有消灭信任。

它只是把:

1
“信任一个中心数据库”

转换成:

1
“信任联盟成员不会联合破坏规则”

使用第三方 DLT 平台

另一条路是使用云厂商或者第三方平台。

部署更简单,但新的问题是:

如果大部分关键节点仍然由平台运营,那么参与者实际上还需要信任平台。

因此不能因为底层用了区块链,就自动把架构描述成“无需信任”。

公链供应链:链下计算,链上验证

如果采用开放公链,供应链会遇到完全不同的约束。

最大的一个问题就是吞吐量。

例如跨境物流中的订单匹配本质上可能是高频计算:

1
2
3
4
5
6
7
货物重量
体积
目的地
出发时间
集装箱空间
温控要求
成本

没有必要把每一次候选组合全部放到链上执行。

更合理的架构是:

flowchart LR
    O[链上订单] --> OFF[链下撮合器]
    OFF --> P[候选运输方案]
    P --> V[参与方验证]
    V --> C[链上确认 / 承诺]

    IOT[IoT 数据] --> F[链下过滤/聚合]
    F --> KEY[关键状态]
    KEY --> C

这体现了一个非常重要的区块链工程原则:

昂贵的共识只处理真正需要全局验证的结果,不要把所有计算都塞进共识层。

大数据链下,关键证明链上

例如集装箱每秒产生温度:

1
2
3
4
5
3.1
3.2
3.1
3.3
...

全部上链既昂贵又没有必要。

可以改成:

1
2
3
4
5
6
7
原始传感器数据

链下数据库

分段聚合 / Hash

关键证明上链

这样既能保存详细数据,又能利用链上记录提供防篡改校验。

DLT 和公链应该怎么选

可以从几个维度理解。

维度 DLT / 联盟链 公链
参与者 明确、许可制 开放
权限控制 需要额外设计
隐私 更容易实现 公共数据必须谨慎
落地成本 容易与现有企业系统集成 业务改造通常更大
Token/开放资产 不是重点 天然适合
基础设施 联盟自行建设 可共享开放网络
治理 核心企业/联盟 协议和社区
信任边界 已知组织之间 更开放的网络

真正的选择标准不是“哪个更区块链”,而是:

1
2
3
4
5
6
7
8
参与者是不是已知的?
数据能不能公开?
谁拥有治理权?
是否需要公共流动性?
是否需要开放资产?
吞吐量多少?
需要怎样的最终性?
监管边界是什么?

在企业供应链场景中,两者甚至可能共存:

1
2
3
4
5
6
7
企业内部和合作伙伴

DLT

关键证明 / 资产接口

公链

从应用重新回到底层:自己搭一条 Tinychain

理解区块链最有效的方法之一,仍然是亲手实现一个最小节点。

目标不是复制 Bitcoin Core,而是把之前分散学习的:

1
2
3
4
5
6
7
8
9
P2P
交易
UTXO
区块
共识
挖矿
数据库
RPC
分叉

真正串起来。

Tinychain 的设计就是为此服务。

Tinychain 的功能边界

一个教学型全节点可以先实现七个基本能力:

  1. P2P 节点发现和区块同步;
  2. 创建公私钥对;
  3. 发送交易;
  4. 查询交易;
  5. 查询余额;
  6. 挖矿;
  7. 日志和状态监控。

再进一步拆解,就会发现至少需要处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
P2P 网络
节点管理
创世区块
区块同步
交易池
交易验证
UTXO
双花检查
区块验证
PoW
难度调整
分叉处理
持久化
私钥
地址
RPC
CLI

一个“简单区块链”很快就会变成真正的分布式系统工程。

Tinychain 的技术选型

原始 Tinychain 采用的是一个刻意追求易理解的教学技术栈。

模块 选择 原因
语言 C++14 接近底层区块链实现
API HTTP JSON-RPC 易调试
P2P 通信 WebSocket 复用 HTTP Server
序列化 JSON 可读性优先
数据库 SQLite3 简单
交易模型 UTXO 避免额外状态维护
Hash SHA-256 与 PoW 复用
共识 PoW 易于实现
密钥 RSA 教学上降低 ECDSA 实现复杂度
Build CMake C++ 工程构建
HTTP Mongoose 轻量 HTTP/WebSocket Server
测试网络 Docker 单机模拟多个节点

这里特别需要注意:

Tinychain 使用 RSA 并不是生产区块链设计建议。

比特币实际使用的是基于 secp256k1 的 ECDSA。Tinychain 选择 RSA,只是为了降低教学代码复杂度。

顶层模块设计

Tinychain 的核心结构可以拆成:

1
2
3
4
5
6
7
tinychain
├── blockchain
├── consensus
├── database
├── network
├── http-server
└── node

命令行客户端则非常轻:

1
2
3
cli-tinychain
├── JSON
└── http-client

整体关系可以画成:

flowchart TB
    CLI[cli-tinychain]
    WEB[WebSocket / REST Client]

    CLI --> SERVER[HTTP / WebSocket Server]
    WEB --> SERVER

    SERVER --> NODE[node]

    NODE --> NETWORK[network]
    NODE --> BC[blockchain]
    NODE --> MINER[miner / consensus]

    BC --> MEM[memory pool]
    BC --> CHAIN[chain database]
    BC --> KEY[key pair database]

    NETWORK --> PEERS[P2P Peers]
    MINER --> BC

node 是最上层聚合对象。

启动节点以后,它负责把:

1
2
3
network
blockchain
miner

组合成一个能够运行的系统。

Server:一个节点的统一入口

Server 同时承担两个方向的入口。

1
2
3
4
5
6
7
8
9
10
11
12
13
本地
CLI / RPC / Web

Server

Node

远程
Peer

Server / Network

Node

一个最小启动代码类似:

1
2
3
4
5
6
7
8
9
10
node my_node;

mgbubble::RestServ server{"webroot", my_node};

auto& conn = server.bind("0.0.0.0:8000");
mg_set_protocol_http_websocket(&conn);

log::info("main") << "httpserver started";

server.run();

本地命令通过 HTTP JSON-RPC 调用节点,而其他节点发送的新交易、新区块则进入网络模块。

node:聚合区块链核心能力

node 可以包含:

1
2
3
4
5
6
7
8
9
10
11
class node {
private:
network network_;
blockchain blockchain_;
miner miner_{blockchain_};

public:
void miner_run(address_t address);
blockchain& chain();
network& p2p();
};

除此之外,节点通常还有一个 Network ID,也就是协议中的网络标识。

1
2
3
mainnet
testnet
private chain

不同网络使用不同标识,可以防止节点错误接收其他网络的数据。

blockchain:链状态的核心

blockchain 内部至少需要:

1
2
3
4
5
6
7
8
9
uint16_t id_;

block genesis_block_;

chain_database chain_;

key_pair_database key_pair_database_;

memory_pool_t pool_;

其中:

1
2
3
4
5
6
7
8
9
10
11
genesis_block_
创世区块

chain_
已确认区块

pool_
尚未进入区块的交易

key_pair_database_
本地私钥

这里已经可以看到一个全节点最重要的两种状态:

1
2
3
4
5
Confirmed State
已经写入主链

Pending State
尚在 Mempool

Mempool

内存池是等待矿工处理的交易缓冲区。

1
2
3
4
5
6
7
8
9
收到新交易

验证

Mempool

矿工选择交易

候选区块

Tinychain 使用 STL 容器模拟即可。

生产系统则还需要考虑:

  • 手续费排序;
  • 最大容量;
  • 冲突交易;
  • 过期;
  • DoS;
  • 重组以后交易重新进入池。

区块的数据结构

一个区块最基本可以分成:

1
2
3
Block
├── Header
└── Transactions

Block Header

Tinychain 参考比特币设计,保留:

1
2
3
4
5
6
7
8
9
10
11
{
"target_bits": "4575460831240",
"hash": "4a9169e2...",
"merkle_tree_hash": "3d228afc...",
"nonce": "3852714822920177480",
"height": 1234567,
"previous_block_hash": "4d2544e0...",
"time_stamp": 1528070857,
"transaction_count": 1,
"version": 1
}

几个字段形成区块链最重要的关系:

1
previous_block_hash

将当前区块连接到上一个区块。

1
merkle_tree_hash

则把当前区块中的全部交易压缩成一个根 Hash。

1
nonce + target

参与 PoW。

Transaction

UTXO 模型下,一笔交易由:

1
2
Inputs
Outputs

构成。

一个极简结构可以是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"hash": "8c14f0db...",
"version": 1,
"inputs": [
{
"prev_out": {
"hash": "previous_tx_hash",
"index": 0
}
}
],
"outputs": [
{
"value": 5000000000,
"address": "f3e6066078e815bb2"
}
]
}

含义不是:

1
2
A 的账户余额减 10
B 的账户余额加 10

而是:

1
2
3
消费一个旧的 Output

创建一个或多个新的 Output

这就是 UTXO 模型。

network:维护 Peer 和传播事件

网络模块至少维护两个结构。

1
2
3
4
5
Address Book
历史上发现过的 Peer

Active Channels
当前已经建立的连接

当本地产生交易:

1
2
3
4
5
transaction

broadcast()

active peers

当本地产生新区块:

1
2
3
4
5
block

broadcast()

active peers

而网络收到数据以后,需要经过:

1
2
3
4
5
6
7
8
9
反序列化

网络 ID 检查

格式检查

共识验证

交给 blockchain

因此 P2P 网络不是单纯的 Socket 通信,而是共识系统的第一道输入边界。

consensus:所有节点必须执行相同规则

共识层首先承担两个验证接口:

1
2
bool validate_tx(const tx& new_tx);
bool validate_block(const block& new_block);

一个非常关键的原则是:

自己产生的数据和网络收到的数据必须使用同一套规则验证。

否则本地矿工和远程节点会拥有不同的规则,网络必然分裂。

交易验证可能包括:

1
2
3
4
5
6
签名是否合法?
引用的 UTXO 是否存在?
是否已经被消费?
Input 总额是否足够?
Output 是否符合规则?
有没有双花?

区块验证则进一步检查:

1
2
3
4
5
6
7
8
Previous Hash
Height
Timestamp
PoW
Merkle Root
Transactions
Coinbase
Difficulty

PoW 挖矿的最小实现

Tinychain 中一个候选新区块需要先填写:

1
2
3
4
5
6
height
previous hash
timestamp
transactions
coinbase
difficulty

然后不断改变 nonce

核心思想可以简化成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
bool miner::pow_once(block& new_block, address_t& addr) {
auto pool = chain_.pool();
auto prev = chain_.get_last_block();

new_block.header_.height =
prev.header_.height + 1;

new_block.header_.prev_hash =
prev.header_.hash;

new_block.header_.timestamp =
get_now_timestamp();

auto coinbase = create_coinbase_tx(addr);
pool.push_back(coinbase);

new_block.setup(pool);

uint64_t target =
0xffffffffffffffff /
prev.header_.difficulty;

for (uint64_t nonce = 0; ; ++nonce) {
new_block.header_.nonce = nonce;

auto hash =
to_sha256(new_block.to_json());

uint64_t candidate =
std::stoull(
hash.substr(0, 16),
nullptr,
16
);

if (candidate < target) {
new_block.header_.hash = hash;
return true;
}
}
}

其本质就是:

1
2
3
Hash(Block Header)
<
Target

如果不满足:

1
nonce++

继续计算。

难度调整

Tinychain 为了让演示效果明显,使用了非常简单的难度调整:

1
2
3
4
5
6
7
区块产生太快

提高难度

区块产生太慢

降低难度

这种算法适合教学,不适合生产。

真正的 PoW 网络必须非常谨慎地设计:

  • 调整周期;
  • 时间窗口;
  • Timestamp 异常;
  • 算力突然变化;
  • Difficulty Manipulation。

历史上不少 PoW 链都曾因为难度算法设计不严谨出现严重问题。

database:节点状态最终必须持久化

数据库层至少负责两个对象。

Chain Database

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
uint64_t height();

block get_last_block();

bool get_block(
const sha256_t& hash,
block& out
);

bool get_tx(
const sha256_t& hash,
tx& out
);

bool push_block(const block& b);

bool pop_block(const sha256_t& hash);

注意 pop_block() 并不是可有可无。

只要支持链重组,就必须能够:

1
2
3
4
5
撤销旧分支

恢复 UTXO

应用新分支

Key Pair Database

1
2
3
4
5
6
7
8
9
10
11
class key_pair_database {
public:
key_pair get_new_key_pair();

const key_pair_database_t&
list_keys() const;

private:
key_pair_database_t
key_pair_database_;
};

私钥数据库的安全级别应该远远高于普通区块数据库。

区块丢失还可以重新同步。

私钥丢失通常意味着:

1
资产控制权永久丢失

commands:CLI 本质上只是 RPC Client

一个设计良好的区块链节点不会把所有逻辑写在命令行客户端中。

更合理的模式是:

1
2
3
4
5
cli-tinychain

HTTP JSON-RPC

Tinychain Node

例如:

1
2
3
4
5
6
7
8
9
std::string url{
"127.0.0.1:8000/rpc"
};

HttpReq req(
url,
3000,
reply_handler(my_impl)
);

CLI 只负责:

  • 解析参数;
  • 发送 RPC;
  • 展示 JSON。

真正的业务规则仍然在节点内部。

这也是 Bitcoin、Ethereum 等大量基础设施常见的设计方式。

第一次运行 Tinychain

编译后会获得:

1
2
tinychain
cli-tinychain

启动:

1
./tinychain

服务监听:

1
127.0.0.1:8000

如果准备好 webroot,还可以使用内置 WebSocket 页面观察节点状态。

创建地址

例如:

1
./cli-tinychain getnewkey

返回类似:

1
2
3
4
5
{
"address": "13389c7ae2872cc16b...",
"private_key": "...",
"public_key": "..."
}

开始挖矿

节点创建创世区块以后,可以向指定地址产生 Coinbase 奖励。

新区块不断产生:

1
2
3
4
height = 1
height = 2
height = 3
...

如果加入动态难度:

1
2
出块太快 -> difficulty ↑
出块太慢 -> difficulty ↓

经过一段时间应逐渐接近目标出块时间。

发送第一笔交易

流程是:

sequenceDiagram
    participant C as CLI
    participant N as Node
    participant V as Consensus
    participant P as Mempool
    participant M as Miner
    participant B as Blockchain

    C->>N: send transaction
    N->>V: validate_tx()
    V-->>N: valid
    N->>P: collect(tx)

    M->>P: select transactions
    M->>M: PoW
    M->>V: validate_block()
    V-->>M: valid
    M->>B: push_block()

至此,一笔交易才从:

1
Pending

变成:

1
Confirmed

分叉为什么是实现区块链时绕不过去的一关

两个矿工可能几乎同时产生区块。

节点 A 先看到:

1
100 -> 101A

节点 B 先看到:

1
100 -> 101B

网络暂时出现:

1
2
3
          ┌-> 101A
100 ------|
└-> 101B

随后:

1
101B -> 102B

如果协议使用累计工作量规则,节点最终会选择 B 分支。

1
100 -> 101B -> 102B

原先的 101A 被淘汰。

这时节点不能只修改一个 latestBlock 指针,而必须处理:

  • 回滚区块;
  • 恢复旧 UTXO;
  • 将孤块中的有效交易重新放回 Mempool;
  • 应用新分支;
  • 更新索引;
  • 更新余额。

这也是为什么区块链节点实现远比“链表 + Hash”复杂。

用 Docker 模拟网络分区

Tinychain 可以利用 Docker 在单机上运行多个节点:

1
2
3
4
node1
node2
node3
node4

然后人为切断:

1
2
3
node1 node2
X
node3 node4

两边继续挖矿,就可以观察:

1
2
3
4
5
6
7
Fork

Network Reconnect

Chain Selection

Reorg

这是理解真实分布式共识非常有效的实验。

Tinychain 还远远不是完整区块链

教学实现的价值恰恰在于暴露真实系统还缺什么。

原始 Tinychain 实践中明确尚未完整实现:

  • 完整 P2P 网络;
  • RSA 公私钥模块集成;
  • 完整 Transaction Validation;
  • 完整 Block Validation;
  • 真正的持久化;
  • 更健壮的分叉处理。

继续扩展时还会遇到:

1
2
3
4
5
6
7
8
9
10
11
12
13
Peer Discovery
DoS 防护
Transaction Fee
UTXO Index
Merkle Tree
Signature
Mempool Policy
Checkpoint
Chain Reorg
Protocol Version
Network Upgrade
Wallet Encryption
Backup

从这里再往前,才逐渐接近一个真正的全节点。

从 Tinychain 看区块链真正的攻击面

一旦把模块拼起来,就会发现攻击面也跟着出现。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Network
-> Eclipse / Peer Flood

Transaction
-> Double Spend
-> Invalid Signature
-> Mempool Spam

Consensus
-> Majority Hash Power
-> Difficulty Manipulation

Node
-> Malformed Message
-> Resource Exhaustion

Wallet
-> Private Key Theft

RPC
-> Unauthorized Access

因此安全不是某个“加密模块”单独承担的任务,而是贯穿:

1
2
3
4
5
6
7
网络
协议
共识
存储
钱包
API
运营

的整体工程问题。

从业区块链真正需要什么能力

早期区块链行业曾经按照项目形态把岗位粗略划分为:

1
2
3
4
DLT / 联盟链解决方案
公链应用和智能合约
公链核心研发
交易所 / 钱包 / 基础设施

具体项目热度会变化,但这种技术分层今天依然适合用来判断学习方向。

DLT 和企业解决方案

更像传统企业架构。

需要理解:

  • 分布式系统;
  • 权限;
  • 数据库;
  • 企业集成;
  • 行业业务;
  • 网络和安全。

重点不只是写链码,而是知道:

为什么客户真的需要多个组织维护同一个账本?

智能合约和链上应用

需要理解:

  • Solidity 等合约语言;
  • 账户模型;
  • Transaction;
  • Gas;
  • Token 标准;
  • 前端钱包交互;
  • 合约安全。

但智能合约只是整个应用的一部分。

一个真正的 DApp 仍然需要:

1
2
3
4
5
6
7
8
Frontend
Backend
Indexer
RPC
Wallet
Contract
Database
Monitoring

公链核心研发

这是最接近 Tinychain 的方向。

需要非常扎实的:

  • C++ / Rust / Go 等系统语言;
  • 操作系统;
  • 网络;
  • 数据结构;
  • 密码学基础;
  • 分布式系统;
  • 数据库;
  • 并发。

公链最难的通常不是“懂区块链名词”,而是拥有足够强的计算机基本功。

钱包、交易所和基础设施

这类岗位反而大量复用传统互联网技术:

1
2
3
4
5
6
7
8
9
10
11
Java
Go
C++
MySQL
Redis
Kafka
WebSocket
微服务
风控
高可用
可观测性

真正特殊的部分集中在:

  • 账本;
  • 撮合;
  • 多链钱包;
  • 私钥;
  • 链上确认;
  • 分叉;
  • 资产安全。

所以 Java 后端工程师并不需要“先把一条公链从头写出来”,才能进入区块链工程。

区块链工程师更重要的是跨领域能力

区块链天然同时碰到:

1
2
3
4
5
6
7
Computer Science
Distributed Systems
Cryptography
Finance
Economics
Governance
Product

只理解技术可能设计出没人愿意使用的系统。

只理解经济模型又可能忽略协议安全。

因此真正稀缺的往往是跨界能力。

例如设计交易所,需要同时理解:

1
2
3
4
5
互联网高并发
金融订单
账务
钱包
安全

设计供应链,则需要:

1
2
3
4
5
分布式账本
供应链业务
IoT
企业权限
金融

设计数字身份,则涉及:

1
2
3
4
5
密码学
权限
隐私
身份标准
数据治理

这也解释了为什么区块链系统很少只是“学习 Solidity 就够了”。

把这些主题放在一起后,区块链的工程边界会清晰很多

从数字资产,到交易所、钱包、BaaS、数字身份、供应链,再到 Tinychain,看起来跨度很大,其实一直围绕同一个问题:

哪些状态值得让多个彼此不能完全互信的主体共同维护?

数字资产回答的是:

1
所有权和价值如何表达?

交易所回答的是:

1
链上资产如何进入高性能链下交易系统?

钱包和 BaaS 回答的是:

1
普通互联网应用如何安全、稳定地访问区块链?

数字身份回答的是:

1
可验证事实如何从平台账户中解耦?

供应链回答的是:

1
多个企业如何共享同一组业务事实?

Tinychain 则把问题重新拉回协议底层:

1
2
3
这些共享事实最终怎样通过
网络 + 交易 + 共识 + 存储
真正形成一条链?

也正因为如此,真正成熟的区块链架构通常不会追求“所有东西都上链”。

更合理的思路是不断判断:

1
2
3
4
5
6
7
什么需要共识?
什么可以链下计算?
什么必须保密?
什么只能由现实机构证明?
什么需要公开验证?
谁控制私钥?
谁承担失败责任?

最后得到的系统通常是一个组合体:

flowchart TB
    U[用户 / 企业] --> APP[业务应用]

    APP --> ID[身份与授权]
    APP --> EX[交易 / 业务逻辑]
    APP --> BAAS[BaaS / Wallet Service]

    EX --> OFF[(链下高性能数据库)]
    BAAS --> IDX[(区块索引)]
    BAAS --> NODE[区块链节点]

    NODE --> BC[区块链网络]

    IOT[现实世界 / IoT / 第三方机构] --> APP

区块链只是其中的一层。

但只要这一层放在正确的位置,它就能够把原来依赖单个机构数据库的“相信我”,转换成更加开放的:

“你可以自己验证。”


区块链应用与工程实践:从数字资产、交易所到 BaaS、供应链与 Tinychain
https://allendericdalexander.github.io/2026/09/07/geeker/009blockchain/04blockchain-application-engineering-practice/
作者
AtLuoFu
发布于
2026年9月7日
许可协议