内容简介:一方面,本系列会提供项目的源码解读 —— 这是其他源码分析也能做到的。更重要的是另一方面,也是本系列的创新点:本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
一方面,本系列会提供项目的源码解读 —— 这是其他源码分析也能做到的。更重要的是另一方面,也是本系列的创新点: 本系列将会示范阅读源码的方法论。
狗哥解码是本公众号新开设的系列,旨在分析区块链世界里的一些重要项目。
一方面,本系列会提供项目的源码解读 —— 这是其他源码分析也能做到的。更重要的是另一方面,也是本系列的创新点:
本系列将会示范阅读源码的方法论。
在一个理想的、存在真空中的球形鸡的世界里,所有代码都有完善的文档,清楚地阐述每一个接口的用途与参数。但是,真实的世界中,代码不断敏捷迭代,文档和代码进行着永恒地「龟兔赛跑」。同时,前人留下的 永远不会修复的 TODO、缺乏注释的变量与各种奇技淫巧 也阻碍我们去理解源码。
在这种情况下,我们实际面临的是这样一种情况 —— 要在没有说明书的情况下去了解一个「机器(程序)」的内部运转原理,在此基础上再对其进行魔改与增强。
1 了解 WeIdentity
在阅读与分析 WeIdentity 的源码之前,首先阅读 WeIdentity 的官方文档 —— 永远先看官方文档而不是二手资料是一个好的习惯:
https://weidentity.readthedocs.io/
WeIdentity 是一套分布式多中心的技术解决方案,可承载实体对象(人或者物)的现实身份与链上身份的可信映射、以及实现实体对象之间安全的访问授权与数据交换。WeIdentity由微众银行自主研发并完全开源,秉承公众联盟链整合资源、交换价值、服务公众的理念,致力于成为链接多个垂直行业领域的分布式商业基础设施,促进泛行业、跨机构、跨地域间的身份认证和数据合作。
通过阅读文档,我们对 WeIdentity 建立起一个最粗浅的模型:
+---------------+ +--------------------+ +-----+ | FISCO BCOS 链 |---| WeId Solidity 合约 |---| SDK | +---------------+ +--------------------+ +-----+
在这个基础上,我们可以进行下一步了——先把示例流程跑通。
2 跑通示例流程
这个过程写在这篇文章里:
https://mp.weixin.qq.com/s/BySSeIkMstBXLTeZ2krIHA
通过跑通示例流程,我们可以更细致地理解这个「机器」的工作原理。
同时,如果仅局限于「使用」,而不涉及「魔改」和「增强」的话,在跑通这个流程后,已经可以上手开发相关的应用了。在开发应用的过程中,我们便会对它产生更多的理解,而无需先研究透彻再上手实践。
3 合约分析
示例流程走完后,我们就可以开始着手分析它的合约了:
https://github.com/WeBankFinTech/weid-contract
这份合约涉及多个文件,因此我们需要梳理合约结构。值得欣慰的是 WeIdentity 的文档比较完善,通过文档我们即能了解到合约结构:
https://fintech.webank.com/developer/docs/weidentity/docs/weidentity-contract-design.html
现在,我们要开始选择分析的第一个部分。结合合约结构和示例流程,我们可以先看下 WeIDContract 合约 —— 因为对它的理解并不依赖于其它模块。
pragma solidity ^0.4.4;
/*
* Copyright© (2018) WeBank Co., Ltd.
*
* This file is part of weidentity-contract.
*
* weidentity-contract is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* weidentity-contract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with weidentity-contract. If not, see <https://www.gnu.org/licenses/>.
*/
contract WeIdContract {
mapping(address => uint) changed;
modifier onlyOwner(address identity, address actor) {
require (actor == identity);
_;
}
bytes32 constant private WEID_KEY_CREATED = "created";
bytes32 constant private WEID_KEY_AUTHENTICATION = "/weId/auth";
event WeIdAttributeChanged(
address indexed identity,
bytes32 key,
bytes value,
uint previousBlock,
int updated
);
function getLatestRelatedBlock(
address identity
)
public
constant
returns (uint)
{
return changed[identity];
}
function createWeId(
address identity,
bytes auth,
bytes created,
int updated
)
public
onlyOwner(identity, msg.sender)
{
WeIdAttributeChanged(identity, WEID_KEY_CREATED, created, changed[identity], updated);
WeIdAttributeChanged(identity, WEID_KEY_AUTHENTICATION, auth, changed[identity], updated);
changed[identity] = block.number;
}
function setAttribute(
address identity,
bytes32 key,
bytes value,
int updated
)
public
onlyOwner(identity, msg.sender)
{
WeIdAttributeChanged(identity, key, value, changed[identity], updated);
changed[identity] = block.number;
}
function isIdentityExist(
address identity
)
public
constant
returns (bool)
{
if (0x0 != identity && 0 != changed[identity]) {
return true;
}
return false;
}
}
这个合约简明易懂,其中涉及**事件(Event)、修饰器(modifier)、映射结构(mapping)**等知识点。
可以通过这篇文章对这些知识点进行了解:
https://mp.weixin.qq.com/s/pNIQ1QCPHF7MQGTRUMNoEA
4 在 Remix 上调试
下面就让我们来愉快地 Play 一下这个合约。打开 Remix:
http://remix.ethereum.org/
1)创建文件夹与合约
2)将 WeIdContract.sol 的内容复制过去
3)注释掉 modifier 相关的字句以方便调试
4)加上两个函数以方便调试
function stringToBytes32(string memory source) returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
function bytes32ToString(bytes32 x) constant returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
我们在写合约和写代码的时候经常会遇到类型转换的问题。我的方式是将代码片段(Snippet)存在 Dash 里,结合 Alfred 进行调用。
5)合约的部署与调用
在 Js VM 中对合约进行部署,然后我们就可以尝试着去调用它了。
以 createWeId 参数为例:
a)在 https://vanity-eth.tk/ 生成一个以太坊地址
b)剩下参数随便填写个合法的
调用成功了,在右下角的控制台里我们可以看到日志等信息:
我们把刚才的地址放到 isIdentityExist 函数里,返回 true,身份信息的确存储上了。
5 以合约为引子阅读 SDK 源码
然而,我们并不满足于光看合约,我们还想知道 WeIdentity-SDK 是如何对合约进行调用的。刚才我们的 auth 、 created 、 updated 等参数是随便填的。通过文档我们可以知道 created 和 updated 是时间戳,那么auth 具体是什么呢?文档中似乎没写,所以我们要看代码。
于是我们找到 weid-build-tools 中的 command 示例,这是整个链条中的最后一环:
……
import com.webank.weid.service.impl.WeIdServiceImpl;
import com.webank.weid.util.FileUtils;
/**
* @author tonychen 2019/4/11
*/
public class CreateWeId {
/**
* log4j.
*/
private static final Logger logger = LoggerFactory.getLogger(CreateWeId.class);
private static WeIdService weIdService = new WeIdServiceImpl();
……
可以看到创建了一个 WeIdService 对象,根据这个线索我们去找 WeIdentity 项目中的对应实现。找到 WeIdServiceImpl.java 这个文件,我们可以看到它是通过调用 weIdServiceEngine 来实现的。
……
private ResponseData<Boolean> processCreateWeId(String weId, String publicKey,
String privateKey) {
String address = WeIdUtils.convertWeIdToAddress(weId);
try {
return weIdServiceEngine.createWeId(address, publicKey, privateKey);
……
于是我们找到 WeIdServiceEngineV2.java 文件,我们终于找到了链条的最末端:
……
public ResponseData<Boolean> createWeId(String weAddress, String publicKey, String privateKey) {
String auth = new StringBuffer()
.append(publicKey)
.append(WeIdConstant.SEPARATOR)
.append(weAddress)
.toString();
String created = DateUtils.getNoMillisecondTimeStampString();
TransactionReceipt receipt;
WeIdContract weIdContract =
reloadContract(fiscoConfig.getWeIdAddress(), privateKey, WeIdContract.class);
try {
receipt = weIdContract.createWeId(
weAddress,
DataToolUtils.stringToByteArray(auth),
DataToolUtils.stringToByteArray(created),
BigInteger.valueOf(DateUtils.getNoMillisecondTimeStamp())
).send();
……
Okay,到这里,这根「链条」的分析就结束了。通过这样的一根根链条的分析,我们最终便能把握整个机器的「原理」。
狗哥解码是本公众号新开设的系列,旨在分析区块链世界里的一些重要项目。
一方面,本系列会提供项目的源码解读 —— 这是其他源码分析也能做到的。更重要的是另一方面,也是本系列的创新点:
本系列将会示范阅读源码的方法论。
在一个理想的、存在真空中的球形鸡的世界里,所有代码都有完善的文档,清楚地阐述每一个接口的用途与参数。但是,真实的世界中,代码不断敏捷迭代,文档和代码进行着永恒地「龟兔赛跑」。同时,前人留下的 永远不会修复的 TODO、缺乏注释的变量与各种奇技淫巧 也阻碍我们去理解源码。
在这种情况下,我们实际面临的是这样一种情况 —— 要在没有说明书的情况下去了解一个「机器(程序)」的内部运转原理,在此基础上再对其进行魔改与增强。
1 了解 WeIdentity
在阅读与分析 WeIdentity 的源码之前,首先阅读 WeIdentity 的官方文档 —— 永远先看官方文档而不是二手资料是一个好的习惯:
https://weidentity.readthedocs.io/
WeIdentity 是一套分布式多中心的技术解决方案,可承载实体对象(人或者物)的现实身份与链上身份的可信映射、以及实现实体对象之间安全的访问授权与数据交换。WeIdentity由微众银行自主研发并完全开源,秉承公众联盟链整合资源、交换价值、服务公众的理念,致力于成为链接多个垂直行业领域的分布式商业基础设施,促进泛行业、跨机构、跨地域间的身份认证和数据合作。
通过阅读文档,我们对 WeIdentity 建立起一个最粗浅的模型:
+---------------+ +--------------------+ +-----+ | FISCO BCOS 链 |---| WeId Solidity 合约 |---| SDK | +---------------+ +--------------------+ +-----+
在这个基础上,我们可以进行下一步了——先把示例流程跑通。
2 跑通示例流程
这个过程写在这篇文章里:
https://mp.weixin.qq.com/s/BySSeIkMstBXLTeZ2krIHA
通过跑通示例流程,我们可以更细致地理解这个「机器」的工作原理。
同时,如果仅局限于「使用」,而不涉及「魔改」和「增强」的话,在跑通这个流程后,已经可以上手开发相关的应用了。在开发应用的过程中,我们便会对它产生更多的理解,而无需先研究透彻再上手实践。
3 合约分析
示例流程走完后,我们就可以开始着手分析它的合约了:
https://github.com/WeBankFinTech/weid-contract
这份合约涉及多个文件,因此我们需要梳理合约结构。值得欣慰的是 WeIdentity 的文档比较完善,通过文档我们即能了解到合约结构:
https://fintech.webank.com/developer/docs/weidentity/docs/weidentity-contract-design.html
现在,我们要开始选择分析的第一个部分。结合合约结构和示例流程,我们可以先看下 WeIDContract 合约 —— 因为对它的理解并不依赖于其它模块。
pragma solidity ^0.4.4;
/*
* Copyright© (2018) WeBank Co., Ltd.
*
* This file is part of weidentity-contract.
*
* weidentity-contract is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* weidentity-contract is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with weidentity-contract. If not, see <https://www.gnu.org/licenses/>.
*/
contract WeIdContract {
mapping(address => uint) changed;
modifier onlyOwner(address identity, address actor) {
require (actor == identity);
_;
}
bytes32 constant private WEID_KEY_CREATED = "created";
bytes32 constant private WEID_KEY_AUTHENTICATION = "/weId/auth";
event WeIdAttributeChanged(
address indexed identity,
bytes32 key,
bytes value,
uint previousBlock,
int updated
);
function getLatestRelatedBlock(
address identity
)
public
constant
returns (uint)
{
return changed[identity];
}
function createWeId(
address identity,
bytes auth,
bytes created,
int updated
)
public
onlyOwner(identity, msg.sender)
{
WeIdAttributeChanged(identity, WEID_KEY_CREATED, created, changed[identity], updated);
WeIdAttributeChanged(identity, WEID_KEY_AUTHENTICATION, auth, changed[identity], updated);
changed[identity] = block.number;
}
function setAttribute(
address identity,
bytes32 key,
bytes value,
int updated
)
public
onlyOwner(identity, msg.sender)
{
WeIdAttributeChanged(identity, key, value, changed[identity], updated);
changed[identity] = block.number;
}
function isIdentityExist(
address identity
)
public
constant
returns (bool)
{
if (0x0 != identity && 0 != changed[identity]) {
return true;
}
return false;
}
}
这个合约简明易懂,其中涉及 事件(Event)、修饰器(modifier)、映射结构(mapping) 等知识点。
可以通过这篇文章对这些知识点进行了解:
https://mp.weixin.qq.com/s/pNIQ1QCPHF7MQGTRUMNoEA
4 在 Remix 上调试
下面就让我们来愉快地 Play 一下这个合约。打开 Remix:
1)创建文件夹与合约
2)将 WeIdContract.sol 的内容复制过去
3)注释掉 modifier 相关的字句以方便调试
4)加上两个函数以方便调试
function stringToBytes32(string memory source) returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly {
result := mload(add(source, 32))
}
}
function bytes32ToString(bytes32 x) constant returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
我们在写合约和写代码的时候经常会遇到类型转换的问题。我的方式是将代码片段(Snippet)存在 Dash 里,结合 Alfred 进行调用。
5)合约的部署与调用
在 Js VM 中对合约进行部署,然后我们就可以尝试着去调用它了。
以 createWeId 参数为例:
a)在 https://vanity-eth.tk/ 生成一个以太坊地址
b)剩下参数随便填写个合法的
调用成功了,在右下角的控制台里我们可以看到日志等信息:
我们把刚才的地址放到 isIdentityExist 函数里,返回 true,身份信息的确存储上了。
5 以合约为引子阅读 SDK 源码
然而,我们并不满足于光看合约,我们还想知道 WeIdentity-SDK 是如何对合约进行调用的。刚才我们的 auth 、 created 、 updated 等参数是随便填的。通过文档我们可以知道 created 和 updated 是时间戳,那么auth 具体是什么呢?文档中似乎没写,所以我们要看代码。
于是我们找到 weid-build-tools 中的 command 示例,这是整个链条中的最后一环:
……
import com.webank.weid.service.impl.WeIdServiceImpl;
import com.webank.weid.util.FileUtils;
/**
* @author tonychen 2019/4/11
*/
public class CreateWeId {
/**
* log4j.
*/
private static final Logger logger = LoggerFactory.getLogger(CreateWeId.class);
private static WeIdService weIdService = new WeIdServiceImpl();
……
可以看到创建了一个 WeIdService 对象,根据这个线索我们去找 WeIdentity 项目中的对应实现。找到 WeIdServiceImpl.java 这个文件,我们可以看到它是通过调用 weIdServiceEngine 来实现的。
……
private ResponseData<Boolean> processCreateWeId(String weId, String publicKey,
String privateKey) {
String address = WeIdUtils.convertWeIdToAddress(weId);
try {
return weIdServiceEngine.createWeId(address, publicKey, privateKey);
……
于是我们找到 WeIdServiceEngineV2.java 文件,我们终于找到了链条的最末端:
……
public ResponseData<Boolean> createWeId(String weAddress, String publicKey, String privateKey) {
String auth = new StringBuffer()
.append(publicKey)
.append(WeIdConstant.SEPARATOR)
.append(weAddress)
.toString();
String created = DateUtils.getNoMillisecondTimeStampString();
TransactionReceipt receipt;
WeIdContract weIdContract =
reloadContract(fiscoConfig.getWeIdAddress(), privateKey, WeIdContract.class);
try {
receipt = weIdContract.createWeId(
weAddress,
DataToolUtils.stringToByteArray(auth),
DataToolUtils.stringToByteArray(created),
BigInteger.valueOf(DateUtils.getNoMillisecondTimeStamp())
).send();
……
Okay,到这里,这根「链条」的分析就结束了。通过这样的一根根链条的分析,我们最终便能把握整个机器的「原理」。
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 22分钟前
- 阅读 ( 18 )
- 学分 ( 0 )
- 分类:FISCO BCOS
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- WeIdentity 源码分析 | 狗哥解码(二)
- ZXing源码解析二:掌握解码步骤
- 开源编解码器 SOLO 源码解读(一):带宽扩展
- netty源码解解析(4.0)-19 ChannelHandler: codec--常用编解码实现
- Netty-解码器架构与常用解码器
- Glide 缓存与解码复用
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
CSS权威指南(第三版·英文影印版)
[美] Eric A.Meyer / 东南大学出版社 / 2007-06 / 68.00元
著名的CSS专家Eric A.Meyer他招牌式的智慧和无与伦比的经验引领读者探索了CSS的各个部 分,包括属性、标记、特性和实现。此外,他还就现实应用中的一些问题,例如浏览器的支持和设计方针,发表了看法。你所要知道的就是HTML 4.0的知识,这样就可以创建整洁、易于维护的脚本,以与桌面出版系统同样的优雅和控制能力管理网站布局和分页。你将会学到: 精妙地设计文本风格 用户界面、......一起来看看 《CSS权威指南(第三版·英文影印版)》 这本书的介绍吧!