FISCO BCOS——SmartDev-Contract——MarriageEvidence结婚证书合约案例分析

2023-11-15

一、合约场景分析

谨以白头之约书向鸿笺,好将红叶之盟载明鸳谱。三千年来,结婚证书的形式一直在变化,但我们相信,它承载的美好爱情和对幸福婚姻生活的向往从未变过。使用区块链技术,让结婚证书上链,定格在区块链的历史长河中——永存。

源码贡献者:

github:Blockchain_Key

源码分析者:

github:Blockchain_Key

源码链接:

https://github.com/WeBankBlockchain/SmartDev-Contract/tree/master/contracts/business_template/marriage_evidence

二丶基础合约介绍

1. 角色合约

Characters.sol

pragma solidity^0.4.25;

import "./Roles.sol";

contract Character{
    using Roles for Roles.Role;
    Roles.Role private _character;
    
    event characterAdded(address amount,string summary);
    event characterRemoved(address amount);
    event characterRevised(address amount,string summary);
    event characterSeeked(address amount);
    
    address owner;
    address[] characters;
    
    
    constructor()public{
        owner = msg.sender;
    }
    
    modifier onlyOwner(){
        require(owner == msg.sender,"Only owner can call");
        _;
    }
    
    function isCharacter(address amount)public view returns(bool){
        return _character.has(amount);
    }
    
    function _addCharacter(address amount,string _summary)internal{
        _character.add(amount,_summary);
        characters.push(amount);
        emit characterAdded(amount,_summary);
    }
    
    function _removeCharacter(address amount)internal{
        _character.remove(amount);
        emit characterRemoved(amount);
    }
    
    function _reviseCharacter(address amount,string _summary)internal{
        _character.revise(amount,_summary);
        emit characterRevised(amount,_summary);
    }
    
    function _seekCharacter(address amount)internal view returns(string){
        return _character.seek(amount);
        emit characterSeeked(amount);
    }
    
    function _removeCharacterByAddress(address amount)internal{
        for (uint i = 0; i < characters.length; i++) {
            if (amount == characters[i])
                for (uint j = i; j < characters.length-1; j++) 
                    characters[j] = characters[j+1];
            characters.length--;
            }
    }   
    
    function addCharacter(address amount,string _summary)public onlyOwner{
        require(!isCharacter(amount),"The character already exist");
        _addCharacter(amount,_summary);
    }
    
    function removeCharacter(address amount)public onlyOwner{
        require(isCharacter(amount),"The character does not exist");
        _removeCharacter(amount);
        _removeCharacterByAddress(amount);
    }
    
    function reviseCharacter(address amount,string _summary)public onlyOwner{
        require(isCharacter(amount),"The character does not exist");
        _reviseCharacter(amount,_summary);
    }
    
    function seekCharacter(address amount)public view returns(string) {
        require(isCharacter(amount),"The character does not exist");
        return _seekCharacter(amount);
    }
    
    function getAllCharater()public view returns(address[]){
        return characters;
    }
    
}

Roles.sol

pragma solidity^0.4.25;

library Roles{
    struct Role{
        mapping(address=>bool) bearer;
        mapping(address=>string) summary;
    }
    //判断角色
    function has(Role storage role,address amount)internal view returns(bool){
        require(amount!=address(0),"Address is zero address");
        return role.bearer[amount];
    }
    //添加角色
    function add(Role storage role,address amount,string _summary)internal{
        require(!has(role,amount),"Address already exists");
        role.bearer[amount] = true;
        role.summary[amount] = _summary;
    }
    //删除角色
    function remove(Role storage role,address amount)internal{
        require(has(role,amount),"Address does not exist");
        role.bearer[amount] = false;
    }
    //修改角色
    function revise(Role storage role,address amount,string _summary)internal {
        require(has(role,amount),"Address does not exist");
        role.summary[amount] = _summary;
    }
    //查询角色
    function seek(Role storage role,address amount)internal view returns(string){
        require(has(role,amount),"Address does not exist");
        return role.summary[amount];
    }
    
}

(1)功能说明

本合约支持角色操作。包含角色的增删改查:

(2)接口说明

提供了两个合约:Roles合约,Character合约。其中Character合约是对外服务合约,Roles合约是库合约,用于数据和逻辑抽象化。

