GetSigOpCount, SetDestination, SetMultiSig + new stubs
authorCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 21:05:40 +0000 (00:05 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 15 Aug 2015 21:05:40 +0000 (00:05 +0300)
Novacoin/CKey.cs [new file with mode: 0644]
Novacoin/CKeyID.cs [new file with mode: 0644]
Novacoin/CPubKey.cs [new file with mode: 0644]
Novacoin/CScript.cs
Novacoin/CScriptID.cs [new file with mode: 0644]
Novacoin/Novacoin.csproj
Novacoin/ScriptOpcode.cs

diff --git a/Novacoin/CKey.cs b/Novacoin/CKey.cs
new file mode 100644 (file)
index 0000000..7dc7330
--- /dev/null
@@ -0,0 +1,18 @@
+\feffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Novacoin
+{
+    public class CKey
+    {
+        public CPubKey GetPubKey()
+        {
+            // stub
+
+            return new CPubKey();
+        }
+    }
+}
diff --git a/Novacoin/CKeyID.cs b/Novacoin/CKeyID.cs
new file mode 100644 (file)
index 0000000..925c0d0
--- /dev/null
@@ -0,0 +1,12 @@
+\feffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Novacoin
+{
+    public class CKeyID : Hash160
+    {
+    }
+}
diff --git a/Novacoin/CPubKey.cs b/Novacoin/CPubKey.cs
new file mode 100644 (file)
index 0000000..48a3c7d
--- /dev/null
@@ -0,0 +1,18 @@
+\feffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Novacoin
+{
+    public class CPubKey
+    {
+        private List<byte> pubKeyBytes;
+
+        public IList<byte> Raw
+        {
+            get { return pubKeyBytes; }
+        }
+    }
+}
index 8a223e4..ca8f96d 100644 (file)
@@ -42,19 +42,19 @@ namespace Novacoin
         /// <summary>
         /// Initializes new instance of CScript and fills it with supplied bytes
         /// </summary>
-        /// <param name="bytes">List of bytes</param>
-        public CScript(IList<byte> bytes)
+        /// <param name="bytes">Enumerator interface for byte sequence</param>
+        public CScript(IEnumerable<byte> bytes)
         {
             codeBytes = new List<byte>(bytes);
         }
 
         /// <summary>
-        /// Initializes new instance of CScript and fills it with supplied bytes
+        /// Return a new instance of WrappedList object for current code bytes
         /// </summary>
-        /// <param name="bytes">Array of bytes</param>
-        public CScript(byte[] bytes)
+        /// <returns></returns>
+        public WrappedList<byte> GetWrappedList()
         {
-            codeBytes = new List<byte>(bytes);
+             return new WrappedList<byte>(codeBytes);
         }
 
         /// <summary>
@@ -249,6 +249,112 @@ namespace Novacoin
         }
 
         /// <summary>
