체인의 구성요소

체인의 구성요소

체인에서 State, 상태는 각각 개별적인 nonce, balance, code, storage 등의 속성을 지닌 Account들로 구성되어있고, Account는 크게 체인 외부에서 만들수 있는 외부 소유 계정인 EOA, 그리고 체인 안에서만 생성이 가능한 CA로 구분된다.

Tx는 이더리움에서 State를 바꿀수 있는데, Tx는 크게

  • 이더전송
  • S.C배포
  • S.C실행

의 기능을 통해 Account에 변화를 주고, State를 바꾼다.
이를 위해서는 개인키 서명이더수수료(가스비)가 반드시 요구되고,
이 두가지를 통해 Tx의 [생성→서명→전송]의 과정을 거치게 된다.

  • <TX의 구성요소>
    Tx {
    to: 받을곳
    Signature: 발신자 확인이 가능한 서명
    Value: 보내는 이더
    Gas: 수수료
    Data: S.C 메시지를 담을 수 있는 데이터 란
    }

이러한 구성요소를 충족시키고, 키를 통해 서명을 하고 전송을 하면 노드들은 전송받은 정보들을 Tx Pool에 담아두고 주변 노드들에 검증 정보를 서로 주고 받는다. 이 과정 중에 채굴자들이 채굴과정의 문제를 해결하면(nonce) 노드들에게서 받은 검증받은 Tx pool을 체인 상에 올리게 되고 올라가는 순간, 전송 결과가 정해지고 사용자 입장에서 볼때 전송이 이루어진것으로 보이게 된다.

개인이 Geth를 통해 테스트넷에 account들을 만들고 account끼리의 송금 명령을 진행했어도 지갑내역을 확인해보면 송금이 이루어지지 않은 이유 또한 추가로 mining을 통해 블록생성을 하지 않았기 때문이다. 블록생성이 되지 않았기 때문에 pending 상태로 tx pool에만 담겨있을 뿐이었어서, 블록 생성과정을 거친 후에 다시 확인을 한다면 송금이 제대로 이루어진 것을 확인할 수 있다.
블록이 생성되고 tx가 체인에 온전하게 올라야만 송금이 제대로 이루어진다고 볼 수 있다.

이더리움의 논스 ( 이중 지불 문제)

Trx를 구성하고 있는 필드인 nonce를 통해 이중지불 문제를 해결한다. 이루어지는 거래는 모두 일회성이고, 각 Trx마다 할당된 번호로 nonce라는 필드가 최초 0부터 1씩 증가하는 방식으로 고유의 값을 지닌 상태로 Trx에 생성된다. 비트코인의 경우에는 UTXO방식으로 개별 UTXO의 판별을 통해 이중지불의 문제를 방지하지만 이더리움의 경우 Account방식이기 때문에 위와 같은 Trx별 고유 nonce를 통해 이중지불의 문제를 해결한다.

블록 헤더 부분의 구성

-헤더가 담고있는 정보들, 논스값을 맞추는게 아니라 일정 범위에 있는 논스를 구하는 것이므로 가장 빨리 구해지는 논스값이 새로운 블록의 논스값으로 정해진다.
(위의 Trx nonce와는 다른 개념으로, 용어 구분에 주의!)

개인키, 공개키를 이용한 비밀 메시지 암호화 복호화 과정

상대방의 공개키로 내가 암호화를 해서 보낼 수 있고, 그렇게 암호화된 메시지는 오직 상대방의 개인키로만 복호화가 되기 때문에 비밀 유지가 가능하다.

컨트랙트 배포

Account의 nonce, balance, code, storage 필드 중 code부분의 구성에 따라 storage의 값이 변경되게 된다. code는 한번 배포할 경우 체인상의 접근이 가능한 누구에게나 공개되고, 수정이 불가한 상태가 된다. 수정된 코드를 재배포하여야만 수정이 가능하다.

리믹스

리믹스 IDE를 통해 편리하게 컨트랙트를 작성하고, 배포하고, 사용해 볼 수 있다.

사용법

  • test 폴더에 sol파일 생성
  • Deploy & run trasaction 메뉴로 이동하여 metamask와 연동
  • Environment에 injected web3로 설정
  • 함수 작성
contract FirstContract {
string name = "vitalik";
function getName() public view returns (string memory){
    return name;
}

function setName(string memory _name) public {
    name = _name;
}
uint age = 19;
function getAge() public view returns (uint ){
    return age;
}
function setAge(uint _age) public {
    age = _age;
}
}

함수를 작성한 후에 deploy를 누르면 name: "vitalik" 이라는 내용을 storage에 담기 위해 서명을 요구하는 창이 뜨게 되고, 서명을 진행하고 블록이 생성되면 account의 storage에 추가한 내용이 담긴걸 확인할 수 있다. getName의 함수의 경우 내용을 담는것이 아닌 읽기 함수(view)로 서명이 필요하진 않다. 다음으로 두번째 함수 setName를 호출할 경우 새로운 name의 값을 지정할 수 있고, 이전에 담겼던 name의 값은 새로운 값으로 대체된다. 만약 10번 이름을 변경하였다고 가정하면 1~9번의 이름은 contract에 기록되어있지 않고 마지막 값만 기록되어있다. 1~9번의 이름을 알고자하는 경우 etherscan 거래기록들 타고 들어가면 개별 거래 기록별로 설정했던 name 값을 확일 할 수있다. storage 부분에는 여러 내용을 저장하는 용도가 아니고, 저장하는 비용이 가장 많이 드므로, 다른 곳에서 조회가 가능한 정보일 경우, 가능한한 적은 내용을 담는것이 중요하다.

좋은 웹페이지 즐겨찾기