From c93a1862cb2a3c6da088ef8562b473fa08701e01 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Sun, 16 Aug 2015 00:05:40 +0300 Subject: [PATCH] GetSigOpCount, SetDestination, SetMultiSig + new stubs --- Novacoin/CKey.cs | 18 +++++++ Novacoin/CKeyID.cs | 12 +++++ Novacoin/CPubKey.cs | 18 +++++++ Novacoin/CScript.cs | 118 +++++++++++++++++++++++++++++++++++++++++++-- Novacoin/CScriptID.cs | 12 +++++ Novacoin/Novacoin.csproj | 4 ++ Novacoin/ScriptOpcode.cs | 4 +- 7 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 Novacoin/CKey.cs create mode 100644 Novacoin/CKeyID.cs create mode 100644 Novacoin/CPubKey.cs create mode 100644 Novacoin/CScriptID.cs diff --git a/Novacoin/CKey.cs b/Novacoin/CKey.cs new file mode 100644 index 0000000..7dc7330 --- /dev/null +++ b/Novacoin/CKey.cs @@ -0,0 +1,18 @@ +using 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 index 0000000..925c0d0 --- /dev/null +++ b/Novacoin/CKeyID.cs @@ -0,0 +1,12 @@ +using 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 index 0000000..48a3c7d --- /dev/null +++ b/Novacoin/CPubKey.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Novacoin +{ + public class CPubKey + { + private List pubKeyBytes; + + public IList Raw + { + get { return pubKeyBytes; } + } + } +} diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs index 8a223e4..ca8f96d 100644 --- a/Novacoin/CScript.cs +++ b/Novacoin/CScript.cs @@ -42,19 +42,19 @@ namespace Novacoin /// /// Initializes new instance of CScript and fills it with supplied bytes /// - /// List of bytes - public CScript(IList bytes) + /// Enumerator interface for byte sequence + public CScript(IEnumerable bytes) { codeBytes = new List(bytes); } /// - /// Initializes new instance of CScript and fills it with supplied bytes + /// Return a new instance of WrappedList object for current code bytes /// - /// Array of bytes - public CScript(byte[] bytes) + /// + public WrappedList GetWrappedList() { - codeBytes = new List(bytes); + return new WrappedList(codeBytes); } /// @@ -249,6 +249,112 @@ namespace Novacoin } /// + /// 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 ... + /// + /// Legacy mode flag + /// Amount of sigops + public int GetSigOpCount(bool fAccurate) + { + WrappedList wCodeBytes = new WrappedList(codeBytes); + + opcodetype opcode; // Current opcode + IEnumerable 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; + } + + /// + /// Accurately count sigOps, including sigOps in + /// pay-to-script-hash transactions + /// + /// pay-to-script-hash scriptPubKey + /// SigOps count + 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 wScriptSig = scriptSig.GetWrappedList(); + + opcodetype opcode; // Current opcode + IEnumerable 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 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); + } + + /// /// Disassemble current script code /// /// Code listing diff --git a/Novacoin/CScriptID.cs b/Novacoin/CScriptID.cs new file mode 100644 index 0000000..32030df --- /dev/null +++ b/Novacoin/CScriptID.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Novacoin +{ + public class CScriptID : Hash160 + { + } +} diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index a3d2f2c..8ca7128 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -31,6 +31,10 @@ + + + + diff --git a/Novacoin/ScriptOpcode.cs b/Novacoin/ScriptOpcode.cs index b967b5a..3cf1ba1 100644 --- a/Novacoin/ScriptOpcode.cs +++ b/Novacoin/ScriptOpcode.cs @@ -565,7 +565,7 @@ namespace Novacoin /// /// Small integer opcode (OP_0 - OP_16) /// Small integer - 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 /// /// Small integer from the range of 0 up to 16. /// Corresponding opcode. - 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) -- 1.7.1