현재 배우고 있는 DID 개념을 Solidity
를 활용해 보려고 합니다.
기존에 졸업증명 개발실습을 진행하였는데, 이를 약간 수정하여 간단한 군 전역증명을 개발하려고 합니다.
크리덴셜 (Credential)
Issuer가 제기한 하나 이상의 Claim 집합. Verifiable Credential(검증가능한 크레덴셜, 이하 VC)은 암호화된 검증을 생성할 수 있는 변조 방지 Credential입니다.
VC를 사용하여 암호화된 Verifiable Presentation(검증가능한 프레젠테이션, 이하 VP)을 만들수 도 있습니다. Credential Claim들은 다른 주체에 관한 것일 수 있습니다.
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.10;
contract DischargedMilitary {
address private issuerAddress;
uint256 private idCount;
mapping(uint8 => string) private armyType;
struct Credential{
// 순서
uint256 id;
// 발급자
address issuer;
// 병과 (육군,해군,공군,해병대)
uint8 armyType;
// 전역날짜
string date;
}
mapping(address => Credential) private credentials;
constructor() {
issuerAddress = msg.sender;
idCount = 1;
armyType[0] = "Army";
armyType[1] = "Navy";
armyType[2] = "Air Force";
armyType[3] = "Marine";
}
function claimCredential(address _alumniAddress, uint8 _armyType, string calldata _date) public returns(bool){
require(issuerAddress == msg.sender, "Not Issuer");
Credential storage credential = credentials[_alumniAddress];
require(credential.id == 0);
credential.id = idCount;
credential.issuer = msg.sender;
credential.armyType = _armyType;
credential.date = _date;
idCount += 1;
return true;
}
function hash(uint256 _id, address _issuer, uint8 _armyType, string memory _date) pure internal returns(bytes32) {
return keccak256(abi.encodePacked(_id,_issuer,_armyType,_date));
}
function getCredential(address _alumniAddress) public view returns (Credential memory){
return credentials[_alumniAddress];
}
}
전체 코드는 다음과 같고 코드를 부분적으로 살펴보며 설명을 이어나가겠습니다.
contract DischargedMilitary {
address private issuerAddress;
uint256 private idCount;
mapping(uint8 => string) private armyType;
struct Credential{
// 순서
uint256 id;
// 발급자
address issuer;
// 병과 (육군,해군,공군,해병대)
uint8 armyType;
// 전역날짜
string date;
}
DischargedMilitary
는 검증가능한 크리덴셜인 VC를 구현하기 위한 구조체입니다. 구성요소로는 id, issuer, armyType, date가 있습니다.
mapping(address => Credential) private credentials;
constructor() {
issuerAddress = msg.sender;
idCount = 1;
armyType[0] = "Army";
armyType[1] = "Navy";
armyType[2] = "Air Force";
armyType[3] = "Marine";
}
크리덴셜이 발행될 때 사용하는 변수를 매핑타입으로 선언해주었습니다.
constructor()
에는 armyType의 정보가 기제되어 있습니다.
function claimCredential(address _alumniAddress, uint8 _armyType, string calldata _date) public returns(bool){
require(issuerAddress == msg.sender, "Not Issuer");
Credential storage credential = credentials[_alumniAddress];
require(credential.id == 0);
credential.id = idCount;
credential.issuer = msg.sender;
credential.armyType = _armyType;
credential.date = _date;
idCount += 1;
return true;
}
claimCredential
함수를 통해 issuer은 holder에게 크리덴셜(Credential)을 발행 가능하게 됩니다.
function hash(uint256 _id, address _issuer, uint8 _armyType, string memory _date) pure internal returns(bytes32) {
return keccak256(abi.encodePacked(_id,_issuer,_armyType,_date));
}
function getCredential(address _alumniAddress) public view returns (Credential memory){
return credentials[_alumniAddress];
}
hash
함수는 크리덴셜 값들을 인코딩하고, 해싱을 하기 위해 구현하였습니다.
getCredential
함수는 holder를 통하여 발행한 크리덴셜을 확인할 수 있는 함수입니다.
해당 과정은 Remix에서 스마트 컨트랙트 배포 & 사용하였습니다.
이더스캔에서 해당 내역 확인하기.
1. 컴파일 진행하기 & 배포
전체 코드를 sol파일 내에 복사-붙여넣기 하고 compile을 진행합니다.
그 다음 Metamask를 이용해 Deploy까지 진행하면
배포가 된 것을 확인할 수 있습니다.
2. claimCredential 함수 실행
배포 이후
claimCredential
함수에 holder의 주소, 병과, 전역날짜를 작성합니다.
transact를 누르면
다음과 같은 컨펌 결과를 볼 수 있습니다.
3. getCredential 함수 실행
컨펌이 완료되었다면, getCredential
함수를 실행합니다.