玩转存证合约(一)| 合约介绍

实验环境

FISCO BCOS (https://github.com/fisco-bcos)

WeBase-Front

Centos7

项目地址:​https://github.com/99Kies/Evidence-Sample-Python

前言

存证合约的主要功能有 添加存证,添加签名。我们此次主要以研读存证合约为主,然后再通过python sdk调用合约实现后端API。

合约部署以及功能介绍

合约内容

EvidenceFactory.sol

pragma solidity ^0.4.4;
import "Evidence.sol";

contract EvidenceFactory{
address[] signers;
event newEvidenceEvent(address addr);
function newEvidence(string evi)public returns(address)
// 创建新存证
{
Evidence evidence = new Evidence(evi, this);
newEvidenceEvent(evidence);
return evidence;
}

function getEvidence(address addr) public constant returns(string,address[],address[]){
// 通过evidence地址获取具体内容。
return Evidence(addr).getEvidence();
}


function addSignatures(address addr) public returns(bool) {
// 添加存证签名
return Evidence(addr).addSignatures();
}

constructor(address[] evidenceSigners){
for(uint i=0; i<evidenceSigners.length; ++i) {
signers.push(evidenceSigners[i]);
}
}

function verify(address addr)public constant returns(bool){
// 验证是否存在该用户。
for(uint i=0; i<signers.length; ++i) {
if (addr == signers[i])
{
return true;
}
}
return false;
}

function getSigner(uint index)public constant returns(address){
// 通过下标索引获取对应的账户地址。
uint listSize = signers.length;
if(index < listSize)
{
return signers[index];
}
else
{
return 0;
}

}

function getSignersSize() public constant returns(uint){
// 获取用户的数量。
return signers.length;
}

function getSigners() public constant returns(address[]){
// 列出所有的用户地址。
return signers;
}

}

Evidence.sol

pragma solidity ^0.4.4;

contract EvidenceSignersDataABI
{
function verify(address addr)public constant returns(bool){}
function getSigner(uint index)public constant returns(address){}
function getSignersSize() public constant returns(uint){}
}

contract Evidence{

string evidence;
address[] signers;
address public factoryAddr;

event addSignaturesEvent(string evi);
event newSignaturesEvent(string evi, address addr);
event errorNewSignaturesEvent(string evi, address addr);
event errorAddSignaturesEvent(string evi, address addr);
event addRepeatSignaturesEvent(string evi);
event errorRepeatSignaturesEvent(string evi, address addr);

function CallVerify(address addr) public constant returns(bool) {
return EvidenceSignersDataABI(factoryAddr).verify(addr);
}

constructor(string evi, address addr) {
factoryAddr = addr;
if(CallVerify(tx.origin))
{
evidence = evi;
signers.push(tx.origin);
newSignaturesEvent(evi,addr);
}
else
{
errorNewSignaturesEvent(evi,addr);
}
}

function getEvidence() public constant returns(string,address[],address[]){
uint length = EvidenceSignersDataABI(factoryAddr).getSignersSize();
address[] memory signerList = new address[](length);
for(uint i= 0 ;i<length ;i++)
{
signerList[i] = (EvidenceSignersDataABI(factoryAddr).getSigner(i));
}
return(evidence,signerList,signers);
}

function addSignatures() public returns(bool) {
for(uint i= 0 ;i<signers.length ;i++)
{
if(tx.origin == signers[i])
{
addRepeatSignaturesEvent(evidence);
return true;
}
}
if(CallVerify(tx.origin))
{
signers.push(tx.origin);
addSignaturesEvent(evidence);
return true;
}
else
{
errorAddSignaturesEvent(evidence,tx.origin);
return false;
}
}

function getSigners()public constant returns(address[])
{
uint length = EvidenceSignersDataABI(factoryAddr).getSignersSize();
address[] memory signerList = new address[](length);
for(uint i= 0 ;i<length ;i++)
{
signerList[i] = (EvidenceSignersDataABI(factoryAddr).getSigner(i));
}
return signerList;
}
}

在这里EvidenceFactory.sol合约导入了Evidence合约,Evidence.sol合约其实相当于提供了一个Evidence类,存证的数据结构和接口在这里实现,EvidenceFactory.sol合约只需要声明和调用即可。(所以需要把这两个合约放在同一级目录下,然后部署EvidenceFactory.sol合约即可)

可见我们的合约里提供了创建新存证获取存证信息添加存证签名验证用户获取所有用户地址获取相应用户地址获取用户数量的函数功能。


tips:EvidenceFactory.sol 中导入了 Evidence.sol合约,所以部署的时候,只需要部署EvidenceFactory.sol即可。


可视化部署

利用webase-front实现部署。

这里需要把Evidence.sol 和 EvidenceFactory.sol 放在同一个文件夹下,然后再部署即可成功。

生成多个测试用户

玩转存证合约(一)| 合约介绍_区块链

玩转存证合约(一)| 合约介绍_区块链_02

玩转存证合约(一)| 合约介绍_ide_03


我这里的两个用户地址分别为 0x28b7a9da9f3a92e139b58181aee04d0720cdd767, 0x405b66921a8ec0899d60961834982aa207acc922。我们需要用到用户来部署合约以及实现签名功能。


部署EvidenceFactory.sol

部署EvidenceFactory合约时需要提供signers的地址列表,所以我们在前面需要创建多个用户用于部署合约

对应代码:

constructor(address[] evidenceSigners){
for(uint i=0; i<evidenceSigners.length; ++i) {
signers.push(evidenceSigners[i]);
}
}


tips:使用​​constructor​​关键字声明的函数。创建合约时执行一次。


把Evidence.sol 和 EvidenFactory.sol存放在同一目录下,并部署EvidenceFactory.sol合约。

玩转存证合约(一)| 合约介绍_ide_04

在这里我们把创建的两个用户以[]address的形式传入。[“0x28b7a9da9f3a92e139b58181aee04d0720cdd767”, “0x405b66921a8ec0899d60961834982aa207acc922”]

玩转存证合约(一)| 合约介绍_ide_05

部署成功

玩转存证合约(一)| 合约介绍_FISCO BCOS_06

调用合约

玩转存证合约(一)| 合约介绍_ide_07

可见创建新存证获取存证信息添加存证签名验证用户获取所有用户地址获取相应用户地址获取用户数量的合约接口。

我们从创建合约开始介绍,一步一步实现存证的多签功能。

newEvidence – 创建新合约

对应的函数

function newEvidence(string evi)public returns(address)
// 创建新存证
{
Evidence evidence = new Evidence(evi, this);
newEvidenceEvent(evidence);
return evidence;
}

选择方法名以及首次签名的用户。

玩转存证合约(一)| 合约介绍_FISCO BCOS_08

写入存证信息。

玩转存证合约(一)| 合约介绍_javascript_09

部署成功。

玩转存证合约(一)| 合约介绍_FISCO BCOS_10

我们可以通过存证地址 0x96B75240e58abff69636510c3d3CE641fA48696B ,来查看存证信息。

getEvidence – 获取存证信息

对应函数:

function getEvidence(address addr) public constant returns(string,address[],address[]){
return Evidence(addr).getEvidence();
}

根据Evidence的地址来查看存证的信息,(存证内容,合约账户,签名者)

玩转存证合约(一)| 合约介绍_Solidity_11

玩转存证合约(一)| 合约介绍_Solidity_12

addSignerature – 添加存证签名

相关函数:

function addSignatures(address addr) public returns(bool) {
return Evidence(addr).addSignatures();
}

根据指定用户向指定合约签名。

选择另外一个用户 ​​fengfeng2​​对 0x96B75240e58abff69636510c3d3CE641fA48696B 合约签名。

玩转存证合约(一)| 合约介绍_FISCO BCOS_13

玩转存证合约(一)| 合约介绍_ide_14

成功签名

玩转存证合约(一)| 合约介绍_ide_15

我们可以重新调用getEvidence 进行查看。

玩转存证合约(一)| 合约介绍_区块链_16

成功实现了多签。

verify – 验证用户

相关函数:

function verify(address addr)public constant returns(bool){
for(uint i=0; i<signers.length; ++i) {
if (addr == signers[i])
{
return true;
}
}
return false;
}

验证地址是否为用户地址。(即是否为合约部署时提供的用户地址)

使用上述的 0x28b7a9da9f3a92e139b58181aee04d0720cdd767 用户地址进行测试。

玩转存证合约(一)| 合约介绍_FISCO BCOS_17

玩转存证合约(一)| 合约介绍_FISCO BCOS_18

getSigners – 获取所有用户地址

相关函数:

function getSigners() public constant returns(address[]){
return signers;
}

获取所有用户地址

玩转存证合约(一)| 合约介绍_ide_19

玩转存证合约(一)| 合约介绍_Solidity_20

getSigner – 获取相应用户地址

相关函数:

function getSigner(uint index)public constant returns(address){
uint listSize = signers.length;
if(index < listSize)
{
return signers[index];
}
else
{
return 0;
}
}

根据下标索引查询用户地址。(下标从0开始)

玩转存证合约(一)| 合约介绍_ide_21

玩转存证合约(一)| 合约介绍_Solidity_22

getSignersSize – 获取用户数量

相关函数:

function getSignersSize() public constant returns(uint){
return signers.length;
}

玩转存证合约(一)| 合约介绍_javascript_23玩转存证合约(一)| 合约介绍_ide_24

总结

在这里我们复现了存证合约并部署和调用了合约,但是如何利用高级开发语言对合约进行调用呢,我会在下节利用Python对这个合约进行调用,实现api接口。

​​

关于作者

​​

我们的公众号平台 — (湖师区块链学会)

欢迎各位大大关注我们湖州师范区块链协会的公众号(湖师区块人),我们会在这里不定期推送区块链相关的“精神食粮”。

玩转存证合约(一)| 合约介绍_javascript_25

欢迎评论关注+点赞啊!