블록체인 인 액션 Ch.3

학미새🐥·2022년 6월 30일
0
post-custom-banner

Best Practice

  • 블록체인 기능이 개발할 app에 반드시 필요한지 확인한다
    • 중개자가 없는 P2P 트랜잭션
    • 신뢰 범위를 넘어서는 서로 알지 못하는 peer 간의 작동
    • 보편적으로 타임스탬프를 가진 변조 불가능한 장부에서 확인, 검증, 저장이 필요한 경우
    • 규칙과 정책에 의해 가이드된 자율적인 오퍼레이션을 가진 경우
  • 스마트 컨트랙트가 개발할 애플리케이션에 반드시 필요한지 확인해야 한다.
  • 스마트 컨트랙트 코드는 간단하고 일관성 잇고 감사 가능하게 작성해야 한다.
  • 솔리디티는 자주 업데이트된다는 점 감안하기! (아직 성숙된 언어가 아니다. 고로 컨트랙트 코드와 컴파일러 버전 맞추는 것 주의!)

신뢰

  • 확인 : 문제 영역의 일반적인/전역적인 요구 조건을 다루는 것
  • 검증 : application / 데이터에 특정한 조건을 다루는 것

신뢰와 무결성을 제공하는 스마트 컨트랙트 설계

(전자 민주주의를 위한 온라인 투표 애플리케이션을 통해)

  • 과정 : use case diagram -> 컨트랙트 diagram -> 스마트 컨트랙트 작성

    유한 상태 머신 (Finite State Machine) 모델

💡Actor

  • 의장 : 투표자 등록, 자신도 스스로 등록하고 투표할 수 있음
  • 투표자 : 투표하기
  • 불특정 다수 : 투표 과정의 승자나 결과를 요청할 수 있음

💡점진적 개발 단계
1. BallotV1 : 스마트 컨트랙트의 데이터 구조를 정의, 테스트
2. BallotV2 : constructor와 투표 상태를 변화시키기 위한 함수 추가
3. BallotV3 : 스마트 컨트랙트의 다른 함수와 신뢰 구축을 위한 solidity 기능을 보여주기 위한 수정자 추가
4. BallotV4 : 신뢰 요소인 require(), revert(), assert()와 함수 접근 수정자 추가

UML FSM 다이어그램

시간과 여러 조건에 의해 변화하는 스마트 컨트랙트의 상태 변화를 나타내는 다이어그램 (시스템 역동성 표현)

  • 후보자 등록은 투표 전 특정 종료 시간까지 마쳐야 함
  • 투표 과정은 특정 순서에 따라 실행돼야 함
  • 투표는 정해진 기간 동안만 진행
  • 투표가 종료돼야만 승자 판단 가능

💡FSM 구성요소

  • states : 시작 상태, 종료 상태 (이중 원)
  • transitions : 한 상태에서 다른 상태로 변화
  • inputs : 상태 변화를 일으키는 입력값 (해당 프로젝트에서는 상태 변화=시간 기반!)
  • outputs : 상태 변화 동안 출력되는 것 (0개 이상)

신뢰 중개

Bapp에서는 규칙으로 표현되는 신뢰를 위반하는 트랜잭션을 되돌리거나 중단시켜서 허가받지 않은 트랜잭션이 블록체인의 변조 불가능 장부에 포함되는 것을 방지해야 한다.

solidity가 신뢰 요구 조건을 다룰 수 있는 여러 언어적 기능과 함수 제공

  • modifier : 확인해야 할 접근 통제 규칙 명시, 누가 데이터&함수에 통제권을 갖는지 관리 (가시성 수정자와 구분하여 "액세스 수정자"라고 부름)
  • require(condition) 선언 : 파라미터로 전달된 조건 검증. 실패할 경우 함수 중단.
  • revert() 선언 : 트랜잭션 중단. 블록체인에 기록되는 것을 막아줌 (보통 수정자 정의에 사용됨)
  • assert(condition) 선언 : 변수의 조건이나 함수의 실행 과정에서 데이터 검증하고 실패할 경우 트랜잭션 되돌림. 어떤 조건을 만족시키지 못해서 예외 상태가 일어나지 않도록 하기 위해 사용.

