๊ฐ์ง๊ณ ์๋ ํธ๋์ญ์
์ค ํธ๋์ญ์
K(์ ๊ทธ๋ฆผ์์ ๋
น์์ผ๋ก ํ์)์ ์๋ณ์กฐ๊ฐ ์์ฌ๋์ด ์๋ณ์กฐ ์ฌ๋ถ๋ฅผ ์กฐ์ฌํ๋ ค ํ๋ค. ์ด๋ ํ์ํ ์ ๋ณด๋ ํ๋์์ผ๋ก ์น ํด์ง 4๊ฐ์ ํด์๊ฐ(H_L, H_IJ, H_ABCDEFGH), ๊ทธ๋ฆฌ๊ณ ๋จธํด ๋ฃจํธ๋ค.
์ค์ ๊ตฌํ: ๊ฐ ํธ๋์ญ์
๋ค์ ํด์(uint 256: SHA256์ ๊ฒฐ๊ณผ๊ฐ์ unsigned 256bit)๋ฅผ ์ ์ฅํ๊ธฐ ์ํด vector<uint256> vMerkleTree๊ฐ ์กด์ฌํ๋ค.
ํธ๋์ญ์
K์ ์๋ณ์กฐ ์ฌ๋ถ๋ฅผ ์กฐ์ฌํ๊ธฐ ์ํด, K์ ๋ํ ํด์๊ฐ(๋
น์์ผ๋ก ํ์)๊ณผ ํ๋์์ผ๋ก ์น ํด์ง 4๊ฐ์ ํด์๊ฐ์ ์ด์ฉํ๋ฉด ๋จธํด ๋ฃจํธ๊ฐ(์ ์ฒด ๊ฑฐ๋๋ด์ญ A~P์ ๋ํ ๊ณ ์ ํ ํด์๊ฐ)์ ์ฌ๊ตฌ์ฑํ ์ ์๋ค. ๋ ๊ฐ์ฉ ์ฐจ๋ก๋ก ์ด์ด๋ถ์ธ ํ ๊ทธ ๊ฐ์ ๋ค์ ํด์ํ๋ ๋ฐฉ์์ผ๋ก ๋ฃจํธ๊ฐ์ด ๋์ฌ ๋๊น์ง ๋ฐ๋ณตํ๋ค. ์ ์ฒด ๊ฑฐ๋๋ด์ญ์ ์กฐํํ๋ ๊ฒ์ด ์๋, ๋จ์ง 4๊ฐ์ ํด์๊ฐ๋ง์ ์ด์ฉํ์ฌ ์๋ณ์กฐ ์ฌ๋ถ๋ฅผ ๊ฒ์ฆํ ์ ์๋ค๋ ๊ฑด ๋งค์ฐ ํจ์จ์ ์ด๋ค.
์ค์ ๊ตฌํ: ๋จผ์ BuildMerkleTree( )๋ฉ์๋๋ก ๋จธํดํธ๋ฆฌ๋ฅผ ๋จผ์ ๊ตฌ์ฑํ๊ณ , ๊ทธ ํ BuildMerkleBranch(๋งค๊ฐ๋ณ์: ์๋ณ์กฐ ๊ฒ์ฆ์ ์ํ๋ ํธ๋์ญ์
์ ํด์) ๋ฉ์๋๋ก ๊ฒ์ฆ์ ํ์ํ ํด์๊ฐ๋ค(์ ๊ทธ๋ฆผ ์์์ ํ๋์์ผ๋ก ์น ํด์ง ๊ฐ๋ค)๋ก ๊ตฌ์ฑ๋ 1์ฐจ์ vector๋ฅผ ๋ฐ๋ก ์ ์ํ๋ค. ์ด vector๋ฅผ ๋จธํด ๋ธ๋์น๋ผ ์นญํ๋ค. ๊ทธ ํ CheckMerkleBranch( ) ๋ฉ์๋๋ก ๋จธํด ๋ธ๋์น์ ์๋ ํด์๊ฐ๋ค, ๊ทธ๋ฆฌ๊ณ ์๋ณ์กฐ ๊ฒ์ฆ์ ์ํ๋ ํธ๋์ญ์
์ ๊ฐ์ง๊ณ ๊ฒ์ฌ๋ฅผ ์งํํ๋ค.
class CBlock in main.h
// header: ํํ ๋งํ๋ ๋ธ๋ก ํค๋์ ์ ์ฒด๋ค. ํ๋
ธ๋๊ฐ ์๋ ๊ฒฝ๋ ํด๋ผ์ด์ธํธ(light client)๋ค์ ๋ธ๋ก ํค๋๋ง ์ ์ฅํ๊ฒ ๋๋ค.
int nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot; // BuildMerkleTree()๋ก ์์ฑ๋๋ ๋จธํด๋ฃจํธ
unsigned int nTime;
unsigned int nBits;
unsigned int nNonce;
// network and disk
vector<CTransaction> vtx; // ํธ๋์ญ์
๋ค์ ์ ์ฅํ ๋๋ CTransaction ํด๋์ค์ ๋ฒกํฐ๋ก ์ ์ฅ
// A block contains multiple transactions, held in vector vtx.
// memory only
mutable vector\<uint256> vMerkleTree;
CBlock::BuildMerkleTree( )
uint256 BuildMerkleTree() const
{
vMerkleTree.clear();
// ๊ฐ ํธ๋์ญ์
๋ค์ ํด์๊ฐ์ ๋ฐ๋ก ์ ์ฅํ์ฌ vMerkleTree ์์ฑ
foreach(const CTransaction& tx, vtx)
vMerkleTree.push_back(tx.GetHash());
int j = 0;
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
{
for (int i = 0; i < nSize; i += 2)
{
// ๋ง์ฝ ํธ๋์ญ์
์ด ์ง์๊ฐ๊ฐ ์๋๋ผ๋ฉด, ๋ง์ง๋ง ํธ๋์ญ์
์ ํด์๋ ์๊ธฐ ์์ ๊ณผ ํด์ํ๊ฒ ๋๋ค.
int i2 = min(i+1, nSize-1);
// ํธ๋์ญ์
์ ํด์๋ฅผ 2๊ฐ์ฉ ๋ฌถ์ด์ ๋ค์ ๋จธํดํธ๋ฆฌ์ ์ฝ์
ํ๋ค.
vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
}
j += nSize; // j๋ ๊ฐ ํธ๋ฆฌ๋ ๋ฒจ์ ๋ง์ถฐ ์ฝ์
ํด์ผํ ์ฒซ๋ฒ์งธ ์์น๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
}
return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
}
// nIndex๋ก ์๋ณ์กฐ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ ํน์ ํธ๋์ญ์
์ ์ ํํ๊ณ ๋จธํด ํธ๋ฆฌ๋ด์ ํธ๋์ญ์
ํด์๊ฐ๊ณผ ์ฐ๊ด๋
// ํธ๋์ญ์
์ ํด์๋ค๋ง ๋ฐ๋ก ์ถ์ถํ์ฌ MerkleBranch๋ฅผ ์์ฑํ๋ค.
vector\<uint256> GetMerkleBranch(int nIndex) const
{ // nIndex์ ํด๋นํ๋ ํธ๋์ญ์
์ฆ๋ช
์ ์ฌ์ฉ๋๋ ๋
ธ๋๋ค์ vMerkleBranch์ ๋ด๋ ์์
์ ์งํ
if (vMerkleTree.empty())
BuildMerkleTree();
vector\<uint256> vMerkleBranch;
int j = 0;
for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
{
int i = min(nIndex^1, nSize-1); // nIndex^1์ ๊ฐ์ 0 ๋๋ 1(๋ฐ๋ณต)
vMerkleBranch.push_back(vMerkleTree[j+i]);
nIndex >>= 1;
j += nSize;
}
return vMerkleBranch;
}
static uint256 CheckMerkleBranch(uint256 hash, const vector\<uint256>& vMerkleBranch, int nIndex)
{
if (nIndex == -1)
return 0;
foreach(const uint256& otherside, vMerkleBranch)
{ // ํด์๋๋ ์์๋ฅผ ์ง์ผ์ฃผ๊ธฐ ์ํด ์๋์ ๋ ๊ฒฝ์ฐ๋ฅผ ๊ตฌ๋ถํ์ฌ ์ฒ๋ฆฌ
if (nIndex & 1) // ํธ๋์ญ์
์ ์ธ๋ฑ์ค๊ฐ ํ์์ผ ๊ฒฝ์ฐ
hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
else // ํธ๋์ญ์
์ ์ธ๋ฑ์ค๊ฐ ์ง์์ผ ๊ฒฝ์ฐ
hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
nIndex >>= 1; // ํด์๋๋ ์์๋ฅผ ๋ง์ถฐ์ค๋ค.
}
return hash; // it should be merkleRoot
}