Merge branch 'master' of https://github.com/CryptoManiac/NovacoinLibrary
authorCryptoManiac <balthazar.ad@gmail.com>
Mon, 31 Aug 2015 16:27:38 +0000 (19:27 +0300)
committerCryptoManiac <balthazar.ad@gmail.com>
Mon, 31 Aug 2015 16:27:38 +0000 (19:27 +0300)
Conflicts:
Novacoin/CBlockStore.cs

13 files changed:
Novacoin/ByteQueue.cs
Novacoin/CBlock.cs
Novacoin/CBlockStore.cs
Novacoin/COutPoint.cs
Novacoin/CPubKey.cs
Novacoin/CScript.cs
Novacoin/CTransaction.cs
Novacoin/CTxIn.cs
Novacoin/CTxOut.cs
Novacoin/NetInfo.cs [new file with mode: 0644]
Novacoin/Novacoin.csproj
Novacoin/VarInt.cs
NovacoinTest/Program.cs

index 9752c02..8af351f 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics.Contracts;
+using System.IO;
 
 namespace Novacoin
 {
@@ -45,104 +46,97 @@ namespace Novacoin
     /// 
     /// TODO: rewrite using MemoryStream
     /// </summary>
-    public class ByteQueue
+    public class ByteQueue : IDisposable
     {
-        private int _Index;
-        private List<byte> _Elements;
+        private bool disposed = false;
 
-        public ByteQueue(byte[] List, int Start)
+        private MemoryStream _Stream;
+        private BinaryReader _Reader;
+
+        public ByteQueue(ref byte[] buffer, int Start)
         {
-            _Elements = new List<byte>(List);
-            _Index = Start;
+            _Stream = new MemoryStream(buffer);
+            _Stream.Seek(Start, SeekOrigin.Begin);
+            _Reader = new BinaryReader(_Stream);
         }
 
-        public ByteQueue(byte[] List)
+        public ByteQueue(ref byte[] buffer)
         {
-            _Elements = new List<byte>(List);
-            _Index = 0;
+            _Stream = new MemoryStream(buffer);
+            _Reader = new BinaryReader(_Stream);
         }
 
-        public ByteQueue(List<byte> List, int Start)
+        public ByteQueue(ref List<byte> List, int Start)
         {
-            _Elements = new List<byte>(List);
-            _Index = Start;
+            _Stream = new MemoryStream(List.ToArray());
+            _Stream.Seek(Start, SeekOrigin.Begin);
+            _Reader = new BinaryReader(_Stream);
         }
 
-        public ByteQueue(List<byte> List)
+        public ByteQueue(ref List<byte> List)
         {
-            _Elements = new List<byte>(List);
-            _Index = 0;
+            _Stream = new MemoryStream(List.ToArray());
+            _Reader = new BinaryReader(_Stream);
         }
 
-        public byte Get()
+        ~ByteQueue()
         {
-            if (_Elements.Count <= _Index)
-            {
-                throw new ByteQueueException("No elements left.");
-            }
-
-            return _Elements[_Index++];
+            Dispose(false);
         }
 
-        public bool TryGet(ref byte Element)
+        public void Dispose()
         {
-            if (_Elements.Count <= _Index)
-            {
-                return false;
-            }
-
-            Element = _Elements[_Index++];
-
-            return true;
+            Dispose(true);
+            GC.SuppressFinalize(this);
         }
 
-        public byte GetCurrent()
+        protected virtual void Dispose(bool disposing)
         {
-            return _Elements[_Index];
+            if (!disposed)
+            {
+                if (disposing)
+                {
+                    _Reader.Dispose();
+                    _Stream.Dispose();
+                }
+
+                disposed = true;
+            }
         }
 
-        public byte[] Get(int nCount)
+        public byte Get()
         {
-            Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
-
-            var result = _Elements.GetRange(_Index, nCount).ToArray();
-            _Index += nCount;
+            if (_Stream.Position == _Stream.Length)
+            {
+                throw new ByteQueueException("No elements left.");
+            }
 
-            return result;
+            return _Reader.ReadByte();
         }
 
-        public bool TryGet(int nCount, ref byte[] Elements)
+        public bool TryGet(ref byte Element)
         {
-            if (Count - Index < nCount)
+            if (_Stream.Position == _Stream.Length)
             {
                 return false;
             }
 
-            Elements = _Elements.GetRange(_Index, nCount).ToArray();
-            _Index += nCount;
+            Element = _Reader.ReadByte();
 
             return true;
         }
 
-        public byte[] GetCurrent(int nCount)
+        public byte[] Get(int nCount)
         {
             Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
 
-            var result = _Elements.GetRange(_Index, nCount).ToArray();
-
-            return result;
+            return _Reader.ReadBytes(nCount);
         }
 
-        public bool TryGetCurrent(int nCount, ref byte[] Elements)
+        public bool TryGet(int nCount, ref byte[] Elements)
         {
-            if (Count - Index < nCount)
-            {
-                return false;
-            }
-
-            Elements = _Elements.GetRange(_Index, nCount).ToArray();
-
-            return true;
+            Elements = _Reader.ReadBytes(nCount);
+            return (Elements.Length == nCount);
         }
 
         /// <summary>
@@ -150,29 +144,38 @@ namespace Novacoin
         /// </summary>
         public int Index
         {
-            get { return _Index; }
+            get { return (int)_Stream.Position; }
         }
 
         public int Count
         {
-            get { return _Elements.Count; }
+            get { return (int)_Stream.Length; }
         }
 
         public ulong GetVarInt()
         {
-            byte prefix = Get();
-
-            switch (prefix)
+            try
             {
-                case 0xfd: // ushort
-                    return BitConverter.ToUInt16(Get(2), 0);
-                case 0xfe: // uint
-                    return BitConverter.ToUInt32(Get(4), 0);
-                case 0xff: // ulong
-                    return BitConverter.ToUInt64(Get(8), 0);
-                default:
-                    return prefix;
+                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;
+                }
+            }
+            catch (EndOfStreamException e)
+            {
+                throw new ByteQueueException("No elements left.", e);
             }
         }
     }
 }
