- 지갑: 사용자의 키를 보관(개인키를 보관)하고 관리하기 위해 사용되는 시스템
일반적인 돈을 직접 보관하는 의미의 지갑이 아니라 이더리움에서는 트랜잭션에 서명하는 개인키와 공개키의 쌍을 지갑에 넣는 것이라고 생각하면된다.
지갑에 있는 키는 트랜잭션을 서명하는데에 사용되며, 블록체인에 기록되고 이더의 소유권을 나타낸다.
무작위 수 ➔ 무작위 키 추출 : 각각의 키들이 서로 관련이 없다.
seed ➔ 여러개의 키 파생
비트코인의 BIP-32표준으로 정의된 HD지갑이 가장 개선된 결정적 지갑이다.
HD지갑은 트리 구조로 부모키로부터 자식키를 파생할 수 있는 구조를 보여준다.
키의 백업과 검색을 위해서 개인키를 인코딩하는 방법 ➔ 니모닉
니모닉: 올바른 순서로 단어 시퀀스를 입력하여 고유한 개인키를 복원하는 방법
대부분의 이더리움 지갑은 BIP-39 표준을 이용하여 호환이 가능한 니모닉으로 시드를 가져오고, 내보낼 수 있다.
장점: 16진수로된 개인키를 기록할 경우, 오류가 발생할 확률이 높다. 단순한 숫자는 오류가 발생했을 때, 복원하기 어려움.
하지만 단어 목록을 사용하면, 'insect'가 'inzect'로 표기되는 오류가 발생하였을 때, 유효하지 않은 단어이므로 'insect'로 수정하는 등 데이터를 정확하게 보관할 수 있다.
니모닉 코드 단어: 결정적 지갑의 시드로 사용되는 난수를 인코딩하는 단어 시퀀스
단어 시퀀스 ➔ 시드(seed) ➔ 모든 파생 키
지갑 애플리케이션에서 지갑을 생성할 때 단어 시퀀스를 함께 보여준다.
숫자가 아니라 단어이므로 읽고, 기억하기 쉽고 오류를 줄일 수 있기 때문에 지갑 백업에 유용하다.
니모닉 코드와 시드의 생성은 BIP-39로 정의된다. 니모닉 단어는 BIP-39에서 정의한 표준화된 절차에 따라서 지갑에서 자동으로 생성된다.
- 128~256비트의 무작위 암호화 시퀀스 S를 생성한다.
- S를 SHA-256으로 해싱한 값을 32비트로 나눈 처음 길이를 체크섬으로 생성한다.
- 무작위 시퀀스 S의 끝에 체크섬을 추가한다.
- 시퀀스와 체크섬을 연결한 것을 11비트 단위로 나눈다.
- 각각의 11비트 값을 사전에 정의된 2,048단어 사전과 매핑한다.
- 단어의 시퀀스로부터 순서를 유지하면서 니모닉 코드를 생성한다.
- PBKDF2 키 스트레칭 함수의 첫 번째 파라미터는 6단계에서 생성된 니모닉이다.
- PBKDF2 키 스트레칭 함수의 두번째 파라미터는 솔트다. 솔트는 문자열 상수 "mnemonic"과 선택적으로 사용자가 지정한 암호문을 연결하여 구성한다.
- PBKDF2는 최종 출력으로 512비트 값을 만드는 HMAC-SHA512 알고리즘으로, 2048 해시 라운드를 사용하여 니모닉과 솔트 파라미터를 확장하며, 이 결과로 나온 512비트 값이 시드(seed)다.
위의 그림에서 "mnemonic"뒤에 추가되는 암호문에따라 다른 시드를 생성한다. 동일한 니모닉 단어에서 암호문이 다르면 다른 시드가 생성된다.
HD지갑은 128, 256 또는 512비트 임의의 숫자인 단일 루트 시드(root seed)로 부터 생성된다. (니모닉 ➔ 시드생성)
HD지갑의 주요한 특징
1. 부모 공개키(상위 계층의 공개키)에서 자식 공개키(하위 계층의 공개키)를 파생할 수 있다.
2. 자식의 개인키(하위 계층의 개인키)에서 자식 공개키 파생
➔ 확장된 공개키는 HD 지갑 구조의 해당 분기(branch)에서 모든 공개키를 파생하는데 사용될 수 있다.
확장된 공개키가 자식 개인키에 대한 접근을 허용하지는 않지만 체인코드를 포함하므로 잠재적인 위험이 있다.
이러한 위험에 대응하기 위해서 HD지갑은 강화 파생(hardened derivation)(단정 유도법)이라고 하는 대체 가능 파생 함수를 사용해 부모 공개키와 자식의 체인코드 사이의 관계를 끊는다.
즉, 체인코드를 파생할 때 공개키 대신에 개인키를 사용함으로써 확장된 공개키를 사용하더라도 개인키의 유출을 막을 수 있다.
하나의 부모 키에서는 여러 자식키를 파생할 수 있는데,(트리구조 생각) 이를 관리하기위해 자식의 순서를 나타내기 위한 인덱스 번호가 있다.
HD 지갑 트리 구조는 무한한 복잡성을 허용하여 각 부모의 확장키는 약 40억 개의 자식키를 가질 수 있다.
➔ 이렇게 무한하게 자식을 갖게되면 트리의 탐색이 어려울 수 있다.
purpose' : 항상 44'로 설정
coin_type' : 암호화폐 동전의 유형을 지정(60'=이더리움, 61'=이더리움 클래식, 0'=비트코인, 1'=모든화폐의 테스트넷)
account' : 지갑을 별도의 논리적 하위 계좌로 세분화한다.
change: 원래 비트코인을 위해 제작된 BIP-44이므로 해당 부분은 이더리움과는 관련이 없다.
2개의 하위트리가 있는데, 하나는 입금 주소, 하나는 잔액 주소를 작성하는데 사용되며, 이더리움에서는 잔액 주소가 필요하지 않으므로 입금 경로만 사용한다.
address_index : 인덱스(주소) 번호를 의미한다.
- 트랜잭션: 외부 소유 계정(EOA)에 의해 서명된 메시지로 이더리움 네트워크에 의해 전송되고 이더리움 블록체인에 기록된다.
즉, 트랜잭션은 EVM(이더리움 가상 머신)에서 컨트랙트를 실행할 수 있는 유일한 방법
- 논스: 해당 주소에서 보낸 트랜잭션 건수 또는 연결된 코드가 있는 계정의 경우 이 계정에서 만든 컨트랙트 생성 건수와 동일한 스칼라 값 ➔ 계정에서 보내는 트랜잭션에 할당된 번호
- 해당 주소에서 트랜잭션이 발생하면 동적으로 계산(1씩 증가)
- 트랜잭션 생성 순서대로 포함
- 트랜잭션 복제 방지 (지급 금액을 복제하는 행위를 막을 수 있다.)
이더리움 네트워크는 논스에 따라 트랜잭션을 순차적으로 처리한다.
- 동시 실행 문제: 여러 독립 시스템에 의한 동시적인 계산이 있는 경우
동일한 핫 월렛(키가 온라인에 저장된 지갑) 계정에서 여러 컴퓨터가 트랜잭션을 생성, 서명 및 브로드캐스트하는 경우
- 가스(gas): 이더리움의 연료. 이더에 대한 자체 환율을 가진 별도의 가상 화폐
이더리움은 튜링 완전한 모델이기때문에 많은 자원을 소모하는 트랜잭션을 방지하기 위해서 가스를 이용해 사용할 수 있는 자원의 양을 제한한다.
- 트랜잭션의 gasPrice 필드: 트랜잭션 생성자가 가스와 교환하여 지급할 가격을 설정할 수 있음.
- gasPrice가 높을 수록 트랜잭션은 더 빨리 컨펌된다.(우선순위 높음)
- gasPrice의 최솟값은 0으로, 무료 트랜잭션(수수료 0)을 생성할 수 있음을 의미한다.
- 트랜잭션의 gasLimit 필드: 트랜잭션을 완료하기 위해 트랜잭션을 시도하는 사람이 최대로 구매할 수 있는 가스의 단위 수
- 트랜잭션을 보내기 전에 지급할 의사가 있는 최대 금액만큼(구매할 수 있는 가스 단위 만큼) 잔액이 있어야한다.
트랜잭션 수신자는 20바이트 이더리움 주소로, EOA(외부 소유 계정) 혹은 컨트랙트 주소일 수 있다.
- 지급(Payment): 값(value)만 있는 트랜잭션
➔ 대상 주소가 EOA 주소인 경우: 이더리움은 상태 변경을 기록하고, 주소 잔액에 보낸 값을 추가한다.
➔ 대상 주소가 컨트랙트인 경우: EVM이 컨트랙트를 실행하고 트랜잭션의 데이터 페이로드에 지정된 함수를 호출하려고 시도한다.
트랜잭션에 데이터가 없다면 폴백(fallback)함수를 호출한다.
- 호출(invocation): 데이터(data)만 있는 트랜잭션
- 지급과 호출: 값과 데이터를 모두 갖는 트랜잭션
- 값과 데이터가 모두 없는 트랜잭션 : 단순한 가스 낭비(가능한 트랜잭션)
트랜잭션에 데이터가 포함된다면, 받는 주소는 컨트랙트 주소가 될 가능성이 크다.
이렇게 데이터를 전달하는 것은 컨트랙트 호출로 해석된다.즉, 컨트랙트에 정의된 함수를 호출하고 인코딩된 인수를 함수에 전달한다.
디지털 서명의 용도
1. 이더리움 계정과 개인키의 소유자가 이더 지출 혹은 컨트랙트 이행을 승인했음을 증명
2. 부인 방지. 즉 승인한 내용을 부인할 수 없음.
3. 트랜잭션이 서명된 후에는 트랜잭션 데이터는 수정될 수 없음을 증명한다.