JavaScript로 블록체인 만들기 #4
JavaScript 로 블록체인 4단계입니다.
#4 지갑 구현
이번 4단계에서는 지갑의 구현됨에 따라, wallet.ts 가 추가되었고, blockchain.ts, main.ts, transaction.ts 에 약간의 변화가 생겼다.
wallet.ts 는 이름에서 볼 수 있듯이 지갑 역할을 하는 파일이다. 개인키와 공개키의 생성 및 저장을 하는 기능과 해당 키로 지갑의 잔고를 알아내는 기능이 구현되어 있다. [1]
wallet.ts 가 추가된 후, blockchain.ts, main.ts, transaction.ts 에도 일정 부분 변화가 생겼다. [2]
이번 4단계에서는
- 개인키 생성 및 저장
- 지갑 잔고
- 거래 생성
- 지갑 사용을 위한 endpoint
순으로 구현할 예정이다.
#4 지갑
개요
지갑의 목표는 사용자에게 더 추상적인 인터페이스를 제공하는 것이다.
사용자는 다음의 기능들을 사용할 수 있어야 한다.
- 새 지갑 생성
- 지갑의 잔고 확인
- 다른 주소로 코인 전송
사용자는 txIns 나 txOuts 가 어떻게 작동하는지 알지 못하는 상태에서도 위의 기능들은 모두 잘 사용할 수 있어야 한다. 비트코인을 예로 들어보자. 비트코인에서 거래를 할 때는 당신의 주소를 사람들에게 알려주고 주소로 코인을 보내고 받는다. 사용자는 여기까지만 알면 된다.
구현할 전체코드는 여기에서 볼 수 있다.
개인키 생성하고 저장하기
이번 단계에서는 지갑을 만들고 저장하는데 있어서 가장 간단한 방법을 사용할 것이다 : 개인키를 생성하여 node/wallet/private_key
에 파일로 저장할 것이다.
공개키는 개인키로부터 계산되어 생성된다.
지금 생성되는 개인키는 unencrypt 된 형태이다. 일단 지금은 간단한 구현을 하는 과정이므로 추가작업은 하지 않고 넘어가겠지만 unencrypt 된 개인키를 저장하는 것은 상당히 안전하지 않다는 것을 명심해라. 또한 이 단계에서의 지갑은 오직 1개의 개인키만 지원한다, 그렇기에 새로운 공개키를 만들기 위해서는 새로운 지갑을 만들어야 한다.
지갑 잔고
이전 챕터의 내용을 한번 더 보자 : 블록체인에서 만약 당신이 일정량의 코인을 소유한다고 할 때, 실질적으로 당신이 보유하고 있는 것은 코인 그 자체가 아니라 당신의 개인키와 일치하는 사용되지 않은 출력값의 리스트(UTXO List)이다.
그렇기에 주어진 주소의 잔고를 계산하는 것은 꽤나 간단하다 : 해당 주소가 “소유한” 사용되지 않은 출력값을 더하기만 하면 되는 것이다.
거래 생성
앞서 언급하였듯이, 코인을 보낼 때, 유저는 거래의 입력값과 출력값의 개념을 굳이 알 필요가 없다. 하지만, 실제 구현을 하는 우리의 입장은 다르다. 만약 A 의 잔고가 50 코인이고 B 에게 10 코인을 보내고 싶은 상황이라면 어떻게 해야할까?
10 코인을 B 의 주소로 보내고 40 코인을 A 에게 다시 보내면 된다. 전체 거래 출력값은 반드시 사용되었어야 했고, 코인에 새로운 출력값을 선정할 때 “나눠지는” 부분이 구현되어야 한다.
아래의 그림처럼 작동하면 될 것이다. (txIns 는 표현하지 않았다) :
조금 더 복잡한 거래 시나리오를 한번 만들어보자 :
- C 는 0 코인을 가지고 있다.
- 3개의 거래가 발생했다. 이 거래들에서 C는 10, 20, 30 의 코인을 받는다.
- C 가 D 에게 55코인을 보내고 싶다. 그렇다면 거래는 어떻게 구성될까?
이런 경우에는, 3개의 output 모두 사용 되어야 하고 D 에게 가는 출력값은 55, C 에게 돌아오는 코인은 5 가 되면 될 것이다.
이제 코드로 한번 짜보자. 먼저 거래 입력값을 만든다. 이를 하기 위해서는, 사용되지 않은 출력값을 검색한다. (모든 출력값은 입력값을 참조하기 때문이다) 이 작업을 출력값들의 합이 보내고자 하는 양만큼 혹은 그 이상이 될 때까지 반복한다.
보이는 것처럼, 다시 우리의 주소로 돌아오는 leftOverAmount
의 값 역시 계산된다.
먼저, 사용되지 않은 출력값의 리스트로 거래의 txIns 를 만들어 낼 수 있다 :
다음으로 2개의 거래 txOuts 가 생기게 된다 : 하나의 txOut 은 코인의 수신자를 위한 것이고 나머지 하나는 leftOverAmount
용이다. 만약 txIns 가 보내져야하는 양과 정확하게 일치한다면, (leftOverAmount 값이 0이라면) “leftOver” 거래를 생성하지 않는다.
이제 txId 를 계산하고 txIns 를 서명한다 :
지갑을 사용하기
지갑의 기능성을 위해서 endpoint 를 추가려고 한다.
결론
이번 단계에서는 우리는 간단한 거래 생성과 함께 지갑을 구현하였다. 비록 우리가 이번에 구현한 거래 생성 알고리즘은 2개 이상의 출력값을 만들 수 없지만 실제 블록체인은 출력값의 개수와 상관없이 모든 종류의 거래를 지원한다. 50개의 입력값 그리고 5,15, 그리고 30의 출력값을 지닌 거래도 생성할 수 있기는 하다, 하지만 우리가 구현한 결과물에서는 /mineRawBlock
인터페이스를 수동적으로 사용하여 생성해야 한다.
또한, 원하는 거래를 블록체인에 포함시키는 유일한 방법은 스스로 채굴하는 것이다. 노드들은 블록체인에 담겨있지 않은 거래에 대한 정보를 서로 교환하지 않는다. 이 부분은 다음 단계 에서 더 보완될 것이다.
구현된 전체코드는 여기서 볼 수 있다.
[1] : wallet.ts 에는 다음의 것들이 구현되어 있다.
const getPrivateFromWallet
const getPublicFromWallet
const generatePrivateKey
const initWallet
const getBalance
const findTxOutsForAmount
const createTxOuts
const createTransaction
[2] : main.ts , transaction.ts , blockchain.ts 에서는 아래와 같이 변화하였다.
main.ts
import wallet
app.post(‘/mineRawBlock’)
app.post(‘/mineBlock’) 변경
app.get(‘/balance’)
app.post(‘/mineTransaction’)
initWallet();
blockchain.ts
const generateNextBlock
const generatenextBlockWithTransaction
const getAccountBalance
transaction.ts
const validateTxIn 변경
원저자 : Lauri Hartikka
원본 : https://lhartikk.github.io