블록은 어떻게 이어져 있을까: 앞 블록의 해시 값을 적는 장부
동아리 회비 장부를 여럿이 돌려 가며 씁니다. 누가 석 달 전 줄의 «간식비 12,000원» 을 «21,000원» 으로 고쳤다면 알아챌 수 있을까요? 블록체인은 장부 가운데 줄을 고치면 드러나게 합니다. 무엇이 드러나게 할까요?
장부 가운데 한 줄
앞 글에서 블록체인은 거래의 차례를 모두가 같게 적어 두는 장부였습니다. 그런데 장부는 한번 적힌 줄이 그대로 남아 있어야 쓸모가 있습니다.
종이 장부나 변경 기록이 없는 스프레드시트에서 한 줄을 고치면 고친 뒤의 모습만 남습니다(그림 1). 줄마다 디지털 서명을 붙여도, 장부를 맡은 사람이 자기 줄을 고치고 다시 서명하면 검증은 통과합니다.
블록마다 앞 블록의 해시 값을 적는다
블록체인은 장부를 블록이라는 묶음으로 나눕니다. 각 블록에는 거래와 앞 블록의 해시 값을 함께 적습니다 [S2]. 블록 2 에는 블록 1 의 해시 값이, 블록 3 에는 블록 2 의 해시 값이 들어갑니다(그림 2).
해시 함수는 입력이 한 글자만 달라도 전혀 다른 값을 내므로(해시 함수 글), 이 칸 하나가 앞 블록 전체에 묶입니다. 실제 비트코인은 블록 전체가 아니라 블록 맨 앞의 헤더만 해시합니다. 헤더에는 그 블록의 거래 전체에서 나온 해시 값이 들어 있어, 거래 하나를 고치면 헤더도 달라집니다 [S4]. 그리고 블록마다 앞 블록 헤더의 해시 값을 적는 32바이트 칸이 있습니다 [S4].
고치면 어긋남이 뒤로 번진다
아래는 다섯 달 치 장부를 나눈 블록 다섯 개입니다. 가운데 블록 3 에 있는 3월 간식비를 고쳐 보세요. 그다음 고친 사람이 되어 어긋난 칸을 새 값으로 고쳐 적어 보세요.
다른 블록의 거래 칸도 직접 고칠 수 있습니다. 블록의 해시 값은 «앞 블록의 해시 값 + 거래» 를 SHA-256 에 넣어 구합니다. 앞 12자리만 보입니다. 처음과 달라진 값은 노랗게 칠합니다. 블록 모양과 SHA-256 코드는 이 글이 직접 짰습니다(교육용 — 실제로 쓰지 말 것).
고친 블록의 해시 값은 다음 블록에 적힌 값과 맞지 않습니다. 그 뒤 블록들은 사슬이 앞에서 끊겨 믿을 수 없습니다. 어긋난 칸을 새 값으로 고쳐 적으면 이번에는 다음 블록의 해시 값이 바뀌어, 어긋남이 한 칸 뒤로 옮겨 갑니다. 이렇게 블록 하나가 바뀌면 그 뒤 블록의 해시 값도 차례로 모두 달라져야 합니다. 그래서 고치기 전 사슬을 가진 네트워크의 다른 컴퓨터들과 견주면, 고친 블록을 쉽게 찾아 거부할 수 있습니다 [S2]. 그래서 거래 하나를 고치려면 그 블록과 뒤 블록을 모두 고쳐야 합니다 [S3].
그럼 뒤를 다 고쳐 쓰면?
끝까지 고쳐 적으면 장부 안에는 어긋난 곳이 남지 않습니다. 얼마나 걸리는지 재 봅니다.
순식간입니다. 누구나 해시 값을 금방 다시 계산할 수 있어서, 해시 값으로 잇는 것만으로는 모자랍니다. 남는 방어선은 둘입니다.
하나는 사본입니다. 다시 맞춘 장부는 마지막 해시 값이 달라집니다. 고치기 전 장부를 가진 사람과 견주면 두 장부가 다르다는 것이 드러납니다. 비트코인은 거래를 모두에게 공개합니다 [S1].
다른 하나는 작업 증명입니다. 비트코인 백서는 블록의 해시 값이 정해진 개수의 0 비트로 시작할 때까지 블록 안의 숫자 하나를 바꿔 가며 해시 값을 다시 계산하게 한다고 설명합니다 [S1]. 그러면 고치는 사람은 그 블록과 뒤 블록의 계산을 모두 다시 하면서, 그사이에도 네트워크의 컴퓨터들이 잇는 사슬을 따라잡고 앞질러야 합니다 [S1]. 더 긴 사슬이 남기 때문입니다(앞 글). 그 계산이 왜 큰지는 다음 글에서 다룹니다.
해시 값으로 이으면 되는 것과 안 되는 것
방금 본 것처럼 고쳐 쓸 수는 있습니다(시뮬레이터 ②). 다만 사본과 견주면 드러나고, 작업 증명이 있으면 다시 쓰는 데 큰 계산이 듭니다. 그래서 블록체인을 «고칠 수 없는» 장부라고 하면 정확하지 않습니다. NIST 는 고치면 드러나고(tamper evident) 고치기 어려운(tamper resistant) 장부라고 적습니다 [S2].
| 물음 | 해시 값으로 잇기만 하면 | 더 필요한 것 |
|---|---|---|
| 가운데 블록을 고치면? | 다음 블록에 적힌 값과 달라 드러납니다 (시뮬레이터 ①) | — |
| 고치고 뒤를 모두 다시 쓰면? | 장부 안에서는 흠이 없습니다 (시뮬레이터 ②) | 고치기 전 사본과 견주기, 다시 쓰기를 비싸게 하는 작업 증명 [S1] — 다음 글에서 다룹니다 |
| 거래 내용을 숨겨 주나? | 아니요. 숨기는 장치가 아니라 고치면 드러나게 하는 장치입니다 | 비트코인의 거래는 모두에게 공개됩니다 [S1] |
| 누가 쓴 거래인가? | 알려 주지 않습니다 | 디지털 서명 |
이 글의 계산과 확인
시뮬레이터의 블록은 «앞 블록의 해시 값(16진수 64자) + 줄바꿈 + 거래 글자» 를 SHA-256 에 넣는 이 글의 교육용 모양입니다. 실제 비트코인은 80바이트 블록 헤더만 해시하고, 거래는 머클 루트라는 해시 값 하나로 묶어 헤더에 넣습니다 [S3] [S4]. 첫 블록의 앞 블록의 해시 값을 0 으로 채우는 것은 흔한 관례를 따랐습니다 [S2].
SHA-256 은 FIPS 180-4 를 옮긴 순수 자바스크립트 코드입니다. Node 의 crypto(OpenSSL)와 교차 확인했습니다. 그림 2 의 해시 값, «블록 3 을 고치면 블록 4 에서 ✗ 가 나고 그 뒤는 검증하지 못한다», «고쳐 적을 때마다 ✗ 가 한 칸 뒤로 간다», «모두 다시 맞추면 장부 안은 모두 ✓ 이지만 마지막 해시 값은 다르다» 를 verify.mjs 가 확인합니다. 시뮬레이터 ② 의 시간은 읽는 기기에서 그 자리에서 한 번 잰 값이라 기기마다 다릅니다.