NULS设计文档解读——账户模块

官方新闻NULSNICE2020-03-13 12:16:04  阅读 -评论 0

摘要:NULS,让区块链更简单!

NULS设计文档解读——账户模块 为什么要有账户模块

在区块链中,信息加密、数字签名和登录认证等应用场景,都需要使用非对称加密算法。非对称加密通常在加密和解密过程中使用两个非对称的密码,分别称为公钥和私钥。

非对称密钥对(公钥和私钥)具有两个特点:一是用其中一个密钥 (公钥或私钥) 加密信息后,只有另一个对应的密钥才能解开;二是公钥可向其他人公开,私钥则保密,其他人无法通过该公钥推算出相应的私钥。

在NULS2.0中,我们选择使用的非对称加密算法是椭圆曲线算法,通过椭圆曲线算法生成公钥和私钥之后,我们需要对公钥和私钥进行管理。

账户模块就是用于管理用户的公钥和私钥的。本质上,账户模块的所有功能都是基于公钥和私钥实现的,例如,基于公钥生成地址,基于密码和私钥生成Keystore,通过私钥进行交易签名等。

账户模块功能

账户模块功能体现了该模块的作用,也是开发该模块需要达到的目标。读者阅读本文档的目标是,理解账户模块具有哪些功能,以及这些功能的实现流程。

账户模块的功能主要分为四类:

账户管理转账交易设置别名交易签名 NULS设计文档解读——账户模块

下面我们将详细讲解以上四类功能的作用及实现流程。

账户管理

账户管理主要包含以下子功能:

创建账户导入账户账户备份修改密码移除账户账户信息查询 创建账户功能

通过创建账户功能,用户可以获得一个NULS账户。

NULS账户中,最重要的属性就是NULS地址,理解NULS账户,要先从理解NULS地址开始。

NULS地址格式

一个NULS地址由多个部分组成,这有点像现实世界的地址,现实世界的地址通常会包含国家、省、市、区等多个组成部分,例如,中国北京市朝阳区朝阳公园南路XX号。

NULS地址(addressString)由前缀(prefix)、分隔符、链ID(chainId)、地址类型(addressType)、公钥摘要(pkh)、校验位(xor)组成。

addressType = prefix +分隔符+ Base58Encode(chainId+addressType+pkh+xor) chainId,为当前链的链id,用于区分不同的区块链。chainId占2个字节,取值范围是1~65535,chainId是地址中非常重要的数据,是跨链操作的基础; addressType,地址类型有三种取值,分别为 :1:普通地址,2:智能合约地址,3:多重签名地址。addressType占一个字节,取值范围为1~128; prefix,前缀是为了便于识别、区分不同链的地址。目前,NULS提供了3种prefix的生成方案: 默认前缀NULS和tNULS。NULS主网chainId为1,默认NULS主网(即chainId为1的链)地址以“NULS”为前缀;NULS核心测试网chainId为2,默认NULS核心测试网(即chainId为2的链)地址以"tNULS"为前缀; 通过登记跨链设置前缀。 在登记跨链时,需要手动填写此链的前缀,系统会维护chainId和前缀的对应关系表,根据对应关系表生成相应的地址前缀; 自动计算。NULS同构体系(通过ChainBox&ChainFactory开发搭建)的区块链,将按照如下的代码规则,自动计算生成一个地址前缀:

//将chainId转换为字节数组,使用base58算法对字节数组进行计算,计算后全部转为大写字母 String prefix = Base58.encode(SerializeUtils.int16ToBytes(chainId)).toUpperCase(); pkh,公钥摘要。1)生成一个NULS地址,首先需要基于椭圆曲线算法获得一个公私钥对(ECKey)。NULS的椭圆曲线参数和比特币一样,使用secp256k1;2)ECKey与地址的关联关系就体现在这一部分,NULS的做法是先用Sha-256对公钥进行一次计算,得到的结果再通过 RIPEMD160进行一次计算得到20个字节的结果,就是pkh; xor,校验位。NULS在生成字符串地址时,会增加一个字节的校验位,计算方式是对前面23个字节(chainId+type+pkh)进行异或运算。 校验位不参与序列化; 分隔符,在前缀和Base58Encode(chainId+addressType+pkh+xor)之间,用一个小写字母进行分隔,便于从地址中提取chainId和验证地址类型及正确性。 小写字母的选择方式为,提供一个数组,按照字母表的顺序填充小写字母,根据prefix的长度来选择分隔的字母:

//前缀长度是几个字母,就选择第几个元素为分隔字母。 //如前缀长度为2,则用b分隔,长度为3用c分隔,长度为4用d分隔,…… String[] LENGTHPREFIX = new String[]{"", "a", "b", "c", "d"......"z"};

创建账户功能主要流程如下:

理解NULS地址的格式之后,下面介绍创建NULS账户的主要流程:

1、生成公私钥对ECKey; 2、生成公钥摘要pkh; 3、将address=(chainId(2) + type(1) + PKH(20))序列化; 4、根据序列化内容,生成校验位xor; 5、添加前缀prefix和分隔符,生成字符串地址: 固定前缀字符串地址

addressString = prefix + 分隔符 + Base58Encode(address+xor) 自动前缀字符串地址

addressString = Base58Encode(chainId) + 分隔符 + Base58Encode(address+xor)

对于像比特币以太坊,这样非NULS体系内的区块链,想要接入NULS生态,就需要有对应的NULS地址,与这些区块链上的每个原生地址形成映射关系。

NULS设计了一个地址转换协议,在NULS生态内,生成对应的映射地址:

address = Base58Encode(chainId+原始地址长度+原始地址+xor)

例如:比特币地址,在地址之前追加两个字节的chainId,之后跟随比特币的原始地址,地址解析方式根据链配置决定,确保任何一个地址都可以在NULS获得映射的地址。

导入账户

通过导入账户功能,用户可以在钱包中将私钥或Keystore导入,在输入密码后,登录到账户中。

导入私钥的主要流程如下:

1、用户导入私钥,输入新密码;2、根据私钥,计算出公钥;3、参考创建账户功能中的流程,在节点本地生成账户,从而得到已有账户信息,完成登录;

导入Keystore的主要流程如下:

1、用户导入Keystore,输入密码;2、根据Keystore和密码,计算得到私钥,再计算出公钥;3、参考创建账户功能中的流程,在节点本地生成账户,从而得到已有账户信息,完成登录。

这里有一个困惑:为何两种方式,都需要重新生成账户,而常见的系统,用账号和密码直接登录就可以?

这是因为区块链的去中心化导致的,因为对于每一个本地的节点来说,用户无论是导入私钥,还是Keystore,本地节点都不一定存储了已有账户的信息,所以通过两种方式导入账户,我们都是重新生成账户,得到已有账户的信息。

而中心化的系统中,每次使用账号密码登录,都是与中心的服务器数据在进行匹配,匹配成功,就会认为登录成功,不需要再生成新的账户。

账户备份

账户备份分为明文私钥备份和Keystore备份两种方式。

明文私钥备份主要流程如下:

1、用户输入密码,发起明文私钥备份请求;2、密码验证通过,根据密码,将本地保存的加密后的私钥进行解密;3、生成明文私钥字符串,返回给用户。

Keystore备份主要流程如下:

1、用户输入密码,发起Keystore备份请求;2、密码验证通过,计算得到账户的公钥;3、将本地保存的加密后的私钥、账户地址字符串、公钥,组装成Json字符串;4、生成Keystore文件,返回给用户。 修改密码

通过修改密码功能,存储用户账户数据的节点,将会根据新密码,对私钥进行加密。

修改密码主要流程如下:

1、用户输入原密码和新密码,发起修改密码请求;2、原密码验证通过,使用原密码将加密的私钥解密;3、用新密码对私钥进行重新加密;4、将重新加密的私钥保存在本地。 移除账户

通过移除账户功能,用户可以将本地节点保存的账户数据删除。

移除账户功能主要流程如下:

1、用户输入密码,发起移除账户请求;2、密码验证通过,删除本地存储的账户信息;3、操作成功,返会操作成功信息给前端。 账户信息查询

账户信息查询功能,是通过提供接口的形式,对外提供服务,让其他模块在实现相关功能时使用。用户通过账户信息查询功能提供的接口,可以查询到账户的地址、余额、别名等账户信息 。具体可以查询到的账户信息,可以参考账户模块提供的查询接口,接口参考[账户模块RPC-API接口文档] 。

