/** * 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 { // ulong 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 int 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 ulong DecodeVarInt(byte[] bytes) { var prefix = bytes[0]; var bytesArray = new byte[bytes.Length - 1]; bytes.CopyTo(bytesArray, 1); // Get rid of prefix switch (prefix) { case 0xfd: // ushort flag return BitConverter.ToUInt16(bytesArray, 0); case 0xfe: // uint flag return BitConverter.ToUInt32(bytesArray, 0); case 0xff: // ulong flag return BitConverter.ToUInt64(bytesArray, 0); default: return prefix; } } public static ulong ReadVarInt(ref BinaryReader reader) { byte prefix = reader.ReadByte(); switch (prefix) { case 0xfd: // ushort return reader.ReadUInt16(); case 0xfe: // uint return reader.ReadUInt32(); case 0xff: // ulong return reader.ReadUInt64(); default: return prefix; } } } }