[Solidity] DID 백신 접종 증명 시스템 개발

yooni·2022년 4월 5일
0
post-thumbnail

💉 Purpose

solidity를 사용해 DID Covid-19 백신접종 증명 시스템을 아주 미니멀한 버전으로 구축하고자 한다.

  • 백신 증명 시스템은 ropsten 네트워크에 스마트 컨트랙트로 배포된다.
  • claimCredential 함수를 통해 백신 접종 사실이 블록체인에 기록된다.
  • getCredental 함수를 통해 input 되는 계정 주소의 백신 증명 사실을 발급받을 수 있다.
  • addVaccineType 함수를 통해 백신 타입을 추가할 수 있다.



⌨️ Code


(1) 상태 변수 및 생성자 정의

address private issuerAddress;
uint256 private idCount;
mapping(uint8 => string) private vaccineEnum;
uint8 vaccineTypeCount;

struct Credential {
  uint256 id;
  uint256 verifiedTime;
  address issuer;
  string vaccineType;
}

mapping(address => Credential) private credentials;

constructor() {
  issuerAddress = msg.sender;
  idCount = 1;
  vaccineEnum[0] = "Pfizer";
  vaccineEnum[1] = "Moderna";
  vaccineEnum[2] = "AstraZeneca";
  vaccineEnum[3] = "Janssen";
  vaccineTypeCount = 4;
}
  • issuerAddress : 컨트랙트 배포자(=Credential 발행자)의 주소
  • vaccineEnum : 백신 타입 넘버별 백신 종류가 저장되는 mapping
  • vaccineTypeCount : 백신 종류를 추가할 때 사용하기 위해 백신 종류의 갯수를 나타내는 상태 변수 (mapping은 length를 가지고 있지 않기 때문)
  • Credential : 접종 증명 정보를 구현하기 위한 구조체
  • credentials : 각 주소에 해당하는 Credential이 저장되는 mapping



(2) claimCredential 함수

function claimCredential(address _address, uint8 _vaccineType) public returns(bool) {
  require(issuerAddress == msg.sender, "Not Issuer");
  Credential storage credential = credentials[_address];
  require(credential.id == 0);
  credential.id = idCount;
  credential.issuer = msg.sender;
  credential.vaccineType = vaccineEnum[_vaccineType];
  credential.verifiedTime = block.timestamp;

  idCount += 1;
  return true;
}
  • require(credential.id == 0);
    새로 생성된 Credential의 기존 발행 이력이 없어야 함을 의미한다. 할당 이전의 id는 자동적으로 0이 된다.

  • credential.verifiedTime = block.timestamp;
    Credential 발행 내용이 블록에 올라간 시간을 기록한다.



(3) getCredential 함수

function getCredential(address _address) public view returns(Credential memory) {
  return credentials[_address];
}

입력된 주소의 백신 증명 정보를 담고 있는 Credintal 구조체를 반환한다.



(4) addVaccineType 함수

새로운 백신이 개발될 수 있으므로, 백신 타입을 추가하는 함수가 필요하다.

function addVaccineType(string memory _newVaccine) public returns(bool) {
  require(issuerAddress == msg.sender, "Now Issuer");
  vaccineEnum[vaccineTypeCount] = _newVaccine;
  vaccineTypeCount++;
  return true;
}

당연히 issuer만 이 함수를 실행할 수 있어야 하며, 백신 타입이 추가될 때마다 vaccineTypeCount가 1씩 증가한다.




🖥 동작 확인

(1) Credintial 발행 및 확인

claimCredential 함수로 Credential을 발행하고, Credential에 해당하는 사람의 주소를 입력하여 addVaccineType 함수를 실행한다.

그 결과 Credential ID, verifiedTime, issuer, vaccineType을 담고 있는 구조체가 반환된다.



(2) 백신 타입 추가

또한, Novavax가 새로운 백신으로 추가되었다고 하고 백신 유형에 추가할 수 있다. 이후 Novavax를 백신 타입으로 지정하여 새로운 Credential을 발행할 수 있다.




✏️ 개발 회고

이전에 학습했었던 DID 졸업증명서 Credential 개발 코드를 최대한 활용하였다. 배운 내용을 활용하여 추가적인 내용을 담고 싶었고, 그것이 백신 타입을 추가하는 getCredential 함수이다.

사실 실생활 백신 시스템처럼 1,2,3차 백신 접종 여부나 접종 후 90일 경과 여부 같은 것들도 구현해내고 싶었지만 구현하고자 하는 모든 것을 솔리디티 코드에 담아서 가스비를 높이는 것 보다는 컨트랙트 코드에는 최대한 간단하고 핵심적인 로직 코드만 구현하고, 이를 프론트에서 가져와 잘 활용하여 가공된 의미있는 정보로 띄워주는는 방법이 좋을 것 같았다.

가령, 접종 후 90일 경과 여부를 나타내는 기능을 굳이 컨트랙트 코드에 메소드로 구현할 필요 없이 이번 코드에 내가 이미 추가해둔 verifiedTime 정보만 가져와서, 프론트에서 구현하는 것이 훨씬 낫지 않을까?

getCredential 함수를 실행하면 Credential 구조체가 반환된다. 나의 코드에서는 반환되는 구조체 정보를 보면, 백신 종류가 type number가 아닌 백신 이름 string으로 보여지고 있다.

하지만 가스비를 절감하기 위한 효율적인 개발을 위해서는, string이 아닌 type number로 리턴해주고 프론트에서 추가 작업을 해주는 방법이 역시 더 좋을 것 같다.

가스비를 최대한 줄이면서 또, 코드의 효율성은 놓치지 않는 방향으로 프론트와 잘 연동된 코드를 짜는 것이 중요할 것이다. web3나 solidity에 대한 개발 실력이 좀 더 향상되면 이번에 매우 간단하게 구현해본 백신 시스템을 좀 더 실생활에 가까운 버전으로 업그레이드 해보고 싶다.



profile
멋쟁이 코린이

0개의 댓글