Character合约:对外服务的唯一接口。包含:

  • addCharacter(address amount,string summary): 管理员进行添加角色操作。amount是添加角色的地址, _summary添加角色的基本信息
  • removeCharacter(address amount): 管理员进行删除角色操作。amount是删除角色的地址
  • reviseCharacter(address amount,string _summary):管理员进行修改角色信息操作。amount是修改角色的地址, _summary修改角色的基本信息
  • seekCharacter(address amount): 任何人都可以进行查询角色信息操作。amount是查询角色的地址
  • getAllCharater():任何人都可以进行查看当前存在的所有角色操作。
  • isCharacter(address amount): 任何人都可以进行查看当前地址是否已经被添加为角色。amount是查询的地址

(3)使用说明

角色的增删改查,整个过程如下:

合约初始化:

- 以管理员地址部署Character合约

合约调用:

- 管理员调用Character.addCharacter提交添加角色请求,参数传入添加角色的地址,角色的基本信息
- 任何人调用Character.getAllCharater提交查看角色请求
- 任何人调用Character.isCharacter提交查询当前地址是否已经被添加成功
- 管理员调用Character.reviseCharacter提交修改角色信息请求,参数传入修改角色的地址,修改角色的基本信息
- 任何人调用Character.seekCharacter提交查询角色信息请求,参数传入查询角色的地址
- 管理员调用Character.removeCharacter提交删除角色的请求,参数传入删除角色的地址
- 任何人调用Character.isCharacter提交查询角色是否还存在请求,参数传入查询角色的地址
- 任何人调用Character.getAllCharater提交查看角色请求

2. 存证合约

Evidence.sol

