Use code contracts.
authorCryptoManiac <balthazar@yandex.ru>
Thu, 27 Aug 2015 19:12:25 +0000 (22:12 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Thu, 27 Aug 2015 19:12:25 +0000 (22:12 +0300)
RunCodeAnalysis=True
CodeContractsEnableRuntimeChecking=True

16 files changed:
Novacoin/AddressTools.cs
Novacoin/ByteQueue.cs
Novacoin/CBlockHeader.cs
Novacoin/CKeyID.cs
Novacoin/CKeyPair.cs
Novacoin/CKeyStore.cs
Novacoin/CNovacoinAddress.cs
Novacoin/COutPoint.cs
Novacoin/CPubKey.cs
Novacoin/CScript.cs
Novacoin/CScriptID.cs
Novacoin/Hash.cs
Novacoin/Interop.cs
Novacoin/Novacoin.csproj
Novacoin/ScriptCode.cs
NovacoinTest/NovacoinTest.csproj

index c0073fe..9ca95b4 100644 (file)
@@ -6,6 +6,7 @@ using Org.BouncyCastle.Math;
 
 namespace Novacoin
 {
+    [Serializable]
     public class Base58Exception : Exception
     {
         public Base58Exception()
index 5513a5d..11601bb 100644 (file)
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
+    [Serializable]
     public class ByteQueueException : Exception
     {
         public ByteQueueException()
@@ -40,69 +42,63 @@ namespace Novacoin
 
     public class ByteQueue
     {
-        private int Index;
-        private List<byte> Elements;
+        private int _Index;
+        private List<byte> _Elements;
 
         public ByteQueue(byte[] List, int Start)
         {
-            Elements = new List<byte>(List);
-            Index = Start;
+            _Elements = new List<byte>(List);
+            _Index = Start;
         }
 
         public ByteQueue(byte[] List)
         {
-            Elements = new List<byte>(List);
-            Index = 0;
+            _Elements = new List<byte>(List);
+            _Index = 0;
         }
 
         public ByteQueue(List<byte> List, int Start)
         {
-            Elements = new List<byte>(List);
-            Index = Start;
+            _Elements = new List<byte>(List);
+            _Index = Start;
         }
 
         public ByteQueue(List<byte> List)
         {
-            Elements = new List<byte>(List);
-            Index = 0;
+            _Elements = new List<byte>(List);
+            _Index = 0;
         }
 
         public byte Get()
         {
-            if (Elements.Count <= Index)
+            if (_Elements.Count <= _Index)
             {
                 throw new ByteQueueException("No elements left.");
             }
 
-            return Elements[Index++];
+            return _Elements[_Index++];
         }
 
         public byte GetCurrent()
         {
-            return Elements[Index];
+            return _Elements[_Index];
         }
 
-        public byte[] Get(int Count)
+        public byte[] Get(int nCount)
         {
-            if (Elements.Count - Index < Count)
-            {
-                throw new ByteQueueException("Unable to read requested amount of data.");
-            }
+            Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
 
-            var result = Elements.GetRange(Index, Count).ToArray();
-            Index += Count;
+            var result = _Elements.GetRange(_Index, nCount).ToArray();
+            _Index += nCount;
 
             return result;
         }
 
-        public byte[] GetCurrent(int Count)
+        public byte[] GetCurrent(int nCount)
         {
-            if (Elements.Count - Index < Count)
-            {
-                throw new ByteQueueException("Unable to read requested amount of data.");
-            }
+            Contract.Requires<ArgumentException>(Count - Index >= nCount, "nCount is greater than amount of elements.");
 
-            var result = Elements.GetRange(Index, Count).ToArray();
+            var result = _Elements.GetRange(_Index, nCount).ToArray();
 
             return result;
         }
@@ -110,9 +106,14 @@ namespace Novacoin
         /// <summary>
         /// Current index value
         /// </summary>
-        public int CurrentIndex
+        public int Index
+        {
+            get { return _Index; }
+        }
+
+        public int Count
         {
-            get { return Index; }
+            get { return _Elements.Count; }
         }
 
         public ulong GetVarInt()
index d7c1dc6..b9c9a4c 100644 (file)
@@ -19,6 +19,7 @@
 using System;
 using System.Text;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
@@ -76,6 +77,8 @@ namespace Novacoin
 
         public CBlockHeader(byte[] bytes)
         {
+            Contract.Requires<ArgumentException>(bytes.Length == 80, "Any valid block header is exactly 80 bytes long.");
+
             nVersion = BitConverter.ToUInt32(bytes, 0);
             prevHash = new Hash256(bytes, 4);
             merkleRoot = new Hash256(bytes, 36);
index ea8e561..d7130a8 100644 (file)
@@ -1,20 +1,23 @@
 \feff/**
- *  Novacoin classes library
- *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
+*  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 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.
+*  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 <http://www.gnu.org/licenses/>.
- */
+*  You should have received a copy of the GNU Affero General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using System;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
@@ -27,6 +30,8 @@ namespace Novacoin
 
         internal CKeyID(byte[] hashBytes)
         {
+            Contract.Requires<ArgumentException>(hashBytes.Length == 20, "Your data doesn't seem like a hash160 of some value.");
+
             _hashBytes = hashBytes;
         }
 
index adecb9b..a1d50a8 100644 (file)
@@ -16,7 +16,6 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-using Org.BouncyCastle.Crypto;
 using Org.BouncyCastle.Crypto.Generators;
 
 using System.Security.Cryptography;
@@ -27,21 +26,20 @@ using Org.BouncyCastle.Security;
 using System.Collections.Generic;
 using System.Linq;
 using System;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
+
     public class CKeyPair : CKey
     {
         private ECPrivateKeyParameters _Private;
-        private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
 
         /// <summary>
         /// Initialize new CKeyPair instance with random secret.
         /// </summary>
         public CKeyPair(bool Compressed = true)
         {
-
-
             var genParams = new ECKeyGenerationParameters(domain, new SecureRandom());
             var generator = new ECKeyPairGenerator("ECDSA");
             generator.Init(genParams);
@@ -50,29 +48,6 @@ namespace Novacoin
             _Private = (ECPrivateKeyParameters)ecKeyPair.Private;
             _Public = (ECPublicKeyParameters)ecKeyPair.Public;
 
-            /*
-              BigInteger D;
-              var buffer1 = new byte[32];
-              var buffer2 = new byte[32];
-
-              do
-              {
-                  rng.GetBytes(buffer1);
-                  rng.GetNonZeroBytes(buffer2);
-
-                  D = new BigInteger(Hash256.ComputeRaw256(ref buffer1, ref buffer2));
-
-                  if (D.BitLength < 249)
-                      System.Console.WriteLine(D.BitLength);
-              }
-              while (D.SignValue == -1);
-
-              var Q = curve.G.Multiply(D);
-
-              _Private = new ECPrivateKeyParameters(D, domain);
-              _Public = new ECPublicKeyParameters(Q, domain);
-            */
-
             if (Compressed)
             {
                 _Public = Compress(_Public);
@@ -86,10 +61,7 @@ namespace Novacoin
         /// <param name="Compressed">Compression flag</param>
         public CKeyPair(byte[] secretBytes, bool Compressed=true)
         {
-            if (secretBytes.Length != 32)
-            {
-                throw new ArgumentException("Serialized secret key must be 32 bytes long.");
-            }
+            Contract.Requires<ArgumentException>(secretBytes.Length == 32, "Serialized secret key must be 32 bytes long.");
 
             // Deserialize secret value
             var D = new BigInteger(secretBytes);
@@ -127,7 +99,7 @@ namespace Novacoin
         {
             var rawSecretBytes = AddressTools.Base58DecodeCheck(strBase58);
 
-            if (rawSecretBytes.Length > 34 || rawSecretBytes.Length < 33)
+            if (rawSecretBytes.Length != 33 && rawSecretBytes.Length != 34)
             {
                 throw new ArgumentException("Though you have provided a correct Base58 representation of some data, this data doesn't represent a valid private key.");
             }
index 8d6ab98..ac7d811 100644 (file)
@@ -21,6 +21,7 @@ using SQLite.Net;
 using SQLite.Net.Attributes;
 using SQLite.Net.Interop;
 using SQLite.Net.Platform.Generic;
+using System;
 using System.IO;
 using System.Linq;
 
@@ -106,11 +107,11 @@ namespace Novacoin
     /// <summary>
     /// Key storage
     /// </summary>
-    public class CKeyStore
+    public class CKeyStore : IDisposable
     {
+        private bool disposed = false;
         private object LockObj = new object();
         private SQLiteConnection dbConn = null;
-
         private int nKeyPoolSize = 100;
 
         /// <summary>
@@ -139,13 +140,35 @@ namespace Novacoin
 
         ~CKeyStore()
         {
-            if (dbConn != null)
+            Dispose(false);
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposed)
             {
-                dbConn.Close();
-                dbConn = null;
+                if (disposing)
+                {
+                    // Free other state (managed objects).
+                }
+
+                if (dbConn != null)
+                {
+                    dbConn.Close();
+                    dbConn = null;
+                }
+
+                disposed = true;
             }
         }
 
+
         /// <summary>
         /// Generate keys and insert them to key store.
         /// </summary>
index bf5321a..c652b22 100644 (file)
@@ -1,23 +1,25 @@
 \feff/**
- *  Novacoin classes library
- *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
+*  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 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.
+*  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 <http://www.gnu.org/licenses/>.
- */
+*  You should have received a copy of the GNU Affero General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
 
 using System.Collections.Generic;
 using System.Linq;
+using System;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
@@ -38,7 +40,7 @@ namespace Novacoin
     public class CNovacoinAddress
     {
         private byte nVersion;
-        private List<byte> addrData;
+        private byte[] addrData = new byte[20];
 
         /// <summary>
         /// Initialize with custom data and version
@@ -47,8 +49,10 @@ namespace Novacoin
         /// <param name="addrDataIn"></param>
         public CNovacoinAddress(byte nVersionIn, byte[] addrDataIn)
         {
+            Contract.Requires<ArgumentException>(addrDataIn.Length == 20, "Your data doesn't look like a valid hash160 of some value.");
+
             nVersion = nVersionIn;
-            addrData = new List<byte>(addrDataIn);
+            addrDataIn.CopyTo(addrData, 0);
         }
 
         /// <summary>
@@ -58,15 +62,7 @@ namespace Novacoin
         public CNovacoinAddress(CKeyID keyID)
         {
             nVersion = (byte)AddrType.PUBKEY_ADDRESS;
-            addrData = new List<byte>((byte[])keyID);
-        }
-
-        public CNovacoinAddress(string strNovacoinAddress)
-        {
-            addrData = AddressTools.Base58DecodeCheck(strNovacoinAddress).ToList();
-
-            nVersion = addrData[0];
-            addrData.RemoveAt(0);
+            addrData = keyID;
         }
 
         /// <summary>
@@ -76,15 +72,32 @@ namespace Novacoin
         public CNovacoinAddress(CScriptID scriptID)
         {
             nVersion = (byte)AddrType.SCRIPT_ADDRESS;
-            addrData = new List<byte>((byte[])scriptID);
+            addrData = scriptID;
+        }
+
+        /// <summary>
+        /// Initialize new instance from base58 string
+        /// </summary>
+        /// <param name="strNovacoinAddress"></param>
+        public CNovacoinAddress(string strNovacoinAddress)
+        {
+            var RawAddrData = AddressTools.Base58DecodeCheck(strNovacoinAddress);
+
+            if (RawAddrData.Length != 21)
+            {
+                throw new ArgumentException("Though you have provided a correct Base58 representation of some data, this data doesn't represent a valid Novacoin address.");
+            }
+
+            nVersion = RawAddrData[0];
+            Array.Copy(RawAddrData, 1, addrData, 0, 20);
         }
 
         /// <summary>
         /// 20 bytes, Hash160 of script or public key
         /// </summary>
-        public byte[] HashBytes
+        public static implicit operator byte[](CNovacoinAddress addr)
         {
-            get { return addrData.ToArray(); }
+            return addr.addrData;
         }
 
         /// <summary>
@@ -115,7 +128,7 @@ namespace Novacoin
                         return false;
                 }
 
-                return addrData.Count == nExpectedSize;
+                return addrData.Length == nExpectedSize;
             }
         }
 
index a8db03d..a65204e 100644 (file)
@@ -18,6 +18,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Text;
 
 namespace Novacoin
@@ -54,6 +55,8 @@ namespace Novacoin
 
         public COutPoint(byte[] bytes)
         {
+            Contract.Requires<ArgumentException>(bytes.Length == 36, "Any valid outpoint reference data item is exactly 36 bytes long.");
+
             hash = new Hash256(bytes);
             n = BitConverter.ToUInt32(bytes, 32);
         }
index 543a261..6d8b2d3 100644 (file)
@@ -52,7 +52,7 @@ namespace Novacoin
         /// <param name="strBase58"></param>
         public CPubKey(string strBase58)
         {
-            var pQ = curve.Curve.DecodePoint(AddressTools.Base58DecodeCheck(strBase58).ToArray());
+            var pQ = curve.Curve.DecodePoint(AddressTools.Base58DecodeCheck(strBase58));
             _Public = new ECPublicKeyParameters(pQ, domain);
         }
 
index a9ca8ef..2762f6c 100644 (file)
@@ -20,26 +20,10 @@ using System;
 using System.Linq;
 using System.Text;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
-    public class CScriptException : Exception
-    {
-        public CScriptException()
-        {
-        }
-
-        public CScriptException(string message)
-            : base(message)
-        {
-        }
-
-        public CScriptException(string message, Exception inner)
-            : base(message, inner)
-        {
-        }
-    }
-
     /// <summary>
     /// Representation of script code
     /// </summary>
@@ -79,10 +63,7 @@ namespace Novacoin
         /// <param name="opcode"></param>
         public void AddInstruction(instruction opcode)
         {
-            if (opcode < instruction.OP_0 || opcode > instruction.OP_INVALIDOPCODE)
-            {
-                throw new CScriptException("CScript::AddInstruction() : invalid instruction");
-            }
+            Contract.Requires<ArgumentException>(opcode >= instruction.OP_0 && opcode <= instruction.OP_INVALIDOPCODE, "Invalid instruction.");
 
             codeBytes.Add((byte)opcode);
         }
index c2cbc1f..bd4dea5 100644 (file)
@@ -1,20 +1,23 @@
 \feff/**
- *  Novacoin classes library
- *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
+*  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 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.
+*  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 <http://www.gnu.org/licenses/>.
- */
+*  You should have received a copy of the GNU Affero General Public License
+*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using System;
+using System.Diagnostics.Contracts;
 
 namespace Novacoin
 {
@@ -25,6 +28,13 @@ namespace Novacoin
             _hashBytes = scriptHash;
         }
 
+        internal CScriptID(byte[] hashBytes)
+        {
+            Contract.Requires<ArgumentException>(hashBytes.Length == 20, "Your data doesn't seem like a hash160 of some value.");
+
+            _hashBytes = hashBytes;
+        }
+
         public override string ToString()
         {
             return (new CNovacoinAddress(this)).ToString();
index d11f0b0..0a988df 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 using System;
+using System.Diagnostics.Contracts;
 using System.Linq;
 
 namespace Novacoin
@@ -50,6 +51,11 @@ namespace Novacoin
         /// <param name="bytesList">Array of bytes</param>
         public Hash(byte[] bytes, int offset = 0)
         {
+            if (bytes.Length - offset < hashSize)
+            {
+                throw new ArgumentException("You need to provide a sufficient amount of data to initialize new instance of hash object.");
+            }
+
             _hashBytes = new byte[hashSize];
             Array.Copy(bytes, offset, _hashBytes, 0, hashSize);
         }
index 49481c9..6771afd 100644 (file)
@@ -22,23 +22,6 @@ using System.Text;
 
 namespace Novacoin
 {
-    public class InteropException : Exception
-    {
-        public InteropException()
-        {
-        }
-
-        public InteropException(string message)
-            : base(message)
-        {
-        }
-
-        public InteropException(string message, Exception inner)
-            : base(message, inner)
-        {
-        }
-    }
-
     /// <summary>
     /// Miscellaneous functions
     /// </summary>
index 788ff16..57f12c6 100644 (file)
@@ -8,6 +8,7 @@
     <RootNamespace>Novacoin</RootNamespace>
     <AssemblyName>Novacoin</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <ConsolePause>false</ConsolePause>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+    <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
+    <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
+    <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+    <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
+    <CodeContractsInferRequires>True</CodeContractsInferRequires>
+    <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+    <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
+    <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+    <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+    <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
+    <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
+    <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
+    <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+    <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsSQLServerOption />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+    <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
+    <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+    <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>full</DebugType>
index 52c36f7..7a0f105 100644 (file)
@@ -18,6 +18,7 @@
 
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Linq;
 using System.Numerics;
 using System.Text;
@@ -369,23 +370,18 @@ namespace Novacoin
         /// <returns>Small integer</returns>
         public static int DecodeOP_N(instruction opcode, bool AllowNegate = false)
         {
-            if (AllowNegate && opcode == instruction.OP_1NEGATE)
-            {
-                return -1;
-            }
-
-            if (opcode == instruction.OP_0)
-            {
-                return 0;
-            }
-
             // Only OP_n instructions are supported, throw exception otherwise.
-            if (opcode < instruction.OP_1 || opcode > instruction.OP_16)
+            Contract.Requires<ArgumentException>((opcode == instruction.OP_1NEGATE && AllowNegate) || (opcode >= instruction.OP_0 && opcode <= instruction.OP_16), "Invalid integer instruction.");
+
+            switch (opcode)
             {
-                throw new ArgumentException("Invalid integer instruction.");
+                case instruction.OP_1NEGATE:
+                    return -1;
+                case instruction.OP_0:
+                    return 0;
+                default:
+                    return (int)opcode - (int)(instruction.OP_1 - 1);
             }
-
-            return (int)opcode - (int)(instruction.OP_1 - 1);
         }
 
         /// <summary>
@@ -395,20 +391,18 @@ namespace Novacoin
         /// <returns>Corresponding instruction.</returns>
         public static instruction EncodeOP_N(int n, bool allowNegate = false)
         {
-            if (allowNegate && n == -1)
-            {
-                return instruction.OP_1NEGATE;
-            }
+            // The n value must be in the range of 1 to 16.
+            Contract.Requires<ArgumentException>((n == -1 && allowNegate) || (n >= 0 && n <= 16), "Invalid integer value.");
 
-            if (n == 0)
+            switch (n)
             {
-                return instruction.OP_0;
+                case -1:
+                    return instruction.OP_1NEGATE;
+                case 0:
+                    return instruction.OP_0;
+                default:
+                    return (instruction.OP_1 + n - 1);
             }
-
-            // The n value must be in the range of 0 to 16.
-            if (n < 0 || n > 16)
-                throw new ArgumentException("Invalid integer value.");
-            return (instruction.OP_1 + n - 1);
         }
 
         public static int ScriptSigArgsExpected(txnouttype t, IList<byte[]> solutions)
@@ -478,7 +472,7 @@ namespace Novacoin
         /// <returns>Result</returns>
         public static bool Solver(CScript scriptPubKey, out txnouttype typeRet, out IList<byte[]> solutions)
         {
-            var scriptBytes = ((byte[])scriptPubKey);
+            byte[] scriptBytes = scriptPubKey;
 
             solutions = new List<byte[]>();
 
@@ -562,12 +556,12 @@ namespace Novacoin
 
                 byte[] args1, args2;
 
-                int last1 = ((byte[])script1).Length -1;
+                int last1 = ((byte[])script1).Length - 1;
                 int last2 = ((byte[])script2).Length - 1;
 
                 while (true)
                 {
-                    if (bq1.CurrentIndex == last1 && bq2.CurrentIndex == last2)
+                    if (bq1.Index == last1 && bq2.Index == last2)
                     {
                         // Found a match
                         typeRet = templateTuple.Item1;
@@ -759,6 +753,7 @@ namespace Novacoin
         /// <summary>
         /// Script machine exception
         /// </summary>
+        [Serializable]
         public class StackMachineException : Exception
         {
             public StackMachineException()
@@ -784,7 +779,10 @@ namespace Novacoin
         {
             int nCount = stack.Count;
             if (nCount == 0)
-                throw new StackMachineException("popstack() : stack empty");
+            {
+                throw new StackMachineException("Stack is empty");
+            }
+
             stack.RemoveAt(nCount - 1);
         }
 
@@ -796,25 +794,10 @@ namespace Novacoin
         /// <returns>Byte sequence</returns>
         private static byte[] stacktop(ref List<byte[]> stack, int nDepth)
         {
-            int nStackElement = stack.Count + nDepth;
-
-            if (nDepth >= 0)
-            {
-                StringBuilder sb = new StringBuilder();
-                sb.AppendFormat("stacktop() : positive depth ({0}) has no sense.", nDepth);
-
-                throw new StackMachineException(sb.ToString());
-            }
+            Contract.Requires<StackMachineException>(nDepth < 0, "Positive stack depth makes no sense.");
+            Contract.Requires<StackMachineException>(stack.Count + nDepth > 0, "Value exceeds real stack depth.");
 
-            if (nStackElement < 0)
-            {
-                StringBuilder sb = new StringBuilder();
-                sb.AppendFormat("stacktop() : nDepth={0} exceeds real stack depth ({1})", nDepth, stack.Count);
-
-                throw new StackMachineException(sb.ToString());
-            }
-
-            return stack[nStackElement];
+            return stack[stack.Count + nDepth];
         }
 
         /// <summary>
@@ -848,10 +831,7 @@ namespace Novacoin
         /// <returns></returns>
         private static BigInteger CastToBigInteger(byte[] value)
         {
-            if (value.Length > 4)
-            {
-                throw new StackMachineException("CastToBigInteger() : overflow");
-            }
+            Contract.Requires<StackMachineException>(value.Length <= 4, "Size limit failed.");
 
             return new BigInteger(value);
         }
@@ -1558,7 +1538,7 @@ namespace Novacoin
                             case instruction.OP_CODESEPARATOR:
                                 {
                                     // Hash starts after the code separator
-                                    nCodeHashBegin = CodeQueue.CurrentIndex;
+                                    nCodeHashBegin = CodeQueue.Index;
                                 }
                                 break;
 
index 18fa9b3..1ad2fad 100644 (file)
@@ -11,6 +11,7 @@
     <AssemblyName>NovacoinTest</AssemblyName>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
+    <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>True</CodeContractsRedundantAssumptions>
+    <CodeContractsAssertsToContractsCheckBox>True</CodeContractsAssertsToContractsCheckBox>
+    <CodeContractsRedundantTests>True</CodeContractsRedundantTests>
+    <CodeContractsMissingPublicRequiresAsWarnings>True</CodeContractsMissingPublicRequiresAsWarnings>
+    <CodeContractsMissingPublicEnsuresAsWarnings>False</CodeContractsMissingPublicEnsuresAsWarnings>
+    <CodeContractsInferRequires>True</CodeContractsInferRequires>
+    <CodeContractsInferEnsures>False</CodeContractsInferEnsures>
+    <CodeContractsInferEnsuresAutoProperties>True</CodeContractsInferEnsuresAutoProperties>
+    <CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
+    <CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
+    <CodeContractsSuggestAssumptionsForCallees>False</CodeContractsSuggestAssumptionsForCallees>
+    <CodeContractsSuggestRequires>False</CodeContractsSuggestRequires>
+    <CodeContractsNecessaryEnsures>True</CodeContractsNecessaryEnsures>
+    <CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
+    <CodeContractsSuggestReadonly>True</CodeContractsSuggestReadonly>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsSQLServerOption />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+    <CodeContractsSkipAnalysisIfCannotConnectToCache>False</CodeContractsSkipAnalysisIfCannotConnectToCache>
+    <CodeContractsFailBuildOnWarnings>False</CodeContractsFailBuildOnWarnings>
+    <CodeContractsBeingOptimisticOnExternal>True</CodeContractsBeingOptimisticOnExternal>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>