Esempio n. 1
0
        public bool Evaluate(IEnumerable <object> scriptCommands, byte[]?sigHash = null)
        {
            var commands = new Queue <object>(scriptCommands ?? throw new ArgumentNullException(nameof(scriptCommands)));
            var stack    = new ScriptStack();
            var altStack = new ScriptStack();

            while (commands.Count > 0)
            {
                if (IsPayToScriptHash(commands))
                {
                    var redeemScript = DecodeRedeemScript((byte[])commands.Dequeue());
                    commands = new Queue <object>(redeemScript.Commands);
                }

                var command = commands.Dequeue();
                if (command is byte[] bytes)
                {
                    stack.Push(bytes);
                }
                else if (command is OpCode opCode)
                {
                    var result = false;
                    try
                    {
                        switch (GetOpertationType(opCode))
                        {
                        case OpertationType.Stack:
                            result = Evaluate(opCode, stack);
                            break;

                        case OpertationType.SigHash:
                            result = Evaluate(opCode, stack, sigHash ?? throw new ArgumentNullException(nameof(sigHash)));
                            break;

                        case OpertationType.Commands:
                            result = Evaluate(opCode, stack, commands);
                            break;

                        case OpertationType.AltStack:
                            result = Evaluate(opCode, stack, altStack);
                            break;
                        }
                    }
                    catch (FormatException ex)
                    {
                        if (throwOnFailure)
                        {
                            throw new VerificationException("Bad format", ex);
                        }
                    }
                    catch (InvalidOperationException ex)
                    {
                        if (throwOnFailure)
                        {
                            throw new VerificationException("Bad operation", ex);
                        }
                    }
                    if (!result)
                    {
                        if (throwOnFailure)
                        {
                            throw new VerificationException("Script evaluation false");
                        }
                        return(false);
                    }
                }
                else
                {
                    throw new InvalidOperationException("Invalid command type");
                }
            }

            return(stack.Count > 0 && stack.Pop().Length > 0);
        }
Esempio n. 2
0
        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);
            }
        }