+
+
index 30350b7..4c87806 100644 (file)
@@ -87,7 +87,7 @@ namespace Novacoin
                {
             try
             {
-                ByteQueue wBytes = new ByteQueue(blockBytes);
+                ByteQueue wBytes = new ByteQueue(ref blockBytes);
 
                 // Fill the block header fields
                 header = new CBlockHeader(wBytes.Get(80));
@@ -185,13 +185,13 @@ namespace Novacoin
                 }
 
                 // Check timestamp
-                if (header.nTime > NetInfo.FutureDrift(NetInfo.GetAdjustedTime()))
+                if (header.nTime > NetUtils.FutureDrift(NetUtils.GetAdjustedTime()))
                 {
                     return false;
                 }
 
                 // Check coinbase timestamp
-                if (header.nTime < NetInfo.PastDrift(vtx[0].nTime))
+                if (header.nTime < NetUtils.PastDrift(vtx[0].nTime))
                 {
                     return false;
                 }
index 1c70f01..2c43d65 100644 (file)
@@ -189,13 +189,13 @@ namespace Novacoin
                 // Seek to the end and then append magic bytes there.
                 writer.Seek(0, SeekOrigin.End);
                 writer.Write(magicBytes, 0, magicBytes.Length);
-                writer.Write(blkLenBytes, 0, blkLenBytes.Length);
 
                 // Save block size and current position in the block cursor fields.
                 nBlockPos = writer.Position;
                 nBlockSize = blockBytes.Length;                
 
                 // Write block and flush the stream.
+                writer.Write(blkLenBytes, 0, blkLenBytes.Length);
                 writer.Write(blockBytes, 0, blockBytes.Length);
                 writer.Flush();
 
@@ -369,12 +369,7 @@ namespace Novacoin
         /// <summary>
         /// Block file stream with read access
         /// </summary>
-        private Stream reader;
-
-        /// <summary>
-        /// Block file stream with write access
-        /// </summary>
-        private Stream writer;
+        private Stream fStreamReadWrite;
 
         /// <summary>
         /// Init the block storage manager.
@@ -389,9 +384,7 @@ namespace Novacoin
             bool firstInit = !File.Exists(strDbFile);
             dbConn = new SQLiteConnection(new SQLitePlatformGeneric(), strDbFile);
 
-            var fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
-            reader = new BinaryReader(fStreamReadWrite).BaseStream;
-            writer = new BinaryWriter(fStreamReadWrite).BaseStream;
+            fStreamReadWrite = File.Open(strBlockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite);
 
             if (firstInit)
             {
@@ -431,6 +424,7 @@ namespace Novacoin
 
         public bool GetTransaction(Hash256 TxID, ref CTransaction tx)
         {
+            var reader = new BinaryReader(fStreamReadWrite).BaseStream;
             var QueryTx = dbConn.Query<CTransactionStoreItem>("select * from [TransactionStorage] where [TransactionHash] = ?", (byte[])TxID);
 
             if (QueryTx.Count == 1)
@@ -445,6 +439,7 @@ namespace Novacoin
 
         private bool AddItemToIndex(ref CBlockStoreItem itemTemplate, ref CBlock block)
         {
+            var writer = new BinaryWriter(fStreamReadWrite).BaseStream;
             var blockHash = new ScryptHash256(itemTemplate.Hash);
 
             if (blockMap.ContainsKey(blockHash))
@@ -527,7 +522,7 @@ namespace Novacoin
             uint nHeight = prevBlockCursor.nHeight + 1;
 
             // Check timestamp against prev
-            if (NetInfo.FutureDrift(block.header.nTime) < prevBlockHeader.nTime)
+            if (NetUtils.FutureDrift(block.header.nTime) < prevBlockHeader.nTime)
             {
                 // block's timestamp is too early
                 return false;
@@ -562,6 +557,8 @@ namespace Novacoin
 
         public bool GetBlock(ScryptHash256 blockHash, ref CBlock block)
         {
+            var reader = new BinaryReader(fStreamReadWrite).BaseStream;
+
             var QueryBlock = dbConn.Query<CBlockStoreItem>("select * from [BlockStorage] where [Hash] = ?", (byte[])blockHash);
 
             if (QueryBlock.Count == 1)
@@ -747,8 +744,7 @@ namespace Novacoin
                 {
                     // Free other state (managed objects).
 
-                    reader.Dispose();
-                    writer.Dispose();
+                    fStreamReadWrite.Dispose();
                 }
 
                 if (dbConn != null)
index a9a347c..ddb40e8 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics.Contracts;
+using System.IO;
 using System.Text;
 
 namespace Novacoin
@@ -73,11 +74,17 @@ namespace Novacoin
 
         public static implicit operator byte[] (COutPoint o)
         {
-            var r = new List<byte>();
-            r.AddRange((byte[])o.hash);
-            r.AddRange(BitConverter.GetBytes(o.n));
+            var stream = new MemoryStream();
+            var writer = new BinaryWriter(stream);
 
-            return r.ToArray();
+            writer.Write(o.hash);
+            writer.Write(o.n);
+
+            var outBytes = stream.ToArray();
+
+            writer.Close();
+
+            return outBytes;
         }
 
         public override string ToString()
index 6d8b2d3..33d1b92 100644 (file)
@@ -67,7 +67,7 @@ namespace Novacoin
 
         public string ToHex()
         {
-            return Interop.ToHex((byte[])this);
+            return Interop.ToHex(this);
         }
 
         /// <summary>
index 8757bb7..229b60b 100644 (file)
@@ -54,7 +54,7 @@ namespace Novacoin
         /// <returns></returns>
         public ByteQueue GetByteQueue()
         {
-             return new ByteQueue(codeBytes);
+             return new ByteQueue(ref codeBytes);
         }
 
         /// <summary>
@@ -157,7 +157,7 @@ namespace Novacoin
             }
 
             var count = 0;
-            var bq1 = new ByteQueue(codeBytes);
+            var bq1 = new ByteQueue(ref codeBytes);
 
             byte[] pushData;
             instruction opcode;
@@ -203,7 +203,7 @@ namespace Novacoin
 
             var count = 0;
             var newScript = new CScript();
-            var bq1 = new ByteQueue(codeBytes);
+            var bq1 = new ByteQueue(ref codeBytes);
 
             while (ScriptCode.GetOp(ref bq1, out opcode, out pushData))
             {
@@ -239,7 +239,7 @@ namespace Novacoin
         {
             get
             {
-                var wCodeBytes = new ByteQueue(codeBytes);
+                var wCodeBytes = new ByteQueue(ref codeBytes);
 
                 instruction opcode; // Current instruction
                 byte[] pushArgs; // OP_PUSHDATAn argument
@@ -265,7 +265,7 @@ namespace Novacoin
         {
             get
             {
-                var wCodeBytes = new ByteQueue(codeBytes);
+                var wCodeBytes = new ByteQueue(ref codeBytes);
 
                 byte[] pushArgs; // OP_PUSHDATAn argument
                 instruction opcode; // Current instruction
@@ -354,7 +354,7 @@ namespace Novacoin
         /// <returns>Amount of sigops</returns>
         public uint GetSigOpCount(bool fAccurate)
         {
-            var wCodeBytes = new ByteQueue(codeBytes);
+            var wCodeBytes = new ByteQueue(ref codeBytes);
 
             instruction opcode; // Current instruction
             byte[] pushArgs; // OP_PUSHDATAn argument
@@ -520,7 +520,7 @@ namespace Novacoin
                public override string ToString()
                {
                        var sb = new StringBuilder();
-            var wCodeBytes = new ByteQueue(codeBytes);
+            var wCodeBytes = new ByteQueue(ref codeBytes);
 
             instruction opcode; // Current instruction
             byte[] pushArgs; // OP_PUSHDATAn argument
index 83d2a09..979b689 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Text;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Novacoin
 {
@@ -244,9 +245,9 @@ namespace Novacoin
             }
             if (nBlockTime == 0)
             {
-                nBlockTime = NetInfo.GetAdjustedTime();
+                nBlockTime = NetUtils.GetAdjustedTime();
             }
-            if (nLockTime < (nLockTime < NetInfo.nLockTimeThreshold ? nBlockHeight : nBlockTime))
+            if (nLockTime < (nLockTime < NetUtils.nLockTimeThreshold ? nBlockHeight : nBlockTime))
             {
                 return true;
             }
@@ -268,7 +269,7 @@ namespace Novacoin
         {
             try
             {
-                var wBytes = new ByteQueue(txBytes);
+                var wBytes = new ByteQueue(ref txBytes);
 
                 nVersion = BitConverter.ToUInt32(wBytes.Get(4), 0);
                 nTime = BitConverter.ToUInt32(wBytes.Get(4), 0);
@@ -401,29 +402,36 @@ namespace Novacoin
         /// </summary>
         public static implicit operator byte[] (CTransaction tx)
         {
-            var resultBytes = new List<byte>();
+            var stream = new MemoryStream();
+            var writer = new BinaryWriter(stream);
 
-            resultBytes.AddRange(BitConverter.GetBytes(tx.nVersion));
-            resultBytes.AddRange(BitConverter.GetBytes(tx.nTime));
-            resultBytes.AddRange(VarInt.EncodeVarInt(tx.vin.LongLength));
+            writer.Write(tx.nVersion);
+            writer.Write(tx.nTime);
+            writer.Write(VarInt.EncodeVarInt(tx.vin.LongLength));
 
             foreach (var input in tx.vin)
             {
-                resultBytes.AddRange((byte[])input);
+                writer.Write(input);
             }
 
-            resultBytes.AddRange(VarInt.EncodeVarInt(tx.vout.LongLength));
+            writer.Write(VarInt.EncodeVarInt(tx.vout.LongLength));
 
             foreach (var output in tx.vout)
             {
-                resultBytes.AddRange((byte[])output);
+                writer.Write(output);
             }
 
-            resultBytes.AddRange(BitConverter.GetBytes(tx.nLockTime));
+            writer.Write(tx.nLockTime);
 
-            return resultBytes.ToArray();
+            var resultBytes = stream.ToArray();
+
+            writer.Close();
+
+            return resultBytes;
         }
 
+
+
         public override string ToString()
         {
             var sb = new StringBuilder();
index af8539f..067ad46 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Text;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Novacoin
 {
@@ -131,18 +132,19 @@ namespace Novacoin
         /// <returns>Byte sequence.</returns>
         public static implicit operator byte[] (CTxIn input)
         {
-            var inputBytes = new List<byte>();
+            var stream = new MemoryStream();
+            var writer = new BinaryWriter(stream);
 
-            inputBytes.AddRange((byte[])input.prevout); // prevout
+            writer.Write(input.prevout); // prevout
+            writer.Write(VarInt.EncodeVarInt(input.scriptSig.Size)); // scriptSig length
+            writer.Write(input.scriptSig); // scriptSig
+            writer.Write(input.nSequence); // nSequence
 
-            var s = (byte[])input.scriptSig;
-            inputBytes.AddRange(VarInt.EncodeVarInt(s.Length)); // scriptSig length
-            inputBytes.AddRange(s); // scriptSig
-            inputBytes.AddRange(BitConverter.GetBytes(input.nSequence)); // Sequence
-
-            return inputBytes.ToArray();
+            var inputBytes = stream.ToArray();
+            writer.Close();
+            return inputBytes;
         }
-        
+
         public bool IsFinal
         {
             get { return (nSequence == uint.MaxValue); }
index 3f63423..eb24845 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Text;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Novacoin
 {
@@ -84,15 +85,18 @@ namespace Novacoin
         /// <returns>Byte sequence.</returns>
         public static implicit operator byte[] (CTxOut output)
         {
-                var resultBytes = new List<byte>();
+            var stream = new MemoryStream();
+            var writer = new BinaryWriter(stream);
 
-                resultBytes.AddRange(BitConverter.GetBytes(output.nValue)); // txout value
+            writer.Write(output.nValue); // txout value
+            writer.Write(VarInt.EncodeVarInt(output.scriptPubKey.Size)); // scriptPubKey length
+            writer.Write(output.scriptPubKey);  // scriptPubKey
 
-                byte[] s = output.scriptPubKey;
-                resultBytes.AddRange(VarInt.EncodeVarInt(s.Length)); // scriptPubKey length
-                resultBytes.AddRange(s); // scriptPubKey
+            var resultBytes = stream.ToArray();
 
-                return resultBytes.ToArray();
+            writer.Close();
+
+            return resultBytes;
         }
 
         /// <summary>
diff --git a/Novacoin/NetInfo.cs b/Novacoin/NetInfo.cs
new file mode 100644 (file)
index 0000000..e0307bc
--- /dev/null
@@ -0,0 +1,25 @@
+\feffusing System;
+
+namespace Novacoin
+{
+    internal class NetUtils
+    {
+        public static readonly uint nLockTimeThreshold = 500000000;
+        private static readonly uint nDrift = 7200;
+
+        public static uint GetAdjustedTime()
+        {
+            return Interop.GetTime();
+        }
+
+        public static uint FutureDrift(uint nTime)
+        {
+            return nTime + nDrift; // up to 2 hours from the future
+        }
+
+        public static uint PastDrift(uint nTime)
+        {
+            return nTime - nDrift; // up to 2 hours from the past
+        }
+    }
+}
\ No newline at end of file
index c5cb553..c15b923 100644 (file)
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AddressTools.cs" />
+    <Compile Include="ByteQueue.cs" />
     <Compile Include="CBlockStore.cs" />
     <Compile Include="CKey.cs" />
     <Compile Include="CKeyID.cs" />
     <Compile Include="SHA1.cs" />
     <Compile Include="SHA256.cs" />
     <Compile Include="VarInt.cs" />
-    <Compile Include="ByteQueue.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="CTxIn.cs" />
     <Compile Include="CTransaction.cs" />
index e78d107..0f77b18 100644 (file)
@@ -18,6 +18,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.IO;
 
 namespace Novacoin
 {
@@ -128,5 +129,23 @@ namespace Novacoin
                     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;
+            }
+        }
+
     }
 }
index 3ccddf4..f374b3c 100644 (file)
@@ -283,6 +283,7 @@ namespace NovacoinTest
 
             Console.WriteLine("{0} != {1} : {2}", hash1.ToString(), hash2.ToString(), hash1 != hash2);
             Console.WriteLine("{0} == {1} : {2}\n", hash2.ToString(), hash3.ToString(), hash2 == hash3);
+            
 
             /*
             /// Pre-09854c5 revisions were affected by integer overflow bug, this issue was caused by incorrect deserialization of input value. Below you can see an example, broken transaction and its normal version.
@@ -293,11 +294,11 @@ namespace NovacoinTest
             Console.WriteLine(txNoBug);
             */
 
-            /*
+            
             Console.WriteLine("Reading the block file...");
             var bs = new CBlockStore();
             bs.ParseBlockFile();
-            */
+            
 
             Console.ReadLine();
         }