扎实:学生认证架构

问题描述

我最近在uDemy上做了一门课程,并获得了第一个概念。我开始为培训中心构建一个真实的应用程序。我要在区块链中注册ID(文档)xxxx的Jhon Doe,在特定日期批准课程“区块链大师”,并注册证书/许可的“到期日期”。

PHP中,我将创建一个像这样的数组:

$certifications[123456] = [
    [
    "name" => "Jhon","lastName" => "Doe","courseName" => "Blockchain master","Expiration date" => "2022-01-01"
    ],[
    "name" => "Jhon","courseName" => "Just another course","Expiration date" => "2021-01-01"
    ]
];

输出

array (size=1)
  123456 => 
    array (size=2)
      0 => 
        array (size=4)
          'name' => string 'Jhon' (length=4)
          'lastName' => string 'Doe' (length=3)
          'courseName' => string 'Blockchain master' (length=17)
          'Expiration date' => string '2022-01-01' (length=10)
      1 => 
        array (size=4)
          'name' => string 'Jhon' (length=4)
          'lastName' => string 'Doe' (length=3)
          'courseName' => string 'Just another course' (length=19)
          'Expiration date' => string '2021-01-01' (length=10)

此外,我想创建一个函数,以按文档ID查找他/她所做的认证。

不用说,我想以持久的方式将其保存在内存中,必要时使用gas。

我曾考虑为此在映射和数组之间创建一个混合体,但也许是结构...但是我感觉自己走错了方向。

所以...任何人都可以指导我或给我发送类似的例子来检查方法吗?

谢谢!

版本1:

我按照一些技巧编写了这段代码,除了两件事外,它都可以正常工作:

pragma solidity 0.6.6;
pragma experimental ABIEncoderV2;
// SPDX-License-Identifier: MIT

import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';

contract Certification {
    using SafeMath for uint256;
    
    address private owner;
    
    struct Certificate {
        string name;
        string lastname;
        string certificationName;
        string instructorName;
        uint256 dueDate;
        uint256 expirationDate;
    }
    
    
    Certificate[] public certifications;

    mapping(uint => uint) public dniToCertification;
    
    event certificateSubscribed(string name,string lastname,uint dni,string certification,string instructor,uint256 date,uint256 untilDate);
    
    constructor() public {
        owner = msg.sender;
    }
    
    modifier isOwner() {
        require(owner == msg.sender);
        _;
    }
    
    function subscribeCertificate(
        string memory name,string memory lastname,string memory certificationName,string memory instructorName,uint256 dueDate,uint256 expirationDate) public isOwner {
            
        certifications.push(Certificate(
           name,lastname,certificationName,instructorName,dueDate,expirationDate
        ));
            
        Certificate storage certification; //certification will be an instance of Struct Certificate
        
        certification.name = name;
        certification.lastname = lastname;
        certification.certificationName = certificationName;
        certification.instructorName = instructorName;
        certification.dueDate = dueDate;
        certification.expirationDate = expirationDate;
        
        uint id = certifications.length - 1;
    
        dniToCertification[dni] = id;
        
        
        emit certificateSubscribed(name,dni,expirationDate);
    }
    
    function checkCertificateByDni(uint id) public view returns (Certificate memory) {
        return (certifications[dniToCertification[id]]);
        
    }
    
}
  1. 映射是不可迭代的,因此我必须使用experimental ABIEncoderV2
  2. 返回整个Struct对象。
  3. 我第二次想打电话给subscribeCertificate时出错,但没有详细信息...

解决方法

我建议将证书数组保存在Structs中,并为用户拥有的ID和文档ID的列表提供映射。

//certificate object
struct Certificate {
    string name;
    string lastName;
    string courseName;
    uint256 expirationDate;
}

// you can save all certifications on this array.
Certificate[] public certifications;

//save every address certifications and address
mapping(address => uint256[]) public userCertifications;

用法示例:

// get certificate  by id
certifications[id]

// get user certifications-> return array of user certifications
userCertifications[msg.sender] or userCertifications[address]

第1版答案

我将您的代码更改为此,我认为它可以为您工作!

pragma solidity 0.6.6;
// SPDX-License-Identifier: MIT

import 'https://github.com/OpenZeppelin/openzeppelin- 
solidity/contracts/math/SafeMath.sol';

contract Certification {
using SafeMath for uint256;

address private owner;

struct Certificate {
    string name;
    string lastName;
    string certificationName;
    string instructorName;
    uint256 dueDate;
    uint256 expirationDate;
}


Certificate[] public certifications;

mapping(uint => uint) public dniToCertification;




event certificateSubscribed(string name,string lastname,uint dni,string certification,string instructor,uint256 date,uint256 untilDate);

constructor() public {
    owner = msg.sender;
}

modifier isOwner() {
    require(owner == msg.sender);
    _;
}

function subscribeCertificate(
    string memory name,string memory lastname,string memory certificationName,string memory instructorName,uint256 dueDate,uint256 expirationDate) public isOwner {
        
        
        certifications.push(Certificate(
           name,lastname,certificationName,instructorName,dueDate,expirationDate));

        uint id = certifications.length - 1;
        
        dniToCertification[dni] = id;
        
        
        emit certificateSubscribed(name,dni,expirationDate);
}

}

复制并粘贴remix,您会发现有两种方法 一个通过dni获得证书,另一个通过dni获得证书。 另外,您不能获得坚固的结构数组,而必须在客户端进行,并使用循环获取整个证书。