转账交易

通过转账交易功能,用户可以发起一笔普通转账,将数字资产从一个账户转移到另一个账户。

理解转账交易功能,需要先理解交易协议,交易协议规定了一个交易需要包含哪些数据。以下是交易协议格式:

Len Fields Data Type Remark 2 type uint16 交易类型 4 time uint32 时间,精确到秒 ? txData VarByte 业务数据 ? coinData VarByte 资产数据 ? remark VarString 备注 ? sigData VarByte 包含公钥和签名数据

CoinData的数据格式

交易协议中的CoinData,是交易的资产数据,由两个列表数据List<CoinFrom>、List<CoinTo>组成,NULS目前定义了一套通用的CoinData格式,具体如下:

froms://List<CoinFrom>格式, tos://List<CoinTo>格式

CoinFrom[70]:

address: //byte[24] 账户地址 assetsChainId://uint16 资产发行链的 assetsId: //uint16 资产 amount: //uint128,转出数量 nonce : //byte[8] 交易顺序号,前一笔交易的hash的后8个字节 locked : //byte 是否是锁定状态(locktime:-1),1代表锁定,0代表非锁定

CoinTo[68]:

address: //byte[24],目标地址 assetsChainId://uint16 资产发行链的 assetsId: //uint16 资产 amount : //uint128,转账金额 lockTime://uint32,解锁高度或解锁时间,-1为永久锁定

在交易协议中,我们规定普通转账的交易类型(type)取值为2,因为转账交易不涉及业务数据,所以业务数据(txData)取值为空,其他数据会根据具体转账交易的情况对数据进行填充。

转账交易功能的主要流程如下:

1、用户填写转账金额,输入密码,发起交易;2、账户模块根据交易协议数据格式,填充对应转账交易数据;3、计算交易数据的Hash值,对交易Hash进行签名(签名过程见下文),广播交易。 设置别名

通过设置别名功能,用户可以为账户设置一个自己想要的别名。

因为设置别名,需要将账户的别名数据上链,所以该功能将会触发一笔交易。设置别名交易的数据格式,遵循前面提到的交易协议,只是交易类型(type)、业务数据(txData)取值的不同。

type: 3 //设置别名交易的类型为3 txData:{ address: //VarByte 设置别名的地址 alias: //VarByte 别名字符串转成的字节数组,用UTF-8解码 } alias(别名)数据格式 Len Fields Data Type Remark 24 address byte[] 设置别名的地址 32 alias byte[] 别名字符串转成的字节数组,用UTF-8解码

设置别名功能的主要流程如下:

1、用户输入别名,输入密码,发起设置别名请求;2、进行相关数据验证,具体包括:

1、别名格式合法性验证 2、主网上是否已经存在此别名 3、该地址是否已经设置过别名 3、账户模块根据交易协议数据格式,填充对应转账交易数据;(注:设置别名交易需要烧毁一个Token单位,所以交易目标地址是一个黑洞地址,其他交易的操作本质上与转账交易没有差别。)4、计算交易数据的Hash值,对交易Hash进行签名(签名过程见下文),广播交易。5、在本地对别名交易进行业务验证,包括主网上是否已经存在此别名、该地址是否已经设置过别名,验证通过,等待其他节点对该交易的处理结果;6、如果其他节点验证该交易通过,则进行提交操作,在节点本地保存该交易,否则,执行回滚。 交易签名

通过交易签名功能,账户模块会使用私钥,对通过交易数据计算得到的交易Hash进行签名。

签名后的交易被认为获得了用户的授权,在签名完成后,交易才会被广播到NULS网络中,其他节点会验证交易的正确性。

交易签名功能的主要流程如下:

1、组装交易数据,计算交易数据的Hash值;2、通过密码和Keystore,获得私钥,对交易Hash进行签名。 其他 Java特有的设计 Account对象设计

该表存储时使用的key:

NULS同构体系:chainId+type+hash160

NULS异构体系:chainId+length+address

