bool CheckMultiSig(ScriptStack stack, byte[] sigHash) { var publicKeys = PopKeys(stack, stack.PopInt()); var signatures = PopSignatures(stack, stack.PopInt()); stack.PopInt(); // Satoshi off-by-one var keyIndex = 0; foreach (var signature in signatures) { while (!publicKeys[keyIndex++].Verify(sigHash, signature)) { if (keyIndex >= publicKeys.Count) { return(false); } } } return(true); }
bool Evaluate(OpCode opCode, ScriptStack stack) { switch (opCode) { case OpCode.OP_0: return(stack.Push(0)); case OpCode.OP_1NEGATE: return(stack.Push(-1)); case OpCode.OP_1: case OpCode.OP_2: case OpCode.OP_3: case OpCode.OP_4: case OpCode.OP_5: case OpCode.OP_6: case OpCode.OP_7: case OpCode.OP_8: case OpCode.OP_9: case OpCode.OP_10: case OpCode.OP_11: case OpCode.OP_12: case OpCode.OP_13: case OpCode.OP_14: case OpCode.OP_15: case OpCode.OP_16: return(stack.Push((int)opCode - (int)OpCode.OP_1 + 1)); case OpCode.OP_NOP: case OpCode.OP_NOP1: case OpCode.OP_NOP4: case OpCode.OP_NOP5: case OpCode.OP_NOP6: case OpCode.OP_NOP7: case OpCode.OP_NOP8: case OpCode.OP_NOP9: case OpCode.OP_NOP10: return(true); case OpCode.OP_DUP: return(stack.Push(stack.Peek())); case OpCode.OP_2DUP: var d1 = stack.Pop(); var d2 = stack.Peek(); stack.Push(d1); stack.Push(d2); return(stack.Push(d1)); case OpCode.OP_SWAP: var s1 = stack.Pop(); var s2 = stack.Pop(); stack.Push(s1); return(stack.Push(s2)); case OpCode.OP_VERIFY: return(stack.Pop().Length > 0); case OpCode.OP_EQUALVERIFY: return(stack.Pop().SequenceEqual(stack.Pop())); case OpCode.OP_HASH160: return(stack.Push(Cipher.Hash160(stack.Pop()))); case OpCode.OP_SHA1: return(stack.Push(Cipher.Sha1(stack.Pop()))); case OpCode.OP_ADD: return(stack.Push(stack.PopInt() + stack.PopInt())); case OpCode.OP_MUL: return(stack.Push(stack.PopInt() * stack.PopInt())); case OpCode.OP_EQUAL: return(stack.Push(stack.Pop().SequenceEqual(stack.Pop()) ? 1 : 0)); case OpCode.OP_NOT: return(stack.Push(stack.Pop().Length == 0 ? 1 : 0)); default: throw new InvalidOperationException("Unknown operation: " + opCode); } }