2.1 介绍
XuperUion是超级链体系下的第一个开源项目,是构建超级联盟网络的底层方案。XuperUnion设计上采用了模块化插件化的设计,具有高性能、安全、高可扩展、多语言开发智能合约和灵活等特点。
2.2 超级节点
实际的网络中,超级节点的实体可以是一个机构,一家公司或政府部门,对外呈现是一个节点,其内部是分布式网络能力,超级节点参与记账权竞争,保证了全网运行的效率,利用超级计算机和分布式架构,突破单机限制,解决区块链网络算力和存储问题,使节点具备无限的计算力和存储力。
2.2.1 存储支持
超级节点会存储所有的历史事务的完整信息,如何支撑 PB 级别的容量非常具有挑战。XuperUnion 底层 KV 存储引擎主要有以下几个特点:
- 事务性表格系统:通过前缀编码的平展化,支持多链 + 多表,且能保证跨链事务的原子性;
- 多盘技术:实现 KV 存储引擎到底层文件系统的虚拟映射层,支持单机多盘存储,从而支撑大容量数据存储;
2.2.2 计算支持
在非 POW 的共识机制下,超级节点的主要计算量为交易上链和合约执行。很多区块链软件对交易的执行以及合约的执行都是串行执行的,优化到极致也只能使用单核,对硬件的利用率很低。超级节点采用多核并行计算与分布式计算相结合的方式以提升计算效率。
- 多核并行计算:XuperUnion 通过智能合约的依赖关系将待打包的事务构造出 N个DAG。每个DAG的交易和合约执行都是并行跑在多个 CPU 核上, DAG 内部无路径依赖的节点也可以并行执行,从而可以最大化 CPU 的利用率,突破系统吞吐瓶颈。平行链和可回归侧链技术也能有效的利用多核并发;
- 分布式计算:XuperUnion 未来构建事务执行的分布式调度集群,链内并行事务和多链事务可分发给调度集群执行,从而利用分布式计算的扩展能力。
2.3 链内并行
当下区块链技术的实现是将所有事物打包后顺序执行。随着智能合约越来越复杂,如果顺序执行智能合约,高并发度将难以实现。顺序执行智能合约不能充分利用多核和分布式的计算能力,造成资源浪费。XuperUnion 将合约中互相依赖的事物挖掘成DAG图的形式,便于并发的执行。依据生成的DAG图来控制事务的并发,最大化资源的利用,提高合约效率。
2.4 XuperModel
XuperUnion能够支持合约链内并行的很大的原因是由于其底层自研的XuperModel数据模型。XuperModel是一个带版本的存储模型,支持读写集生成。该模型是比特币utxo模型的一个演变。在比特币的utxo模型中,每个交易都需要在输入字段中引用早期交易的输出,以证明资金来源。同样,在XuperModel中,每个事务读取的数据需要引用上一个事务写入的数据。在XuperModel中,事务的输入表示在执行智能合约期间读取的数据源,即事务的输出来源。事务的输出表示事务写入状态数据库的数据,这些数据在未来事务执行智能合约时将被引用,如下图所示:
为了在运行时获取合约的读写集,在预执行每个合约时XuperModel为其提供智能缓存。该缓存对状态数据库是只读的,它可以为合约的预执行生成读写集和结果。验证合约时,验证节点根据事务内容初始化缓存实例。节点将再次执行一次合约,但此时合约只能从读集读取数据。同样,写入数据也会在写入集中生效。当验证完生成的写集和事务携带的写集一致时合约验证通过,将事务写入账本,cache的原理如下所示,图中左边部分是合约预执行时的示意图,右边部分是合约验证时的示意图:
2.5 XuperBridge
XuperBridge为所有合约提供统一的链上数据访问接口,从抽象方式上类似于linux内核对应于应用程序,内核代码是一份,应用程序可以用各种语言实现,比如go,c。类比到合约上就是各种合约的功能,如KV访问,QueryBlock, QueryTx等,这些请求都会通过跟xchain通信的方式来执行,这样在其上实现的各种合约虚拟机只需要做纯粹的无状态合约代码执行。
2.6 账户权限控制模型
2.6.1 背景
超级链需要一套去中心化的,内置的权限系统为了实现这个目标,我们借鉴了业界很多现有系统如Ethereum、EOS、Fabric 的优点,设计一个基于账户的合约权限系统
2.6.2 名词解释
AK(Access Key)
:具体的一个address,由密码学算法生成一组公私钥对,然后将公钥用指定编码方式压缩为一个地址。账号(Account)
: 在超级链上部署合约需要有账号, 账号可以绑定一组AK(公钥),并且AK可以有不同的权重。 账户的名字具有唯一性。合约 (Contract)
: 一段部署在区块链上的可执行字节码,合约的运行会更新区块链的状态。我们允许一个账户部署多个合约。合约的名字具有唯一性。
2.6.3 模型简介
系统会首先识别用户,然后根据被操作对象的ACL的信息来决定用户能否对其进行哪些操作
在超级链中,账户和合约的关系如下所述:
- 个人账户AK:是指一个具体的地址Addr;
- 用户的创建是离线的行为,可以通过命令行工具或者API进行创建
- 合约账户:超级链智能合约的管理单元。
- 账户的创建:
- 任何账户或者AK都可以调用系统级智能合约创建账户;
- 创建账户需要指定账户对应的拥有者的地址集,如果一个账户中只有一个地址, 那么这个Addr对账户完全控制;
- 创建账户需要指定ACL控制策略,用于账户其他管理动作的权限控制;
- 创建账户需要消耗账户资源;
- 账户名命名规则;
- 中间为长度为16位字符串;
- 以”XC”开头;
- 以”@链名”结尾;
- 账户管理:依地址集合据创建时指定的地址集和权限策略,管理账户其他操作;
- 账户股东剔除和加入;
- 账户资产转账;
- 创建合约,创建智能合约需要消耗账户资源,先将utxo资源打到账户下,通过消耗账户的utxo资源创建合约,验证的逻辑需要走账户的ACL控制;
- 合约Method权限模型管理;
- 账户的创建:
- 智能合约:超级链中的一个具体的合约,属于某个账户;
- 账户所属人员允许在账户内部署合约;
- 账户所属人员可以定义合约管理的权限模型;
- 设置合约方法的权限模型,合约内有一个权限表,记录:{ contract.method,permission_model}
- 合约命名规则:长度为4~16个字符(包括4和16),首字母可选项为[ a-ZA-Z ],末尾字符可选项为[ a-zA-Z0-9 ],中间部分的字符可选项为[ a-zA-Z_. ]
2.6.4 实现功能
主要有两个功能:账号权限管理、合约权限管理
- 账号权限管理账号的创建、添加和删除AK、设置AK权重、权限模型
- 合约权限管理设置合约调用权限, 支持2种权限模型:a. 背书阈值:在名单中的AK或Account签名且他们的权重值加起来超过一定阈值,就可以调用合约b. AK集合: 定义多组AK集合,集合内的AK需要全部签名,集合间只要有一个集合有全部签名即可
2.6.5 系统设计
2.6.5.1 ACL数据结构说明
// -------- Account and Permission Section -------
enum PermissionRule {
NULL = 0; // 无权限控制
SIGN_THRESHOLD = 1; // 签名阈值策略
SIGN_AKSET = 2; // AKSet签名策略
SIGN_RATE = 3; // 签名率策略
SIGN_SUM = 4; // 签名个数策略
CA_SERVER = 5; // CA服务器鉴权
COMMUNITY_VOTE = 6; // 社区治理
}
message PermissionModel {
PermissionRule rule = 1;
double acceptValue = 2; // 取决于用哪种rule, 可以表示签名率,签名数或权重阈值
}
// AK集的表示方法
message AkSet {
repeated string aks = 1; //一堆公钥
}
message AkSets {
map<string, AkSet> sets = 1; // 公钥or账户名集
string expression = 2; // 表达式,一期不支持表达式,默认集合内是and,集合间是or
}
// Acl实际使用的结构
message Acl {
PermissionModel pm = 1; // 采用的权限模型
map<string, double> aksWeight = 2; // 公钥or账户名 -> 权重
AkSets akSets = 3;
}
签名阈值策略: Sum{Weight(AK_i) , if sign_ok(AK_i)} >= acceptValue
2.6.5.2 系统合约接口
合约接口 | 用途 |
---|---|
NewAccountMethod | 创建新的账户 |
SetAccountACLMethod | 更新账户的ACL |
SetMethodACLMethod | 更新合约Method的ACL |
2.6.6 样例
// 当acl作用在账户上时,那么账户相关的管理操作(包括更新账户的acl、管理合约Method的ACL等操作)就需要经过该acl的控制;
// 当acl作用在合约Method上时,那么调用该Method就需要经过该acl的控制。
acl模型如下:
{
"pm": {
"rule": 1,//阈值签名模型
"acceptValue": 1.0 // 阈值模型要求的通过权限验证的最低阈值
},
"aksWeight": {
"AK1": 1.0, // AK1的阈值
"AK2": 1.0 // AK2的阈值
}
}
含义:签名的ak对应的weight值加起来>acceptValue,则符合要求
2.7 身份认证
2.7.1 背景
Xuperchain节点之间存在双重身份:P2P节点ID和Xuperchain address,为了解决节点间的身份互信,防止中间人攻击和消息篡改,节点间需要一种身份认证机制,可以证明对称节点声明的XChain address是真实有效的
2.7.2 名词解释
Xuperchain address:当前节点的address,一般为data/keys/addressP2P节点ID:当前节点P2P的peer.ID
2.7.3 P2P建立连接过程
2.7.4 实现过程
- 新建的net.Stream连接,已经完成了ECDH密钥协商流程,因此此时节点间已经是加密连接。
- 连接建立后,增加一步身份认证流程,如果通过,则stream建立成功,加入到streamPool中
其中,身份认证流程如下:
- 身份认证流程通过开关控制,可开启和关闭DefaultIsAuthentication: true or false
- 身份验证支持XChain address的验证方式
- 如果开启身份验证,则身份验证不通过的Stream直接关闭
- 身份验证是使用XChain的私钥对PeerID+XChain地址的SHA256哈希值进行签名,并将PeerID、Xuperchain公钥、Xuperchain地址、签名数据一起传递给对方进行验证
2.7.5 主要结构修改点
stream 增加authenticate接口
func (s *Stream) Authenticate() error {}
收到身份验证消息后的回调处理函数接口
func (p *P2PServerV2) handleGetAuthentication(ctx context.Context, msg *xuper_p2p.XuperMessage) (*xuper_p2p.XuperMessage, error) {}