Use implicit type casting operator for serialization.
[NovacoinLibrary.git] / Novacoin / ScriptCode.cs
1 /**
2  *  Novacoin classes library
3  *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
4
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using System;
20 using System.Collections.Generic;
21 using System.Linq;
22 using System.Numerics;
23 using System.Text;
24
25 namespace Novacoin
26 {
27     /// <summary>
28     /// Script instructions
29     /// </summary>
30     public enum instruction
31     {
32         // push value
33         OP_0 = 0x00,
34         OP_FALSE = OP_0,
35         OP_PUSHDATA1 = 0x4c,
36         OP_PUSHDATA2 = 0x4d,
37         OP_PUSHDATA4 = 0x4e,
38         OP_1NEGATE = 0x4f,
39         OP_RESERVED = 0x50,
40         OP_1 = 0x51,
41         OP_TRUE = OP_1,
42         OP_2 = 0x52,
43         OP_3 = 0x53,
44         OP_4 = 0x54,
45         OP_5 = 0x55,
46         OP_6 = 0x56,
47         OP_7 = 0x57,
48         OP_8 = 0x58,
49         OP_9 = 0x59,
50         OP_10 = 0x5a,
51         OP_11 = 0x5b,
52         OP_12 = 0x5c,
53         OP_13 = 0x5d,
54         OP_14 = 0x5e,
55         OP_15 = 0x5f,
56         OP_16 = 0x60,
57
58         // control
59         OP_NOP = 0x61,
60         OP_VER = 0x62,
61         OP_IF = 0x63,
62         OP_NOTIF = 0x64,
63         OP_VERIF = 0x65,
64         OP_VERNOTIF = 0x66,
65         OP_ELSE = 0x67,
66         OP_ENDIF = 0x68,
67         OP_VERIFY = 0x69,
68         OP_RETURN = 0x6a,
69
70         // stack ops
71         OP_TOALTSTACK = 0x6b,
72         OP_FROMALTSTACK = 0x6c,
73         OP_2DROP = 0x6d,
74         OP_2DUP = 0x6e,
75         OP_3DUP = 0x6f,
76         OP_2OVER = 0x70,
77         OP_2ROT = 0x71,
78         OP_2SWAP = 0x72,
79         OP_IFDUP = 0x73,
80         OP_DEPTH = 0x74,
81         OP_DROP = 0x75,
82         OP_DUP = 0x76,
83         OP_NIP = 0x77,
84         OP_OVER = 0x78,
85         OP_PICK = 0x79,
86         OP_ROLL = 0x7a,
87         OP_ROT = 0x7b,
88         OP_SWAP = 0x7c,
89         OP_TUCK = 0x7d,
90
91         // splice ops
92         OP_CAT = 0x7e,
93         OP_SUBSTR = 0x7f,
94         OP_LEFT = 0x80,
95         OP_RIGHT = 0x81,
96         OP_SIZE = 0x82,
97
98         // bit logic
99         OP_INVERT = 0x83,
100         OP_AND = 0x84,
101         OP_OR = 0x85,
102         OP_XOR = 0x86,
103         OP_EQUAL = 0x87,
104         OP_EQUALVERIFY = 0x88,
105         OP_RESERVED1 = 0x89,
106         OP_RESERVED2 = 0x8a,
107
108         // numeric
109         OP_1ADD = 0x8b,
110         OP_1SUB = 0x8c,
111         OP_2MUL = 0x8d,
112         OP_2DIV = 0x8e,
113         OP_NEGATE = 0x8f,
114         OP_ABS = 0x90,
115         OP_NOT = 0x91,
116         OP_0NOTEQUAL = 0x92,
117
118         OP_ADD = 0x93,
119         OP_SUB = 0x94,
120         OP_MUL = 0x95,
121         OP_DIV = 0x96,
122         OP_MOD = 0x97,
123         OP_LSHIFT = 0x98,
124         OP_RSHIFT = 0x99,
125
126         OP_BOOLAND = 0x9a,
127         OP_BOOLOR = 0x9b,
128         OP_NUMEQUAL = 0x9c,
129         OP_NUMEQUALVERIFY = 0x9d,
130         OP_NUMNOTEQUAL = 0x9e,
131         OP_LESSTHAN = 0x9f,
132         OP_GREATERTHAN = 0xa0,
133         OP_LESSTHANOREQUAL = 0xa1,
134         OP_GREATERTHANOREQUAL = 0xa2,
135         OP_MIN = 0xa3,
136         OP_MAX = 0xa4,
137
138         OP_WITHIN = 0xa5,
139
140         // crypto
141         OP_RIPEMD160 = 0xa6,
142         OP_SHA1 = 0xa7,
143         OP_SHA256 = 0xa8,
144         OP_HASH160 = 0xa9,
145         OP_HASH256 = 0xaa,
146         OP_CODESEPARATOR = 0xab,
147         OP_CHECKSIG = 0xac,
148         OP_CHECKSIGVERIFY = 0xad,
149         OP_CHECKMULTISIG = 0xae,
150         OP_CHECKMULTISIGVERIFY = 0xaf,
151
152         // expansion
153         OP_NOP1 = 0xb0,
154         OP_NOP2 = 0xb1,
155         OP_NOP3 = 0xb2,
156         OP_NOP4 = 0xb3,
157         OP_NOP5 = 0xb4,
158         OP_NOP6 = 0xb5,
159         OP_NOP7 = 0xb6,
160         OP_NOP8 = 0xb7,
161         OP_NOP9 = 0xb8,
162         OP_NOP10 = 0xb9,
163
164         // template matching params
165         OP_SMALLDATA = 0xf9,
166         OP_SMALLINTEGER = 0xfa,
167         OP_PUBKEYS = 0xfb,
168         OP_PUBKEYHASH = 0xfd,
169         OP_PUBKEY = 0xfe,
170
171         OP_INVALIDOPCODE = 0xff,
172     };
173
174     /// <summary>
175     /// Transaction output types.
176     /// </summary>
177     public enum txnouttype
178     {
179         TX_NONSTANDARD,
180
181         // 'standard' transaction types:
182         TX_PUBKEY,
183         TX_PUBKEYHASH,
184         TX_SCRIPTHASH,
185         TX_MULTISIG,
186         TX_NULL_DATA,
187     };
188
189     /// <summary>
190     /// Signature hash types/flags
191     /// </summary>
192     public enum sigflag
193     {
194         SIGHASH_ALL = 1,
195         SIGHASH_NONE = 2,
196         SIGHASH_SINGLE = 3,
197         SIGHASH_ANYONECANPAY = 0x80,
198     };
199
200     /** Script verification flags */
201     public enum scriptflag
202     {
203         SCRIPT_VERIFY_NONE = 0,
204         SCRIPT_VERIFY_P2SH = (1 << 0), // evaluate P2SH (BIP16) subscripts
205         SCRIPT_VERIFY_STRICTENC = (1 << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
206         SCRIPT_VERIFY_LOW_S = (1 << 2), // enforce low S values in signatures (depends on STRICTENC)
207         SCRIPT_VERIFY_NOCACHE = (1 << 3), // do not store results in signature cache (but do query it)
208         SCRIPT_VERIFY_NULLDUMMY = (1 << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
209     };
210
211     public static class ScriptCode
212     {
213         public static string GetTxnOutputType(txnouttype t)
214         {
215             switch (t)
216             {
217                 case txnouttype.TX_NONSTANDARD: return "nonstandard";
218                 case txnouttype.TX_PUBKEY: return "pubkey";
219                 case txnouttype.TX_PUBKEYHASH: return "pubkeyhash";
220                 case txnouttype.TX_SCRIPTHASH: return "scripthash";
221                 case txnouttype.TX_MULTISIG: return "multisig";
222                 case txnouttype.TX_NULL_DATA: return "nulldata";
223             }
224             return string.Empty;
225         }
226
227         /// <summary>
228         /// Get the name of instruction
229         /// </summary>
230         /// <param name="opcode">Instruction</param>
231         /// <returns>Instruction name</returns>
232         public static string GetOpName(instruction opcode)
233         {
234             if (opcode == instruction.OP_0) // OP_0 and OP_FALSE are synonyms
235                 return "OP_0";
236             if (opcode == instruction.OP_1) // OP_1 and OP_TRUE are synonyms
237                 return "OP_1";
238
239             return Enum.GetName(typeof(instruction), opcode);
240         }
241
242         /// <summary>
243         /// Get next instruction from list of bytes and extract push arguments if there are some.
244         /// </summary>
245         /// <param name="codeBytes">ByteQueue reference.</param>
246         /// <param name="opcodeRet">Found instruction.</param>
247         /// <param name="bytesRet">IEnumerable out param which is used to get the push arguments.</param>
248         /// <returns>Result of operation</returns>
249         public static bool GetOp(ref ByteQueue codeBytes, out instruction opcodeRet, out byte[] bytesRet)
250         {
251             bytesRet = new byte[0];
252             opcodeRet = instruction.OP_INVALIDOPCODE;
253
254             instruction opcode;
255
256             try
257             {
258                 // Read instruction
259                 opcode = (instruction)codeBytes.Get();
260             }
261             catch (ByteQueueException)
262             {
263                 // No instruction found there
264                 return false;
265             }
266
267             // Immediate operand
268             if (opcode <= instruction.OP_PUSHDATA4)
269             {
270                 var szBytes = new byte[4] { 0, 0, 0, 0 }; // Zero length
271                 int nSize = 0;
272
273                 try
274                 {
275                     if (opcode < instruction.OP_PUSHDATA1)
276                     {
277                         // Zero value instructions (OP_0, OP_FALSE)
278                         nSize = (int) opcode;
279                     }
280                     else if (opcode == instruction.OP_PUSHDATA1)
281                     {
282                         // The next byte contains the number of bytes to be pushed onto the stack, 
283                         //    i.e. you have something like OP_PUSHDATA1 0x01 [0x5a]
284                         nSize = codeBytes.Get();
285                     }
286                     else if (opcode == instruction.OP_PUSHDATA2)
287                     {
288                         // The next two bytes contain the number of bytes to be pushed onto the stack,
289                         //    i.e. now your operation will seem like this: OP_PUSHDATA2 0x01 0x00 [0x5a]
290                         nSize = BitConverter.ToInt16(codeBytes.Get(2), 0);
291                     }
292                     else if (opcode == instruction.OP_PUSHDATA4)
293                     {
294                         // The next four bytes contain the number of bytes to be pushed onto the stack,
295                         //   OP_PUSHDATA4 0x01 0x00 0x00 0x00 [0x5a]
296                         nSize = BitConverter.ToInt32(codeBytes.Get(4), 0);
297                     }
298                 }
299                 catch (ByteQueueException)
300                 {
301                     // Unable to read operand length
302                     return false;
303                 }
304
305                 if (nSize > 0)
306                 {
307                     // If nSize is greater than zero then there is some data available
308                     try
309                     {
310                         // Read found number of bytes into list of OP_PUSHDATAn arguments.
311                         bytesRet = codeBytes.Get(nSize);
312                     }
313                     catch (ByteQueueException)
314                     {
315                         // Unable to read data
316                         return false;
317                     }
318                 }
319             }
320
321             opcodeRet = opcode;
322
323             return true;
324         }
325
326         /// <summary>
327         /// Convert value bytes into readable representation.
328         /// 
329         /// If list lengh is equal or lesser than 4 bytes then bytes are interpreted as integer value. Otherwise you will get hex representation of supplied data.
330         /// </summary>
331         /// <param name="bytes">Collection of value bytes.</param>
332         /// <returns>Formatted value.</returns>
333         public static string ValueString(byte[] bytes)
334         {
335             var sb = new StringBuilder();
336
337             if (bytes.Length <= 4)
338             {
339                 sb.Append(new BigInteger(bytes));
340             }
341             else
342             {
343                 return Interop.ToHex(bytes);
344             }
345
346             return sb.ToString();
347         }
348
349         /// <summary>
350         /// Convert list of stack items into human readable representation.
351         /// </summary>
352         /// <param name="stackList">List of stack items.</param>
353         /// <returns>Formatted value.</returns>
354         public static string StackString(IList<byte[]> stackList)
355         {
356             var sb = new StringBuilder();
357             foreach (var bytes in stackList)
358             {
359                 sb.Append(ValueString(bytes));
360             }
361
362             return sb.ToString();
363         }
364
365         /// <summary>
366         /// Decode instruction to integer value
367         /// </summary>
368         /// <param name="opcode">Small integer instruction (OP_1_NEGATE and OP_0 - OP_16)</param>
369         /// <returns>Small integer</returns>
370         public static int DecodeOP_N(instruction opcode, bool AllowNegate = false)
371         {
372             if (AllowNegate && opcode == instruction.OP_1NEGATE)
373             {
374                 return -1;
375             }
376
377             if (opcode == instruction.OP_0)
378             {
379                 return 0;
380             }
381
382             // Only OP_n instructions are supported, throw exception otherwise.
383             if (opcode < instruction.OP_1 || opcode > instruction.OP_16)
384             {
385                 throw new ArgumentException("Invalid integer instruction.");
386             }
387
388             return (int)opcode - (int)(instruction.OP_1 - 1);
389         }
390
391         /// <summary>
392         /// Converts integer into instruction
393         /// </summary>
394         /// <param name="n">Small integer from the range of -1 up to 16.</param>
395         /// <returns>Corresponding instruction.</returns>
396         public static instruction EncodeOP_N(int n, bool allowNegate = false)
397         {
398             if (allowNegate && n == -1)
399             {
400                 return instruction.OP_1NEGATE;
401             }
402
403             if (n == 0)
404             {
405                 return instruction.OP_0;
406             }
407
408             // The n value must be in the range of 0 to 16.
409             if (n < 0 || n > 16)
410                 throw new ArgumentException("Invalid integer value.");
411             return (instruction.OP_1 + n - 1);
412         }
413
414         public static int ScriptSigArgsExpected(txnouttype t, IList<byte[]> solutions)
415         {
416             switch (t)
417             {
418                 case txnouttype.TX_NONSTANDARD:
419                     return -1;
420                 case txnouttype.TX_NULL_DATA:
421                     return 1;
422                 case txnouttype.TX_PUBKEY:
423                     return 1;
424                 case txnouttype.TX_PUBKEYHASH:
425                     return 2;
426                 case txnouttype.TX_MULTISIG:
427                     if (solutions.Count < 1 || solutions.First().Length < 1)
428                         return -1;
429                     return solutions.First()[0] + 1;
430                 case txnouttype.TX_SCRIPTHASH:
431                     return 1; // doesn't include args needed by the script
432             }
433             return -1;
434         }
435
436         /// <summary>
437         /// Is it a standart type of scriptPubKey?
438         /// </summary>
439         /// <param name="scriptPubKey">CScript instance</param>
440         /// <param name="whichType">utut type</param>
441         /// <returns>Checking result</returns>
442         public static bool IsStandard(CScript scriptPubKey, out txnouttype whichType)
443         {
444             IList<byte[]> solutions;
445
446             if (!Solver(scriptPubKey, out whichType, out solutions))
447             {
448                 // No solutions found
449                 return false;
450             }
451
452             if (whichType == txnouttype.TX_MULTISIG)
453             {
454                 // Additional verification of OP_CHECKMULTISIG arguments
455                 var m = solutions.First()[0];
456                 var n = solutions.Last()[0];
457
458                 // Support up to x-of-3 multisig txns as standard
459                 if (n < 1 || n > 3)
460                 {
461                     return false;
462                 }
463                 if (m < 1 || m > n)
464                 {
465                     return false;
466                 }
467             }
468
469             return whichType != txnouttype.TX_NONSTANDARD;
470         }
471
472         /// <summary>
473         /// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
474         /// </summary>
475         /// <param name="scriptPubKey">CScript instance</param>
476         /// <param name="typeRet">Output type</param>
477         /// <param name="solutions">Set of solutions</param>
478         /// <returns>Result</returns>
479         public static bool Solver(CScript scriptPubKey, out txnouttype typeRet, out IList<byte[]> solutions)
480         {
481             var scriptBytes = ((byte[])scriptPubKey);
482
483             solutions = new List<byte[]>();
484
485             // There are shortcuts for pay-to-script-hash and pay-to-pubkey-hash, which are more constrained than the other types.
486
487             // It is always OP_HASH160 20 [20 byte hash] OP_EQUAL
488             if (scriptPubKey.IsPayToScriptHash)
489             {
490                 typeRet = txnouttype.TX_SCRIPTHASH;
491
492                 // Take 20 bytes with offset of 2 bytes
493                 var hashBytes = scriptBytes.Skip(2).Take(20);
494                 solutions.Add(hashBytes.ToArray());
495
496                 return true;
497             }
498
499             // It is always OP_DUP OP_HASH160 20 [20 byte hash] OP_EQUALVERIFY OP_CHECKSIG
500             if (scriptPubKey.IsPayToPubKeyHash)
501             {
502                 typeRet = txnouttype.TX_PUBKEYHASH;
503
504                 // Take 20 bytes with offset of 3 bytes
505                 var hashBytes = scriptBytes.Skip(3).Take(20);
506                 solutions.Add(hashBytes.ToArray());
507
508                 return true;
509             }
510
511             var templateTuples = new List<Tuple<txnouttype, byte[]>>();
512
513             // Sender provides pubkey, receiver adds signature
514             // [ECDSA public key] OP_CHECKSIG
515             templateTuples.Add(
516                 new Tuple<txnouttype, byte[]>(
517                     txnouttype.TX_PUBKEY,
518                     new byte[] {
519                         (byte)instruction.OP_PUBKEY,
520                         (byte)instruction.OP_CHECKSIG
521                     })
522             );
523
524             // Sender provides N pubkeys, receivers provides M signatures
525             // N [pubkey1] [pubkey2] ... [pubkeyN] M OP_CHECKMULTISIG
526             // Where N and M are small integer instructions (OP1 ... OP_16)
527             templateTuples.Add(
528                 new Tuple<txnouttype, byte[]>(
529                     txnouttype.TX_MULTISIG,
530                     new byte[] {
531                         (byte)instruction.OP_SMALLINTEGER,
532                         (byte)instruction.OP_PUBKEYS,
533                         (byte)instruction.OP_SMALLINTEGER,
534                         (byte)instruction.OP_CHECKMULTISIG
535                     })
536             );
537
538             // Data-carrying output
539             // OP_RETURN [up to 80 bytes of data]
540             templateTuples.Add(
541                 new Tuple<txnouttype, byte[]>(
542                     txnouttype.TX_NULL_DATA,
543                     new byte[] {
544                         (byte)instruction.OP_RETURN,
545                         (byte)instruction.OP_SMALLDATA
546                     })
547             );
548
549             // Nonstandard tx output
550             typeRet = txnouttype.TX_NONSTANDARD;
551
552             foreach (var templateTuple in templateTuples)
553             {
554                 var script1 = scriptPubKey;
555                 var script2 = new CScript(templateTuple.Item2);
556
557                 instruction opcode1, opcode2;
558
559                 // Compare
560                 var bq1 = script1.GetByteQUeue();
561                 var bq2 = script2.GetByteQUeue();
562
563                 byte[] args1, args2;
564
565                 int last1 = ((byte[])script1).Length -1;
566                 int last2 = ((byte[])script2).Length - 1;
567
568                 while (true)
569                 {
570                     if (bq1.CurrentIndex == last1 && bq2.CurrentIndex == last2)
571                     {
572                         // Found a match
573                         typeRet = templateTuple.Item1;
574                         if (typeRet == txnouttype.TX_MULTISIG)
575                         {
576                             // Additional checks for TX_MULTISIG:
577                             var m = solutions.First().First();
578                             var n = solutions.Last().First();
579
580                             if (m < 1 || n < 1 || m > n || solutions.Count - 2 != n)
581                             {
582                                 return false;
583                             }
584                         }
585                         return true;
586                     }
587
588                     if (!GetOp(ref bq1, out opcode1, out args1))
589                     {
590                         break;
591                     }
592                     if (!GetOp(ref bq2, out opcode2, out args2))
593                     {
594                         break;
595                     }
596
597                     // Template matching instructions:
598                     if (opcode2 == instruction.OP_PUBKEYS)
599                     {
600                         while (args1.Count() >= 33 && args1.Count() <= 120)
601                         {
602                             solutions.Add(args1);
603                             if (!GetOp(ref bq1, out opcode1, out args1))
604                             {
605                                 break;
606                             }
607                         }
608                         if (!GetOp(ref bq2, out opcode2, out args2))
609                         {
610                             break;
611                         }
612                         // Normal situation is to fall through
613                         // to other if/else statements
614                     }
615                     if (opcode2 == instruction.OP_PUBKEY)
616                     {
617                         int PubKeyLen = args1.Count();
618                         if (PubKeyLen < 33 || PubKeyLen > 120)
619                         {
620                             break;
621                         }
622                         solutions.Add(args1);
623                     }
624                     else if (opcode2 == instruction.OP_PUBKEYHASH)
625                     {
626                         if (args1.Count() != 20) // hash160 size
627                         {
628                             break;
629                         }
630                         solutions.Add(args1);
631                     }
632                     else if (opcode2 == instruction.OP_SMALLINTEGER)
633                     {
634                         // Single-byte small integer pushed onto solutions
635                         try
636                         {
637                             var n = (byte)DecodeOP_N(opcode1);
638                             solutions.Add(new byte[] { n });
639                         }
640                         catch (Exception)
641                         {
642                             break;
643                         }
644                     }
645                     else if (opcode2 == instruction.OP_SMALLDATA)
646                     {
647                         // small pushdata, <= 80 bytes
648                         if (args1.Length > 80)
649                         {
650                             break;
651                         }
652                     }
653                     else if (opcode1 != opcode2 || !args1.SequenceEqual(args2))
654                     {
655                         // Others must match exactly
656                         break;
657                     }
658                 }
659             }
660
661             solutions.Clear();
662             typeRet = txnouttype.TX_NONSTANDARD;
663
664             return false;
665         }
666
667         /// <summary>
668         /// Generation of SignatureHash. This method is responsible for removal of transaction metadata. It's necessary signature can't sign itself. 
669         /// </summary>
670         /// <param name="script">Spending instructions</param>
671         /// <param name="txTo">Instance of transaction</param>
672         /// <param name="nIn">Input number</param>
673         /// <param name="nHashType">Hash type flag</param>
674         /// <returns></returns>
675         public static Hash256 SignatureHash(CScript script, CTransaction txTo, int nIn, int nHashType)
676         {
677             if (nIn >= txTo.vin.Length)
678             {
679                 var sb = new StringBuilder();
680                 sb.AppendFormat("ERROR: SignatureHash() : nIn={0} out of range\n", nIn);
681                 throw new ArgumentOutOfRangeException("nIn", sb.ToString());
682             }
683
684             // Init a copy of transaction
685             var txTmp = new CTransaction(txTo);
686
687             // In case concatenating two scripts ends up with two codeseparators,
688             // or an extra one at the end, this prevents all those possible incompatibilities.
689             script.RemoveInstruction(instruction.OP_CODESEPARATOR);
690
691             // Blank out other inputs' signatures
692             for (int i = 0; i < txTmp.vin.Length; i++)
693             {
694                 txTmp.vin[i].scriptSig = new CScript();
695             }
696             txTmp.vin[nIn].scriptSig = script;
697
698             // Blank out some of the outputs
699             if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_NONE)
700             {
701                 // Wildcard payee
702                 txTmp.vout = new CTxOut[0];
703
704                 // Let the others update at will
705                 for (int i = 0; i < txTmp.vin.Length; i++)
706                 {
707                     if (i != nIn)
708                     {
709                         txTmp.vin[i].nSequence = 0;
710                     }
711                 }
712             }
713             else if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_SINGLE)
714             {
715                 // Only lock-in the txout payee at same index as txin
716                 int nOut = nIn;
717                 if (nOut >= txTmp.vout.Length)
718                 {
719                     StringBuilder sb = new StringBuilder();
720                     sb.AppendFormat("ERROR: SignatureHash() : nOut={0} out of range\n", nOut);
721                     throw new ArgumentOutOfRangeException("nOut", sb.ToString());
722                 }
723                 Array.Resize(ref txTmp.vout, nOut + 1);
724
725                 for (int i = 0; i < nOut; i++)
726                 {
727                     txTmp.vout[i] = new CTxOut();
728                 }
729
730                 // Let the others update at will
731                 for (int i = 0; i < txTmp.vin.Length; i++)
732                 {
733                     if (i != nIn)
734                     {
735                         txTmp.vin[i].nSequence = 0;
736                     }
737                 }
738             }
739
740             // Blank out other inputs completely, not recommended for open transactions
741             if ((nHashType & (int)sigflag.SIGHASH_ANYONECANPAY) != 0)
742             {
743                 txTmp.vin[0] = txTmp.vin[nIn];
744                 Array.Resize(ref txTmp.vin, 1);
745             }
746
747             // Concatenate and hash
748             var txBytes = (byte[])txTmp;
749             var nHashTypeBytes = BitConverter.GetBytes(nHashType);
750
751             return Hash256.Compute256(ref txBytes, ref nHashTypeBytes);
752         }
753
754         //
755         // Script is a stack machine (like Forth) that evaluates a predicate
756         // returning a bool indicating valid or not.  There are no loops.
757         //
758
759         /// <summary>
760         /// Script machine exception
761         /// </summary>
762         public class StackMachineException : Exception
763         {
764             public StackMachineException()
765             {
766             }
767
768             public StackMachineException(string message)
769                 : base(message)
770             {
771             }
772
773             public StackMachineException(string message, Exception inner)
774                 : base(message, inner)
775             {
776             }
777         }
778
779         /// <summary>
780         /// Remove last element from stack
781         /// </summary>
782         /// <param name="stack">Stack reference</param>
783         private static void popstack(ref List<byte[]> stack)
784         {
785             int nCount = stack.Count;
786             if (nCount == 0)
787                 throw new StackMachineException("popstack() : stack empty");
788             stack.RemoveAt(nCount - 1);
789         }
790
791         /// <summary>
792         /// Get element at specified stack depth
793         /// </summary>
794         /// <param name="stack">Stack reference</param>
795         /// <param name="nDepth">Depth</param>
796         /// <returns>Byte sequence</returns>
797         private static byte[] stacktop(ref List<byte[]> stack, int nDepth)
798         {
799             int nStackElement = stack.Count + nDepth;
800
801             if (nDepth >= 0)
802             {
803                 StringBuilder sb = new StringBuilder();
804                 sb.AppendFormat("stacktop() : positive depth ({0}) has no sense.", nDepth);
805
806                 throw new StackMachineException(sb.ToString());
807             }
808
809             if (nStackElement < 0)
810             {
811                 StringBuilder sb = new StringBuilder();
812                 sb.AppendFormat("stacktop() : nDepth={0} exceeds real stack depth ({1})", nDepth, stack.Count);
813
814                 throw new StackMachineException(sb.ToString());
815             }
816
817             return stack[nStackElement];
818         }
819
820         /// <summary>
821         /// Cast argument to boolean value
822         /// </summary>
823         /// <param name="value">Some byte sequence</param>
824         /// <returns></returns>
825         private static bool CastToBool(byte[] arg)
826         {
827             for (var i = 0; i < arg.Length; i++)
828             {
829                 if (arg[i] != 0)
830                 {
831                     // Can be negative zero
832                     if (i == arg.Length - 1 && arg[i] == 0x80)
833                     {
834                         return false;
835                     }
836
837                     return true;
838                 }
839             }
840
841             return false;
842         }
843
844         /// <summary>
845         /// Cast argument to integer value
846         /// </summary>
847         /// <param name="value"></param>
848         /// <returns></returns>
849         private static BigInteger CastToBigInteger(byte[] value)
850         {
851             if (value.Length > 4)
852             {
853                 throw new StackMachineException("CastToBigInteger() : overflow");
854             }
855
856             return new BigInteger(value);
857         }
858
859         /// <summary>
860         /// Execution of script
861         /// </summary>
862         /// <param name="stack"></param>
863         /// <param name="script">Script to execute</param>
864         /// <param name="txTo">Transaction instance</param>
865         /// <param name="nIn">Input number</param>
866         /// <param name="flags">Signature checking flags</param>
867         /// <param name="nHashType">Hash type flag</param>
868         /// <returns></returns>
869         public static bool EvalScript(ref List<byte[]> stack, CScript script, CTransaction txTo, int nIn, int flags, int nHashType)
870         {
871             var scriptBytes = ((byte[])script);
872
873             if (scriptBytes.Length > 10000)
874             {
875                 return false; // Size limit failed
876             }
877
878             var vfExec = new List<bool>();
879
880             int nOpCount = 0;
881             int nCodeHashBegin = 0;
882
883             var falseBytes = new byte[0];
884             var trueBytes = new byte[] { 0x01 };
885
886             var CodeQueue = script.GetByteQUeue();
887             var altStack = new List<byte[]>();
888
889             try
890             {
891                 instruction opcode;
892                 byte[] pushArg;
893
894                 while (GetOp(ref CodeQueue, out opcode, out pushArg)) // Read instructions
895                 {
896                     bool fExec = vfExec.IndexOf(false) == -1;
897
898                     if (pushArg.Length > 520)
899                     {
900                         return false; // Script element size limit failed
901                     }
902
903                     if (opcode > instruction.OP_16 && ++nOpCount > 201)
904                     {
905                         return false;
906                     }
907
908                     if (fExec && 0 <= opcode && opcode <= instruction.OP_PUSHDATA4)
909                     {
910                         stack.Add(pushArg); // Push argument to stack
911                     }
912                     else if (fExec || (instruction.OP_IF <= opcode && opcode <= instruction.OP_ENDIF))
913                         switch (opcode)
914                         {
915                             //
916                             // Disabled instructions
917                             //
918                             case instruction.OP_CAT:
919                             case instruction.OP_SUBSTR:
920                             case instruction.OP_LEFT:
921                             case instruction.OP_RIGHT:
922                             case instruction.OP_INVERT:
923                             case instruction.OP_AND:
924                             case instruction.OP_OR:
925                             case instruction.OP_XOR:
926                             case instruction.OP_2MUL:
927                             case instruction.OP_2DIV:
928                             case instruction.OP_MUL:
929                             case instruction.OP_DIV:
930                             case instruction.OP_MOD:
931                             case instruction.OP_LSHIFT:
932                             case instruction.OP_RSHIFT:
933                                 return false;
934
935                             //
936                             // Push integer instructions
937                             //
938                             case instruction.OP_1NEGATE:
939                             case instruction.OP_1:
940                             case instruction.OP_2:
941                             case instruction.OP_3:
942                             case instruction.OP_4:
943                             case instruction.OP_5:
944                             case instruction.OP_6:
945                             case instruction.OP_7:
946                             case instruction.OP_8:
947                             case instruction.OP_9:
948                             case instruction.OP_10:
949                             case instruction.OP_11:
950                             case instruction.OP_12:
951                             case instruction.OP_13:
952                             case instruction.OP_14:
953                             case instruction.OP_15:
954                             case instruction.OP_16:
955                                 {
956                                     // ( -- value)
957                                     BigInteger bn = DecodeOP_N(opcode, true);
958                                     stack.Add(bn.ToByteArray());
959                                 }
960                                 break;
961
962                             //
963                             // Extension
964                             //
965                             case instruction.OP_NOP:
966                             case instruction.OP_NOP1:
967                             case instruction.OP_NOP2:
968                             case instruction.OP_NOP3:
969                             case instruction.OP_NOP4:
970                             case instruction.OP_NOP5:
971                             case instruction.OP_NOP6:
972                             case instruction.OP_NOP7:
973                             case instruction.OP_NOP8:
974                             case instruction.OP_NOP9:
975                             case instruction.OP_NOP10:
976                                 {
977                                     // Just do nothing
978                                 }
979                                 break;
980
981                             //
982                             // Control
983                             //
984                             case instruction.OP_IF:
985                             case instruction.OP_NOTIF:
986                                 {
987                                     // <expression> if [statements] [else [statements]] endif
988                                     var fValue = false;
989                                     if (fExec)
990                                     {
991                                         if (stack.Count() < 1)
992                                         {
993                                             return false;
994                                         }
995                                         var vch = stacktop(ref stack, -1);
996                                         fValue = CastToBool(vch);
997                                         if (opcode == instruction.OP_NOTIF)
998                                         {
999                                             fValue = !fValue;
1000                                         }
1001                                         popstack(ref stack);
1002                                     }
1003                                     vfExec.Add(fValue);
1004                                 }
1005                                 break;
1006
1007                             case instruction.OP_ELSE:
1008                                 {
1009                                     int nExecCount = vfExec.Count();
1010                                     if (nExecCount == 0)
1011                                     {
1012                                         return false;
1013                                     }
1014                                     vfExec[nExecCount - 1] = !vfExec[nExecCount - 1];
1015                                 }
1016                                 break;
1017
1018                             case instruction.OP_ENDIF:
1019                                 {
1020                                     int nExecCount = vfExec.Count();
1021                                     if (nExecCount == 0)
1022                                     {
1023                                         return false;
1024                                     }
1025                                     vfExec.RemoveAt(nExecCount - 1);
1026                                 }
1027                                 break;
1028
1029                             case instruction.OP_VERIFY:
1030                                 {
1031                                     // (true -- ) or
1032                                     // (false -- false) and return
1033                                     if (stack.Count() < 1)
1034                                     {
1035                                         return false;
1036                                     }
1037
1038                                     bool fValue = CastToBool(stacktop(ref stack, -1));
1039                                     if (fValue)
1040                                     {
1041                                         popstack(ref stack);
1042                                     }
1043                                     else
1044                                     {
1045                                         return false;
1046                                     }
1047                                 }
1048                                 break;
1049
1050                             case instruction.OP_RETURN:
1051                                 {
1052                                     return false;
1053                                 }
1054
1055                             //
1056                             // Stack ops
1057                             //
1058                             case instruction.OP_TOALTSTACK:
1059                                 {
1060                                     if (stack.Count() < 1)
1061                                     {
1062                                         return false;
1063                                     }
1064                                     altStack.Add(stacktop(ref stack, -1));
1065                                     popstack(ref stack);
1066                                 }
1067                                 break;
1068
1069                             case instruction.OP_FROMALTSTACK:
1070                                 {
1071                                     if (altStack.Count() < 1)
1072                                     {
1073                                         return false;
1074                                     }
1075                                     stack.Add(stacktop(ref stack, -1));
1076                                     popstack(ref altStack);
1077                                 }
1078                                 break;
1079
1080                             case instruction.OP_2DROP:
1081                                 {
1082                                     // (x1 x2 -- )
1083                                     if (stack.Count() < 2)
1084                                     {
1085                                         return false;
1086                                     }
1087                                     popstack(ref stack);
1088                                     popstack(ref stack);
1089                                 }
1090                                 break;
1091
1092                             case instruction.OP_2DUP:
1093                                 {
1094                                     // (x1 x2 -- x1 x2 x1 x2)
1095                                     if (stack.Count() < 2)
1096                                     {
1097                                         return false;
1098                                     }
1099                                     var vch1 = stacktop(ref stack, -2);
1100                                     var vch2 = stacktop(ref stack, -1);
1101                                     stack.Add(vch1);
1102                                     stack.Add(vch2);
1103                                 }
1104                                 break;
1105
1106                             case instruction.OP_3DUP:
1107                                 {
1108                                     // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
1109                                     if (stack.Count() < 3)
1110                                     {
1111                                         return false;
1112                                     }
1113                                     var vch1 = stacktop(ref stack, -3);
1114                                     var vch2 = stacktop(ref stack, -2);
1115                                     var vch3 = stacktop(ref stack, -1);
1116                                     stack.Add(vch1);
1117                                     stack.Add(vch2);
1118                                     stack.Add(vch3);
1119                                 }
1120                                 break;
1121
1122                             case instruction.OP_2OVER:
1123                                 {
1124                                     // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
1125                                     if (stack.Count() < 4)
1126                                     {
1127                                         return false;
1128                                     }
1129                                     var vch1 = stacktop(ref stack, -4);
1130                                     var vch2 = stacktop(ref stack, -3);
1131                                     stack.Add(vch1);
1132                                     stack.Add(vch2);
1133                                 }
1134                                 break;
1135
1136                             case instruction.OP_2ROT:
1137                                 {
1138                                     int nStackDepth = stack.Count();
1139                                     // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
1140                                     if (nStackDepth < 6)
1141                                     {
1142                                         return false;
1143                                     }
1144                                     var vch1 = stacktop(ref stack, -6);
1145                                     var vch2 = stacktop(ref stack, -5);
1146                                     stack.RemoveRange(nStackDepth - 6, 2);
1147                                     stack.Add(vch1);
1148                                     stack.Add(vch2);
1149                                 }
1150                                 break;
1151
1152                             case instruction.OP_2SWAP:
1153                                 {
1154                                     // (x1 x2 x3 x4 -- x3 x4 x1 x2)
1155                                     int nStackDepth = stack.Count;
1156                                     if (nStackDepth < 4)
1157                                     {
1158                                         return false;
1159                                     }
1160                                     stack.Swap(nStackDepth - 4, nStackDepth - 2);
1161                                     stack.Swap(nStackDepth - 3, nStackDepth - 1);
1162                                 }
1163                                 break;
1164
1165                             case instruction.OP_IFDUP:
1166                                 {
1167                                     // (x - 0 | x x)
1168                                     if (stack.Count() < 1)
1169                                     {
1170                                         return false;
1171                                     }
1172
1173                                     var vch = stacktop(ref stack, -1);
1174
1175                                     if (CastToBool(vch))
1176                                     {
1177                                         stack.Add(vch);
1178                                     }
1179                                 }
1180                                 break;
1181
1182                             case instruction.OP_DEPTH:
1183                                 {
1184                                     // -- stacksize
1185                                     BigInteger bn = new BigInteger((ushort)stack.Count());
1186                                     stack.Add(bn.ToByteArray());
1187                                 }
1188                                 break;
1189
1190                             case instruction.OP_DROP:
1191                                 {
1192                                     // (x -- )
1193                                     if (stack.Count() < 1)
1194                                     {
1195                                         return false;
1196                                     }
1197
1198                                     popstack(ref stack);
1199                                 }
1200                                 break;
1201
1202                             case instruction.OP_DUP:
1203                                 {
1204                                     // (x -- x x)
1205                                     if (stack.Count() < 1)
1206                                     {
1207                                         return false;
1208                                     }
1209
1210                                     var vch = stacktop(ref stack, -1);
1211                                     stack.Add(vch);
1212                                 }
1213                                 break;
1214
1215                             case instruction.OP_NIP:
1216                                 {
1217                                     // (x1 x2 -- x2)
1218                                     int nStackDepth = stack.Count();
1219                                     if (nStackDepth < 2)
1220                                     {
1221                                         return false;
1222                                     }
1223
1224                                     stack.RemoveAt(nStackDepth - 2);
1225                                 }
1226                                 break;
1227
1228                             case instruction.OP_OVER:
1229                                 {
1230                                     // (x1 x2 -- x1 x2 x1)
1231                                     if (stack.Count() < 2)
1232                                     {
1233                                         return false;
1234                                     }
1235
1236                                     var vch = stacktop(ref stack, -2);
1237                                     stack.Add(vch);
1238                                 }
1239                                 break;
1240
1241                             case instruction.OP_PICK:
1242                             case instruction.OP_ROLL:
1243                                 {
1244                                     // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
1245                                     // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
1246
1247                                     int nStackDepth = stack.Count();
1248                                     if (nStackDepth < 2)
1249                                     {
1250                                         return false;
1251                                     }
1252
1253                                     int n = (int)CastToBigInteger(stacktop(ref stack, -1));
1254                                     popstack(ref stack);
1255
1256                                     if (n < 0 || n >= stack.Count())
1257                                     {
1258                                         return false;
1259                                     }
1260
1261                                     var vch = stacktop(ref stack, -n - 1);
1262                                     if (opcode == instruction.OP_ROLL)
1263                                     {
1264                                         stack.RemoveAt(nStackDepth - n - 1);
1265                                     }
1266
1267                                     stack.Add(vch);
1268                                 }
1269                                 break;
1270
1271                             case instruction.OP_ROT:
1272                                 {
1273                                     // (x1 x2 x3 -- x2 x3 x1)
1274                                     //  x2 x1 x3  after first swap
1275                                     //  x2 x3 x1  after second swap
1276                                     int nStackDepth = stack.Count();
1277                                     if (nStackDepth < 3)
1278                                     {
1279                                         return false;
1280                                     }
1281                                     stack.Swap(nStackDepth - 3, nStackDepth - 2);
1282                                     stack.Swap(nStackDepth - 2, nStackDepth - 1);
1283
1284                                 }
1285                                 break;
1286
1287                             case instruction.OP_SWAP:
1288                                 {
1289                                     // (x1 x2 -- x2 x1)
1290                                     int nStackDepth = stack.Count();
1291                                     if (nStackDepth < 2)
1292                                     {
1293                                         return false;
1294                                     }
1295                                     stack.Swap(nStackDepth - 2, nStackDepth - 1);
1296                                 }
1297                                 break;
1298
1299                             case instruction.OP_TUCK:
1300                                 {
1301                                     // (x1 x2 -- x2 x1 x2)
1302                                     int nStackDepth = stack.Count();
1303                                     if (nStackDepth < 2)
1304                                     {
1305                                         return false;
1306                                     }
1307                                     var vch = stacktop(ref stack, -1);
1308                                     stack.Insert(nStackDepth - 2, vch);
1309                                 }
1310                                 break;
1311
1312
1313                             case instruction.OP_SIZE:
1314                                 {
1315                                     // (in -- in size)
1316                                     if (stack.Count() < 1)
1317                                     {
1318                                         return false;
1319                                     }
1320
1321                                     var bnSize = new BigInteger((ushort)stacktop(ref stack, -1).Count());
1322                                     stack.Add(bnSize.ToByteArray());
1323                                 }
1324                                 break;
1325
1326
1327                             //
1328                             // Bitwise logic
1329                             //
1330                             case instruction.OP_EQUAL:
1331                             case instruction.OP_EQUALVERIFY:
1332                                 //case instruction.OP_NOTEQUAL: // use OP_NUMNOTEQUAL
1333                                 {
1334                                     // (x1 x2 - bool)
1335                                     if (stack.Count() < 2)
1336                                     {
1337                                         return false;
1338                                     }
1339
1340                                     var vch1 = stacktop(ref stack, -2);
1341                                     var vch2 = stacktop(ref stack, -1);
1342                                     bool fEqual = (vch1.SequenceEqual(vch2));
1343                                     // OP_NOTEQUAL is disabled because it would be too easy to say
1344                                     // something like n != 1 and have some wiseguy pass in 1 with extra
1345                                     // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
1346                                     //if (opcode == instruction.OP_NOTEQUAL)
1347                                     //    fEqual = !fEqual;
1348                                     popstack(ref stack);
1349                                     popstack(ref stack);
1350                                     stack.Add(fEqual ? trueBytes : falseBytes);
1351
1352                                     if (opcode == instruction.OP_EQUALVERIFY)
1353                                     {
1354                                         if (fEqual)
1355                                         {
1356                                             popstack(ref stack);
1357                                         }
1358                                         else
1359                                         {
1360                                             return false;
1361                                         }
1362                                     }
1363                                 }
1364                                 break;
1365
1366
1367                             //
1368                             // Numeric
1369                             //
1370                             case instruction.OP_1ADD:
1371                             case instruction.OP_1SUB:
1372                             case instruction.OP_NEGATE:
1373                             case instruction.OP_ABS:
1374                             case instruction.OP_NOT:
1375                             case instruction.OP_0NOTEQUAL:
1376                                 {
1377                                     // (in -- out)
1378                                     if (stack.Count() < 1)
1379                                     {
1380                                         return false;
1381                                     }
1382
1383                                     var bn = CastToBigInteger(stacktop(ref stack, -1));
1384                                     switch (opcode)
1385                                     {
1386                                         case instruction.OP_1ADD:
1387                                             bn = bn + 1;
1388                                             break;
1389                                         case instruction.OP_1SUB:
1390                                             bn = bn - 1;
1391                                             break;
1392                                         case instruction.OP_NEGATE:
1393                                             bn = -bn;
1394                                             break;
1395                                         case instruction.OP_ABS:
1396                                             bn = BigInteger.Abs(bn);
1397                                             break;
1398                                         case instruction.OP_NOT:
1399                                             bn = bn == 0 ? 1 : 0;
1400                                             break;
1401                                         case instruction.OP_0NOTEQUAL:
1402                                             bn = bn != 0 ? 1 : 0;
1403                                             break;
1404                                     }
1405
1406                                     popstack(ref stack);
1407                                     stack.Add(bn.ToByteArray());
1408                                 }
1409                                 break;
1410
1411                             case instruction.OP_ADD:
1412                             case instruction.OP_SUB:
1413                             case instruction.OP_BOOLAND:
1414                             case instruction.OP_BOOLOR:
1415                             case instruction.OP_NUMEQUAL:
1416                             case instruction.OP_NUMEQUALVERIFY:
1417                             case instruction.OP_NUMNOTEQUAL:
1418                             case instruction.OP_LESSTHAN:
1419                             case instruction.OP_GREATERTHAN:
1420                             case instruction.OP_LESSTHANOREQUAL:
1421                             case instruction.OP_GREATERTHANOREQUAL:
1422                             case instruction.OP_MIN:
1423                             case instruction.OP_MAX:
1424                                 {
1425                                     // (x1 x2 -- out)
1426                                     if (stack.Count() < 2)
1427                                     {
1428                                         return false;
1429                                     }
1430
1431                                     var bn1 = CastToBigInteger(stacktop(ref stack, -2));
1432                                     var bn2 = CastToBigInteger(stacktop(ref stack, -1));
1433                                     BigInteger bn = 0;
1434
1435                                     switch (opcode)
1436                                     {
1437                                         case instruction.OP_ADD:
1438                                             bn = bn1 + bn2;
1439                                             break;
1440                                         case instruction.OP_SUB:
1441                                             bn = bn1 - bn2;
1442                                             break;
1443                                         case instruction.OP_BOOLAND:
1444                                             bn = (bn1 != 0 && bn2 != 0) ? 1 : 0;
1445                                             break;
1446                                         case instruction.OP_BOOLOR:
1447                                             bn = (bn1 != 0 || bn2 != 0) ? 1 : 0;
1448                                             break;
1449                                         case instruction.OP_NUMEQUAL:
1450                                             bn = (bn1 == bn2) ? 1 : 0;
1451                                             break;
1452                                         case instruction.OP_NUMEQUALVERIFY:
1453                                             bn = (bn1 == bn2) ? 1 : 0;
1454                                             break;
1455                                         case instruction.OP_NUMNOTEQUAL:
1456                                             bn = (bn1 != bn2) ? 1 : 0;
1457                                             break;
1458                                         case instruction.OP_LESSTHAN:
1459                                             bn = (bn1 < bn2) ? 1 : 0;
1460                                             break;
1461                                         case instruction.OP_GREATERTHAN:
1462                                             bn = (bn1 > bn2) ? 1 : 0;
1463                                             break;
1464                                         case instruction.OP_LESSTHANOREQUAL:
1465                                             bn = (bn1 <= bn2) ? 1 : 0;
1466                                             break;
1467                                         case instruction.OP_GREATERTHANOREQUAL:
1468                                             bn = (bn1 >= bn2) ? 1 : 0;
1469                                             break;
1470                                         case instruction.OP_MIN:
1471                                             bn = (bn1 < bn2 ? bn1 : bn2);
1472                                             break;
1473                                         case instruction.OP_MAX:
1474                                             bn = (bn1 > bn2 ? bn1 : bn2);
1475                                             break;
1476                                     }
1477
1478                                     popstack(ref stack);
1479                                     popstack(ref stack);
1480                                     stack.Add(bn.ToByteArray());
1481
1482                                     if (opcode == instruction.OP_NUMEQUALVERIFY)
1483                                     {
1484                                         if (CastToBool(stacktop(ref stack, -1)))
1485                                         {
1486                                             popstack(ref stack);
1487                                         }
1488                                         else
1489                                         {
1490                                             return false;
1491                                         }
1492                                     }
1493                                 }
1494                                 break;
1495
1496                             case instruction.OP_WITHIN:
1497                                 {
1498                                     // (x min max -- out)
1499                                     if (stack.Count() < 3)
1500                                     {
1501                                         return false;
1502                                     }
1503
1504                                     var bn1 = CastToBigInteger(stacktop(ref stack, -3));
1505                                     var bn2 = CastToBigInteger(stacktop(ref stack, -2));
1506                                     var bn3 = CastToBigInteger(stacktop(ref stack, -1));
1507
1508                                     bool fValue = (bn2 <= bn1 && bn1 < bn3);
1509
1510                                     popstack(ref stack);
1511                                     popstack(ref stack);
1512                                     popstack(ref stack);
1513
1514                                     stack.Add(fValue ? trueBytes : falseBytes);
1515                                 }
1516                                 break;
1517
1518                             //
1519                             // Crypto
1520                             //
1521                             case instruction.OP_RIPEMD160:
1522                             case instruction.OP_SHA1:
1523                             case instruction.OP_SHA256:
1524                             case instruction.OP_HASH160:
1525                             case instruction.OP_HASH256:
1526                                 {
1527                                     // (in -- hash)
1528                                     if (stack.Count() < 1)
1529                                     {
1530                                         return false;
1531                                     }
1532                                     Hash hash = null;
1533                                     var data = stacktop(ref stack, -1);
1534
1535                                     switch (opcode)
1536                                     {
1537                                         case instruction.OP_HASH160:
1538                                             hash = Hash160.Compute160(data);
1539                                             break;
1540                                         case instruction.OP_HASH256:
1541                                             hash = Hash256.Compute256(data);
1542                                             break;
1543                                         case instruction.OP_SHA1:
1544                                             hash = SHA1.Compute1(data);
1545                                             break;
1546                                         case instruction.OP_SHA256:
1547                                             hash = SHA256.Compute256(data);
1548                                             break;
1549                                         case instruction.OP_RIPEMD160:
1550                                             hash = RIPEMD160.Compute160(data);
1551                                             break;
1552                                     }
1553                                     popstack(ref stack);
1554                                     stack.Add(hash);
1555                                 }
1556                                 break;
1557
1558                             case instruction.OP_CODESEPARATOR:
1559                                 {
1560                                     // Hash starts after the code separator
1561                                     nCodeHashBegin = CodeQueue.CurrentIndex;
1562                                 }
1563                                 break;
1564
1565                             case instruction.OP_CHECKSIG:
1566                             case instruction.OP_CHECKSIGVERIFY:
1567                                 {
1568                                     // (sig pubkey -- bool)
1569                                     if (stack.Count() < 2)
1570                                     {
1571                                         return false;
1572                                     }
1573
1574                                     var sigBytes = stacktop(ref stack, -2);
1575                                     var pubkeyBytes = stacktop(ref stack, -1);
1576
1577                                     // Subset of script starting at the most recent codeseparator
1578                                     var scriptCode = new CScript(scriptBytes.Skip(nCodeHashBegin).ToArray());
1579
1580                                     // There's no way for a signature to sign itself
1581                                     scriptCode.RemovePattern(sigBytes);
1582
1583                                     bool fSuccess = IsCanonicalSignature(sigBytes, flags) && IsCanonicalPubKey(pubkeyBytes, flags) && CheckSig(sigBytes, pubkeyBytes, scriptCode, txTo, nIn, nHashType, flags);
1584
1585                                     popstack(ref stack);
1586                                     popstack(ref stack);
1587
1588                                     stack.Add(fSuccess ? trueBytes : falseBytes);
1589
1590                                     if (opcode == instruction.OP_CHECKSIGVERIFY)
1591                                     {
1592                                         if (fSuccess)
1593                                         {
1594                                             popstack(ref stack);
1595                                         }
1596                                         else
1597                                         {
1598                                             return false;
1599                                         }
1600                                     }
1601                                 }
1602                                 break;
1603
1604                             case instruction.OP_CHECKMULTISIG:
1605                             case instruction.OP_CHECKMULTISIGVERIFY:
1606                                 {
1607                                     // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
1608
1609                                     int i = 1;
1610                                     if (stack.Count() < i)
1611                                     {
1612                                         return false;
1613                                     }
1614
1615                                     int nKeysCount = (int)CastToBigInteger(stacktop(ref stack, -i));
1616                                     if (nKeysCount < 0 || nKeysCount > 20)
1617                                     {
1618                                         return false;
1619                                     }
1620                                     nOpCount += nKeysCount;
1621                                     if (nOpCount > 201)
1622                                     {
1623                                         return false;
1624                                     }
1625                                     int ikey = ++i;
1626                                     i += nKeysCount;
1627                                     if (stack.Count() < i)
1628                                     {
1629                                         return false;
1630                                     }
1631
1632                                     int nSigsCount = (int)CastToBigInteger(stacktop(ref stack, -i));
1633                                     if (nSigsCount < 0 || nSigsCount > nKeysCount)
1634                                     {
1635                                         return false;
1636                                     }
1637                                     int isig = ++i;
1638                                     i += nSigsCount;
1639                                     if (stack.Count() < i)
1640                                     {
1641                                         return false;
1642                                     }
1643
1644                                     // Subset of script starting at the most recent codeseparator
1645                                     var scriptCode = new CScript(scriptBytes.Skip(nCodeHashBegin).ToArray());
1646
1647                                     // There is no way for a signature to sign itself, so we need to drop the signatures
1648                                     for (int k = 0; k < nSigsCount; k++)
1649                                     {
1650                                         var vchSig = stacktop(ref stack, -isig - k);
1651                                         scriptCode.RemovePattern(vchSig);
1652                                     }
1653
1654                                     bool fSuccess = true;
1655                                     while (fSuccess && nSigsCount > 0)
1656                                     {
1657                                         var sigBytes = stacktop(ref stack, -isig);
1658                                         var pubKeyBytes = stacktop(ref stack, -ikey);
1659
1660                                         // Check signature
1661                                         bool fOk = IsCanonicalSignature(sigBytes, flags) && IsCanonicalPubKey(pubKeyBytes, flags) && CheckSig(sigBytes, pubKeyBytes, scriptCode, txTo, nIn, nHashType, flags);
1662
1663                                         if (fOk)
1664                                         {
1665                                             isig++;
1666                                             nSigsCount--;
1667                                         }
1668                                         ikey++;
1669                                         nKeysCount--;
1670
1671                                         // If there are more signatures left than keys left,
1672                                         // then too many signatures have failed
1673                                         if (nSigsCount > nKeysCount)
1674                                         {
1675                                             fSuccess = false;
1676                                         }
1677                                     }
1678
1679                                     while (i-- > 1)
1680                                     {
1681                                         popstack(ref stack);
1682                                     }
1683
1684                                     // A bug causes CHECKMULTISIG to consume one extra argument
1685                                     // whose contents were not checked in any way.
1686                                     //
1687                                     // Unfortunately this is a potential source of mutability,
1688                                     // so optionally verify it is exactly equal to zero prior
1689                                     // to removing it from the stack.
1690                                     if (stack.Count() < 1)
1691                                     {
1692                                         return false;
1693                                     }
1694                                     if ((flags & (int)scriptflag.SCRIPT_VERIFY_NULLDUMMY) != 0 && stacktop(ref stack, -1).Count() != 0)
1695                                     {
1696                                         return false; // CHECKMULTISIG dummy argument not null
1697                                     }
1698                                     popstack(ref stack);
1699
1700                                     stack.Add(fSuccess ? trueBytes : falseBytes);
1701
1702                                     if (opcode == instruction.OP_CHECKMULTISIGVERIFY)
1703                                     {
1704                                         if (fSuccess)
1705                                         {
1706                                             popstack(ref stack);
1707                                         }
1708                                         else
1709                                         {
1710                                             return false;
1711                                         }
1712                                     }
1713                                 }
1714                                 break;
1715
1716                             default:
1717                                 return false;
1718                         }
1719
1720                     // Size limits
1721                     if (stack.Count() + altStack.Count() > 1000)
1722                     {
1723                         return false;
1724                     }
1725                 }
1726             }
1727             catch (Exception)
1728             {
1729                 // If there are any exceptions then just return false.
1730                 return false;
1731             }
1732
1733             if (vfExec.Count() != 0)
1734             {
1735                 // Something went wrong with conditional instructions.
1736                 return false;
1737             }
1738
1739             return true;
1740         }
1741
1742
1743         public static bool IsCanonicalPubKey(byte[] pubKeyBytes, int flags)
1744         {
1745             if ((flags & (int)scriptflag.SCRIPT_VERIFY_STRICTENC) == 0)
1746                 return true;
1747
1748             if (pubKeyBytes.Length < 33)
1749                 return false;  // Non-canonical public key: too short
1750             if (pubKeyBytes[0] == 0x04)
1751             {
1752                 if (pubKeyBytes.Length != 65)
1753                     return false; // Non-canonical public key: invalid length for uncompressed key
1754             }
1755             else if (pubKeyBytes[0] == 0x02 || pubKeyBytes[0] == 0x03)
1756             {
1757                 if (pubKeyBytes.Length != 33)
1758                     return false; // Non-canonical public key: invalid length for compressed key
1759             }
1760             else
1761             {
1762                 return false; // Non-canonical public key: compressed nor uncompressed
1763             }
1764             return true;
1765         }
1766
1767         public static bool IsCanonicalSignature(byte[] sigBytes, int flags)
1768         {
1769             // STUB
1770
1771             return true;
1772         }
1773
1774         /// <summary>
1775         /// Check signature.
1776         /// </summary>
1777         /// <param name="sigBytes">Signature</param>
1778         /// <param name="pubkeyBytes">Public key</param>
1779         /// <param name="script">Spending script</param>
1780         /// <param name="txTo">CTransaction instance</param>
1781         /// <param name="nIn">Input number</param>
1782         /// <param name="nHashType">Hashing type flag</param>
1783         /// <param name="flags">Signature checking flags</param>
1784         /// <returns>Checking result</returns>
1785         public static bool CheckSig(byte[] sigBytes, byte[] pubkeyBytes, CScript script, CTransaction txTo, int nIn, int nHashType, int flags)
1786         {
1787             CPubKey pubkey;
1788
1789             try
1790             {
1791                 // Trying to initialize the public key instance
1792
1793                 pubkey = new CPubKey(pubkeyBytes);
1794             }
1795             catch (Exception)
1796             {
1797                 // Exception occurred while initializing the public key
1798
1799                 return false; 
1800             }
1801
1802             if (!pubkey.IsValid)
1803             {
1804                 return false;
1805             }
1806
1807             if (sigBytes.Length == 0)
1808             {
1809                 return false;
1810             }
1811
1812             // Hash type is one byte tacked on to the end of the signature
1813             if (nHashType == 0)
1814             {
1815                 nHashType = sigBytes.Last();
1816             }
1817             else if (nHashType != sigBytes.Last())
1818             {
1819                 return false;
1820             }
1821
1822             // Remove hash type
1823             Array.Resize(ref sigBytes, sigBytes.Length - 1);
1824
1825             var sighash = SignatureHash(script, txTo, nIn, nHashType);
1826
1827             if (!pubkey.VerifySignature(sighash, sigBytes))
1828             {
1829                 return false;
1830             }
1831
1832             return true;
1833         }
1834
1835         /// <summary>
1836         /// Evaluates the both scriptSig and scriptPubKey.
1837         /// </summary>
1838         /// <param name="scriptSig"></param>
1839         /// <param name="scriptPubKey"></param>
1840         /// <param name="txTo">Transaction</param>
1841         /// <param name="nIn">Input number</param>
1842         /// <param name="flags">Script validation flags</param>
1843         /// <param name="nHashType">Hash type flag</param>
1844         /// <returns></returns>
1845         public static bool VerifyScript(CScript scriptSig, CScript scriptPubKey, CTransaction txTo, int nIn, int flags, int nHashType)
1846         {
1847             var stack = new List<byte[]>();
1848             List<byte[]> stackCopy = null;
1849
1850             if (!EvalScript(ref stack, scriptSig, txTo, nIn, flags, nHashType))
1851             {
1852                 return false;
1853             }
1854
1855             if ((flags & (int)scriptflag.SCRIPT_VERIFY_P2SH) != 0)
1856             {
1857                 stackCopy = new List<byte[]>(stack);
1858             }
1859
1860             if (!EvalScript(ref stack, scriptPubKey, txTo, nIn, flags, nHashType))
1861             {
1862                 return false;
1863             }
1864
1865             if (stack.Count == 0 || CastToBool(stack.Last()) == false)
1866             {
1867                 return false;
1868             }
1869
1870             // Additional validation for spend-to-script-hash transactions:
1871             if ((flags & (int)scriptflag.SCRIPT_VERIFY_P2SH) != 0 && scriptPubKey.IsPayToScriptHash)
1872             {
1873                 if (!scriptSig.IsPushOnly) // scriptSig must be literals-only
1874                 {
1875                     return false;
1876                 }
1877
1878                 // stackCopy cannot be empty here, because if it was the
1879                 // P2SH  HASH <> EQUAL  scriptPubKey would be evaluated with
1880                 // an empty stack and the EvalScript above would return false.
1881
1882                 if (stackCopy.Count == 0)
1883                 {
1884                     throw new StackMachineException("Fatal script validation error.");
1885                 }
1886
1887                 var pubKey2 = new CScript(stackCopy.Last());
1888                 popstack(ref stackCopy);
1889
1890                 if (!EvalScript(ref stackCopy, pubKey2, txTo, nIn, flags, nHashType))
1891                     return false;
1892                 if (stackCopy.Count == 0)
1893                     return false;
1894
1895                 return CastToBool(stackCopy.Last());
1896             }
1897
1898             return true;
1899         }
1900     };
1901 }