블럭인덱스 (Block Index)

Block Index

BlockIndex 개요

Bitcoin은 블럭체인의 블럭들에 대한 메타데이타를 저장하기 위해 LevelDB를 사용하고 있는데, 이를 흔히 블럭 인덱스(Block Index)라 부른다. 블럭 인덱스는 모든 블럭들에 대한 메타데이타를 저장하고 있는데, 여기에는 현재 사용되는 블럭체인(active blockchain)에 있는 블럭들 뿐만 아니라, 그 블럭체인에 포함되지 못한 블럭들(예: orphaned block)도 포함된다.

BlockIndex는 Key-Value 엔트리 형태로 LevelDB에 저장된다. 키(Key)는 한 바이트의 타입과 해당 타입의 키 데이타로 구성되는데, 예를 들어, 블럭 인덱스 레코드 타입인 경우 키값은 맨 앞에 b (0x62) 라는 1 바이트 타입이 지정되고 그 다음에 32 바이트의 블럭 해시값이 지정된다.

키(key) 레코드 타입 메타데이타 키 샘플
b (0x62) + 32 바이트 블럭해시 블럭 인덱스 레코드 블럭 헤더, 블럭 Height, 블럭 내 트랜잭션 수, 블럭파일 내의 위치, Undo 파일 내의 위치 621c7802d4734f3a9b8cb1f1ebd15a9412a41b78d44c6a207badbdff5862b84c21 = 62 (b) + 214cb86258ffbdad7b206a4cd4781ba412945ad1ebf1b18c9b3a4f73d402781c (블럭해시값, 역순)
f (0x66) + 4 바이트 파일번호 파일 정보 레코드 해당 파일에 저장된 블럭 수, 블럭파일 크기, Undo파일 크기, 블럭파일에 저장된 블럭 Height 범위, 블럭파일에 저장된 Timestamp 범위 6600000000 = 66 (f) + 00000000 (blk00000.dat(블럭파일), rev00000.data(Undo파일) 에 대한 파일번호)
l (0x6c) 마지막 파일번호 마지막 파일블럭의 파일번호 (4 바이트 파일번호) 6c
R (0x52) 리인덱싱 여부 현재 리인덱싱(reindexing) 중인지 아닌지를 1 바이트 boolean값으로 리턴. 1이면 현재 리인덱싱 중. 52
t (0x74) + 32 바이트 트랜잭션 해시 트랜잭션 인덱스 레코드 지정된 트랜잭션이 저장된 블럭 파일번호, 블럭파일에서 트랜잭션이 저장된 블럭의 offset 위치, 해당 블럭 내에서의 트랜잭션의 offset 위치 74648c71f6a2eed3936365ff2a57863607a3a7b1a0e422b70946fb3eeb4a8cb833 = 74 (t) + 33b88c4aeb3efb4609b722e4a0b1a7a3073686572aff656393d3eea2f6718c64 (트랜잭션해시, 역순)
F (0x46) + 1 바이트 플래그 길이 + 플래그명 플래그 On/Off 지정된 플래그가 On, Off 되어 있는지를 리턴. 1이면 On, 0이면 Off 상태. 플래그 "txindex"는 트랜잭션 인덱싱을 사용하는지 여부를 나타냄. 46

비트코인의 원 프로그램인 Bitcoin Core 프로그램은 기본적으로 txindex=0 을 사용하는데, 이 셋팅은 자신의 월렛에 해당하는 트랜잭션만 인덱스로 관리하게 된다. 만약 비트코인 구성파일(bitcoin.conf) 안에 txindex=1 을 설정하면 자신의 트랜잭션 이외에 모든 트랜잭션에 대한 인덱스를 가지게 된다.

아래 예제는 비트코인 블럭 인덱스를 C:\Temp\index 에 복사한 후, 해당 LevelDB 안에 있는 모든 데이타를 출력해 보는 C# 코드이다.

    // using LevelDB;
    string dbpath = @"C:\Temp\index";
    var dbOptions = new Options { CreateIfMissing = true };
    var db = new DB(dbOptions, dbpath);

    var iterator = db.CreateIterator();
    iterator.SeekToFirst();
    int i = 0;
    while (iterator.IsValid())
    {
        byte[] k = iterator.Key();
        byte[] v = iterator.Value();

        Console.WriteLine($"i: {i++}");
        Console.WriteLine($"k: {k.ToHex()}");
        Console.WriteLine($"v: {v.ToHex()}");

        iterator.Next();
    }
    db.Close();