using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; 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 IList EncodeVarInt(ulong n) { List 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; } /// /// 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 IList EncodeVarInt(long n) { return EncodeVarInt((ulong)n); } /// /// 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(IList bytes) { byte prefix = bytes[0]; bytes.RemoveAt(0); // Remove prefix byte[] bytesArray = bytes.ToArray(); 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; } } } }