2 using System.Collections.Generic;
5 using System.Threading.Tasks;
12 /// Encodes unsigned integer value into compact representation.
14 /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
16 /// <param name="n">Unsigned integer value</param>
17 /// <returns>Byte sequence</returns>
18 public static IList<byte> EncodeVarInt(ulong n)
20 List<byte> resultBytes = new List<byte>();
24 // Values up to 0xfc are stored directly without any prefix
25 resultBytes.Add((byte)n);
32 if (n <= ushort.MaxValue)
36 valueBytes = Interop.LEBytes((ushort)n);
38 else if (n <= uint.MaxValue)
42 valueBytes = Interop.LEBytes((uint)n);
48 valueBytes = Interop.LEBytes(n);
51 resultBytes.Add(prefix);
52 resultBytes.AddRange(valueBytes);
59 /// Encodes integer value into compact representation.
61 /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
63 /// <param name="n">Integer value</param>
64 /// <returns>Byte sequence</returns>
65 public static IList<byte> EncodeVarInt(long n)
67 return EncodeVarInt((ulong)n);
71 /// Decodes integer value from compact representation
73 /// See https://bitcoin.org/en/developer-reference#compactsize-unsigned-integers for additional information.
75 /// <param name="bytes">Byte sequence</param>
76 /// <returns>Integer value</returns>
77 public static ulong DecodeVarInt(IList<byte> bytes)
79 byte prefix = bytes[0];
81 bytes.RemoveAt(0); // Remove prefix
83 byte[] bytesArray = bytes.ToArray();
85 if (BitConverter.IsLittleEndian)
89 case 0xfd: // ushort flag
90 return BitConverter.ToUInt16(bytesArray, 0);
91 case 0xfe: // uint flag
92 return BitConverter.ToUInt32(bytesArray, 0);
93 case 0xff: // ulong flag
94 return BitConverter.ToUInt64(bytesArray, 0);
101 // Values are stored in little-endian order
104 case 0xfd: // ushort flag
105 Array.Resize<byte>(ref bytesArray, 2);
106 Array.Reverse(bytesArray);
107 return BitConverter.ToUInt16(bytesArray, 0);
108 case 0xfe: // uint flag
109 Array.Resize<byte>(ref bytesArray, 4);
110 Array.Reverse(bytesArray);
111 return BitConverter.ToUInt32(bytesArray, 0);
112 case 0xff: // ulong flag
113 Array.Resize<byte>(ref bytesArray, 8);
114 Array.Reverse(bytesArray);
115 return BitConverter.ToUInt64(bytesArray, 0);
123 /// Read and decode variable integer from wrapped list object.
125 /// Note: Should be used only if there is some variable integer data at current position. Otherwise you will get undefined behavior, so make sure that you know what you are doing.
127 /// <param name="wBytes"></param>
128 /// <returns></returns>
129 public static ulong ReadVarInt(ref WrappedList<byte> wBytes)
131 byte prefix = wBytes.GetItem();
136 return Interop.LEBytesToUInt16(wBytes.GetItems(2));
138 return Interop.LEBytesToUInt32(wBytes.GetItems(4));
140 return Interop.LEBytesToUInt64(wBytes.GetItems(8));