어제 비트코인 네트워크는 지난 4년 동안 우리가 목격한 가장 심각한 문제 중 하나를 경험했습니다. 블록 225430부터 블록체인이 실제로 두 개로 나뉘어, 네트워크의 한쪽 절반은 체인의 한 버전에 블록을 추가하고, 다른 절반은 다른 버전에 블록을 추가했습니다. 다음 6시간 동안 두 개의 비트코인 네트워크가 동시에 운영되었으며, 각각 고유한 거래 기록을 가지고 있었습니다. 분할은 24 블록 또는 6시간 동안 지속되었고, 결국 블록 225454에서 한 버전의 체인이 다른 버전보다 확실히 앞서면서 해결되었습니다. 다른 체인은 대부분 버려졌고, 이제 주요 체인을 인식할 수 없는 소수의 채굴자만이 여전히 그 체인을 채굴하고 있었으며, 나머지 네트워크는 빠르게 정상으로 돌아갔습니다.
포크는 3월 11일 월요일 GMT 23:30경에 처음 발견되었습니다. 비트코인 개발자 IRC 채널의 “thermoman”이 “어떤 클라이언트가 내 클라이언트에게 (다른 호스트가) 225431 블록을 가지고 있다고 말했지만, 블록 탐색기는 현재 블록 수가 225430이라고 말하고 있다”고 언급했습니다. 다른 블록체인 리소스도 225430 블록을 보여주었습니다. 다음 30분 동안 다른 사용자들이 비트코인 클라이언트 로그에서 더 이상한 보고서를 보고하기 시작했습니다. 비트코인 개발자 피터 위유(Peter Wuille, IRC에서 “sipa”로 알려짐)는 자신이 블록 225435에 있다고 주장했고, 곧 225439에 도달했다고 했습니다. 다른 소스들은 여전히 225431을 보고하고 있었습니다. 3월 12일 00:00 GMT에 sipa는 “네트워크에서 무엇이 이를 촉발했는지 궁금하다. 대규모 재조직 같은 것”이라고 게시했습니다. 실제로 블록체인 재조직이 발생했으며, 이는 클라이언트가 이전에 작업하던 블록체인보다 더 긴 새로운 블록체인을 발견하고 전환할 때 발생하는 이벤트입니다. 그리고 몇 분 후 모두가 무슨 일이 일어나고 있는지 깨달았습니다: 블록체인 포크였습니다.
무슨 일이 있었는지 다음과 같습니다. 비트코인 채굴자들이 가장 많이 사용하는 비트코인 구현인 bitcoind의 최신 버전 0.8이 블록과 거래를 저장하는 데 사용하는 데이터베이스를 BerkeleyDB에서 더 효율적인 LevelDB로 전환했습니다. 이는 블록체인 동기화 시간을 줄이기 위한 노력의 일환이었습니다. 그러나 개발자들이 그 당시 깨닫지 못한 것은 그렇게 함으로써 비트코인 프로토콜의 규칙에 변경을 우연히 도입했다는 것입니다. 데이터베이스를 업데이트하기 위해 데이터베이스 프로세스는 특정 정보 항목을 저장하는 데이터베이스의 일부에 “잠금”을 설정해야 하며, 이는 두 개의 변경이 동시에 발생하여 데이터베이스가 손상되는 것을 방지하기 위해 구현된 메커니즘입니다. B-tree에서 BerkeleyDB가 객체를 저장하는 데 사용하는 데이터 구조에서 업데이트당 두 개의 잠금이 필요합니다. 그러나 BerkeleyDB는 사용자가 동시에 설정할 수 있는 잠금 수에 제한을 두도록 요구합니다; “값이 너무 작으면,” FAQ 페이지는 경고합니다, “응용 프로그램에서 잠금 요청이 실패합니다. 값이 너무 크면 잠금 하위 시스템이 필요 이상으로 많은 자원을 소모합니다.” 비트코인의 경우, 제한은 10,000이었습니다. 블록 225430에서 발생한 일은 단일 블록이 5,000개 이상의 거래 상태에 동시에 영향을 미쳐 b-tree에서 동시에 10,000개 이상의 잠금을 요구했습니다. 결과적으로 BerkeleyDB가 실패했고, 이전 버전의 bitcoind 0.7은 블록을 읽을 수 없었습니다. bitcoind 0.8의 경우 LevelDB는 그러한 제한이 없으므로 해당 블록을 잘 수용할 수 있었습니다. 비트코인 프로토콜은 거래 기록을 쌓아가며, 이는 주로 모든 사람의 계좌 잔액을 계산하고 합의하는 데 사용되며, 기존의 유효한 블록 위에 약 10분 간격의 거래를 나타내는 새로운 블록을 생성하여 이루어집니다(따라서 “블록체인”). bitcoind 0.8을 사용하는 채굴자들은 문제의 블록을 포함하는 블록체인 버전을 구축하기 시작했고, bitcoind 0.7을 사용하는 채굴자들은 이를 거부하고 자신만의 블록체인에서 작업을 시작했습니다. 비트코인Qt 0.7을 사용하는 일반 사용자나 bitcoind 0.7을 서버로 사용하는 플랫폼은 0.7 포크를 보았고, 나머지 모든 사람은 0.8 포크를 보았습니다.
포크가 진행되는 동안 비트코인 개발자들은 선택의 기로에 놓였습니다: 0.8 포크를 지원할 것인가, 아니면 0.7 포크를 지원할 것인가? 궁극적으로 하나만 존재할 수 있었습니다; 각 개인이 가진 돈의 양에 대한 두 개의 서로 다른 데이터베이스가 있다면 화폐 시스템은 기능할 수 없습니다. 0.8 포크는 훨씬 더 많은 컴퓨팅 파워를 가지고 있었고, 커뮤니티가 문제를 해결하기 위한 노력을 기울일 수 있을 때까지 이미 8 블록 앞서 있었습니다. 0.8로의 업그레이드는 결국 해야 할 일이었습니다. 반면, 0.8 포크가 장악하게 되면 0.7의 수천 명의 사용자가 비트코인을 사용하기 위해 업그레이드해야 했고, 이는 0.7 포크가 장악할 경우에는 발생하지 않을 일이었습니다. 개발자들은 빠르게 0.7로 정착했고, 커뮤니티는 다음 작업에 착수했습니다: 주요 채굴자와 채굴 풀 운영자에게 그들이 해야 할 일을 알리는 것이었습니다.
다음 몇 시간 동안 거의 모든 주요 비트코인 개발자와 채굴 풀 운영자가 bitcoin-dev IRC 채널에 합류했습니다. bitcoind 0.8을 사용하는 주요 채굴 풀은 중단하고 0.7로 다운그레이드한 후 다시 켰습니다. 상인들도 통보받았으며; 비트코인스토어, 비트페이, 사토시다이스, 그리고 MtGox를 포함한 대부분의 대기업은 이중 지출 공격으로부터 자신을 보호하기 위해 입금을 중단했습니다. 비트페이는 서버가 0.7 포크에 있을 때 빠르게 다시 켰습니다; “안전 모드가 문제를 알렸습니다,” 비트페이의 토니 갈리피가 씁니다. “그때 스티브가 IRC에 뛰어들어 합의가 어디로 가고 있는지 확인했고, 우리는 매우 빠르게 비즈니스로 돌아갔습니다.” 해시 파워를 0.8로 전환하는 진행은 처음에는 느린 것처럼 보였고, 블록 225451에서 0.8 체인은 0.7보다 13 블록 더 길었습니다. 그러나 그것이 0.8 체인이 앞서 나갈 수 있는 최대 길이였습니다. 그때 두 체인은 대략 동기화되어 성장하고 있었고, 약 03:30에 전환점이 왔습니다. 0.7 체인은 빠르게 따라잡아 10 블록 뒤로, 그 다음 8 블록 뒤로, 그리고 06:19에 두 체인은 블록 225454에서 같은 길이로 수렴하여 거의 모든 남은 채굴자가 다른 체인을 포기하게 만들었습니다.
이번 사건은 비트코인 프로토콜이 실제로 실패할 뻔한 가장 가까운 순간 중 하나로 역사에 남을 것입니다. 그러나 이것이 지금까지 발생한 가장 심각한 위반은 아닙니다. 2010년 8월, 블록 74638의 거래는 1840억 이상을 합산하는 두 개의 출력을 포함하고 있었습니다 – 2^64 사토시를 약간 초과하는 양입니다. 그 결과는 정수 오버플로우 버그로, 기계식 주행 거리계가 자동차가 999,999킬로미터를 주행한 후 0으로 돌아가는 디지털 동등물입니다.
오버플로우로 인해 소프트웨어는 거래가 실제로는 2100만 개보다 수천 배 더 많은 BTC를 포함하고 있는 반면, 거래가 소량의 BTC만 포함하고 있다고 생각하게 되었습니다. 비트코인 소프트웨어의 새로운 버전을 게시해야 했고, 블록체인은 포크되었으며, 새로운 유효한 체인이 블록 74691에서 이전 체인을 추월했습니다 – 원래 포크 이후 53 블록 후입니다. 이번에는 24 블록이 걸렸고, 시스템에 생명에 치명적인 위협이 되지도 않았습니다 – 개발자들이 아무것도 하지 않았다면 비트코인은 여전히 계속되었을 것이며, 단지 bitcoind와 BitcoinQt 사용자가 0.7에 있었고 업그레이드해야 했던 불편함만 초래했을 것입니다.
경제적 피해는 상당했지만 비교적 작았습니다; 보고된 유일한 금전적 손실은 이제 영원히 버려진 체인에서 24개의 채굴된 블록에서 발생한 25 BTC의 채굴 보상으로 약 26,000달러와 OKPay에 대한 10,000달러의 이중 지출입니다. 잃어버린 채굴 수익과 이 이중 지출 외에는 거래에 영향을 미치지 않았고 비트코인이 “잃어버린” 것은 없었습니다; 이제 버려진 체인에 포함된 모든 거래는 새로운 체인에도 포함되었으므로 포크 중에 지출된 모든 비트코인은 이제 적절한 목적지에 도달했습니다.
어떤 면에서 이것은 이러한 일이 발생하기에 가장 좋은 시점이었습니다. 비트코인 가격은 꾸준한 상승세를 보였고, 사건 발생 당시 24%의 가격 하락은 빠르게 반전되었으며, 이 글을 쓰는 시점에서 비트코인은 44-46달러에 거래되고 있으며, 하루 전 48달러에서 하락했지만 일주일 전 36달러에서 상승했습니다. 비트코인에 대한 대중 매체의 관심은 매우 긍정적이며, 2011년처럼 비트코인을 공격하기보다는 많은 기자들이 비트코인 개발 팀의 신속한 대응을 칭찬했습니다. Ars Technica의 팀othy B Lee는 사건에 대해 중립적인 기사를 작성하며 “이 사건은 암호화폐의 분산 거버넌스 구조에 대한 중요한 시험이 될 것”이라고 썼고, 이 주제에 대한 ecurrency.ec의 기사는 “비트코인 소프트웨어 버그가 신속하게 해결되었습니다”라는 제목이 붙었습니다.
그러나 이 사건은 비트코인 프로토콜의 본질에 대한 심각한 질문을 제기하며, 비트코인의 “탈중앙화” 개념에 대한 불편한 사실들을 조명합니다. 대부분의 보안 프로토콜, 암호화 알고리즘, 해시 알고리즘 및 전체 규모의 프로토콜은 여러 프로그래밍 언어로 수십 개의 구현이 있으며, 프로토콜 사양은 모든 개별 구현이 준수 여부를 확인할 수 있는 명확한 표준에 의해 결정됩니다. 그러나 비트코인의 경우 상황이 다릅니다. 비트코인 위키 페이지에는 기술적으로 표준이 있지만, 때때로 잘 업데이트되지 않았으며, 현실은 bitcoind 구현이 표준이며 비트코인 네트워크의 거의 모든 채굴자가 그 버전을 사용하고 있다는 것입니다. 몇 가지 대체 구현이 있지만, 가장 완전한 것은 아미르 타키의 libbitcoin이며, 마이크 헌의 BitcoinJ(자바로 작성됨)가 그 뒤를 따르고 있지만, 지금까지 채굴에서 사용되는 비율은 매우 낮습니다. 더욱이 비트코인 개발 커뮤니티의 일부는 여러 코드베이스를 사용하는 아이디어에 적극 반대하고 있습니다.
다행히도 대부분의 비트코인 개발자들은 이러한 관점을 지지하지 않지만, 많은 사람들이 건강한 수준의 신중함을 유지하는 데 찬성하고 있습니다. 마이크 헌은 2011년 6월 Bitcointalk 포럼에 다음과 같이 썼습니다:
가빈은 BitCoinJ 출시 며칠 후에 나에게 대체 구현을 보게 되어 얼마나 기쁜지 이야기했습니다. 사토시는 매우 유사한 감정을 표현했습니다. 대체 구현에 반대하는 사람은 없습니다.
어떤 사람들이, 특히 사토시가 말한 것은 전체 시스템을 재구현하고 그 재구현을 사용하여 채굴하는 것과 관련된 비정상적으로 높은 위험이 있다는 것입니다. 비트코인은 매우 복잡하며, 숙련되지 않거나 매우 철저하지 않으면 작은, 감지하기 어려운 방식으로 그 행동에서 벗어날 가능성이 높습니다. 이는 체인을 포크하고 경제를 분할할 수 있습니다. 이것은 비트코인을 즉시 죽일 수 있는 몇 안 되는 것 중 하나입니다.
주요 비트코인 개발자 가빈 안드레센은 같은 스레드의 다른 게시자에게 “정말요? 나는 대체 구현을 장려해왔는데, 권력을 탐내는 핵심 개발자는 누구인가?”라고 답했고, 2012년 11월 비트코인 재단 업데이트에서 “해결책의 일부는 참조 구현과 다른 신뢰/편의성 거래를 만드는 대체 구현을 장려하는 것입니다. 교차 구현 테스트에 대한 많은 비하인드 작업이 있었으며(예를 들어 “testnet3” 블록체인은 수백 개의 거래 유효성 검사 테스트 사례를 포함하고 있습니다), 대체 구현을 지원하기 위해 프로토콜에 새로운 기능이 추가되고 있습니다.”라고 썼습니다.
그러나 대체 구현은 단순히 서로 다른 신뢰/편의성 거래를 지원하는 데 유용할 뿐만 아니라 비트코인의 탈중앙화 주장을 현실로 만드는 데도 중요합니다. 만약 포크 당시 다섯 개의 뚜렷한 비트코인 구현이 사용되고 있었다면, 다섯 개 중 하나가 잘못된 블록체인을 인식하고 포크되어 소수의 채굴자에게 수익 손실을 초래하고 해당 구현을 사용하는 클라이언트의 사용자에게 업그레이드를 요구했을 것입니다. 비정상적인 구현의 블록체인 포크는 처음부터 다른 것들보다 훨씬 약해질 것이므로 이중 지출 공격의 위험은 최소화될 것입니다. 더 많은 구현이 있을수록 포크 사건이 더 많이 발생할 것이라고 주장할 수 있지만, 각 사건은 효과가 더 작을 것이며, 출시 전에 테스트넷에서 모든 구현을 함께 테스트하면 프로덕션 소프트웨어에 침투하는 버그의 수를 오늘날 우리가 보는 빈도와 비슷하게 줄일 수 있습니다.
이번 사건이 비트코인의 탈중앙화에 대한 또 다른 측면을 의문시하는 것은 채굴 풀입니다. 0.7 포크로의 통제된 전환이 가능했던 이유는 비트코인 네트워크의 해시 파워의 70% 이상이 소수의 채굴 풀과 ASIC 채굴자에 의해 통제되었기 때문이며, 따라서 채굴자들은 모두 개별적으로 연락을 받고 즉시 다운그레이드하도록 설득될 수 있었습니다. 포크에 대한 또 다른 기사는 [러시아어]: “실제 문제는 비트코인 네트워크를 지원하는 코드에 있는 것이 아닙니다; 버그는 어디에나 있습니다. 오히려, 누가 그것을 통제하는가의 문제입니다. 이 사건은 잘 설계된 시스템조차도 매우 소수의 사람들의 의지에 의해 통제된다는 것을 분명히 보여주었습니다 – 특히 채굴 풀 운영자들입니다. 현재 새로운 블록의 70% 이상이 풀에서 발견되고 있으며, 개인 솔로 채굴자에서는 발견되지 않고 있습니다. 시스템의 기본 아이디어는 자비로운 다수가 소수의 공격자를 저지할 수 있다는 것이지만, 현재로서는 단순히 작동하지 않습니다. 가능한 인수에서 승자는 더 큰 컴퓨팅 파워를 가진 자가 될 것이며, 다른 누구도 아닙니다.” 비트코인은 분명히 많은 초기 지지자들이 상상했던 직접 민주주의가 아니며, 일부는 비트코인 커뮤니티의 중앙집중적인 핵심이 비트코인 블록체인을 바로잡기 위한 이러한 긴급 조치를 성공적으로 수행할 만큼 강력하다면, 그들이 할 수 있는 다른 일은 무엇인지 걱정합니다. 백만 달러 도난을 되돌리기 위해 이중 지출을 강제할 수 있을까요? 실크로드에서 유래된 거래를 차단하거나 심지어 리디렉션할 수 있을까요? 심지어 비트코인의 신성한 2100만 통화 공급 한도를 수정할 수 있을까요?
그러나 이러한 두려움이 실제로 실현될 가능성이 매우 낮다는 강력한 주장을 할 수 있습니다. 그 이유는 비트코인 채굴 풀 운영자의 특정 신원이나 비트코인 채굴 커뮤니티의 응집력과는 아무런 관련이 없으며, 오히려 비트코인 채굴이 여전히 사실상 상당히 탈중앙화되어 있다는 사실입니다; 단지 다른 방식으로 탈중앙화되어 있을 뿐입니다. 정치적 비유를 들자면, 가장 가까운 동등물은 유동 민주주의입니다: 사람들이 개별 법안에 대해 스스로 투표하거나 정치인에게 위임할 수 있는 직접 민주주의와 대의 민주주의의 혼합으로, 주어진 정치인이 하는 일이 마음에 들지 않으면 언제든지 다른 사람에게 투표 권한을 전환할 수 있는 조건이 있습니다. 비트코인의 세계로 돌아가면, 비트코인 네트워크의 해시 파워의 대부분이 채굴 풀 운영자에게 집중되어 있지만, 모든 개별 채굴자는 거의 즉시 한 풀에서 다른 풀로 전환할 수 있으므로, 채굴 풀 운영자들이 비트코인 프로토콜을 위반하기로 결정하면 채굴자들은 정직한 풀로 즉시 전환하여 범죄자들의 권력을 빼앗을 수 있습니다. 지금까지 어떤 채굴 풀도 비트코인 프로토콜을 적극적으로 전복하려고 시도한 적은 없지만, 이러한 종류의 “투표”는 이전에 이루어진 적이 있습니다; 2011년에는 채굴 풀 Deepbit이 전체 네트워크 해시 파워의 50%를 초과한 여러 사건이 있었고, 각 경우에 채굴자들은 균형을 맞추기 위해 다른 풀로 대규모로 이탈했습니다. 명목상의 권력은 채굴 풀 운영자에게 있을 수 있지만, 커뮤니티의 피드백은 항상 한 걸음 떨어져 있습니다.
전체적으로 이번 사건은 매우 잘 처리되었으며, 비트코인 커뮤니티의 모든 구성원들은 문제를 신속하게 해결한 것과 무조건적인 협력에 대해 스스로 축하해야 합니다. 비트코인 커뮤니티는 항상 완벽한 조화를 이루는 것은 아니며; 비트코인 도박 사이트인 사토시다이스와 여러 비트코인 개발자, 특히 루크 대셔는 사토시다이스의 대량 거래 수가 비트코인 블록체인을 부풀리고 있다는 우려로 종종 대립하고 있지만, 어제는 커뮤니티가 문제를 해결하기 위해 함께 작업하는 동안 차이점이 제쳐졌습니다. 우리는 또한 많은 것을 배웠으며, 상인들은 앞으로 이러한 사건에 훨씬 더 잘 대비할 가능성이 높으며, 아마도 자동 포크 감지와 같은 기술을 구현하여 포크를 처리하고 즉각적인 수동 개입 없이 이중 지출을 피할 수 있을 것입니다. 오늘 이전에 많은 사람들은 비트코인 네트워크에서 어떤 테스트가 올 것이라는 것을 알고 있었으며, 1MB 블록 크기 제한 또는 다른 곳에서 올 것이라는 점에서, 커뮤니티가 그러한 일을 어떻게 처리할지는 알 수 없었습니다. 이제 테스트가 지나갔고, 비트코인 커뮤니티가 테스트를 어떻게 처리했는지는 모두에게 알려졌습니다: 우리는 훌륭하게 통과했습니다.