+        /// Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs
+        /// as 20 sigops. With pay-to-script-hash, that changed:
+        /// CHECKMULTISIGs serialized in scriptSigs are
+        /// counted more accurately, assuming they are of the form
+        ///  ... OP_N CHECKMULTISIG ...
+        /// </summary>
+        /// <param name="fAccurate">Legacy mode flag</param>
+        /// <returns>Amount of sigops</returns>
+        public int GetSigOpCount(bool fAccurate)
+        {
+            WrappedList<byte> wCodeBytes = new WrappedList<byte>(codeBytes);
+
+            opcodetype opcode; // Current opcode
+            IEnumerable<byte> pushArgs; // OP_PUSHDATAn argument
+
+            int nCount = 0;
+            opcodetype lastOpcode = opcodetype.OP_INVALIDOPCODE;
+
+            // Scan opcodes sequence
+            while (ScriptOpcode.GetOp(ref wCodeBytes, out opcode, out pushArgs))
+            {
+                if (opcode == opcodetype.OP_CHECKSIG || opcode == opcodetype.OP_CHECKSIGVERIFY)
+                {
+                    nCount++;
+                }
+                else if (opcode == opcodetype.OP_CHECKMULTISIG || opcode == opcodetype.OP_CHECKMULTISIGVERIFY)
+                {
+                    if (fAccurate && lastOpcode >= opcodetype.OP_1 && lastOpcode <= opcodetype.OP_16)
+                    {
+                        nCount += ScriptOpcode.DecodeOP_N(lastOpcode);
+                    }
+                    else
+                    {
+                        nCount += 20;
+                    }
+                }
+            }
+
+            return nCount;
+        }
+
+        /// <summary>
+        /// Accurately count sigOps, including sigOps in
+        /// pay-to-script-hash transactions
+        /// </summary>
+        /// <param name="scriptSig">pay-to-script-hash scriptPubKey</param>
+        /// <returns>SigOps count</returns>
+        public int GetSigOpCount(CScript scriptSig)
+        {
+            if (!IsPayToScriptHash())
+            {
+                return GetSigOpCount(true);
+            }
+
+            // This is a pay-to-script-hash scriptPubKey;
+            // get the last item that the scriptSig
+            // pushes onto the stack:
+            WrappedList<byte> wScriptSig = scriptSig.GetWrappedList();
+
+            opcodetype opcode; // Current opcode
+            IEnumerable<byte> pushArgs; // OP_PUSHDATAn argument
+
+            while (ScriptOpcode.GetOp(ref wScriptSig, out opcode, out pushArgs))
+            {
+                if (opcode > opcodetype.OP_16)
+                    return 0;
+            }
+
+            /// ... and return its opcount:
+            CScript subScript = new CScript(pushArgs);
+
+            return subScript.GetSigOpCount(true);
+
+        }
+
+        public void SetDestination(CKeyID ID)
+        {
+            codeBytes.Clear();
+            AddOp(opcodetype.OP_DUP);
+            AddOp(opcodetype.OP_HASH160);
+            AddHash(ID);
+            AddOp(opcodetype.OP_EQUAL);
+        }
+
+        public void SetDestination(CScriptID ID)
+        {
+            codeBytes.Clear();
+            AddOp(opcodetype.OP_HASH160);
+            AddHash(ID);
+            AddOp(opcodetype.OP_EQUAL);
+        }
+
+        public void SetMultiSig(int nRequired, IEnumerable<CKey> keys)
+        {
+            codeBytes.Clear();
+            AddOp(ScriptOpcode.EncodeOP_N(nRequired));
+
+            foreach (CKey key in keys)
+            {
+                PushData(key.GetPubKey().Raw);
+            }
+            AddOp(ScriptOpcode.EncodeOP_N(keys.Count()));
+            AddOp(opcodetype.OP_CHECKMULTISIG);
+        }
+
+        /// <summary>
         /// Disassemble current script code
         /// </summary>
         /// <returns>Code listing</returns>
diff --git a/Novacoin/CScriptID.cs b/Novacoin/CScriptID.cs
new file mode 100644 (file)
index 0000000..32030df
--- /dev/null
@@ -0,0 +1,12 @@
+\feffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Novacoin
+{
+    public class CScriptID : Hash160
+    {
+    }
+}
index a3d2f2c..8ca7128 100644 (file)
     <Reference Include="System" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="CKey.cs" />
+    <Compile Include="CKeyID.cs" />
+    <Compile Include="CPubKey.cs" />
+    <Compile Include="CScriptID.cs" />
     <Compile Include="Hash.cs" />
     <Compile Include="WrappedList.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
index b967b5a..3cf1ba1 100644 (file)
@@ -565,7 +565,7 @@ namespace Novacoin
         /// </summary>
         /// <param name="opcode">Small integer opcode (OP_0 - OP_16)</param>
         /// <returns>Small integer</returns>
-        static int DecodeOP_N(opcodetype opcode)
+        public static int DecodeOP_N(opcodetype opcode)
         {
             if (opcode == opcodetype.OP_0)
                 return 0;
@@ -581,7 +581,7 @@ namespace Novacoin
         /// </summary>
         /// <param name="n">Small integer from the range of 0 up to 16.</param>
         /// <returns>Corresponding opcode.</returns>
-        static opcodetype EncodeOP_N(int n)
+        public static opcodetype EncodeOP_N(int n)
         {
             // The n value must be in the range of 0 to 16.
             if (n < 0 || n > 16)