본 문서는 비트코인 커뮤니티의 기여자로서 마스터링 비트코인(Mastering Bitcoin 3rd Edition) 및 다양한 기술문서를 전문적으로 작성하는 데이비드 하딩(David Harding)의 에라타(errata) 문서를 한글로 번역하고, 비트코인 백서를 중심으로 비트코인 구현체의 과거와 현재를 연구하고 있는 비트코인 연구그룹(Bitcoin Research Team in Orakle@Kaist)의 연구 결과물을 기술문서의 형태로서 커뮤니티에 기여하기 위해 작성하는 것임을 명시합니다.
데이비드 하딩(David Harding)의 에라타(errata) 문서는 사토시 나카모토의 논문 "비트코인: Peer-to-Peer 전자 화폐 시스템"에서 알려진 문제들에 대한 설명과 용어 변경에 대한 주석 및 논문에서 설명된 내용과 비트코인의 실제 구현이 어떻게 다른지에 대한 설명입니다.
가장 긴 체인(The longest chain)은 목격된 사건들의 순서를 증명할 뿐만 아니라, 가장 큰 CPU 파워 풀에서 생성되었음을 증명다.
-
구현 세부 사항: 체인의 각 링크(비트코인에서 "블록"이라 함)가 동일한 양의 PoW(Proof of Work)를 사용하여 구축이 되었다면, 가장 긴 체인은 가장 큰 계산 능력 풀로 뒷받침되는 체인 일것입니다. 그러나 비트코인은 블록마다 PoW의 양이 다를 수 있는 방식으로 구현되었기 때문에 "가 장 긴 체인(the longest chain)"을 확인하는 것이 아니라 "가장 많은 PoW를 보여주는 체인 (the chain demonstrating the most POW)"을 확인하는 것이 중요해졌습니다. 이는 종종 "가장강한 체인(strongest chain)"으로 단축됩니다.
체인의 길이를 확인하는 것에서 가장 많은 작업량을 가진 체인을 확인하는 것으로 변경 된 것은 비트코인의 초기 출시 후 한참 지난 2010년 7월에 발생했습니다.
- if (pindexNew->nHeight > nBestHeight) + if (pindexNew->bnChainWork > bnBestChainWork)
-
용어 변경: 초기 비트코인 블록을 생성하는 작업 증명(POW)에는 일반 CPU가 사용되었지만, 오늘날에는 주로 전문적인 응용 특화 집적 회로(ASIC)가 사용됩니다. 따라서 "CPU 파워"라고 말하는 것보다 "연산 파워" 또는 단순히 "해시율"이라고 하는 것이 더 정확합니다.
대다수의 CPU 파워가 네트워크를 공격하기 위해 협력하지 않는 노드들에 의해 통제되는 한, 그들은 가장 긴 체인을 생성하고 공격자들을 앞설 것입니다.
-
용어 변경: 오늘날 "노드(Node)"라는 용어는 시스템의 모든 규칙을 시행하는 프로그램을 의미하는 전체 검증 노드를 지칭합니다. 현재 체인을 확장하는 프로그램(및 하드웨어)은 나카모토가 논문의 6장에서 금광 채굴자에 비유한 것을 바탕으로 "채굴자(Miners)"라고 불립니다. 나카모토는 모든 채굴자가 노드가 되기를 기대했지만, 그가 출시한 소프트웨어는 모든 노드가 채굴자가 되는것을 필수 사항으로 요구하지 않았습니다. 초기의 소프트웨어에서는 노드 GUI의 간단한 메뉴 항목을 통해 채굴 기능을 켜거나 끌 수 있었습니다.
오늘날에는 압도적인 수의 노드가 채굴자가 아니며, 채굴 하드웨어를 소유한 많은 개인들이 이를 자신들의 노드 와 함께 사용하지 않고 있습니다(자신의 노드와 함께 채굴을 하는 경우에도 새로 발견된 블록 위에서 짧은 기간 동안 채굴할 뿐, 그들의 노드가 새 블록을 유효하다고 간주하는 것을 확인하지 않는 경우가 많습니다). 논문의 초기 부분에서 "노드"가 주로 수식어 없이 사용되는 경우는 전체 검증 노드를 사용한 채굴을 의미하며, 논문의 후반부에서 "네트워크 노드"라고 언급되는 것은 주로 채굴을 하지 않더라도 노드가 할 수 있는 일을 의미합니다.
-
발표 후 발견된 사실: 새로운 블록이 생성되면, 그 블록을 생성한 채굴자는 즉시 그 후속 작업을 시작 할 수 있지만, 다른 모든 채굴자는 그 새로운 블록이 네트워크를 통해 자신에게 전파될 때까지 기다려야 합니다. 이는 많은 블록을 생성하는 채굴자가 적은 블록을 생성하는 채굴자보다 유리하게 하며, 이는 이른바 이기적 채굴 공격(selfish mining attack)으로 악용될 수 있어 전체 네트워크 해시 레이트의 약 30%를 차지하는 공격자가 다른 채굴자의 수익성을 감소시키고, 아마도 공격자 채굴자의 정책을 따르게 만들 수 있습니다. 따라서 "네트워크를 공격하지 않기 위해 협력하지 않는 노드들이 CPU 파워의 대부분을 통제한다"고 말하는 대신 "네트워크를 공격하기 위해 협력하는 노드들이 네트워크의 약 30% 미만을 통제 하는 한"이라고 말하는 것이 더 정확할 수 있습니다.
우리는 전자적인 코인을 디지털 서명의 체인으로 정의합니다. 각 소유자는 이전 거래의 해시와 다음 소유자의 공개 키를 디지털 서명하여 이를 코인의 끝에 추가함으로써 코인을 다음 소유자에게 이전합니다.
- 구현 세부사항: 비트코인은 디지털 서명이 직접 사용되지 않고 대신 "결정론적 표현(deterministic expression)"이 사용되는 이 시스템의 더 일반적인 버전을 구현합니다. 알려진 공개 키에 일치하는 서명이 결제를 가능하게 하는 것처럼, 알려진 표현을 충족시키는 데이터도 결제를 가능하게 할 수 있습니다. 일반적으로, 비트코인에서 코인을 사용하기 위해 충족해야 하는 표현을 "구속(encumbrance)" 이라고 합니다. 지금까지 비트코인의 거의 모든 구속은 적어도 하나의 서명을 제공해야 합니다. 따라서 "디지털 서명의 체인(a chain of digital signatures)" 이라고 말하는 대신 "구속의 체인(a chain of encumbrances)"이라고 말하는 것이 더 정확합니다. 거래에는 종종 하나 이상의 입력과 하나 이상의 출력이 있으므로, 구조가 매우 체인과 같지 않고, 더 정확하게는 유향 비순환 그래프(DAG)로 묘사됩니다.
- 구현 세부사항:
우리는 블록의 논스를 증가시키면서 블록의 해시에 필요한 0비트를 가지는 값을 찾을때까지 작업 증명을 구현합니다.
- 구현 세부사항: 아담백(Adam Back)의 Hashcash구현은 필요한 개수의 선행 0비트를 가진 해시를 찾도록 요구합니다. 비트코인은 해시를 정수로 취급하고, 지정된 정수보다 작아야 한다고 요구하며 사실상 비트의 소수 개수를 지정할 수 있게 합니다. 작업 증명은 본질적으로 한 CPU가 하나의 투표권을 갖는 것입니다.
작업 증명(Proof-of-Work)은 본질적으로 '1CPU당 1표' 입니다.
- 중요한 참고 사항: 여기서의 투표는 시스템의 규칙에 관한 것이 아니라, "전자 코인"이 쉽게 이중 지불되지 않도록 하기 위해 거래의 순서를 정하는 것입니다. 이는 논문의 11장에서 더 자세히 설명 되어 있으며, "공격자가 정직한 체인보다 더 빠르게 대체 체인을 생성하려고 시도하는 시나리오를 고려합 니다. 설령 이것이 성공하더라도 시스템을 임의의 변경하도록 하는 즉, 예를 들어 무에서 가치를 창출하거나 공격자에게 속하지 않은 돈을 가져가는 것과 같은 변경에 열어두지는 않습니다. 노드들은 유효하지 않은 거래를 결제로 받아들이지 않을 것이며, 정직한 노드들은 그러한 거래를 포함하는 블록을 결코 받아들이지 않을 것입니다." 라고 명시되어 있습니다. 작업 증명 난이도는 시간당 평균 블록 수를 목표로 하는 이동 평균에 의해 결정 됩니다.
작업 증명의 난이도는 시간당 평균 블록 수를 목표로 하는 이동 평균에 의해 결정됩니다.
- 구현 세부사항: 이동 평균은 사용되지 않습니다. 대신 매 2,016번째 블록의 생성 시간과 이전 블록의 생성 시간을 비교하여 그 차이를 사용해 조정에 사용되는 평균을 계산합니다.
더욱이, 비트코인에 구현된 평균은 시간당 블록 수가 아니라 2주당 평균 블록 수를 목표로 합니다(텍스트에서 암시할 수 있는 것처럼 시간당 블록 수가 아닙니다). 또한, 조정이 기간당 블록 생성 속도를 300% 이상 증가 시키거나 75% 이상 감소시킬 수 없다는 규칙과 같은, 조정 속도를 더욱 늦출 수 있는 다른 구현된 규칙들이 있습니다.
두 노드가 동시에 블록을 다른 버전을 브로드캐스트할 경우, 일부 노드는 먼저 받은 블록에서 작업하지만 다른 블록에 대한 브랜치도 저장하여 더 길어질 경우에 대비합니다. 작업 증명이 발견되어 한 브랜치가 더 길어지면, 다른 브랜치에서 작업하던 노드들은 더 긴 브랜치로 전환합니다.
-
용어 변경: 비트코인 초기 코드에서는 PruneOrphanBlocks 함수가 DEFAULT_MAX_ORPHAN_BLOCKS 설정 매개변수를 사용하여 네트워크에 보관할 수 있는 오펀 블록의 최대 수를 제한했습니다. 이 매개변수는 함수와 함께 나중에 제거되었습니다. "Headers-First" 변경 사항이 도입되면서, 네트워크는 블록 데이터를 모두 받기 전에 블록 헤더를 먼저 받고 검증하는 방식을 채택하게 되었습니다. 이를 통해 블록체인 네트워크의 효율성을 높이고, 데이터 전송량을 줄이며, 체인 리오르그(reorg)시 복잡성을 줄일 수 있었습니다. 오펀 블록의 개념은 현재 "스테일 블록(stale block)"이라는 개념으로 진화했습니다. 스테일 블록은 네트워크에서 유효하지만, 더 강한체인(긴 체인에 관한 데이비드 하딩이 해시율에 기반한 더 합리적 표현주장)이 나타나 채택되지 않은 블록을 의미합니다.
-
중요한 참고 사항: 비트코인 네트워크의 초기 구현에서는 오펀 블록(Orphan Blocks)에 대한 개념이 있었습니다. 이는 두 개의 노드가 동시에 다른 블록을 발견하여 발생하는 상황에서, 그 중 하나가 "유기된" 상태가 되는 것을 의미합니다. 노드들은 이런 블록들을 나중에 더 긴 체인이 나타날 때까지 임시로 보관됩니다. 즉 오펀 블록은 네트워크에서 동시에 두 개 이상의 블록이 발견될 때 발생하는 임시적인 현상입니다. 이러한 블록은 일시적으로 보관되며, 나중에 더 긴 체인이 나타날 때 폐기될 수 있었습니다. 스테일 블록은 유효한 블록이지만, 블록체인의 일관성을 유지하기 위해 채택되지 않는 블록입니다. 이러한 블록은 네트워크가 가장 긴 체인을 채택하기로 한 합의 메커니즘의 결과로 발생합니다. 비트코인 네트워크의 설계는 데이터의 무결성을 유지하고 네트워크의 효율성을 높이기 위해 오펀 블록과 스테일 블록을 적절히 처리하는 메커니즘을 포함하고 있습니다.
-
구현 세부사항: 사토시가 작성한 초기의 코드에는 PruneOrphanBlocks 함수가 있었고 이 함수는 오펀 블록의 수를 제한하기 위해 DEFAULT_MAX_ORPHAN_BLOCKS라는 설정 매개변수값을 750로 사용했습니다. 이는 11장에서 볼 수 있는 시스템의 보안 관점에서 공격자가 정직한 체인보다 더 빠르게 대체 체인을 생성하려고 할 때의 시나리오에 대한 내용을 P(공격자의 성공 확률), q(공격자가 다음 블록을 찾을 확률), z(공격자가 뒤처지고있는 블록 수)에 대한 값에서 z값이 오펀블록을 허용하고 값이 높아질 수록 공격의 성곡확률이 지수함수으로 낮아지는 확률 결과가 포함된 내용(백서상에서는 P < 0.001인 경우에 해당하는 지점을 찾기 위한 과정에서 z를 340까지 계산한것으로 보임)입니다.
사토시가 작성한 750개의 오펀블록의 수를 코드에서 제거하게 된 것은 비트코인 코어 개발자들의 논의후 사토시가 한참 지난 2014년 12월에 발생했습니다.
- strUsage += " -maxorphanblocks=<n> " + strprintf(_("Keep at most <n> unconnectable blocks in memory (default: %u)"), DEFAULT_MAX_ORPHAN_BLOCKS) + "\n"; - static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
...
- 용어 변경:
- 중요한 참고 사항:
- 구현 세부사항:
...
- 용어 변경:
- 중요한 참고 사항:
- 구현 세부사항:
...
이를 방어하는 한 가지 전략은 네트워크 노드에서 잘못된 블록이 감지되었을 때 경고를 받아 사용자의 소프트웨어가 전체 블록과 경고된 거래를 다운로드하여 불일치를 확인하도록 하는 것입니다.
- 중요한 참고 사항: 일부 소프트웨어는 이 섹션의 일부를 구현하고 이를 간이 결제 검증(Simplified Payment Verification, SPV) 이라고 부르지만, 현재 이러한 프로그램 중 어떤 것도 잘못된 블록이 감지되었을 때 네트워크 노드(전체 검증 노드)로부터 경고를 수신하지 않습니다. 이는 과거에 SPV 지갑에 비트코인을 보관할 때 위험을 초래한 적이 있습니다.
...
- 용어 변경:
- 중요한 참고 사항:
- 구현 세부사항:
...
- 용어 변경:
- 중요한 참고 사항:
- 구현 세부사항:
...
수신자는 새 키 쌍을 생성하고 서명하기 직전에 공개 키를 발신자에게 전달합니다. 이것은 발신자가 지속적으로 작업하여 사전에 블록 체인을 준비한 다음, 충분히 앞서 나갈 때까지 행운이 따라야 트랜잭션을 실행할 수 있기 때문에 이를 방지하는 역할을 합니다.
-
게시 후 발견: 수신자가 서명 직전에 공개 키를 생성하는 것은 발신자가 사전에 블록 체인을 준비하는 것을 막지 못합니다. 초기 비트코인 사용자 할 피니(Hal Finney)는 이 공격을 발견하고 이를 다음과 같이 설명했습니다: "공격자가 가끔씩 블록을 생성한다고 가정합시다. 그는 생성한 각 블록에 자신이 제어하는 주소 A에서 B로의 전송을 포함시킵니다.
"속이기 위해, 그는 블록을 생성할 때 이를 방송하지 않습니다. 대신, 그는 가게로 달려가 자신의 주소 A에서 당신의 주소 C로 결제를 합니다. 당신은 몇 초 기다리다가 아무 소리도 못 듣고 물건을 넘겨줍니다. 그는 이제 자신의 블록을 방송하고, 그의 트랜잭션이 당신의 것보다 우선하게 됩니다."
이 공격은 어떤 수의 확인에도 적용될 수 있으며, 가끔 "피니 공격(Finney Attack)"이라고 불립니다.
...
- 용어 변경:
- 중요한 참고 사항:
- 구현 세부사항: ...
A description of known problems in Satoshi Nakamoto's paper, "Bitcoin: A Peer-to-Peer Electronic Cash System", as well as notes on terminology changes and how Bitcoin's implementation differs from that described in the paper.
The longest chain not only serves as proof of the sequence of events witnessed, but proof that it came from the largest pool of CPU power.
-
Implementation detail: If each link in the chain (called "blocks" in Bitcoin) was built using the same amount of Proof Of Work (POW), the longest chain would be the one backed by the largest pool of computational power. However, Bitcoin was implemented in such a way that the amount of POW can vary between blocks, so it became important not to check for the "the longest chain" but rather "the chain demonstrating the most POW"; this is often shortened to "strongest chain".
The change from checking for the longest chain to checking for the most-work chain occurred in July 2010, long after Bitcoin's initial release:
- if (pindexNew->nHeight > nBestHeight) + if (pindexNew->bnChainWork > bnBestChainWork)
-
Terminology change: General CPUs were used to generate the POW for the earliest Bitcoin blocks but POW generation today is mostly performed by specialist Application Specific Integrated Circuits (ASICs), so instead of saying "CPU power" it is perhaps more correct to say "computational power" or, simply, "hash rate" for the hashing used in generating the POW.
As long as a majority of CPU power is controlled by nodes that are not cooperating to attack the network, they'll generate the longest chain and outpace attackers.
-
Terminology change: The term "nodes" today is used to refer to full validation nodes, which are programs that enforce all the rules of the system. Programs (and hardware) that extend the chain today are called "miners" based on Nakamoto's analogy to gold miners in section 6 of the paper. Nakamoto expected all miners to be nodes but the software he released did not require all nodes to be miners. In the the original software, a simple menu item in the node GUI allowed toggling the mining function or or off.
Today it is the case that the overwhelming number of nodes are not miners and that many individuals who own mining hardware do not use it with their own nodes (and even those that do mine with their own nodes often mine for short periods of time on top of newly discovered blocks without ensuring their node considers the new block valid). The early parts of the paper where "nodes" is mostly used without modification refer to mining using a full validation node; the later parts of the paper which refer to "network nodes" is mainly about what nodes can do even if they aren't mining.
-
Post-publication discovery: When a new block is produced, the miner who produces that block can begin working on its sequel immediately but all other miners must wait for that new block to propagate across the network to them. This gives miners who produce many blocks an edge over miners who produce fewer blocks, and this can be exploited in what's known as the selfish mining attack to allow an attacker with around 30% of total network hash rate to make other miners less profitable, perhaps driving them into following the attacking miner's policy. So instead of saying "a majority of CPU power is controlled by nodes that are not cooperating to attack the network" it is perhaps more correct to say "as long as nodes cooperating to attack the network control less than about 30% of the network".
We define an electronic coin as a chain of digital signatures. Each owner transfers the coin to the next by digitally signing a hash of the previous transaction and the public key of the next owner and adding these to the end of the coin.
- Implementation detail: Bitcoin implements a more general version of this system where digital signatures are not used directly but rather a "deterministic expression" is used instead. Just as a signature that matches a known public key can be used to enable a payment, the data that satisfies an known expression can also enable a payment. Generically, the expression that must be satisfied in Bitcoin in order to spend a coin is known as an "encumbrance". Almost all encumbrances in Bitcoin to date require providing at least one signature. So instead of saying "a chain of digital signatures" it is more correct to say "a chain of encumbrances". Given that transactions often have more than one input and more than one output, the structure is not very chain-like; it's more accurately described as a directed acyclic graph (DAG).
we implement the proof-of-work by incrementing a nonce in the block until a value is found that gives the block's hash the required zero bits.
- Implementation detail: Adam Back's Hashcash implementation requires finding a hash with the required number of leading zero bits. Bitcoin treats the hash as an integer and requires that it be less than a specified integer, which effectively allows a fractional number of bits to be specified.
Proof-of-work is essentially one-CPU-one-vote.
- Important note: the vote here is not on the rules of the system but merely on the ordering of the transactions in order to provide assurances that an "electronic coin" cannot be easily double spent. This is described in more detail in section 11 of the paper where it says, "We consider the scenario of an attacker trying to generate an alternate chain faster than the honest chain. Even if this is accomplished, it does not throw the system open to arbitrary changes, such as creating value out of thin air or taking money that never belonged to the attacker. Nodes are not going to accept an invalid transaction as payment, and honest nodes will never accept a block containing them."
proof-of-work difficulty is determined by a moving average targeting an average number of blocks per hour.
-
Implementation detail: A moving average is not used. Instead, every 2,016th block has its reported generation time compared to the generation time for an earlier block, and the difference between them is used to calculate the average used for adjustment.
Further, the average implemented in Bitcoin targets an average number of blocks per two weeks (not per hour as might be implied by the text). Other implemented rules may further slow adjustments, such as a rule that the adjustment can not increase block production speed by more than 300% per period, nor slow it by more than 75%.
Once the latest transaction in a coin is buried under enough blocks, the spent transactions before it can be discarded to save disk space
- Possible post-publication discovery: Although the Merkle Tree structure described in this section can prove a transaction was included in a particular block, there is currently no way in Bitcoin to prove that a transaction has not been spent except to process all subsequent data in the blockchain. This means the method described here cannot be universally used for reclaiming disk space among all nodes, as all new nodes will need to process all transactions.
One strategy to protect against this would be to accept alerts from network nodes when they detect an invalid block, prompting the user's software to download the full block and alerted transactions to confirm the inconsistency.
- Important Note: although software has been produced that implements some parts of this section and calls that Simplified Payment Verification (SPV), none of these programs currently accepts alerts from network nodes (full validation nodes) when invalid blocks have been detected. This has placed bitcoins in so-called SPV wallets at risk in the past.
Some linking is still unavoidable with multi-input transactions, which necessarily reveal that their inputs were owned by the same owner
-
Post-publication invention: the revelation of a common owner for different inputs isn't necessary if owners often mix their inputs with inputs belonging to other owners. For example, there's no public difference between Alice and Bob each contributing one of their inputs towards paying Charlie and Dan than there is between just Alice contributing two of her inputs towards paying Charlie and Dan.
This technique is known today as CoinJoin and software implementing it has been in use since 2015.
The receiver generates a new key pair and gives the public key to the sender shortly before signing. This prevents the sender from preparing a chain of blocks ahead of time by working on it continuously until he is lucky enough to get far enough ahead, then executing the transaction at that moment.
-
Post-publication discovery: nothing about the receiver generating a public key shortly before the spender signs a transaction prevents the spender from preparing a chain of blocks ahead of time. Early Bitcoin user Hal Finney discovered this attack and described it: "Suppose the attacker is generating blocks occasionally. in each block he generates, he includes a transfer from address A to address B, both of which he controls.
"To cheat you, when he generates a block, he doesn't broadcast it. Instead, he runs down to your store and makes a payment to your address C with his address A. You wait a few seconds, don't hear anything, and transfer the goods. He broadcasts his block now, and his transaction will take precedence over yours."
The attack works for any number of confirmations, and is sometimes named the Finney Attack.
Disclaimer: the author of this document was not the first person to identify any of the problems described here---he has merely collected them into a single document.
License: this errata document is released under the CC0 1.0 Universal Public Domain Dedication
Updates:
-
2018-06-14: Link to the commit where Nakamoto changed the consensus convergence mechanism from greatest-height to most-work. Credit for commit archaeology to Gregory Maxwell.
-
2018-06-14: A moving average is not used. Mentioned on an IRC channel where logging is disallowed.
-
2018-06-14: Late key distribution does not prevent attackers from preparing forks, e.g. the Finney Attack. Mentioned by Kalle Rosenbaum on Twitter.
-
2018-06-14: Inputs being spent in the same transaction does not necessarily lead to a privacy degradation thanks to Coinjoin. Mentioned by Chris Belcher in a GitHub comment.
-
2023-08-01: clarified a sentence about nodes not needing to be miners. Mentioned by Janaka-Steph in a GitHub comment.
-
2023-08-01: the "chain of encumbrances" is more accurately described as a DAG. Mentioned by Mark "Murch" Erhardt in a GitHub comment.