`字段名称` `type` `说明` chainId short 链ID address String 账户地址(Base58(address)+Base58(chainId)) alias String 账户别名 status Integer 是否默认账户(不保存) pubKey byte[] 公匙 priKey byte[] 私匙-未加密 encryptedPriKey byte[] 已加密私匙 extend byte[] 扩展数据 remark String 备注 createTime long 创建时间 Address对象设计(不持久化存储) `字段名称` `type` `说明` chainId short 链ID addressType byte 地址类型 hash160 byte[] 公匙hash addressBytes byte[] 地址字节数组 Alias对象设计

该表存储时使用的key:

address和alias分别作为key存储,别名数据存储两份

需要按照不同的链分别创建不同的别名表

`字段名称` `type` `说明` address byte[] 账户地址 alias String 账户别名 账户模块启动时需要依赖的模块 NULS设计文档解读——账户模块

账户模块在启动时,需要依赖以下三个模块:

1、交易模块:因为账户模块需要提供转账交易和设置别名两个功能,这两个功能是涉及到交易,需要在交易模块中,进行注册;

2、网络模块:账户模块需要通过网络模块对外发送消息,需要在网络模块中注册自己需要发送的消息类型;

3、协议升级模块:协议升级模块会自动检测是否有协议升级,账户模块在启动时,会将转账交易和设置别名交易的协议注册到协议升级模块中。

声明:链世界登载此文仅出于分享区块链知识,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。此文如侵犯到您的合法权益,请联系我们kefu@lianshijie.com

参与讨论 (0 人参与讨论)

相关推荐

新冠大流行下,美议会希望用数字货币帮助无银行账户者

新冠大流行下,美议会希望用数字货币帮助无银行账户者

暴走时评:在关于应对新冠病毒大流行的大规模刺激计划的辩论中,美国众议院的民主党议员希望推出数字美元,以简化在传统金融体系之外向美国公民支付补助的流程。

英格兰银行报告:央行数字货币机遇、挑战与设计

英格兰银行报告:央行数字货币机遇、挑战与设计

英格兰银行的主要目标是维持货币和金融稳定。英格兰银行计划与利益相关者一起评估实行 CBDC 的效益、风险和实用性。英格兰银行独立运营 CBDC 不太可能满足大多数设计原则。

公告|NULS主网映射结束,部分已转入社区基金池

公告|NULS主网映射结束,部分已转入社区基金池

致亲爱的NULS社区成员:根据此前发布的映射公告,NULS主网映射功能已经在2020年3月21日正式关闭,逾期未映射的ERC20Token将无法继续进行映射操作,相关ERC20Token将默认捐赠至NULS社区基金。以上特此公告NULS团队2020年3月24日

Nerve致NULS社区的公开信

Nerve致NULS社区的公开信

我是Nerve,一个去中心化的数字资产服务网络,我即将成为NULS生态中最重要的成员。这是我给NULS社区准备的另外一件礼物。

A Letter to the NULS Community From Nerve

A Letter to the NULS Community From Nerve

摘要:am Nerve, a decentralized digital asset service network. Dear NULS community,I amNerve, a decentr

比特币是为应对金融危机而设计的—到目前为止表现良好

比特币是为应对金融危机而设计的—到目前为止表现良好

比特币投资者对上周50%的暴跌感到憋屈,但必须记住,比特币是专门为应对全球危机而设计的。比特币能否在当前的金融危机中生存?期待比特币自诞生以来,一直在耐心等待全球危机的到来。

人人都能读懂的「以太坊2.0分片设计」

人人都能读懂的「以太坊2.0分片设计」

本文将从这些问题出发,来弄清以太坊2.0的分片到底是怎么一回事。在实现上,以太坊是由用户自己选择加入哪一个分片,而不是按自然村庄分片。彻底解决这一问题的时候,就是以太坊2.0可以被使用的时候。

NULS社区2020年第一季度贡献人物评选

NULS社区2020年第一季度贡献人物评选

NULS社区2020年第一季度贡献人物评选正式开始。NULS社区季度贡献人物评选,是NULS社区的一个传统活动,从NULS诞生之初便已形成。

麦妖榜
更新日期 2019-09-03
排名用户贡献值
1牛市来了30910
2BitettFan24187
3等待的宿命23810
4区块大康20369
5六叶树20310
6linjm122719429
7天下无双16192
8lizhen00215280
9让时间淡忘14586
10yelanyi050511349
返回顶部 ↑