가변 길이 정수

가변 길이 정수

비트코인에서 길이를 표시할 때 공간을 절약하기 위해 종종 가변 길이를 사용한다. 가변길이로 이루어진 정수(Variable length integer)는 아래와 같이 숫자 범위에 따라 1 ~ 9 바이트까지 가변적인 바이트 배열에 값을 저장하게 된다. 가변 길이 정수가 2 바이트 이상의 배열인 경우, 정수값은 리틀 엔디안(Little endian) 형태로 저장된다.

숫자 범위 바이트 수 저장 포맷
< 0xFD 1 길이 (직접입력)
<= 0xFFFF 3 0xFD + 길이(2 바이트)
<= 0xFFFFFFFF 5 0xFE + 길이(4 바이트)
> 0xFFFFFFFF 9 0xFF + 길이(8 바이트)

가변 길이 정수는 C#에서 이를 아래와 같이 VarInt 타입으로 정의할 수 있다.

    public class VarInt
    {
        public ulong Value { get; private set; }

        // number bytes are stored in little-endian
        public byte[] Bytes { get; private set; }

        public VarInt(int number) : this((ulong)number)
        {
        }

        public VarInt(ulong number)
        {
            this.Value = number;

            if (number <= 0xfc)
            {
                Bytes = new byte[1];
                Bytes[0] = (byte)number;
            }
            else if (number <= 0xffff)
            {
                Bytes = new byte[3];
                Bytes[0] = 0xfd;
                byte[] num = BitConverter.GetBytes((UInt16)number);
                Array.Copy(num, 0, Bytes, 1, 2);
            }
            else if (number <= 0xffffffff)
            {
                Bytes = new byte[5];
                Bytes[0] = 0xfe;
                byte[] num = BitConverter.GetBytes((UInt32)number);
                Array.Copy(num, 0, Bytes, 1, 4);
            }
            else
            {
                Bytes = new byte[9];
                Bytes[0] = 0xff;
                byte[] num = BitConverter.GetBytes(number);
                Array.Copy(num, 0, Bytes, 1, 8);
            }
        }

        //...생략...
    }