pragma solidity ^0.4.25;

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;//工厂合约地址
    //返回事件信息,查看log->判断正确或错误的信息
    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;
       //tx.origin =>启动交易的原始地址(其实就是部署者的地址)
       //如果是外部调用,在此可以理解为函数调用者地址
       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++)
        {
            //此时的tx.orgin为当前调用此方法的调用者地址
            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

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

contract EvidenceFactory{
        address[] signers;  //存储签名者地址
		event newEvidenceEvent(address addr); //新签证事件,返回地址
		//传入签名内容 string类型,创建合约Evidence并初始化
        function newEvidence(string evi)public returns(address)
        {
            //this:代表当前工厂合约的地址
            Evidence evidence = new Evidence(evi, this);
            newEvidenceEvent(evidence);
            return evidence;
        }
        //获得签证信息
        function getEvidence(address addr) public constant returns(string,address[],address[]){
            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;
        }

}

(1)功能说明

实现普通存证信息的创建,存储,获取

(2)接口说明

  • newEvidence(string evi)public returns(address):创建新签证事件,返回地址
  • getEvidence(address addr) public constant returns(string,address[],address[]):获取存证信息
  • addSignatures(address addr) public returns(bool):添加合法签名者
  • getSigner(uint index)public constant returns(address):返回签名者地址
  • getSignersSize() public constant returns(uint):获取总签名人数
  • getSigners() public constant returns(address[]):返回所有合约签名者的地址

(3)使用说明

  • 部署合约,初始化传入2个用户地址
    0x76c4e6e1d093092135d79677b724ae3470cdd6e3
    0xad6110c4f698ec996667fd5e2da0cdf5f1ee78e8
    在这里插入图片描述

  • 查看合法签名者地址
    在这里插入图片描述
    在这里插入图片描述

  • 查看是否为合法地址
    在这里插入图片描述
    在这里插入图片描述

  • 创建签证合约(只有合法签名者才能成功创建)
    在这里插入图片描述
    在这里插入图片描述

  • 查看签证信息
    在这里插入图片描述
    在这里插入图片描述

  • 合法签名者签名签证合约
    在这里插入图片描述
    在这里插入图片描述

  • 再次查看签证信息
    在这里插入图片描述

三丶业务合约介绍

1. 结婚证书合约

MarriageEvidence.sol

pragma solidity^0.4.25;
import "./EvidenceFactory.sol";
import "./Character.sol";

contract MarriageEvidence is Character{
    address admin;
    address eviContractAddress;
    address eviAddress;
    constructor() public Character{
        admin = msg.sender;
    }
    
    modifier adminOnly{  
        require(msg.sender == admin ,"require admin");
        _;
    }
    
    modifier charactersMustBeAddedFirst{
        require(getAllCharater().length != 0,"It is null");
        _;
    }
    
    modifier signersOnly{
        require(EvidenceFactory(eviContractAddress).verify(msg.sender),"you not is signer");
        _;
    }
    function deployEvi() external adminOnly charactersMustBeAddedFirst{
        addCharacter(msg.sender,"民政局");
        EvidenceFactory evi = new EvidenceFactory(getAllCharater());
        eviContractAddress = address(evi);
    }
    
    function getSigners() public constant returns(address[]){
        return EvidenceFactory(eviContractAddress).getSigners();
    }
    
    function newEvi(string _evi)public adminOnly returns(address){
        eviAddress = EvidenceFactory(eviContractAddress).newEvidence(_evi);
        return eviAddress;
    }
    
    function sign() public signersOnly returns(bool) {
            return EvidenceFactory(eviContractAddress).addSignatures(eviAddress);
    }
    function getEvi() public constant returns(string,address[],address[]){
            return EvidenceFactory(eviContractAddress).getEvidence(eviAddress);
    }
}

(1)功能说明

实现结婚证书的创建,发放,夫妻签名,验证合法性等

(2)接口说明

  • addCharacter(address amount,string _summary):传入要添加的夫妻地址,以及基本信息
  • deployEvi() external adminOnly charactersMustBeAddedFirst:此方法必须要提前添加人物角色
  • getSigners() public constant returns(address[]):获取夫妻地址,返回地址数组
  • newEvi(string _evi)public adminOnly returns(address):传入结婚信息,创建结婚证书请求,返回证书地址
  • sign() public signersOnly returns(bool):夫妻分调用此接口对证书进行签名,使其具有合法性
  • getEvi()public constant returns(string,address[],address[]):获取结婚证书相关信息

(3)使用说明

  • 部署 MarriageEvidence 合约(民政局管理员key调用部署合约)
    在这里插入图片描述
    在这里插入图片描述

  • 调用添加角色接口

民政局管理员Key调用方法:
添加丈夫地址:0x004a8b8f111b02bc49a06bc4c8b19c29048b939c
添加丈夫信息:{ "name": "K", "url": "https://blog.csdn.net/weixin_43402353", "id": 321183200007270010, "sex": male, "address": { "street": "科技园路.", "city": "江苏苏州", "country": "中国" } }
添加妻子地址:0xd3c34312ae665884c453d46325341d649eb3c05b
添加妻子信息:{ "name": "T", "url": "https://blog.csdn.net/weixin_43402353", "id": 320382200012100001, "sex": female, "address": { "street": "国际中心", "city": "江苏扬州", "country": "中国" } }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 调用查看信息接口
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 部署存证合约(调用 deployEvi 方法)
    在这里插入图片描述

  • 创建结婚证书(本质上是支持多签的一条存证)
    在这里插入图片描述
    在这里插入图片描述

  • 调用sign接口(夫妻分别签名)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 调用getEvi查看证书
    在这里插入图片描述
    在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FISCO BCOS——SmartDev-Contract——MarriageEvidence结婚证书合约案例分析 的相关文章

随机推荐

  • 时序预测

    时序预测 MATLAB实现GM 1 1 灰色时间序列预测 目录 时序预测 MATLAB实现GM 1 1 灰色时间序列预测 预测效果 基本介绍 建模步骤 程序设计 学习总结 参考资料 预测效果 基本介绍 GM 1 1 模型的预测原理是 对某一
  • Linux修改主机名永久生效

    Linux centos7非此方法 修改主机名 永久生效 linux查看主机名 查看主机命令 root linux epm2 hostname localhost localdomain localhost localdomain即为默认的
  • 如何发布tms xdata server(sqlite)

    1 在fdconnection中将数据库路径设置成 employee db即可 2 在云服务上创建一个文件夹如d sparkle文件夹 3 复制exe sqlite3 dll employee db 数据库 运行 4 结果
  • html表单填写保存,如何从HTML表单读取输入并将其保存在文件中-Golang

    我试图建立一个非常简单的Web服务器 用户可以在其中访问站点并写入一个字符串和一个整数 然后我想保存这两个输入 我的想法是将其保存到一个文本文件中 该文件也可以显示在浏览器 textfile 我不知道关于SO的规范是多少代码可以发布 但是到
  • 【沧海拾昧】MATLAB/Simulink仿真的基本操作

    C0402 沧海茫茫千钟粟 且拾吾昧一微尘 沧海拾昧集 CuPhoenix 阅前敬告 沧海拾昧集仅做个人学习笔记之用 所述内容不专业不严谨不成体系 如有问题必是本集记录有谬 切勿深究 目录 一 新建Simulink仿真 二 几种常用的模块和
  • 【Android】【移动应用开发】APP案列

    1 通讯录功能实现 页面布局代码如下 activity main xml 主界面布局代码
  • 职场上会用Python的人到底有多牛?

    这个人工智能崛起的时代 似乎人人都在聊 Python 从硬件的芯片层面 物联网 一路杀到云端 大数据 人工智能这些炙手可热的领域 无论什么领域 只要它需要编程 都会有Python的身影 下面就和大家一起来聊聊 Python 的好 到底它牛在
  • python3 tkinter 刷新标签图片

    coding utf 8 import tkinter as tk import os class RuKou tk Frame 登入的入口 将要做成运行时显示接口所返回的图片并展示 def init self master None 在这
  • Linux获取当前时间

    1 Linux下与时间有关的结构体 struct timeval int tv sec int tv usec 其中tv sec是由凌晨开始算起的秒数 tv usec则是微秒 10E 6 second struct timezone int
  • 在Markdown中用LaTeX/KaTeX输入公式-csdn

    在Markdown中用LaTeX输入公式 csdn Markdown语法简洁 LaTeX版面优美 相互配合 可以使用Markdown处理大多数的公式输入 LaTeX的教程中 刘海洋的 LaTeX入门 全面专业 其中第1章第2节的示例 杂谈勾
  • TCP之Delay Ack和Nagle算法

    TCP之Delay Ack和Nagle算法 1 Delay Ack TCP是可靠传输 可靠的核心是收到包后回复一个ack来告诉对方收到了
  • 推挽电路 MOS管、推挽输出和开漏输出

    专题5 硬件设计 之 48 推挽电路驱动MOS管 嵌入式工程师成长之路的博客 CSDN博客 推挽驱动 专题2 电子工程师 之 硬件 之 44 MOS管的功能特点 专题2 电子工程师 之 硬件 之 45 AON6244 MOS管数据手册分析
  • java 判断一个对象是否为空对象

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 最近项目中遇到一个问题 在用户没填数据的时候 我们需要接收从前端传过来的对象为null 但是前端说他们一个一个判断特别麻烦 只能传个空对象过来
  • WEBRTC+windows10+vs2017编译全过程

    1 下载depot tools https storage googleapis com chrome infra depot tools zip 下载后将其解压到相应文件夹中 并将其路径添加到系统的环境变量中 2 自动更新工具 管理员权限
  • 04 ZooKeeperAPI实战

    文章目录 04 ZooKeeperAPI实战 1 IDEA环境搭建 2 zk连接创建与关闭 3 创建节点 4 删除节点 5 获取数据和验证连接转移 6 注册watcher监听和监听事件被触发 7 判断节点是否存在和修改节点 8 判断节点是否
  • 机器人到达终点有几条路径(动态规划)

    无障碍版本 A robot is located at the top left corner of a m x n grid marked Start in the diagram below The robot can only mov
  • Python中的“ @”(@)符号有什么作用?

    我正在看一些使用 符号的Python代码 但我不知道它的作用 我也不知道要搜索什么 因为搜索Python文档时会出现 或者当包含 符号时Google不会返回相关结果 1楼 此代码段 def decorator func return fun
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • Docker搭建Hadoop集群

    目录 1 拉取centos镜像 2 基础镜像配置 基于centos构建hadoopbase镜像 3 集群环境配置 1 创建3个容器 2 配置网络 3 配置主机和ip的映射关系 4 配置3个节点的免密登录 4 搭建hadoop集群 1 安装h
  • FISCO BCOS——SmartDev-Contract——MarriageEvidence结婚证书合约案例分析

    MarriageEvidence结婚证书合约案例分析 一 合约场景分析 二丶基础合约介绍 1 角色合约 1 功能说明 2 接口说明 3 使用说明 2 存证合约 1 功能说明 2 接口说明 3 使用说明 三丶业务合约介绍 1 结婚证书合约 1