Fisco-Bcos智能合约开发案例----多签存证合约

多签存证合约功能在这里插入图片描述

1. 编写多签存证接口和存证合约

pragma solidity^0.8.7;

interface IEvidence{
    
    
    //验证某个人是否具有签名资格
   function verify(address _signer) external view returns(bool);
   //根据编号查看某个人的具体签名信息
   function getSigner(uint256 _index)external view returns(address);
   //查看所有人的签名信息
   function getAllSigner()external view returns(address[] memory);
   //查看需要签名的用户数量
   function getSignersSize()external view returns(uint256);
}
contract Evidence{
    
    
    //数据定义
    string evidence;
    address[] signers;//已签过名列表
    address public factoryAddr;//工厂合约接口地址

    event NewSignaturesEvidence(string _evi,address _sender);
    event AddRepeatSignatureEvidence(string _evi,address _sender);
    event AddSignatureEvidence(string _evi,address _sender);
    
    //验证调用合约的人是否具有签名的资格
    function callVerify(address _signer) public view returns(bool){
    
    
        return IEvidence(factoryAddr).verify(_signer);
    }

    //function
    constructor(string memory _evi,address _factory){
    
    
        factoryAddr=_factory;
        //此处不能使用msg.sender,因为A合约调用B合约,B合约中的msg.sender是A合约的地址,而不是调用合约的账户地址,tx.origin交易的原始发起者
        require(callVerify(tx.origin),"_signer is not valid!");
        //记录存证信息
        evidence=_evi;
        //存入签名列表中
        signers.push(tx.origin);

        emit NewSignaturesEvidence(_evi,tx.origin);
    }

    //查看某个存证信息,具体包括存证数据,待签名列表,已签名列表
    function getEvidence() public view returns(string memory,address[] memory,address[] memory){
    
    
        uint256 isize = IEvidence(factoryAddr).getSignersSize();
        address[] memory signerList= new address[](isize);
        for(uint256 i=0;i<isize;i++){
    
    
            signerList[i]=IEvidence(factoryAddr).getSigner(i);
        }
        return(evidence,signerList,signers);
    }
    //查看所有存证信息,具体包括存证数据,待签名列表,已签名列表
    function getAllEvidence() public view returns(string memory,address[] memory,address[] memory){
    
    
        uint256 isize = IEvidence(factoryAddr).getSignersSize();
        address[] memory signerList= new address[](isize);
        for(uint256 i=0;i<isize;i++){
    
    
            signerList[i]=IEvidence(factoryAddr).getSigner(i);
        }
        return(evidence,signerList,signers);
    }

    //签名
    function sign()public returns(bool){
    
    
        //判断该人是否有签名资格
         require(callVerify(tx.origin),"_signer is not valid!");
         //该人是否已经签过名
         if(isSigned(tx.origin)){
    
    
             emit  AddRepeatSignatureEvidence(evidence,tx.origin);
             return true;
         }
         signers.push(tx.origin);
         emit  AddSignatureEvidence(evidence,tx.origin);
         return true;

    }
    //验证是否已经签过名
    function isSigned(address _signer)internal  view returns(bool){
    
    
        for(uint256 i=0;i<signers.length;i++){
    
    
            if(signers[i]==_signer){
    
    
                return true;
            }
        }
        return  false;
    } 
    //是否所有人都已签过名
    function isAllSigned()public view returns(bool,string memory){
    
    
         uint256 isize = IEvidence(factoryAddr).getSignersSize();
         for(uint256 i=0;i<isize;i++){
    
    
             if(!isSigned(IEvidence(factoryAddr).getSigner(i))){
    
    
                 return(false,"");
             }
         }
         return(true,evidence);
    }
}

2. 编写工厂合约

pragma solidity^0.8.7;

import "./Evidence.sol";

contract EvidenceFactory is IEvidence{
    
    

    mapping(string=>address) evi_keys; //记录若干个存证合约信息
    address[] signers; //签名列表
   //记录存证合约信息,存证合约的创建者,存证合约地址
    event NewEvidence(string  _evi,address _sender,address _eviAddr);

    constructor(address[]memory _signers){
    
    
        for(uint256 i=0;i<_signers.length;i++){
    
    
            signers.push(_signers[i]);
        }
    }

     //验证某个人是否具有签名资格
   function verify(address _signer)override external view returns(bool){
    
    
      for(uint256 i=0;i<signers.length;i++){
    
    
          if(signers[i]==_signer){
    
    
              return true;
          }
      }
      return false;
   }
   //根据编号查看某个人的具体签名信息
   function getSigner(uint256 _index) override external view returns(address){
    
    
       if(_index<signers.length){
    
    
           return signers[_index];
       }else{
    
    
           return address(0);
       }
   }
    //查看所有人的签名信息
   function getAllSigner() override external view returns(address[] memory){
    
    
       return signers;
   }
   //查看需要签名的用户数量
   function getSignersSize() override external view returns(uint256){
    
    
       return signers.length;
   }

   //创建存证 ,第二个参数是为了记录存证合约地址,有了地址,才可以进行后续操作
   function newEvidence(string memory _evi,string memory _key)public returns(address){
    
    
        Evidence evidence = new Evidence(_evi,address(this));
        evi_keys[_key] = address(evidence); //强制类型转换
        emit NewEvidence(_evi,msg.sender, address(evidence));
        return address(evidence);
   }
   //查询存证
   function getEvidence(string memory _key)public view returns(string memory,address[] memory,address[] memory){
    
    
       address addr = evi_keys[_key];
       return Evidence(addr).getEvidence();
   }
   //签名方法
   function sign(string memory _key)public returns(bool){
    
    
           address addr = evi_keys[_key];
           return Evidence(addr).sign();
   }
   //是否所有都签名
   function isAllSigned(string memory _key) public view returns(bool,string memory){
    
    
          address addr = evi_keys[_key];
           return Evidence(addr).isAllSigned();
   }

}

3.测试

部署工厂合约,初始化需要签名的列表
在这里插入图片描述
在这里插入图片描述

1. 查看需要签名的人数

在这里插入图片描述

2. 查看某个签名信息

在这里插入图片描述

3. 查看所有签名信息

在这里插入图片描述

4.创建存证

在这里插入图片描述

5.查询存证信息

包含存证信息,待签名列表,已签名列表,创建存证的人默认已经签名
在这里插入图片描述

6.签名

使用未在签名列表的账户进行签名

在这里插入图片描述
在这里插入图片描述

出现以下错误
在这里插入图片描述
使用正确的账户进行签名
在这里插入图片描述
查询存证信息,已经2人签名
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.查看是否全部签名

在这里插入图片描述

注意

//此处不能使用msg.sender,因为A合约调用B合约,B合约中的msg.sender是A合约的地址,而不是调用合约的账户地址,tx.origin交易的原始发起者
        require(callVerify(tx.origin),"_signer is not valid!");

猜你喜欢

转载自blog.csdn.net/qq_38716929/article/details/124396673