/** * Novacoin classes library * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ using System; using System.Collections.Generic; using System.IO; namespace Novacoin { public class VarInt { /// /// Encodes unsigned integer value into compact representation. /// /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information. /// /// Unsigned integer value /// Byte sequence public static byte[] EncodeVarInt(ulong n) { var resultBytes = new List(); if (n <= 0xfc) { // Values up to 0xfc are stored directly without any prefix resultBytes.Add((byte)n); } else { byte prefix; byte[] valueBytes; if (n <= ushort.MaxValue) { // ushort flag prefix = 0xfd; valueBytes = BitConverter.GetBytes((ushort)n); } else if (n <= uint.MaxValue) { // uint flag prefix = 0xfe; valueBytes = BitConverter.GetBytes((uint)n); } else { // long flag prefix = 0xff; valueBytes = BitConverter.GetBytes(n); } resultBytes.Add(prefix); resultBytes.AddRange(valueBytes); } return resultBytes.ToArray(); } /// /// Encodes integer value into compact representation. /// /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information. /// /// Integer value /// Byte sequence public static byte[] EncodeVarInt(long n) { return EncodeVarInt((ulong)n); } public static uint GetEncodedSize(long n) { if (n <= 0xfc) { return 1; } else if (n <= ushort.MaxValue) { return 3; } else if (n <= uint.MaxValue) { return 5; } else { return 9; } } /// /// Decodes integer value from compact representation /// /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information. /// /// Byte sequence /// Integer value public static long DecodeVarInt(byte[] bytes) { var prefix = bytes[0]; if (bytes.Length > 1) { var bytesArray = new byte[bytes.Length - 1]; Array.Copy(bytes, 1, bytesArray, 0, bytesArray.Length); switch (prefix) { case 0xfd: // ushort flag return BitConverter.ToUInt16(bytesArray, 0); case 0xfe: // uint flag return BitConverter.ToUInt32(bytesArray, 0); case 0xff: // long flag return BitConverter.ToInt64(bytesArray, 0); } } return prefix; // Values lower than 0xfd are stored directly } public static long ReadVarInt(ref BinaryReader reader) { byte prefix = reader.ReadByte(); switch (prefix) { case 0xfd: // ushort return reader.ReadUInt16(); case 0xfe: // uint return reader.ReadUInt32(); case 0xff: // long return reader.ReadInt64(); default: return prefix; } } } }