예제 #1
0
        bool CheckSig(ScriptStack stack, byte[] sigHash)
        {
            var publicKey = stack.PopPublicKey();
            var signature = stack.PopSignature();
            var result    = publicKey.Verify(sigHash, signature);

            return(result);
        }
예제 #2
0
        IList <Signature> PopSignatures(ScriptStack stack, BigInteger count)
        {
            var signatures = new List <Signature>();

            while (count-- > 0)
            {
                signatures.Add(stack.PopSignature());
            }

            return(signatures);
        }
예제 #3
0
        IList <PublicKey> PopKeys(ScriptStack stack, BigInteger count)
        {
            var publicKeys = new List <PublicKey>();

            while (count-- > 0)
            {
                publicKeys.Add(stack.PopPublicKey());
            }

            return(publicKeys);
        }
예제 #4
0
        bool Evaluate(OpCode opCode, ScriptStack stack, byte[] sigHash)
        {
            switch (opCode)
            {
            case OpCode.OP_CHECKSIG:
                return(stack.Push(CheckSig(stack, sigHash)));

            case OpCode.OP_CHECKMULTISIG:
                return(stack.Push(CheckMultiSig(stack, sigHash)));

            default:
                throw new NotImplementedException();
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
 bool Evaluate(OpCode opCode, ScriptStack stack, ScriptStack altStack)
 {
     throw new NotImplementedException();
 }
예제 #7
0
 bool Evaluate(OpCode opCode, ScriptStack stack, IEnumerable <object> commands)
 {
     throw new NotImplementedException();
 }
예제 #8
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);
        }
예제 #9
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);
            }
        }