本文首发于「NebulaGraph 技术社区」公众号
▌一、背景
区块链的核心魅力在于其透明性。每一笔交易都被永久记录在公共账本上,任何人都可以查看。
然而,随着交易量的激增,链上数据正在爆炸式增长,并且原始区块链数据通常是分散且非结构化的,理解这些交易之间复杂的关系网络变得极具挑战性。
区别于传统账户模型(Account-based),Sui 是基于对象模型(Object-based)的区块链,带来了新的数据关系分析挑战。
Sui 是由 Mysten Labs 开发的下一代高性能区块链平台,Sui 引入了一种以对象为中心的编程模型,在 Sui 中,资产和状态被表示为对象,每个对象都有唯一的 ID 和所有权属性。
Sui的核心架构基于一种称为 “因果关系排序”(Causal Ordering)的设计理念,不同于传统区块链需要全局排序所有交易的方式。 Sui 区分了两类交易:对单拥有者交易(只影响一个拥有者的对象)Sui 采用简化的流程直接处理,无需经过完整的共识流程,而对共享对象交易(影响多方拥有的对象),则使用名为 Narwhal 和 Bullshark 的高吞吐量 DAG(有向无环图)共识引擎)
在区块链关系分析中,传统关系型数据库存在诸多局限:
-
多跳查询性能差:在复杂的交易网络中,往往需要进行多跳查询。但 SQL 的 JOIN 操作在处理大规模、多层级的交易数据时效率低下,难以满足实时分析需求。
-
难以建模动态关系:区块链上钱包地址之间的关系是动态变化的。传统关系型数据库无法轻松地对这些不断演变的关系进行建模和适配。
-
图算法支持有限:检测链上异常行为、识别洗钱模式或进行社群分析等任务,需要依赖 PageRank、社区发现等图算法。传统数据库缺乏原生的图计算能力,需要将数据导出到专门的图计算平台进行处理。
图数据库凭借其天然的图结构存储和查询能力,能够高效处理复杂的关系数据,并原生支持多种图算法,使其成为区块链数据分析的理想选择。
因此,为解决上述问题,基于 NebulaGraph 数据库构建了一个 Sui 区块链交易关系分析平台,支持自动化链上数据采集、交易关系分析算法、交易网络可视化,帮助用户发现隐藏的钱包关联关系和风险模式。
GitHub
▌二、Why NebulaGraph?
NebulaGraph 是一个开源的分布式图数据库,天然适配链上数据分析:
-
复杂关系查询:通过 NebulaGraph 图查询语言 (nGQL) 进行多跳查询、路径分析和环路检测,从而能轻松在海量链上数据中发现深层关系。
-
高性能图计算:支持 PageRank、社区发现、中心性等图算法,为高级分析提供强大支持。
-
实时分析:毫秒级查询延时,满足区块链数据的实时分析需求。
-
灵活建模:图模型天然适配区块链数据的动态特性,便于对钱包、交易、对象等实体及其复杂关系进行建模和扩展。
▌三、架构系统与数据模型
(一)架构概览
Sui-Nebula-Analyzer 的后端服务由两部分组成:Next.js Server 和 Gateway Server.
-
前端应用 (Next.js Application):用户界面,负责数据可视化和用户交互。
-
API 层 (Next.js API Routes):提供应用特定的 API 接口,处理业务逻辑,并与 Gateway Server 协调进行数据库操作。例如,
/api/execute
用于执行查询,/api/data-collection
用于区块链数据摄取,/api/debug-db
用于数据库调试。 -
Gateway Server (Express App):由于 NebulaGraph 的 HTTP API 由 Nebula Gateway 提供,但 Nebula Gateway SDK 与 Next.js Server 的兼容性欠佳(难以使用原生模块),因此这里使用了一个纯 Node.js 服务来连接和访问 Nebula Gateway.
-
NebulaGraph 数据库:存储和管理 Sui 链上数据,提供高性能的图查询和计算能力。
(二)数据采集与处理
Sui-Nebula-Analyzer 实现了自动化的链上数据采集,将原始的 Sui 区块链数据转换为适合存储在图数据库中的结构化数据。采集过程涉及从 Sui 链获取交易、事件和对象信息,并将它们映射为 NebulaGraph 中的点和边。
(三)NebulaGraph 数据模型
为了高效存储和查询 Sui 链上数据,在 NebulaGraph 中设计了特定的图空间、标签 (Tag) 和边类型 (Edge Type)。
- 图空间管理:
DROP SPACE IF EXISTS sui_analysis;
CREATE SPACE IF NOT EXISTS sui_analysis (partition_num = 10, replica_factor = 1, vid_type = FIXED_STRING(64));
- 标签 (Tag) 定义:
wallet
标签代表 Sui 链上的钱包地址,具有以下属性:
CREATE TAG IFNOTEXISTSwallet (
address stringNOTNULL,
first_seen datetime,
last_seen datetime,
transaction_count intDEFAULT0,
total_amount doubleDEFAULT0.0,
is_contract boolDEFAULTfalse,
sui_balance doubleDEFAULT0.0,
owned_objects_count intDEFAULT0,
last_activity datetime
);
- 边类型 (Edge Type) 定义:
transaction
边类型代表钱包之间的交易,具有以下属性:
CREATE EDGE IFNOTEXISTStransaction (
amount doubleNOTNULL,
tx_timestamp datetime NOTNULL,
tx_hash stringNOTNULL,
gas_used intDEFAULT0,
successboolDEFAULTtrue,
transaction_type stringDEFAULT'unknown'
);
related_to
边类型代表钱包之间的关系,这些关系源自分析算法,具有以下属性:
CREATE EDGE IFNOTEXISTS related_to (
relationship_score doubleNOTNULL,
common_transactions intDEFAULT0,
total_amount doubleDEFAULT0.0,
first_interaction datetime,
last_interaction datetime,
relationship_type stringDEFAULT"unknown",
avg_gas_used doubleDEFAULT0.0
▌四、 核心功能与应用
Sui-Nebula-Analyzer 在其功能模块中广泛使用了 NebulaGraph 的图查询能力。以下是使用 nGQL 高效分析链上数据的实际应用示例。
(一)统计分析
Sui-Nebula-Analyzer 提供了基本的链上统计查询,帮助用户快速了解 Sui 的整体情况:
- 钱包计数:
USE sui_analysis;
MATCH (n:wallet) RETURN count(n) as count;
- 交易计数:
USE sui_analysis;
MATCH ()-[e:transaction]->() RETURN count(e) as count;
- 关系计数:
USE sui_analysis; MATCH ()-[r:related_to]->() RETURN count(r) as count;
(二)关系查询与分析
这是 Sui-Nebula-Analyzer 的核心功能之一。通过 nGQL 强大的图遍历和模式匹配能力,揭示钱包之间的复杂关系。
- 基础模式: 关系查询:此查询检索钱包之间预计算的关系,通常基于
related_to
边类型及其relationship_score
属性。
USE sui_analysis;
MATCH (a:wallet)-[r:related_to]-(b:wallet)
WHERE r.relationship_score >= 0.1
RETURN a.wallet.address AS addr1,
b.wallet.address AS addr2,
r.relationship_score AS score,
r.common_transactions AS common_tx,
r.total_amount AS amount
LIMIT 50;
- 进阶模式: 查询增强字段:在基础查询之上,此查询返回更详细的关系信息,如平均 Gas 消耗、首次和末次交互时间、关系类型以及钱包余额和对象数量。
USE sui_analysis;
MATCH (a:wallet)-[r:related_to]-(b:wallet)
WHERE r.relationship_score >= 0.1
RETURN a.wallet.address AS addr1,
b.wallet.address AS addr2,
r.relationship_score AS score,
r.common_transactions AS common_tx,
r.total_amount AS amount,
r.avg_gas_used AS avg_gas,
r.first_interaction AS first_interaction,
r.last_interaction AS last_interaction,
r.relationship_type AS rel_type,
a.wallet.sui_balance AS addr1_balance,
a.wallet.owned_objects_count AS addr1_objects,
a.wallet.is_contract AS addr1_contract
LIMIT 50;
- 兜底查询: 从交易边推断关系(当没有预计算关系时):当没有预计算的
related_to
边时,可以通过直接查询交易边来推断钱包之间的关系。这对于实时或更细粒度的交易分析非常有用。
USE sui_analysis;
MATCH (a:wallet)-[r:transaction]-(b:wallet)
RETURN a.wallet.address AS addr1,
b.wallet.address AS addr2,
r.amount AS amount,
r.gas_used AS gas_used,
r.success AS success,
r.transaction_type AS tx_type,
r.tx_timestamp AS tx_time,
a.wallet.sui_balance AS addr1_balance,
a.wallet.owned_objects_count AS addr1_objects,
a.wallet.is_contract AS addr1_contract
LIMIT 200;
(三)地址详情与关联账户查询
支持用户查询特定 Sui 钱包地址的详细信息及其直接关联的账户,这对于深入分析单个实体的行为模式至关重要。
- 查询目标地址基本信息:
USE sui_analysis;
MATCH (target:wallet)
WHERE id(target) == "${searchAddress}"
RETURN target.wallet.address AS address,
target.wallet.transaction_count AS tx_count,
target.wallet.total_amount AS total_amount,
target.wallet.first_seen AS first_seen,
target.wallet.last_seen AS last_seen;
- 查询目标地址的关联账户:
USE sui_analysis;
MATCH (target:wallet)-[r:related_to]-(related:wallet)
WHERE id(target) == "${searchAddress}"
RETURN related.wallet.address AS address,
r.relationship_score AS score,
r.common_transactions AS common_tx,
r.total_amount AS total_amount,
r.first_interaction AS first_interaction,
r.last_interaction AS last_interaction,
r.relationship_type AS type
LIMIT 20;
- 兜底方案: 从交易边分析关系:当需要从原始交易数据分析特定地址的关系时,可以使用此查询。
USE sui_analysis;
MATCH (target:wallet)-[r:transaction]-(related:wallet)
WHERE id(target) == "${searchAddress}"
RETURN related.wallet.address AS address,
related.wallet.transaction_count AS tx_count,
related.wallet.total_amount AS amount,
r.amount AS tx_amount,
r.tx_timestamp AS tx_time
LIMIT 10;
(四)网络连接可视化
为了提供直观的交易网络视图,Sui-Nebula-Analyzer 支持查询中心节点及其关系,为前端可视化提供数据支持。
- 查询中心节点信息:
USE sui_analysis;
MATCH (center:wallet)
WHERE id(center) == "${searchAddress}"
RETURN center.wallet.address AS center_address,
center.wallet.transaction_count AS center_tx_count,
center.wallet.total_amount AS center_amount;
- 查询网络关系:
USE sui_analysis;
MATCH (center:wallet)-[r:transaction]-(connected:wallet)
WHERE id(center) == "${searchAddress}"
RETURN connected.wallet.address AS connected_address,
connected.wallet.transaction_count AS connected_tx_count,
connected.wallet.total_amount AS connected_amount,
r.amount AS edge_amount,
r.tx_timestamp AS tx_time
LIMIT 50;
▌五、总结
Sui-Nebula-Analyzer 基于 NebulaGraph 图数据库,构建了一个高效、灵活的链上关系分析平台。
尽管它目前只是一个 demo,但所提供的思路和技术架构是极具启发性的,并验证了 NebulaGraph 在区块链场景的强大功能和可扩展性。在生产环境中,可以在此基础上集成更多的图算法(如社区发现、影响力分析),以实现更精确的关系分析。
欢迎大家提交 issue 和 PR, 让 Sui-Nebula-Analyzer 更加强大~
GitHub