From 8b06904374c83d9e4216bcd202913c5e5ce10442 Mon Sep 17 00:00:00 2001 From: CryptoManiac Date: Thu, 6 Aug 2015 13:28:21 +0300 Subject: [PATCH] Init some fields, add ToString() for Hash160 and Hash256, start implementation of CScript class --- Novacoin/CBlock.cs | 2 +- Novacoin/CBlockHeader.cs | 16 +- Novacoin/CScript.cs | 429 ++++++++++++++++++++++++++++++++++++++++++++++ Novacoin/CTransaction.cs | 6 +- Novacoin/CTxIn.cs | 19 ++- Novacoin/CTxOut.cs | 11 +- Novacoin/Hash160.cs | 18 ++ Novacoin/Hash256.cs | 16 ++ Novacoin/Novacoin.csproj | 1 + 9 files changed, 503 insertions(+), 15 deletions(-) create mode 100644 Novacoin/CScript.cs diff --git a/Novacoin/CBlock.cs b/Novacoin/CBlock.cs index a794846..4eb3a33 100644 --- a/Novacoin/CBlock.cs +++ b/Novacoin/CBlock.cs @@ -20,7 +20,7 @@ namespace Novacoin /// /// Block header signature. /// - public byte[] signature; + public byte[] signature = {}; public CBlock () { diff --git a/Novacoin/CBlockHeader.cs b/Novacoin/CBlockHeader.cs index 0ccc1fb..de9f449 100644 --- a/Novacoin/CBlockHeader.cs +++ b/Novacoin/CBlockHeader.cs @@ -2,41 +2,43 @@ namespace Novacoin { + /// + /// Block header + /// public class CBlockHeader { /// /// Version of block schema. /// - public uint nVersion; + public uint nVersion = 6; /// /// Previous block hash. /// - public Hash256 prevHash; + public Hash256 prevHash = new Hash256(); /// /// Merkle root hash. /// - public Hash256 merkleRoot; + public Hash256 merkleRoot = new Hash256(); /// /// Block timestamp. /// - public uint nTime; + public uint nTime = 0; /// /// Compressed difficulty representation. /// - public uint nBits; + public uint nBits = 0; /// /// Nonce counter. /// - public uint nNonce; + public uint nNonce = 0; public CBlockHeader () { } } } - diff --git a/Novacoin/CScript.cs b/Novacoin/CScript.cs new file mode 100644 index 0000000..70cf412 --- /dev/null +++ b/Novacoin/CScript.cs @@ -0,0 +1,429 @@ +using System; +using System.Text; + +namespace Novacoin +{ + /** Script opcodes */ + enum opcodetype + { + // push value + OP_0 = 0x00, + OP_FALSE = OP_0, + OP_PUSHDATA1 = 0x4c, + OP_PUSHDATA2 = 0x4d, + OP_PUSHDATA4 = 0x4e, + OP_1NEGATE = 0x4f, + OP_RESERVED = 0x50, + OP_1 = 0x51, + OP_TRUE=OP_1, + OP_2 = 0x52, + OP_3 = 0x53, + OP_4 = 0x54, + OP_5 = 0x55, + OP_6 = 0x56, + OP_7 = 0x57, + OP_8 = 0x58, + OP_9 = 0x59, + OP_10 = 0x5a, + OP_11 = 0x5b, + OP_12 = 0x5c, + OP_13 = 0x5d, + OP_14 = 0x5e, + OP_15 = 0x5f, + OP_16 = 0x60, + + // control + OP_NOP = 0x61, + OP_VER = 0x62, + OP_IF = 0x63, + OP_NOTIF = 0x64, + OP_VERIF = 0x65, + OP_VERNOTIF = 0x66, + OP_ELSE = 0x67, + OP_ENDIF = 0x68, + OP_VERIFY = 0x69, + OP_RETURN = 0x6a, + + // stack ops + OP_TOALTSTACK = 0x6b, + OP_FROMALTSTACK = 0x6c, + OP_2DROP = 0x6d, + OP_2DUP = 0x6e, + OP_3DUP = 0x6f, + OP_2OVER = 0x70, + OP_2ROT = 0x71, + OP_2SWAP = 0x72, + OP_IFDUP = 0x73, + OP_DEPTH = 0x74, + OP_DROP = 0x75, + OP_DUP = 0x76, + OP_NIP = 0x77, + OP_OVER = 0x78, + OP_PICK = 0x79, + OP_ROLL = 0x7a, + OP_ROT = 0x7b, + OP_SWAP = 0x7c, + OP_TUCK = 0x7d, + + // splice ops + OP_CAT = 0x7e, + OP_SUBSTR = 0x7f, + OP_LEFT = 0x80, + OP_RIGHT = 0x81, + OP_SIZE = 0x82, + + // bit logic + OP_INVERT = 0x83, + OP_AND = 0x84, + OP_OR = 0x85, + OP_XOR = 0x86, + OP_EQUAL = 0x87, + OP_EQUALVERIFY = 0x88, + OP_RESERVED1 = 0x89, + OP_RESERVED2 = 0x8a, + + // numeric + OP_1ADD = 0x8b, + OP_1SUB = 0x8c, + OP_2MUL = 0x8d, + OP_2DIV = 0x8e, + OP_NEGATE = 0x8f, + OP_ABS = 0x90, + OP_NOT = 0x91, + OP_0NOTEQUAL = 0x92, + + OP_ADD = 0x93, + OP_SUB = 0x94, + OP_MUL = 0x95, + OP_DIV = 0x96, + OP_MOD = 0x97, + OP_LSHIFT = 0x98, + OP_RSHIFT = 0x99, + + OP_BOOLAND = 0x9a, + OP_BOOLOR = 0x9b, + OP_NUMEQUAL = 0x9c, + OP_NUMEQUALVERIFY = 0x9d, + OP_NUMNOTEQUAL = 0x9e, + OP_LESSTHAN = 0x9f, + OP_GREATERTHAN = 0xa0, + OP_LESSTHANOREQUAL = 0xa1, + OP_GREATERTHANOREQUAL = 0xa2, + OP_MIN = 0xa3, + OP_MAX = 0xa4, + + OP_WITHIN = 0xa5, + + // crypto + OP_RIPEMD160 = 0xa6, + OP_SHA1 = 0xa7, + OP_SHA256 = 0xa8, + OP_HASH160 = 0xa9, + OP_HASH256 = 0xaa, + OP_CODESEPARATOR = 0xab, + OP_CHECKSIG = 0xac, + OP_CHECKSIGVERIFY = 0xad, + OP_CHECKMULTISIG = 0xae, + OP_CHECKMULTISIGVERIFY = 0xaf, + + // expansion + OP_NOP1 = 0xb0, + OP_NOP2 = 0xb1, + OP_NOP3 = 0xb2, + OP_NOP4 = 0xb3, + OP_NOP5 = 0xb4, + OP_NOP6 = 0xb5, + OP_NOP7 = 0xb6, + OP_NOP8 = 0xb7, + OP_NOP9 = 0xb8, + OP_NOP10 = 0xb9, + + + // template matching params + OP_SMALLDATA = 0xf9, + OP_SMALLINTEGER = 0xfa, + OP_PUBKEYS = 0xfb, + OP_PUBKEYHASH = 0xfd, + OP_PUBKEY = 0xfe, + + OP_INVALIDOPCODE = 0xff, + }; + + public class CScript + { + private byte[] scriptCode = {}; + + public CScript () + { + } + + private string GetOpName(opcodetype opcode) + { + switch (opcode) { + // push value + case opcodetype.OP_0: + return "0"; + case opcodetype.OP_PUSHDATA1: + return "OP_PUSHDATA1"; + case opcodetype.OP_PUSHDATA2: + return "OP_PUSHDATA2"; + case opcodetype.OP_PUSHDATA4: + return "OP_PUSHDATA4"; + case opcodetype.OP_1NEGATE: + return "-1"; + case opcodetype.OP_RESERVED: + return "OP_RESERVED"; + case opcodetype.OP_1: + return "1"; + case opcodetype.OP_2: + return "2"; + case opcodetype.OP_3: + return "3"; + case opcodetype.OP_4: + return "4"; + case opcodetype.OP_5: + return "5"; + case opcodetype.OP_6: + return "6"; + case opcodetype.OP_7: + return "7"; + case opcodetype.OP_8: + return "8"; + case opcodetype.OP_9: + return "9"; + case opcodetype.OP_10: + return "10"; + case opcodetype.OP_11: + return "11"; + case opcodetype.OP_12: + return "12"; + case opcodetype.OP_13: + return "13"; + case opcodetype.OP_14: + return "14"; + case opcodetype.OP_15: + return "15"; + case opcodetype.OP_16: + return "16"; + + // control + case opcodetype.OP_NOP: + return "OP_NOP"; + case opcodetype.OP_VER: + return "OP_VER"; + case opcodetype.OP_IF: + return "OP_IF"; + case opcodetype.OP_NOTIF: + return "OP_NOTIF"; + case opcodetype.OP_VERIF: + return "OP_VERIF"; + case opcodetype.OP_VERNOTIF: + return "OP_VERNOTIF"; + case opcodetype.OP_ELSE: + return "OP_ELSE"; + case opcodetype.OP_ENDIF: + return "OP_ENDIF"; + case opcodetype.OP_VERIFY: + return "OP_VERIFY"; + case opcodetype.OP_RETURN: + return "OP_RETURN"; + + // stack ops + case opcodetype.OP_TOALTSTACK: + return "OP_TOALTSTACK"; + case opcodetype.OP_FROMALTSTACK: + return "OP_FROMALTSTACK"; + case opcodetype.OP_2DROP: + return "OP_2DROP"; + case opcodetype.OP_2DUP: + return "OP_2DUP"; + case opcodetype.OP_3DUP: + return "OP_3DUP"; + case opcodetype.OP_2OVER: + return "OP_2OVER"; + case opcodetype.OP_2ROT: + return "OP_2ROT"; + case opcodetype.OP_2SWAP: + return "OP_2SWAP"; + case opcodetype.OP_IFDUP: + return "OP_IFDUP"; + case opcodetype.OP_DEPTH: + return "OP_DEPTH"; + case opcodetype.OP_DROP: + return "OP_DROP"; + case opcodetype.OP_DUP: + return "OP_DUP"; + case opcodetype.OP_NIP: + return "OP_NIP"; + case opcodetype.OP_OVER: + return "OP_OVER"; + case opcodetype.OP_PICK: + return "OP_PICK"; + case opcodetype.OP_ROLL: + return "OP_ROLL"; + case opcodetype.OP_ROT: + return "OP_ROT"; + case opcodetype.OP_SWAP: + return "OP_SWAP"; + case opcodetype.OP_TUCK: + return "OP_TUCK"; + + // splice ops + case opcodetype.OP_CAT: + return "OP_CAT"; + case opcodetype.OP_SUBSTR: + return "OP_SUBSTR"; + case opcodetype.OP_LEFT: + return "OP_LEFT"; + case opcodetype.OP_RIGHT: + return "OP_RIGHT"; + case opcodetype.OP_SIZE: + return "OP_SIZE"; + + // bit logic + case opcodetype.OP_INVERT: + return "OP_INVERT"; + case opcodetype.OP_AND: + return "OP_AND"; + case opcodetype.OP_OR: + return "OP_OR"; + case opcodetype.OP_XOR: + return "OP_XOR"; + case opcodetype.OP_EQUAL: + return "OP_EQUAL"; + case opcodetype.OP_EQUALVERIFY: + return "OP_EQUALVERIFY"; + case opcodetype.OP_RESERVED1: + return "OP_RESERVED1"; + case opcodetype.OP_RESERVED2: + return "OP_RESERVED2"; + + // numeric + case opcodetype.OP_1ADD: + return "OP_1ADD"; + case opcodetype.OP_1SUB: + return "OP_1SUB"; + case opcodetype.OP_2MUL: + return "OP_2MUL"; + case opcodetype.OP_2DIV: + return "OP_2DIV"; + case opcodetype.OP_NEGATE: + return "OP_NEGATE"; + case opcodetype.OP_ABS: + return "OP_ABS"; + case opcodetype.OP_NOT: + return "OP_NOT"; + case opcodetype.OP_0NOTEQUAL: + return "OP_0NOTEQUAL"; + case opcodetype.OP_ADD: + return "OP_ADD"; + case opcodetype.OP_SUB: + return "OP_SUB"; + case opcodetype.OP_MUL: + return "OP_MUL"; + case opcodetype.OP_DIV: + return "OP_DIV"; + case opcodetype.OP_MOD: + return "OP_MOD"; + case opcodetype.OP_LSHIFT: + return "OP_LSHIFT"; + case opcodetype.OP_RSHIFT: + return "OP_RSHIFT"; + case opcodetype.OP_BOOLAND: + return "OP_BOOLAND"; + case opcodetype.OP_BOOLOR: + return "OP_BOOLOR"; + case opcodetype.OP_NUMEQUAL: + return "OP_NUMEQUAL"; + case opcodetype.OP_NUMEQUALVERIFY: + return "OP_NUMEQUALVERIFY"; + case opcodetype.OP_NUMNOTEQUAL: + return "OP_NUMNOTEQUAL"; + case opcodetype.OP_LESSTHAN: + return "OP_LESSTHAN"; + case opcodetype.OP_GREATERTHAN: + return "OP_GREATERTHAN"; + case opcodetype.OP_LESSTHANOREQUAL: + return "OP_LESSTHANOREQUAL"; + case opcodetype.OP_GREATERTHANOREQUAL: + return "OP_GREATERTHANOREQUAL"; + case opcodetype.OP_MIN: + return "OP_MIN"; + case opcodetype.OP_MAX: + return "OP_MAX"; + case opcodetype.OP_WITHIN: + return "OP_WITHIN"; + + // crypto + case opcodetype.OP_RIPEMD160: + return "OP_RIPEMD160"; + case opcodetype.OP_SHA1: + return "OP_SHA1"; + case opcodetype.OP_SHA256: + return "OP_SHA256"; + case opcodetype.OP_HASH160: + return "OP_HASH160"; + case opcodetype.OP_HASH256: + return "OP_HASH256"; + case opcodetype.OP_CODESEPARATOR: + return "OP_CODESEPARATOR"; + case opcodetype.OP_CHECKSIG: + return "OP_CHECKSIG"; + case opcodetype.OP_CHECKSIGVERIFY: + return "OP_CHECKSIGVERIFY"; + case opcodetype.OP_CHECKMULTISIG: + return "OP_CHECKMULTISIG"; + case opcodetype.OP_CHECKMULTISIGVERIFY: + return "OP_CHECKMULTISIGVERIFY"; + + // expanson + case opcodetype.OP_NOP1: + return "OP_NOP1"; + case opcodetype.OP_NOP2: + return "OP_NOP2"; + case opcodetype.OP_NOP3: + return "OP_NOP3"; + case opcodetype.OP_NOP4: + return "OP_NOP4"; + case opcodetype.OP_NOP5: + return "OP_NOP5"; + case opcodetype.OP_NOP6: + return "OP_NOP6"; + case opcodetype.OP_NOP7: + return "OP_NOP7"; + case opcodetype.OP_NOP8: + return "OP_NOP8"; + case opcodetype.OP_NOP9: + return "OP_NOP9"; + case opcodetype.OP_NOP10: + return "OP_NOP10"; + + // template matching params + case opcodetype.OP_PUBKEYHASH: + return "OP_PUBKEYHASH"; + case opcodetype.OP_PUBKEY: + return "OP_PUBKEY"; + case opcodetype.OP_SMALLDATA: + return "OP_SMALLDATA"; + + case opcodetype.OP_INVALIDOPCODE: + return "OP_INVALIDOPCODE"; + default: + return "OP_UNKNOWN"; + } + } + + public override string ToString() + { + // TODO: disassembly + + StringBuilder sb = new StringBuilder(scriptCode.Length * 2); + foreach (byte b in scriptCode) + { + sb.AppendFormat ("{0:x2}", b); + } + return sb.ToString(); + } + } +} + diff --git a/Novacoin/CTransaction.cs b/Novacoin/CTransaction.cs index 29de940..422c849 100644 --- a/Novacoin/CTransaction.cs +++ b/Novacoin/CTransaction.cs @@ -10,12 +10,12 @@ namespace Novacoin /// /// Version of transaction schema. /// - public uint nVersion; + public uint nVersion = 1; /// /// Transaction timestamp. /// - public uint nTime; + public uint nTime = 0; /// /// Array of transaction inputs @@ -30,7 +30,7 @@ namespace Novacoin /// /// Block height or timestamp when transaction is final /// - public uint nLockTime; + public uint nLockTime = 0; public CTransaction () { diff --git a/Novacoin/CTxIn.cs b/Novacoin/CTxIn.cs index 6c4b5ec..4e6c615 100644 --- a/Novacoin/CTxIn.cs +++ b/Novacoin/CTxIn.cs @@ -1,18 +1,22 @@ using System; +using System.Text; namespace Novacoin { + /// + /// Transaction input. + /// public class CTxIn { /// /// Hash of parent transaction. /// - public Hash256 txID; + public Hash256 txID = new Hash256(); /// /// Parent input number. /// - public uint nInput; + public uint nInput = 0; /// /// First half of script, signatures for the scriptPubKey @@ -22,11 +26,20 @@ namespace Novacoin /// /// Transaction variant number, irrelevant if nLockTime isn't specified. Its value is 0xffffffff by default. /// - public uint nSequence; + public uint nSequence = 0xffffffff; public CTxIn () { } + + public override string ToString () + { + StringBuilder sb = new StringBuilder (); + sb.AppendFormat ("CTxIn(txId={0},n={1},scriptSig={2}", nInput, nInput, scriptSig.ToString()); + + return sb.ToString (); + } + } } diff --git a/Novacoin/CTxOut.cs b/Novacoin/CTxOut.cs index 2dc5344..8ac5c7c 100644 --- a/Novacoin/CTxOut.cs +++ b/Novacoin/CTxOut.cs @@ -1,4 +1,5 @@ using System; +using System.Text; namespace Novacoin { @@ -10,7 +11,7 @@ namespace Novacoin /// /// Input value. /// - public ulong nValue; + public ulong nValue = 0; /// /// Second half of script which contains spending instructions. @@ -20,6 +21,14 @@ namespace Novacoin public CTxOut () { } + + public override string ToString () + { + StringBuilder sb = new StringBuilder (); + sb.AppendFormat ("CTxOut(nValue={0},scriptPubKey={1}", nValue, scriptPubKey.ToString()); + + return sb.ToString (); + } } } diff --git a/Novacoin/Hash160.cs b/Novacoin/Hash160.cs index 8a995d5..993e4c9 100644 --- a/Novacoin/Hash160.cs +++ b/Novacoin/Hash160.cs @@ -1,4 +1,6 @@ using System; +using System.Text; +using System.Linq; namespace Novacoin { @@ -12,9 +14,25 @@ namespace Novacoin /// private byte[] h; + /// + /// Initializes an empty instance of the Hash160 class. + /// public Hash160 () { + // Fill with 20 zero bytes + h = Enumerable.Repeat (0, 20).ToArray (); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(h.Length * 2); + foreach (byte b in h) + { + sb.AppendFormat ("{0:x2}", b); + } + return sb.ToString(); } + } } diff --git a/Novacoin/Hash256.cs b/Novacoin/Hash256.cs index 655b300..365f778 100644 --- a/Novacoin/Hash256.cs +++ b/Novacoin/Hash256.cs @@ -1,4 +1,6 @@ using System; +using System.Text; +using System.Linq; namespace Novacoin { @@ -12,8 +14,22 @@ namespace Novacoin /// private byte[] h; + /// + /// Initializes an empty instance of the Hash256 class. + /// public Hash256 () { + h = Enumerable.Repeat(0, 32).ToArray(); + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(h.Length * 2); + foreach (byte b in h) + { + sb.AppendFormat ("{0:x2}", b); + } + return sb.ToString(); } } } diff --git a/Novacoin/Novacoin.csproj b/Novacoin/Novacoin.csproj index 9f14b3c..9c9934b 100644 --- a/Novacoin/Novacoin.csproj +++ b/Novacoin/Novacoin.csproj @@ -39,6 +39,7 @@ + \ No newline at end of file -- 1.7.1