이더리움 - 계정, 트랜잭션, 메시지 (Ethereum - Account, Transaction, Message)
이더리움 계정 (Account)
이더리움 계정에는 20바이트의 주소와 정보를 직접 전달해주는 상태변환을 가지고 있으며 다음 네 개의 필드가 존재합니다.
- nonce: 각 트랜잭션이 오직 한번만 처리되게 하는 카운터
- value: 계정의 현재 ether 잔고
- contract code: 계정의 컨트랙트코드 (값이 없을 수 있음)
- storage: 계정의 저장공간 (초기설정에는 비어있음)
이더리움의 계정에는 2가지 종류가 있습니다. 외부 소유 계정(External Owned Account - EOA) 과 계약 계정(Contract Account - CA) 입니다. EOA는 누군가가 소유하고 있는 지갑과 같은 계정이라고 생각하시면 됩니다. CA는 배포된 코드와 저장공간 이 추가로 존재하며 스마트 컨트랙트 역할을 할 수 있습니다. 두 가지 계정 중 EOA가 상위 계정이고 새로 생성되는 트랜잭션은 모두 이 EOA에서 시작하게 됩니다. (CA는 EOA가 만든 컨트랙트만 실행할 수 있음 - 생성 X)
EOA는 아무런 코드도 가지고 있지 않으며, 이 계정에서 메시지를 보내기 위해서는 새로운 트랜잭션을 만들고 서명을 해야 합니다. CA는 이러한 메시지를 받을 때마다 자신의 코드를 활성화 시키고 이 활성화된 코드에 따라 메시지를 읽거나 내부 저장공간에 기록하고 다른 메시지들을 보내거나 컨트랙트들을 차례로 생성하게 됩니다. 즉, CA는 컨트랙트를 생성할 수 없고 EOA가 만든 컨트랙트만 실행할 수 있습니다. 모든 컨트랙트에는 해당 컨트랙트가 참이라는 인증이 존재해야 하는데 인증을 담당하는 것은 개인키를 통한 서명이고, 서명을 할 수 있는 것은 EOA이기 때문입니다.
이더리움에서 컨트랙트는 수행되거나 컴파일 되어져야 할 어떤 것이라기 보다는 이더리움의 실행 환경안에 살아있는 자율 에이전트로서 메시지나 트랜잭션이 도착하면 항상 특정한 코드를 실행하고 자신의 이더 잔고와 영속적인 변수들을 추적하기 위해 자신의 키/값 저장소를 직접적으로 통제하는 역할을 합니다. 이러한 개념을 스마트 컨트랙트(Smart Contract) 라 부릅니다.
이더리움은 다양한 매개변수를 가지는 타원곡선암호(=ECC)를 사용하여 비대칭 암호 키를 생성합니다. 매개변수는 속도와 보안성을 조절하는 데 사용되며, 이더리움은 secp256k1을 사용합니다. 이더리움의 개인 키와 공개 키는 256bit의 숫자이고, 모든 계정은 주소로 표현됩니다. 공개 키를 이용해 주소를 만드는 순서는 다음과 같습니다.
- 공개 키의 keccak-256 해시 생성
- 앞 96비트(12바이트)를 버림
- 주소를 16진수 문자열로 인코딩. 최종적으로 남은 40개 문자의 바이트 스트링이 유저의 계정 주소.
트랜잭션 (Transaction)
트랜잭션(transaction)은 EOA가 보낼 메시지를 가지고 있는 서명된 데이터 패키지를 말합니다. 이 트랜잭션은 다음 값들을 포함하고 있습니다.
- to: 메시지 수신처
- signature: 발신처를 확인할 수 있는 서명
- value: 발신처가 수신처로 보내는 이더의 양
- data: 선택적(optional) 데이터 필드 -> 컨트랙트 메시지를 담을 수 있는 데이터 필드
- gaslimit: STARTGAS 값, 트랜잭션 실행이 수행되도록 허용된 최대 계산 단계수
- gasprice: GASPRICE 값, 매 계산단계마다 발신처가 지불하는 수수료
트랜잭션은 하나의 서명된 데이터 패키지 입니다. 이더를 한 계정에서 다른 계정으로, 또는 컨트랙트로 보내거나 컨트랙트의 함수 호출 및 새 컨트랙트를 배포할 때의 서명으로 쓰입니다. 트랜잭션은 타원곡선암호를 기반으로 하는 디지털 서명 알고리즘인 ECDSA를 이용하여 서명됩니다. 트랜잭션은 메시지 수신자, 송신자를 식별하고 의도를 증명하기 위한 서명, 전송할 이더의 양, 트랜잭션 실행을 위해 허용되는 최대 연산 단계, 트랜잭션 송신자가 각 연산 단계를 위해 지불할 의사가 있는 비용을 포함합니다.
위 트랜잭션이 포함하고 있는 값들 중, 처음 세 항목(to, signature, value)은 암호화폐에서 거의 표준처럼 사용되는 값입니다.
data 는 초기값으로 설정된 기능은 가지고 있지 않지만, 버추얼 머신(EVM) 은 컨트랙트가 이 데이터에 접근할 때 사용할 수행코드(opcode) 를 가지고 있습니다. 예를 들어, 블록체인 위에 도메인 등록 서비스로 기능하고 있는 컨트랙트가 있을 경우, 이 컨트랙트로 보내지는 data는 두개의 필드를 가지고 있는 것으로 해석할 수 있습니다. 첫번째 필드는 등록하고자 하는 도메인이고, 두번째 필드는 IP 주소입니다. 컨트랙트는 메시지 데이터로부터 이 값들을 읽어서 저장소 내 적당한 위치에 저장합니다. 내용이 복잡할 수 있는데 간단하게 EVM에는 해당 데이터에 어떤 값이 존재하는지 미리 알고 있다고 이해하면 편합니다.
gaslimit과 gasprice 필드는 이더리움의 anti-DoS 모델에 있어서 매우 중요한 역할을 합니다. 코드 내의 무한루프 (우연이거나 악의적 전부), 또는 계산 낭비를 방지하기 위해 각각의 트랜잭션은 사용할 수 있는 코드 실행의 계산 단계 수를 제한하도록 설정되어야 합니다. 계산의 기본 단위는 gas 이고, 보통 계산 단계는 1 gas의 비용이 소요되지만 어떤 연산은 더 비싼 계산 비용을 치루거나 상태의 일부분으로 저장되어야 하는 데이터의 양이 많을 경우엔 더 많은 gas 비용이 필요하게 됩니다. 또한 트랜잭션 데이터에 있는 모든 바이트는 바이트당 5 gas 의 수수료가 듭니다. 이러한 수수료 시스템의 의도는 만약 해커가 이더리움이나 dAapp을 해킹했을 때, 해커들이 실행하는 모든 리소스에 비례하여 강제로 수수료를 지불하게 하는데 있습니다.
메시지 (Message)
위 트랜잭션에서 설명한 것과 같이 컨트랙트는 다른컨트랙트에게 메시지를 전달할 수 있습니다. 메시지는 따로 저장될 필요가 없는 이더리움의 실행 환경(EVM)에서만 존재하는 가상의 객체입니다. 메시지는 다음 값들을 포함하고 있습니다.
- from: (암묵적으로) 메시지 발신처
- to: 메시지 수신처
- value: 메시지와 함께 전달되는 이더
- data: 선택적 데이터 필드
- gaslimit: STARTGAS 값
메시지는 EOA가 아닌 컨트랙트에 의해 생성된다는 것을 제외하면 트랜잭션과 유사합니다. 현재 코드 수행을 하고 있는 컨트랙트가 메시지를 생성하고 실행하라는 수행코드(opcode) 를 만나게 되면 메시지를 생성합니다. 트랜잭션과 마찬가지로, 메시지는 해당 코드를 실행하는 수신자 계정(컨트랙트 계정)에 도달하게 됩니다. 따라서, 컨트랙트는 EOA가 하는 것과 정확히 같은 방식으로 다른 컨트랙트와 관계를 맺을 수 있습니다. 트랜잭션이나 컨트랙트에 의해 할당된 gas 허용치는 그 트랜잭션과 모든 하위 실행에 의해 소모된 총 gas 에 적용됩니다. 예를 들어, EOA인 A가 B에게 1000 gas와 함께 트랜잭션을 보내고, B는 600 gas를 소모한 뒤 C에게 메시지를 보내고, C의 내부 실행에 300 gas를 소모한 후 반환하면, B는 gas가 모두 소모되기 전에 100 gas를 더 사용할 수 있습니다.
예시) A가 B에게 5ETH를 전송하면서 이더리움이 100만원이 되면 B가 2ETH를 C에게 전송
위와 같은 트랜잭션을 만든다고 가정합니다.
우선 A는 자신의 EOA로 이 내용을 담은 트랜잭션을 만들어서 서명을 하고 블록에 포함시켜야 합니다. A가 보낸 트랜잭션은 모든 노드들이 검증한 후 블록에 담겨 B에게 전송됩니다. 이 트랜잭션에는 이더를 송금하는 것 외에 이더리움이 100만원이 되면 C에게 2ETH 전송 이라는 조건을 담은 메시지가 들어있어 B의 CA는 이 메시지를 저장됩니다. 이더리움이 100만원이 되면, B의 CA는 A로부터 받은 계약을 자동으로 실행시킵니다. 3ETH를 B의 EOA로 전송하고 남은 2ETH를 C의 EOA로 전송합니다. C에게 전송할 땐 조건이 없어 CA로 보낼 필요가 없습니다.
이렇게 자동으로 실행되는 것이 스마트 컨트랙트입니다.