💡수정자

//수정자 구문
modifier name_of_modifier(parameters) {    //헤더라인
    require { conditions_to_be_checked };  //체크해야할 조건
    _;                                     //조건 통과 후 실행해야 할 코드 (=수정자가 보호하고 있는 코드)
}

//valiePhase 규칙을 위한 실제 수정자 정의
modifier validPhase(Phase reqPhase) {  
    require(state == reqPhase);  // 투표 과정 상태가 올바른 단계에 있는지 확인
    _;
}

함수 정의와 수정자 정의를 분리하는 이유 : 신뢰와 무결성 구축을 위해 컨트랙트가 강제하는 규칙을 명확히 보여줄 수 있도록 확인, 검증, 예외 부분 분리

수정자 적용

    function register(address voter) public validPhase(Phase.Regs) {  //투표자 등록
        // if (state != Phase.Regs) { revert(); }  -> 전통적인 조건 체크 방식
        if (msg.sender != chairperson || voters[voter].voted) return;
        voters[voter].weight = 1;
        voters[voter].voted = false;
    }
  • 함수의 헤더만 봐도 함수가 다른 것을 처리하기 전에 투표 단계를 체크함을 알 수 있다

코드넣기!!!!!!!!!!!!!!!!!!!!!!!!

  • memory 변수 : 블록체인 저장 공간 낭비를 막는다
    -> 함수 내에서 로컬 변수구조체를 정의할 때, memory / storage 타입을 명시해준다.

테스트 프로세스

  • 긍정 테스트 : 유효한 입력값 -> 기대한 바대로 올바르게 작동
  • 부정 테스트 : 유효하지 않은 입력값 -> 스마트 컨트랙트가 확인과 검증을 통해 오류를 잡아내고 함수 중단

긍정 테스트

  1. 의장 account 설정 & 세명의 투표자 register (의장은 배포시 생성자를 통해 등록됨)
  2. 의장 account 설정 -> 2 인자 입력, stateChange 실행 -> state public 변수 접근 함수를 통해 단계 확인!
  3. 의장 account 설정 -> 2 인자 입력, vote 실행
  4. 각 투표자 account 설정 -> 1 인자 입력, vote 실행
  5. 의장 account 설정 -> 3 인자 입력, stateChange 실행
  6. reqWinner 실행하면 1후보가 이겼음을 알 수 있음

부정 테스트

  • 의장이 아닌 account가 투표자 등록
  • 3 state일 때 vote 실행
  • 존재하지 않는 후보 번호에 투표

수정자, require(), revert() 사용하기

함수를 실행하는 데에 다수의 규칙이 필요할 경우

modifier onlyChair () {
  require(msg.sender == chairperson);
  _;
}
function register(address voter) public validPhase(Phase.Regs) onlyChair {
  ...
}
  • 함수 헤드에 빈칸으로 분리된 리스트로 다수의 수정자 적용 가능
    -> 두 수정자는 순서대로 실행되는 점 유의

assert() 선언

이 또한 솔리디티의 내장 함수!
어떤 함수 내에서의 연산 과정에서 특정한 조건을 충족했는지 여부를 확인해줌

  • 이기기 위해 과반수(ex-3)의 표가 필요하다는 설정
    -> reqWinner() 함수에 assert() 문을 추가해서 규칙 추가
  • 스마트 컨트랙트에 입력되는 파라미터가 아닌, 함수 내에서 연산이 일어나는 중에 검증한다는 차이점!
    ex) assert(winningVoteCount >= 3) 를 통해 최대 투표수가 3 미만이거나 전체 투표자 수가 3미만일 때 함수 중단시킴
  • if 구문 대신 require()를 사용하여 조건 실패 시 트랜잭션이 중단된다는 것을 확실히 알 수 있음 -> 어떠한 트랜잭션도 블록체인에 기록되지 않음 by revert()

BallotV4.sol

BallotV3.sol

BallotV2.sol

BallotV1.sol

profile
뭐든 다해보려는 공대생입니다
post-custom-banner

0개의 댓글