2 * Novacoin classes library
3 * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
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.
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.
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/>.
20 using System.Collections.Generic;
21 using System.Diagnostics.Contracts;
23 using System.Numerics;
29 /// Script instructions
31 public enum instruction
73 OP_FROMALTSTACK = 0x6c,
105 OP_EQUALVERIFY = 0x88,
130 OP_NUMEQUALVERIFY = 0x9d,
131 OP_NUMNOTEQUAL = 0x9e,
133 OP_GREATERTHAN = 0xa0,
134 OP_LESSTHANOREQUAL = 0xa1,
135 OP_GREATERTHANOREQUAL = 0xa2,
147 OP_CODESEPARATOR = 0xab,
149 OP_CHECKSIGVERIFY = 0xad,
150 OP_CHECKMULTISIG = 0xae,
151 OP_CHECKMULTISIGVERIFY = 0xaf,
165 // template matching params
167 OP_SMALLINTEGER = 0xfa,
169 OP_PUBKEYHASH = 0xfd,
172 OP_INVALIDOPCODE = 0xff,
176 /// Transaction output types.
178 public enum txnouttype
182 // 'standard' transaction types:
191 /// Signature hash types/flags
198 SIGHASH_ANYONECANPAY = 0x80,
201 /** Script verification flags */
202 public enum scriptflag
204 SCRIPT_VERIFY_NONE = 0,
205 SCRIPT_VERIFY_P2SH = (1 << 0), // evaluate P2SH (BIP16) subscripts
206 SCRIPT_VERIFY_STRICTENC = (1 << 1), // enforce strict conformance to DER and SEC2 for signatures and pubkeys
207 SCRIPT_VERIFY_LOW_S = (1 << 2), // enforce low S values in signatures (depends on STRICTENC)
208 SCRIPT_VERIFY_NOCACHE = (1 << 3), // do not store results in signature cache (but do query it)
209 SCRIPT_VERIFY_NULLDUMMY = (1 << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length
212 public static class ScriptCode
214 public static string GetTxnOutputType(txnouttype t)
218 case txnouttype.TX_NONSTANDARD: return "nonstandard";
219 case txnouttype.TX_PUBKEY: return "pubkey";
220 case txnouttype.TX_PUBKEYHASH: return "pubkeyhash";
221 case txnouttype.TX_SCRIPTHASH: return "scripthash";
222 case txnouttype.TX_MULTISIG: return "multisig";
223 case txnouttype.TX_NULL_DATA: return "nulldata";
229 /// Get the name of instruction
231 /// <param name="opcode">Instruction</param>
232 /// <returns>Instruction name</returns>
233 public static string GetOpName(instruction opcode)
235 if (opcode == instruction.OP_0) // OP_0 and OP_FALSE are synonyms
237 if (opcode == instruction.OP_1) // OP_1 and OP_TRUE are synonyms
240 return Enum.GetName(typeof(instruction), opcode);
244 /// Get next instruction from list of bytes and extract push arguments if there are some.
246 /// <param name="codeBytes">ByteQueue reference.</param>
247 /// <param name="opcodeRet">Found instruction.</param>
248 /// <param name="bytesRet">IEnumerable out param which is used to get the push arguments.</param>
249 /// <returns>Result of operation</returns>
250 public static bool GetOp(ref InstructionQueue codeBytes, out instruction opcodeRet, out byte[] bytesRet)
252 bytesRet = new byte[0];
253 instruction opcode = opcodeRet = instruction.OP_INVALIDOPCODE;
257 if (!codeBytes.TryGet(ref opVal))
261 opcode = (instruction)opVal;
264 if (opcode <= instruction.OP_PUSHDATA4)
266 var szBytes = new byte[4] { 0, 0, 0, 0 }; // Zero length
271 if (opcode < instruction.OP_PUSHDATA1)
273 // Zero value instructions (OP_0, OP_FALSE)
274 nSize = (int) opcode;
276 else if (opcode == instruction.OP_PUSHDATA1)
278 // The next byte contains the number of bytes to be pushed onto the stack,
279 // i.e. you have something like OP_PUSHDATA1 0x01 [0x5a]
280 nSize = codeBytes.Get();
282 else if (opcode == instruction.OP_PUSHDATA2)
284 // The next two bytes contain the number of bytes to be pushed onto the stack,
285 // i.e. now your operation will seem like this: OP_PUSHDATA2 0x01 0x00 [0x5a]
286 nSize = BitConverter.ToInt16(codeBytes.Get(2), 0);
288 else if (opcode == instruction.OP_PUSHDATA4)
290 // The next four bytes contain the number of bytes to be pushed onto the stack,
291 // OP_PUSHDATA4 0x01 0x00 0x00 0x00 [0x5a]
292 nSize = BitConverter.ToInt32(codeBytes.Get(4), 0);
295 catch (InstructionQueueException)
297 // Unable to read operand length
303 // Trying to read found number of bytes into list of OP_PUSHDATAn arguments.
304 if (!codeBytes.TryGet(nSize, ref bytesRet))
306 // Unable to read data
318 /// Convert value bytes into readable representation.
320 /// 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.
322 /// <param name="bytes">Collection of value bytes.</param>
323 /// <returns>Formatted value.</returns>
324 public static string ValueString(byte[] bytes)
326 var sb = new StringBuilder();
328 if (bytes.Length <= 4)
330 sb.Append(new BigInteger(bytes));
334 return Interop.ToHex(bytes);
337 return sb.ToString();
341 /// Convert list of stack items into human readable representation.
343 /// <param name="stackList">List of stack items.</param>
344 /// <returns>Formatted value.</returns>
345 public static string StackString(IList<byte[]> stackList)
347 var sb = new StringBuilder();
348 foreach (var bytes in stackList)
350 sb.Append(ValueString(bytes));
353 return sb.ToString();
357 /// Decode instruction to integer value
359 /// <param name="opcode">Small integer instruction (OP_1_NEGATE and OP_0 - OP_16)</param>
360 /// <returns>Small integer</returns>
361 public static int DecodeOP_N(instruction opcode, bool AllowNegate = false)
363 // Only OP_n instructions are supported, throw exception otherwise.
364 Contract.Requires<ArgumentException>((opcode == instruction.OP_1NEGATE && AllowNegate) || (opcode >= instruction.OP_0 && opcode <= instruction.OP_16), "Invalid integer instruction.");
368 case instruction.OP_1NEGATE:
370 case instruction.OP_0:
373 return (int)opcode - (int)(instruction.OP_1 - 1);
378 /// Converts integer into instruction
380 /// <param name="n">Small integer from the range of -1 up to 16.</param>
381 /// <returns>Corresponding instruction.</returns>
382 public static instruction EncodeOP_N(int n, bool allowNegate = false)
384 // The n value must be in the range of 1 to 16.
385 Contract.Requires<ArgumentException>((n == -1 && allowNegate) || (n >= 0 && n <= 16), "Invalid integer value.");
390 return instruction.OP_1NEGATE;
392 return instruction.OP_0;
394 return (instruction.OP_1 + n - 1);
398 public static int ScriptSigArgsExpected(txnouttype t, IList<byte[]> solutions)
402 case txnouttype.TX_NONSTANDARD:
404 case txnouttype.TX_NULL_DATA:
406 case txnouttype.TX_PUBKEY:
408 case txnouttype.TX_PUBKEYHASH:
410 case txnouttype.TX_MULTISIG:
411 if (solutions.Count < 1 || solutions.First().Length < 1)
413 return solutions.First()[0] + 1;
414 case txnouttype.TX_SCRIPTHASH:
415 return 1; // doesn't include args needed by the script
421 /// Is it a standart type of scriptPubKey?
423 /// <param name="scriptPubKey">CScript instance</param>
424 /// <param name="whichType">utut type</param>
425 /// <returns>Checking result</returns>
426 public static bool IsStandard(CScript scriptPubKey, out txnouttype whichType)
428 IList<byte[]> solutions;
430 if (!Solver(scriptPubKey, out whichType, out solutions))
432 // No solutions found
436 if (whichType == txnouttype.TX_MULTISIG)
438 // Additional verification of OP_CHECKMULTISIG arguments
439 var m = solutions.First()[0];
440 var n = solutions.Last()[0];
442 // Support up to x-of-3 multisig txns as standard
453 return whichType != txnouttype.TX_NONSTANDARD;
457 /// Return public keys or hashes from scriptPubKey, for 'standard' transaction types.
459 /// <param name="scriptPubKey">CScript instance</param>
460 /// <param name="typeRet">Output type</param>
461 /// <param name="solutions">Set of solutions</param>
462 /// <returns>Result</returns>
463 public static bool Solver(CScript scriptPubKey, out txnouttype typeRet, out IList<byte[]> solutions)
465 byte[] scriptBytes = scriptPubKey;
467 solutions = new List<byte[]>();
469 // There are shortcuts for pay-to-script-hash and pay-to-pubkey-hash, which are more constrained than the other types.
471 // It is always OP_HASH160 20 [20 byte hash] OP_EQUAL
472 if (scriptPubKey.IsPayToScriptHash)
474 typeRet = txnouttype.TX_SCRIPTHASH;
476 // Take 20 bytes with offset of 2 bytes
477 var hashBytes = scriptBytes.Skip(2).Take(20);
478 solutions.Add(hashBytes.ToArray());
483 // It is always OP_DUP OP_HASH160 20 [20 byte hash] OP_EQUALVERIFY OP_CHECKSIG
484 if (scriptPubKey.IsPayToPubKeyHash)
486 typeRet = txnouttype.TX_PUBKEYHASH;
488 // Take 20 bytes with offset of 3 bytes
489 var hashBytes = scriptBytes.Skip(3).Take(20);
490 solutions.Add(hashBytes.ToArray());
495 var templateTuples = new List<Tuple<txnouttype, byte[]>>();
497 // Sender provides pubkey, receiver adds signature
498 // [ECDSA public key] OP_CHECKSIG
500 new Tuple<txnouttype, byte[]>(
501 txnouttype.TX_PUBKEY,
503 (byte)instruction.OP_PUBKEY,
504 (byte)instruction.OP_CHECKSIG
508 // Sender provides N pubkeys, receivers provides M signatures
509 // N [pubkey1] [pubkey2] ... [pubkeyN] M OP_CHECKMULTISIG
510 // Where N and M are small integer instructions (OP1 ... OP_16)
512 new Tuple<txnouttype, byte[]>(
513 txnouttype.TX_MULTISIG,
515 (byte)instruction.OP_SMALLINTEGER,
516 (byte)instruction.OP_PUBKEYS,
517 (byte)instruction.OP_SMALLINTEGER,
518 (byte)instruction.OP_CHECKMULTISIG
522 // Data-carrying output
523 // OP_RETURN [up to 80 bytes of data]
525 new Tuple<txnouttype, byte[]>(
526 txnouttype.TX_NULL_DATA,
528 (byte)instruction.OP_RETURN,
529 (byte)instruction.OP_SMALLDATA
533 // Nonstandard tx output
534 typeRet = txnouttype.TX_NONSTANDARD;
536 foreach (var templateTuple in templateTuples)
538 var script1 = scriptPubKey;
539 var script2 = new CScript(templateTuple.Item2);
541 instruction opcode1, opcode2;
544 var bq1 = script1.GetInstructionQueue();
545 var bq2 = script2.GetInstructionQueue();
549 int last1 = ((byte[])script1).Length - 1;
550 int last2 = ((byte[])script2).Length - 1;
554 if (bq1.Index == last1 && bq2.Index == last2)
557 typeRet = templateTuple.Item1;
558 if (typeRet == txnouttype.TX_MULTISIG)
560 // Additional checks for TX_MULTISIG:
561 var m = solutions.First().First();
562 var n = solutions.Last().First();
564 if (m < 1 || n < 1 || m > n || solutions.Count - 2 != n)
572 if (!GetOp(ref bq1, out opcode1, out args1))
576 if (!GetOp(ref bq2, out opcode2, out args2))
581 // Template matching instructions:
582 if (opcode2 == instruction.OP_PUBKEYS)
584 while (args1.Count() >= 33 && args1.Count() <= 120)
586 solutions.Add(args1);
587 if (!GetOp(ref bq1, out opcode1, out args1))
592 if (!GetOp(ref bq2, out opcode2, out args2))
596 // Normal situation is to fall through
597 // to other if/else statements
599 if (opcode2 == instruction.OP_PUBKEY)
601 int PubKeyLen = args1.Count();
602 if (PubKeyLen < 33 || PubKeyLen > 120)
606 solutions.Add(args1);
608 else if (opcode2 == instruction.OP_PUBKEYHASH)
610 if (args1.Count() != 20) // hash160 size
614 solutions.Add(args1);
616 else if (opcode2 == instruction.OP_SMALLINTEGER)
618 // Single-byte small integer pushed onto solutions
621 var n = (byte)DecodeOP_N(opcode1);
622 solutions.Add(new byte[] { n });
629 else if (opcode2 == instruction.OP_SMALLDATA)
631 // small pushdata, <= 80 bytes
632 if (args1.Length > 80)
637 else if (opcode1 != opcode2 || !args1.SequenceEqual(args2))
639 // Others must match exactly
646 typeRet = txnouttype.TX_NONSTANDARD;
652 /// Generation of SignatureHash. This method is responsible for removal of transaction metadata. It's necessary signature can't sign itself.
654 /// <param name="script">Spending instructions</param>
655 /// <param name="txTo">Instance of transaction</param>
656 /// <param name="nIn">Input number</param>
657 /// <param name="nHashType">Hash type flag</param>
658 /// <returns></returns>
659 public static Hash256 SignatureHash(CScript script, CTransaction txTo, int nIn, int nHashType)
661 Contract.Requires<ArgumentOutOfRangeException>(nIn < txTo.vin.Length, "nIn out of range.");
663 // Init a copy of transaction
664 var txTmp = new CTransaction(txTo);
666 // In case concatenating two scripts ends up with two codeseparators,
667 // or an extra one at the end, this prevents all those possible incompatibilities.
668 script.RemoveInstruction(instruction.OP_CODESEPARATOR);
670 // Blank out other inputs' signatures
671 for (int i = 0; i < txTmp.vin.Length; i++)
673 txTmp.vin[i].scriptSig = new CScript();
675 txTmp.vin[nIn].scriptSig = script;
677 // Blank out some of the outputs
678 if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_NONE)
681 txTmp.vout = new CTxOut[0];
683 // Let the others update at will
684 for (int i = 0; i < txTmp.vin.Length; i++)
688 txTmp.vin[i].nSequence = 0;
692 else if ((nHashType & 0x1f) == (int)sigflag.SIGHASH_SINGLE)
694 // Only lock-in the txout payee at same index as txin
696 if (nOut >= txTmp.vout.Length)
698 StringBuilder sb = new StringBuilder();
699 sb.AppendFormat("ERROR: SignatureHash() : nOut={0} out of range\n", nOut);
700 throw new ArgumentOutOfRangeException("nOut", sb.ToString());
702 Array.Resize(ref txTmp.vout, nOut + 1);
704 for (int i = 0; i < nOut; i++)
706 txTmp.vout[i] = new CTxOut();
709 // Let the others update at will
710 for (int i = 0; i < txTmp.vin.Length; i++)
714 txTmp.vin[i].nSequence = 0;
719 // Blank out other inputs completely, not recommended for open transactions
720 if ((nHashType & (int)sigflag.SIGHASH_ANYONECANPAY) != 0)
722 txTmp.vin[0] = txTmp.vin[nIn];
723 Array.Resize(ref txTmp.vin, 1);
726 // Concatenate and hash
727 var txBytes = (byte[])txTmp;
728 var nHashTypeBytes = BitConverter.GetBytes(nHashType);
730 return Hash256.Compute256(ref txBytes, ref nHashTypeBytes);
734 // Script is a stack machine (like Forth) that evaluates a predicate
735 // returning a bool indicating valid or not. There are no loops.
739 /// Script machine exception
742 public class StackMachineException : Exception
744 public StackMachineException()
748 public StackMachineException(string message)
753 public StackMachineException(string message, Exception inner)
754 : base(message, inner)
760 /// Remove last element from stack
762 /// <param name="stack">Stack reference</param>
763 private static void popstack(ref List<byte[]> stack)
765 Contract.Requires<StackMachineException>(stack.Count > 0, "Stack is empty.");
767 stack.RemoveAt(stack.Count - 1);
771 /// Get element at specified stack depth
773 /// <param name="stack">Stack reference</param>
774 /// <param name="nDepth">Depth</param>
775 /// <returns>Byte sequence</returns>
776 private static byte[] stacktop(ref List<byte[]> stack, int nDepth)
778 Contract.Requires<StackMachineException>(nDepth < 0, "Positive or zero stack depth makes no sense.");
779 Contract.Requires<StackMachineException>(stack.Count + nDepth >= 0, "Value exceeds real stack depth.");
781 return stack[stack.Count + nDepth];
785 /// Cast argument to boolean value
787 /// <param name="value">Some byte sequence</param>
788 /// <returns></returns>
789 private static bool CastToBool(byte[] arg)
791 for (var i = 0; i < arg.Length; i++)
795 // Can be negative zero
796 if (i == arg.Length - 1 && arg[i] == 0x80)
809 /// Cast argument to integer value
811 /// <param name="value"></param>
812 /// <returns></returns>
813 private static BigInteger CastToBigInteger(byte[] value)
815 Contract.Requires<StackMachineException>(value.Length <= 4, "Size limit failed.");
817 return new BigInteger(value);
821 /// Execution of script
823 /// <param name="stack"></param>
824 /// <param name="script">Script to execute</param>
825 /// <param name="txTo">Transaction instance</param>
826 /// <param name="nIn">Input number</param>
827 /// <param name="flags">Signature checking flags</param>
828 /// <param name="nHashType">Hash type flag</param>
829 /// <returns></returns>
830 public static bool EvalScript(ref List<byte[]> stack, CScript script, CTransaction txTo, int nIn, int flags, int nHashType)
832 var scriptBytes = ((byte[])script);
834 if (scriptBytes.Length > 10000)
836 return false; // Size limit failed
839 var vfExec = new List<bool>();
842 int nCodeHashBegin = 0;
844 var falseBytes = new byte[0];
845 var trueBytes = new byte[] { 0x01 };
847 var CodeQueue = script.GetInstructionQueue();
848 var altStack = new List<byte[]>();
857 while (GetOp(ref CodeQueue, out opcode, out pushArg)) // Read instructions
859 bool fExec = vfExec.IndexOf(false) == -1;
861 if (pushArg.Length > 520)
863 return false; // Script element size limit failed
866 if (opcode > instruction.OP_16 && ++nOpCount > 201)
871 if (fExec && 0 <= opcode && opcode <= instruction.OP_PUSHDATA4)
873 stack.Add(pushArg); // Push argument to stack
875 else if (fExec || (instruction.OP_IF <= opcode && opcode <= instruction.OP_ENDIF))
879 // Disabled instructions
881 case instruction.OP_CAT:
882 case instruction.OP_SUBSTR:
883 case instruction.OP_LEFT:
884 case instruction.OP_RIGHT:
885 case instruction.OP_INVERT:
886 case instruction.OP_AND:
887 case instruction.OP_OR:
888 case instruction.OP_XOR:
889 case instruction.OP_2MUL:
890 case instruction.OP_2DIV:
891 case instruction.OP_MUL:
892 case instruction.OP_DIV:
893 case instruction.OP_MOD:
894 case instruction.OP_LSHIFT:
895 case instruction.OP_RSHIFT:
899 // Push integer instructions
901 case instruction.OP_1NEGATE:
902 case instruction.OP_1:
903 case instruction.OP_2:
904 case instruction.OP_3:
905 case instruction.OP_4:
906 case instruction.OP_5:
907 case instruction.OP_6:
908 case instruction.OP_7:
909 case instruction.OP_8:
910 case instruction.OP_9:
911 case instruction.OP_10:
912 case instruction.OP_11:
913 case instruction.OP_12:
914 case instruction.OP_13:
915 case instruction.OP_14:
916 case instruction.OP_15:
917 case instruction.OP_16:
920 BigInteger bn = DecodeOP_N(opcode, true);
921 stack.Add(bn.ToByteArray());
928 case instruction.OP_NOP:
929 case instruction.OP_NOP1:
930 case instruction.OP_NOP2:
931 case instruction.OP_NOP3:
932 case instruction.OP_NOP4:
933 case instruction.OP_NOP5:
934 case instruction.OP_NOP6:
935 case instruction.OP_NOP7:
936 case instruction.OP_NOP8:
937 case instruction.OP_NOP9:
938 case instruction.OP_NOP10:
947 case instruction.OP_IF:
948 case instruction.OP_NOTIF:
950 // <expression> if [statements] [else [statements]] endif
954 if (stack.Count() < 1)
958 var vch = stacktop(ref stack, -1);
959 fValue = CastToBool(vch);
960 if (opcode == instruction.OP_NOTIF)
970 case instruction.OP_ELSE:
972 int nExecCount = vfExec.Count();
977 vfExec[nExecCount - 1] = !vfExec[nExecCount - 1];
981 case instruction.OP_ENDIF:
983 int nExecCount = vfExec.Count();
988 vfExec.RemoveAt(nExecCount - 1);
992 case instruction.OP_VERIFY:
995 // (false -- false) and return
996 if (stack.Count() < 1)
1001 bool fValue = CastToBool(stacktop(ref stack, -1));
1004 popstack(ref stack);
1013 case instruction.OP_RETURN:
1021 case instruction.OP_TOALTSTACK:
1023 if (stack.Count() < 1)
1027 altStack.Add(stacktop(ref stack, -1));
1028 popstack(ref stack);
1032 case instruction.OP_FROMALTSTACK:
1034 if (altStack.Count() < 1)
1038 stack.Add(stacktop(ref stack, -1));
1039 popstack(ref altStack);
1043 case instruction.OP_2DROP:
1046 if (stack.Count() < 2)
1050 popstack(ref stack);
1051 popstack(ref stack);
1055 case instruction.OP_2DUP:
1057 // (x1 x2 -- x1 x2 x1 x2)
1058 if (stack.Count() < 2)
1062 var vch1 = stacktop(ref stack, -2);
1063 var vch2 = stacktop(ref stack, -1);
1069 case instruction.OP_3DUP:
1071 // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
1072 if (stack.Count() < 3)
1076 var vch1 = stacktop(ref stack, -3);
1077 var vch2 = stacktop(ref stack, -2);
1078 var vch3 = stacktop(ref stack, -1);
1085 case instruction.OP_2OVER:
1087 // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
1088 if (stack.Count() < 4)
1092 var vch1 = stacktop(ref stack, -4);
1093 var vch2 = stacktop(ref stack, -3);
1099 case instruction.OP_2ROT:
1101 int nStackDepth = stack.Count();
1102 // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
1103 if (nStackDepth < 6)
1107 var vch1 = stacktop(ref stack, -6);
1108 var vch2 = stacktop(ref stack, -5);
1109 stack.RemoveRange(nStackDepth - 6, 2);
1115 case instruction.OP_2SWAP:
1117 // (x1 x2 x3 x4 -- x3 x4 x1 x2)
1118 int nStackDepth = stack.Count;
1119 if (nStackDepth < 4)
1123 stack.Swap(nStackDepth - 4, nStackDepth - 2);
1124 stack.Swap(nStackDepth - 3, nStackDepth - 1);
1128 case instruction.OP_IFDUP:
1131 if (stack.Count() < 1)
1136 var vch = stacktop(ref stack, -1);
1138 if (CastToBool(vch))
1145 case instruction.OP_DEPTH:
1148 BigInteger bn = new BigInteger((ushort)stack.Count());
1149 stack.Add(bn.ToByteArray());
1153 case instruction.OP_DROP:
1156 if (stack.Count() < 1)
1161 popstack(ref stack);
1165 case instruction.OP_DUP:
1168 if (stack.Count() < 1)
1173 var vch = stacktop(ref stack, -1);
1178 case instruction.OP_NIP:
1181 int nStackDepth = stack.Count();
1182 if (nStackDepth < 2)
1187 stack.RemoveAt(nStackDepth - 2);
1191 case instruction.OP_OVER:
1193 // (x1 x2 -- x1 x2 x1)
1194 if (stack.Count() < 2)
1199 var vch = stacktop(ref stack, -2);
1204 case instruction.OP_PICK:
1205 case instruction.OP_ROLL:
1207 // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
1208 // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
1210 int nStackDepth = stack.Count();
1211 if (nStackDepth < 2)
1216 int n = (int)CastToBigInteger(stacktop(ref stack, -1));
1217 popstack(ref stack);
1219 if (n < 0 || n >= stack.Count())
1224 var vch = stacktop(ref stack, -n - 1);
1225 if (opcode == instruction.OP_ROLL)
1227 stack.RemoveAt(nStackDepth - n - 1);
1234 case instruction.OP_ROT:
1236 // (x1 x2 x3 -- x2 x3 x1)
1237 // x2 x1 x3 after first swap
1238 // x2 x3 x1 after second swap
1239 int nStackDepth = stack.Count();
1240 if (nStackDepth < 3)
1244 stack.Swap(nStackDepth - 3, nStackDepth - 2);
1245 stack.Swap(nStackDepth - 2, nStackDepth - 1);
1250 case instruction.OP_SWAP:
1253 int nStackDepth = stack.Count();
1254 if (nStackDepth < 2)
1258 stack.Swap(nStackDepth - 2, nStackDepth - 1);
1262 case instruction.OP_TUCK:
1264 // (x1 x2 -- x2 x1 x2)
1265 int nStackDepth = stack.Count();
1266 if (nStackDepth < 2)
1270 var vch = stacktop(ref stack, -1);
1271 stack.Insert(nStackDepth - 2, vch);
1276 case instruction.OP_SIZE:
1279 if (stack.Count() < 1)
1284 var bnSize = new BigInteger((ushort)stacktop(ref stack, -1).Count());
1285 stack.Add(bnSize.ToByteArray());
1293 case instruction.OP_EQUAL:
1294 case instruction.OP_EQUALVERIFY:
1295 //case instruction.OP_NOTEQUAL: // use OP_NUMNOTEQUAL
1298 if (stack.Count() < 2)
1303 var vch1 = stacktop(ref stack, -2);
1304 var vch2 = stacktop(ref stack, -1);
1305 bool fEqual = (vch1.SequenceEqual(vch2));
1306 // OP_NOTEQUAL is disabled because it would be too easy to say
1307 // something like n != 1 and have some wiseguy pass in 1 with extra
1308 // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
1309 //if (opcode == instruction.OP_NOTEQUAL)
1310 // fEqual = !fEqual;
1311 popstack(ref stack);
1312 popstack(ref stack);
1313 stack.Add(fEqual ? trueBytes : falseBytes);
1315 if (opcode == instruction.OP_EQUALVERIFY)
1319 popstack(ref stack);
1333 case instruction.OP_1ADD:
1334 case instruction.OP_1SUB:
1335 case instruction.OP_NEGATE:
1336 case instruction.OP_ABS:
1337 case instruction.OP_NOT:
1338 case instruction.OP_0NOTEQUAL:
1341 if (stack.Count() < 1)
1346 var bn = CastToBigInteger(stacktop(ref stack, -1));
1349 case instruction.OP_1ADD:
1352 case instruction.OP_1SUB:
1355 case instruction.OP_NEGATE:
1358 case instruction.OP_ABS:
1359 bn = BigInteger.Abs(bn);
1361 case instruction.OP_NOT:
1362 bn = bn == 0 ? 1 : 0;
1364 case instruction.OP_0NOTEQUAL:
1365 bn = bn != 0 ? 1 : 0;
1369 popstack(ref stack);
1370 stack.Add(bn.ToByteArray());
1374 case instruction.OP_ADD:
1375 case instruction.OP_SUB:
1376 case instruction.OP_BOOLAND:
1377 case instruction.OP_BOOLOR:
1378 case instruction.OP_NUMEQUAL:
1379 case instruction.OP_NUMEQUALVERIFY:
1380 case instruction.OP_NUMNOTEQUAL:
1381 case instruction.OP_LESSTHAN:
1382 case instruction.OP_GREATERTHAN:
1383 case instruction.OP_LESSTHANOREQUAL:
1384 case instruction.OP_GREATERTHANOREQUAL:
1385 case instruction.OP_MIN:
1386 case instruction.OP_MAX:
1389 if (stack.Count() < 2)
1394 var bn1 = CastToBigInteger(stacktop(ref stack, -2));
1395 var bn2 = CastToBigInteger(stacktop(ref stack, -1));
1400 case instruction.OP_ADD:
1403 case instruction.OP_SUB:
1406 case instruction.OP_BOOLAND:
1407 bn = (bn1 != 0 && bn2 != 0) ? 1 : 0;
1409 case instruction.OP_BOOLOR:
1410 bn = (bn1 != 0 || bn2 != 0) ? 1 : 0;
1412 case instruction.OP_NUMEQUAL:
1413 bn = (bn1 == bn2) ? 1 : 0;
1415 case instruction.OP_NUMEQUALVERIFY:
1416 bn = (bn1 == bn2) ? 1 : 0;
1418 case instruction.OP_NUMNOTEQUAL:
1419 bn = (bn1 != bn2) ? 1 : 0;
1421 case instruction.OP_LESSTHAN:
1422 bn = (bn1 < bn2) ? 1 : 0;
1424 case instruction.OP_GREATERTHAN:
1425 bn = (bn1 > bn2) ? 1 : 0;
1427 case instruction.OP_LESSTHANOREQUAL:
1428 bn = (bn1 <= bn2) ? 1 : 0;
1430 case instruction.OP_GREATERTHANOREQUAL:
1431 bn = (bn1 >= bn2) ? 1 : 0;
1433 case instruction.OP_MIN:
1434 bn = (bn1 < bn2 ? bn1 : bn2);
1436 case instruction.OP_MAX:
1437 bn = (bn1 > bn2 ? bn1 : bn2);
1441 popstack(ref stack);
1442 popstack(ref stack);
1443 stack.Add(bn.ToByteArray());
1445 if (opcode == instruction.OP_NUMEQUALVERIFY)
1447 if (CastToBool(stacktop(ref stack, -1)))
1449 popstack(ref stack);
1459 case instruction.OP_WITHIN:
1461 // (x min max -- out)
1462 if (stack.Count() < 3)
1467 var bn1 = CastToBigInteger(stacktop(ref stack, -3));
1468 var bn2 = CastToBigInteger(stacktop(ref stack, -2));
1469 var bn3 = CastToBigInteger(stacktop(ref stack, -1));
1471 bool fValue = (bn2 <= bn1 && bn1 < bn3);
1473 popstack(ref stack);
1474 popstack(ref stack);
1475 popstack(ref stack);
1477 stack.Add(fValue ? trueBytes : falseBytes);
1484 case instruction.OP_RIPEMD160:
1485 case instruction.OP_SHA1:
1486 case instruction.OP_SHA256:
1487 case instruction.OP_HASH160:
1488 case instruction.OP_HASH256:
1491 if (stack.Count() < 1)
1496 var data = stacktop(ref stack, -1);
1500 case instruction.OP_HASH160:
1501 hash = Hash160.Compute160(data);
1503 case instruction.OP_HASH256:
1504 hash = Hash256.Compute256(data);
1506 case instruction.OP_SHA1:
1507 hash = SHA1.Compute1(data);
1509 case instruction.OP_SHA256:
1510 hash = SHA256.Compute256(data);
1512 case instruction.OP_RIPEMD160:
1513 hash = RIPEMD160.Compute160(data);
1516 popstack(ref stack);
1521 case instruction.OP_CODESEPARATOR:
1523 // Hash starts after the code separator
1524 nCodeHashBegin = CodeQueue.Index;
1528 case instruction.OP_CHECKSIG:
1529 case instruction.OP_CHECKSIGVERIFY:
1531 // (sig pubkey -- bool)
1532 if (stack.Count() < 2)
1537 var sigBytes = stacktop(ref stack, -2);
1538 var pubkeyBytes = stacktop(ref stack, -1);
1540 // Subset of script starting at the most recent codeseparator
1541 var scriptCode = new CScript(scriptBytes.Skip(nCodeHashBegin).ToArray());
1543 // There's no way for a signature to sign itself
1544 scriptCode.RemovePattern(sigBytes);
1546 bool fSuccess = IsCanonicalSignature(sigBytes, flags) && IsCanonicalPubKey(pubkeyBytes, flags) && CheckSig(sigBytes, pubkeyBytes, scriptCode, txTo, nIn, nHashType, flags);
1548 popstack(ref stack);
1549 popstack(ref stack);
1551 stack.Add(fSuccess ? trueBytes : falseBytes);
1553 if (opcode == instruction.OP_CHECKSIGVERIFY)
1557 popstack(ref stack);
1567 case instruction.OP_CHECKMULTISIG:
1568 case instruction.OP_CHECKMULTISIGVERIFY:
1570 // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)
1573 if (stack.Count() < i)
1578 int nKeysCount = (int)CastToBigInteger(stacktop(ref stack, -i));
1579 if (nKeysCount < 0 || nKeysCount > 20)
1583 nOpCount += nKeysCount;
1590 if (stack.Count() < i)
1595 int nSigsCount = (int)CastToBigInteger(stacktop(ref stack, -i));
1596 if (nSigsCount < 0 || nSigsCount > nKeysCount)
1602 if (stack.Count() < i)
1607 // Subset of script starting at the most recent codeseparator
1608 var scriptCode = new CScript(scriptBytes.Skip(nCodeHashBegin).ToArray());
1610 // There is no way for a signature to sign itself, so we need to drop the signatures
1611 for (int k = 0; k < nSigsCount; k++)
1613 var vchSig = stacktop(ref stack, -isig - k);
1614 scriptCode.RemovePattern(vchSig);
1617 bool fSuccess = true;
1618 while (fSuccess && nSigsCount > 0)
1620 var sigBytes = stacktop(ref stack, -isig);
1621 var pubKeyBytes = stacktop(ref stack, -ikey);
1624 bool fOk = IsCanonicalSignature(sigBytes, flags) && IsCanonicalPubKey(pubKeyBytes, flags) && CheckSig(sigBytes, pubKeyBytes, scriptCode, txTo, nIn, nHashType, flags);
1634 // If there are more signatures left than keys left,
1635 // then too many signatures have failed
1636 if (nSigsCount > nKeysCount)
1644 popstack(ref stack);
1647 // A bug causes CHECKMULTISIG to consume one extra argument
1648 // whose contents were not checked in any way.
1650 // Unfortunately this is a potential source of mutability,
1651 // so optionally verify it is exactly equal to zero prior
1652 // to removing it from the stack.
1653 if (stack.Count() < 1)
1657 if ((flags & (int)scriptflag.SCRIPT_VERIFY_NULLDUMMY) != 0 && stacktop(ref stack, -1).Count() != 0)
1659 return false; // CHECKMULTISIG dummy argument not null
1661 popstack(ref stack);
1663 stack.Add(fSuccess ? trueBytes : falseBytes);
1665 if (opcode == instruction.OP_CHECKMULTISIGVERIFY)
1669 popstack(ref stack);
1684 if (stack.Count() + altStack.Count() > 1000)
1693 // If there are any exceptions then just return false.
1698 if (vfExec.Count() != 0)
1700 // Something went wrong with conditional instructions.
1708 public static bool IsCanonicalPubKey(byte[] pubKeyBytes, int flags)
1710 if ((flags & (int)scriptflag.SCRIPT_VERIFY_STRICTENC) == 0)
1713 if (pubKeyBytes.Length < 33)
1714 return false; // Non-canonical public key: too short
1715 if (pubKeyBytes[0] == 0x04)
1717 if (pubKeyBytes.Length != 65)
1718 return false; // Non-canonical public key: invalid length for uncompressed key
1720 else if (pubKeyBytes[0] == 0x02 || pubKeyBytes[0] == 0x03)
1722 if (pubKeyBytes.Length != 33)
1723 return false; // Non-canonical public key: invalid length for compressed key
1727 return false; // Non-canonical public key: compressed nor uncompressed
1732 public static bool IsCanonicalSignature(byte[] sigBytes, int flags)
1740 /// Check signature.
1742 /// <param name="sigBytes">Signature</param>
1743 /// <param name="pubkeyBytes">Public key</param>
1744 /// <param name="script">Spending script</param>
1745 /// <param name="txTo">CTransaction instance</param>
1746 /// <param name="nIn">Input number</param>
1747 /// <param name="nHashType">Hashing type flag</param>
1748 /// <param name="flags">Signature checking flags</param>
1749 /// <returns>Checking result</returns>
1750 public static bool CheckSig(byte[] sigBytes, byte[] pubkeyBytes, CScript script, CTransaction txTo, int nIn, int nHashType, int flags)
1756 // Trying to initialize the public key instance
1758 pubkey = new CPubKey(pubkeyBytes);
1762 // Exception occurred while initializing the public key
1767 if (!pubkey.IsValid)
1772 if (sigBytes.Length == 0)
1777 // Hash type is one byte tacked on to the end of the signature
1780 nHashType = sigBytes.Last();
1782 else if (nHashType != sigBytes.Last())
1788 Array.Resize(ref sigBytes, sigBytes.Length - 1);
1790 var sighash = SignatureHash(script, txTo, nIn, nHashType);
1792 if (!pubkey.VerifySignature(sighash, sigBytes))
1801 /// Evaluates the both scriptSig and scriptPubKey.
1803 /// <param name="scriptSig"></param>
1804 /// <param name="scriptPubKey"></param>
1805 /// <param name="txTo">Transaction</param>
1806 /// <param name="nIn">Input number</param>
1807 /// <param name="flags">Script validation flags</param>
1808 /// <param name="nHashType">Hash type flag</param>
1809 /// <returns></returns>
1810 public static bool VerifyScript(CScript scriptSig, CScript scriptPubKey, CTransaction txTo, int nIn, int flags, int nHashType)
1812 var stack = new List<byte[]>();
1813 List<byte[]> stackCopy = null;
1815 if (!EvalScript(ref stack, scriptSig, txTo, nIn, flags, nHashType))
1820 if ((flags & (int)scriptflag.SCRIPT_VERIFY_P2SH) != 0)
1822 stackCopy = new List<byte[]>(stack);
1825 if (!EvalScript(ref stack, scriptPubKey, txTo, nIn, flags, nHashType))
1830 if (stack.Count == 0 || CastToBool(stack.Last()) == false)
1835 // Additional validation for spend-to-script-hash transactions:
1836 if ((flags & (int)scriptflag.SCRIPT_VERIFY_P2SH) != 0 && scriptPubKey.IsPayToScriptHash)
1838 if (!scriptSig.IsPushOnly) // scriptSig must be literals-only
1843 // stackCopy cannot be empty here, because if it was the
1844 // P2SH HASH <> EQUAL scriptPubKey would be evaluated with
1845 // an empty stack and the EvalScript above would return false.
1847 if (stackCopy.Count == 0)
1849 throw new StackMachineException("Fatal script validation error.");
1852 var pubKey2 = new CScript(stackCopy.Last());
1853 popstack(ref stackCopy);
1855 if (!EvalScript(ref stackCopy, pubKey2, txTo, nIn, flags, nHashType))
1857 if (stackCopy.Count == 0)
1860 return CastToBool(stackCopy.Last());