블록체인은 왜 필요했을까: 서명이 못 막는 이중 지불

노란 동전 하나에서 화살표 두 개가 두 가게로 나간다. 위 가게로 가는 화살표는 이어져 ✓ 가 붙고, 아래 가게로 가는 화살표는 점선으로 흐려져 ✗ 가 붙는다.

디지털 서명은 남의 돈을 내가 보내지 못하게 막습니다. 그럼 내 돈을 두 번 보내면 어떨까요? 영희가 같은 1만 원을 가게 A 와 가게 B 에 보냅니다. 은행이 없다면 무엇이 막을까요?

서명이 맞는 거래 두 개

돈은 하나인데 거래는 둘입니다(그림 1). 이것을 이중 지불이라고 합니다 [S2].

돈 하나에서 두 가게로 가는 화살표 두 개 왼쪽에 영희의 1만 원이 하나 있다. 여기서 화살표 두 개가 나와 하나는 가게 A 로, 하나는 가게 B 로 간다. 두 화살표 모두 영희의 서명이 붙은 거래다. 영희 1만 원 거래 + 영희의 서명 거래 + 영희의 서명 가게 A 가게 B
그림 1. 영희가 같은 1만 원을 두 가게에 보냅니다. 두 거래 모두 영희가 서명했습니다.

두 거래 모두 영희가 자기 개인 키로 서명합니다. 가게는 영희의 공개 키로 그 서명을 검증합니다. 직접 보내 보세요.

질문: 같은 돈을 두 가게에 보낸 두 거래는 서명 검증을 통과할까?
영희의 돈1만 원 영희의 공개 키

가게 A 가 받은 거래

아직 보내지 않음

가게 B 가 받은 거래

아직 보내지 않음

서명과 검증에는 브라우저의 서명 기능(Web Crypto, ECDSA)을 씁니다. 곡선은 P-256 입니다. 비트코인은 secp256k1 곡선을 쓰지만 [S4], Web Crypto 표준에는 그 곡선이 없습니다 [S5]. 거래의 모양은 이 글이 정한 교육용입니다.

둘 다 ✓ 입니다. 서명 검증은 거래를 하나씩 봅니다. «영희가 이 거래에 서명했는가» 는 알려 주지만, 같은 돈으로 다른 거래에도 서명했는지는 알려 주지 않습니다. 비트코인 백서도 받는 쪽은 앞 주인이 그 돈을 이중 지불하지 않았는지 검증할 수 없다고 짚습니다 [S1].

은행은 어떻게 막나, 은행이 없으면

가운데에 한 곳을 두면 쉽습니다. 모든 거래가 그곳을 지나면, 그곳에서 어느 거래가 먼저 왔는지 정합니다. 먼저 온 거래만 인정하면 됩니다 [S1]. 은행이 하는 일입니다. 대신 돈 전체가 그 한 곳에 달려 있습니다 [S1].

그 한 곳 없이 하려면 두 가지가 필요합니다. 거래를 모두에게 공개하고, 참여자들이 거래의 차례를 하나로 합의해야 합니다 [S1]. 풀어야 할 것은 서명이 아니라 차례였습니다.

블록이 차례를 정한다

블록체인은 그 차례를 적는 방법입니다. 네트워크의 컴퓨터들이 거래 여러 개를 블록 하나로 묶습니다. 각 블록에 앞 블록의 해시 값을 넣어 한 줄로 잇습니다(그림 2) [S1]. 이 사슬이 거래의 차례를 적은 장부가 됩니다 [S3]. 새 블록은 네트워크의 모든 컴퓨터에 전해지고 [S1], 저마다 검사해 자기 사슬에 잇습니다. 그래서 보통은 모두 같은 사슬을 갖습니다 [S3].

앞 블록의 해시 값으로 이어진 블록 세 개 블록 1, 블록 2, 블록 3 이 왼쪽에서 오른쪽으로 놓여 있다. 블록 2 와 블록 3 에는 앞 블록의 해시 값이 들어 있어 앞 블록을 가리킨다. 블록 1 에는 영희가 1만 원을 받은 거래가, 블록 2 에는 영희가 가게 A 로 보낸 거래가 들어 있다. 영희가 가게 B 로 보낸 거래는 블록 3 에 들어가려 하지만 이미 쓴 돈이라 들어가지 못한다. 먼저 나중 블록 1 앞 블록의 해시 값 영희가 1만 원 받음 다른 거래들 블록 2 앞 블록의 해시 값 영희 → 가게 A 다른 거래들 블록 3 앞 블록의 해시 값 다른 거래들 영희 → 가게 B ✗ 이미 쓴 돈 — 못 들어감
그림 2. 블록마다 앞 블록의 해시 값이 들어 있어 한 줄로 이어집니다. 가게 A 로 가는 거래가 블록 2 에 먼저 들었으므로, 같은 돈을 쓰는 가게 B 로 가는 거래는 뒤 블록에 들어가지 못합니다.

규칙은 은행과 같습니다. 블록에 든 거래가 이미 쓴 돈을 또 쓰면, 네트워크의 컴퓨터들은 그 블록을 받지 않습니다 [S1]. 같은 돈은 블록체인에서 한 번만 쓸 수 있습니다 [S3]. 먼저 든 것만 인정합니다.

두 거래가 동시에 다른 블록에 들어가면

블록을 만드는 곳은 여럿입니다. 두 곳이 거의 같은 때에 블록을 만들면 사슬이 잠깐 둘로 갈라집니다 [S3]. 한쪽 블록에는 가게 A 로 가는 거래가, 다른 쪽에는 가게 B 로 가는 거래가 들었다고 합시다. 어느 쪽이 남을까요?

질문: 두 거래가 서로 다른 블록에 들어가 사슬이 갈라지면, 어느 쪽이 남을까?

다음 블록이 어느 쪽에 붙을지는 난수로 흉내 냅니다(양쪽 계산력이 같다고 두어 반반). 실제 작업 증명 계산이 아닙니다. 블록의 해시 값은 실제 SHA-256 으로 계산합니다.

네트워크의 컴퓨터들은 가장 긴 사슬을 옳은 것으로 봅니다. 여기서는 블록마다 드는 작업이 같다고 둡니다. 다음 블록이 한쪽에 붙어 그쪽이 길어지면 모두 그쪽으로 옮깁니다 [S1]. 짧은 쪽 블록은 버려집니다 [S3]. 그 블록에 있던 가게 B 로 가는 거래는, 남은 사슬에서는 이미 쓴 돈을 또 쓰는 거래라 다시 들어가지 못합니다. 앞 장의 «먼저 든 것만» 규칙 그대로입니다. 같은 돈을 쓰지 않는 다른 거래라면 대기 줄로 돌아가 뒤 블록에 들어갈 수 있습니다 [S2].

어느 쪽이 남을지는 다음 블록이 나오기 전에는 알 수 없습니다. 쌓인 블록도 더 긴 사슬에 덮일 수 있습니다. 그래서 받는 쪽은 보통 자기 거래가 든 블록 위에 블록이 몇 개 더 쌓일 때까지 기다립니다 [S2].

그 차례를 못 고치게

남은 걱정은 영희가 지난 차례를 고쳐 쓰는 것입니다. 가게 A 에서 물건을 받은 뒤 그 거래가 없는 사슬을 따로 더 길게 만들어 내놓으면 돈을 되찾으려 할 수 있습니다 [S1]. 이것을 어렵게 하는 것이 작업 증명입니다. 블록을 만들려면 조건에 맞는 해시 값을 찾는 계산(작업)을 해야 합니다 [S1].

뒤 블록이 앞 블록에 이어져 있습니다. 지난 블록 하나를 고치려면 그 뒤 모든 블록의 작업도 다시 해야 합니다 [S1]. 블록이 어떻게 이어져 있는지, 그 작업이 왜 비싼지는 다음 글부터 차례로 다룹니다.

한계도 있습니다. 백서의 조건은 정직한 쪽이 계산력의 과반을 쥐고 있는 것입니다 [S1]. 그래서 블록체인은 «절대 못 고치는 장부» 가 아닙니다. 고치면 드러나고, 고치기 어려운 장부입니다 [S2].

이 글의 계산과 확인

시뮬레이터 ① 은 서명·검증에 브라우저의 Web Crypto ECDSA(P-256 곡선, SHA-256)를 씁니다. 키는 페이지를 열 때마다 새로 만들고, 어디에도 보내지 않습니다. 비트코인이 쓰는 secp256k1 곡선 [S4] 은 Web Crypto 표준이 정한 곡선(P-256·P-384·P-521)에 없어 [S5] 곡선만 바꿨습니다. «서명이 두 거래를 구별하는가» 는 곡선과 상관없습니다.

거래와 블록의 모양, «같은 돈을 쓰는 거래는 먼저 든 것만 유효» · «더 긴 사슬이 남는다» 를 판정하는 코드는 이 글이 직접 짠 교육용입니다 (실제로 쓰지 말 것). 실제 비트코인의 거래·블록 형식이 아니고, 시뮬레이터 ② 는 작업 증명을 하지 않습니다. 시뮬레이터의 블록은 만드는 데 드는 작업이 모두 같다고 둡니다. 그래서 «가장 긴 사슬» 이 곧 «다시 만들기 가장 어려운 사슬» [S3] 입니다.

같은 계산을 Node 의 crypto(OpenSSL)로 교차 확인했습니다. Node 는 같은 돈을 쓰는 두 거래의 서명을 모두 검증했습니다. Node 가 만든 서명도 이 글의 검증을 통과했습니다. 받는 이·금액·서명 한 비트를 고치거나 다른 키를 쓰면 검증에 실패합니다. 사슬에 먼저 든 거래만 유효로 판정하고, 갈라진 사슬에서 긴 쪽을 고르며, 버려진 블록의 거래가 남은 사슬에 다시 들어가지 못하는 것도 시험했습니다 (verify.mjs 47개 통과).

출처

  1. [S1] Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System (2008) — §2, §3, §4, §5, §11
  2. [S2] NIST IR 8202, Blockchain Technology Overview (2018) — §4.7, §7.1, 용어집
  3. [S3] Bitcoin Developer Guide — Block Chain
  4. [S4] Bitcoin Developer Guide — Transactions
  5. [S5] W3C, Web Cryptography API — Named Curve