예제 #1
0
        public void ConstructorTest()
        {
            NotIfOp op = new NotIfOp(null, null);

            Assert.Equal(OP.NotIf, op.OpValue);
            Helper.ComparePrivateField(op, "runWithTrue", false);
        }
예제 #2
0
        public void Run_FailTest()
        {
            NotIfOp    op   = new NotIfOp(null, null);
            MockOpData data = new MockOpData()
            {
                _itemCount = 0
            };

            bool b = op.Run(data, out string error);

            Assert.False(b);
            Assert.Equal(Err.OpNotEnoughItems, error);
        }
예제 #3
0
        public void RunTest(IOperation[] main, IOperation[] other, byte[] popData, bool checkRes, bool runResult, string expErr)
        {
            MockOpData data = new MockOpData(FuncCallName.Pop)
            {
                _itemCount = 1,
                conditionalBoolCheckResult   = checkRes,
                expectedConditionalBoolBytes = popData,
                popData = new byte[][] { popData }
            };

            NotIfOp op = new NotIfOp(main, other);
            bool    b  = op.Run(data, out string error);

            Assert.Equal(runResult, b);
            Assert.Equal(expErr, error);
        }
예제 #4
0
        private bool TryRead(byte[] data, List <IOperation> opList, ref int offset, out string error)
        {
            if (IsPushOp(data[offset]))
            {
                PushDataOp op = new PushDataOp();
                if (!op.TryRead(data, ref offset, out error, IsWitness))
                {
                    return(false);
                }
                opList.Add(op);
            }
            else if (data[offset] == (byte)OP.RETURN)
            {
                ReturnOp op = new ReturnOp();
                if (!op.TryRead(data, ref offset, out error, len))
                {
                    return(false);
                }
                opList.Add(op);
            }
            else
            {
                switch ((OP)data[offset])
                {
                // Invalid OPs:
                case OP.VerIf:
                case OP.VerNotIf:
                    error = $"Invalid OP was found: {GetOpName((OP)data[offset])}";
                    return(false);

                // Disabled OPs:
                case OP.CAT:
                case OP.SubStr:
                case OP.LEFT:
                case OP.RIGHT:
                case OP.INVERT:
                case OP.AND:
                case OP.OR:
                case OP.XOR:
                case OP.MUL2:
                case OP.DIV2:
                case OP.MUL:
                case OP.DIV:
                case OP.MOD:
                case OP.LSHIFT:
                case OP.RSHIFT:
                    error = $"Disabled OP was found: {GetOpName((OP)data[offset])}";
                    return(false);

                // Special case of IFs:
                case OP.IF:
                    IFOp ifop = new IFOp();
                    List <IOperation> ifOps = new List <IOperation>();
                    offset++;
                    while (data[offset] != (byte)OP.EndIf && data[offset] != (byte)OP.ELSE && offset < endIndex)
                    {
                        if (!TryRead(data, ifOps, ref offset, out error))
                        {
                            return(false);
                        }
                        if (offset > endIndex)
                        {
                            error = "Bad format.";
                            return(false);
                        }
                        if (ifOps.Count == 0)
                        {
                            error = "Empty OP_IF";
                            return(false);
                        }
                    }
                    if (data[offset] == (byte)OP.ELSE)
                    {
                        List <IOperation> elseOps = new List <IOperation>();
                        offset++;
                        while (data[offset] != (byte)OP.EndIf && offset < endIndex)
                        {
                            if (!TryRead(data, elseOps, ref offset, out error))
                            {
                                return(false);
                            }
                        }
                        if (offset > endIndex)
                        {
                            error = "Bad format.";
                            return(false);
                        }
                        if (elseOps.Count == 0)
                        {
                            error = "Empty OP_ELSE";
                            return(false);
                        }
                        ifop.elseOps = elseOps.ToArray();
                    }

                    if (data[offset] != (byte)OP.EndIf)
                    {
                        error = "No OP_ENDIF was found.";    //this may never happen!
                        return(false);
                    }

                    ifop.mainOps = ifOps.ToArray();

                    opList.Add(ifop);
                    break;

                case OP.NotIf:
                    NotIfOp           notifOp = new NotIfOp();
                    List <IOperation> ifOps2  = new List <IOperation>();
                    offset++;
                    while (data[offset] != (byte)OP.EndIf && data[offset] != (byte)OP.ELSE && offset < endIndex)
                    {
                        if (!TryRead(data, ifOps2, ref offset, out error))
                        {
                            return(false);
                        }
                        if (offset > endIndex)
                        {
                            error = "Bad format.";
                            return(false);
                        }
                        if (ifOps2.Count == 0)
                        {
                            error = "Empty OP_IF";
                            return(false);
                        }
                    }
                    if (data[offset] == (byte)OP.ELSE)
                    {
                        List <IOperation> elseOps2 = new List <IOperation>();
                        offset++;
                        while (data[offset] != (byte)OP.EndIf && offset < endIndex)
                        {
                            if (!TryRead(data, elseOps2, ref offset, out error))
                            {
                                return(false);
                            }
                        }
                        if (offset > endIndex)
                        {
                            error = "Bad format.";
                            return(false);
                        }
                        if (elseOps2.Count == 0)
                        {
                            error = "Empty OP_ELSE";
                            return(false);
                        }
                        notifOp.elseOps = elseOps2.ToArray();
                    }

                    if (data[offset] != (byte)OP.EndIf)
                    {
                        error = "No OP_ENDIF was found.";    //this may never happen!
                        return(false);
                    }

                    notifOp.mainOps = ifOps2.ToArray();

                    opList.Add(notifOp);
                    break;

                case OP.ELSE:
                    error = "OP_ELSE found without prior OP_IF or OP_NOTIF.";
                    return(false);

                case OP.EndIf:
                    error = "OP_EndIf found without prior OP_IF or OP_NOTIF.";
                    return(false);

                // From OP_0 to OP_16 except OP_Reserved is already handled.

                case OP.Reserved:
                    opList.Add(new ReservedOp());
                    break;

                case OP.NOP:
                    opList.Add(new NOPOp());
                    break;

                case OP.VER:
                    opList.Add(new VEROp());
                    break;

                // OP.IF and OP.NotIf moved to top
                // OP.VerIf and OP.VerNotIf moved to top (Invalid tx)
                // OP.ELSE and OP.EndIf moved to top

                case OP.VERIFY:
                    opList.Add(new VerifyOp());
                    break;

                // OP.RETURN is already handled

                case OP.ToAltStack:
                    opList.Add(new ToAltStackOp());
                    break;

                case OP.FromAltStack:
                    opList.Add(new FromAltStackOp());
                    break;

                case OP.DROP2:
                    opList.Add(new DROP2Op());
                    break;

                case OP.DUP2:
                    opList.Add(new DUP2Op());
                    break;

                case OP.DUP3:
                    opList.Add(new DUP3Op());
                    break;

                case OP.OVER2:
                    opList.Add(new OVER2Op());
                    break;

                case OP.ROT2:
                    opList.Add(new ROT2Op());
                    break;

                case OP.SWAP2:
                    opList.Add(new SWAP2Op());
                    break;

                case OP.IfDup:
                    opList.Add(new IfDupOp());
                    break;

                case OP.DEPTH:
                    opList.Add(new DEPTHOp());
                    break;

                case OP.DROP:
                    opList.Add(new DROPOp());
                    break;

                case OP.DUP:
                    opList.Add(new DUPOp());
                    break;

                case OP.NIP:
                    opList.Add(new NIPOp());
                    break;

                case OP.OVER:
                    opList.Add(new OVEROp());
                    break;

                case OP.PICK:
                    opList.Add(new PICKOp());
                    break;

                case OP.ROLL:
                    opList.Add(new ROLLOp());
                    break;

                case OP.ROT:
                    opList.Add(new ROTOp());
                    break;

                case OP.SWAP:
                    opList.Add(new SWAPOp());
                    break;

                case OP.TUCK:
                    opList.Add(new TUCKOp());
                    break;

                // OP_ (CAT SubStr LEFT RIGHT INVERT AND OR XOR) are moved to top

                case OP.SIZE:
                    opList.Add(new SizeOp());
                    break;

                case OP.EQUAL:
                    opList.Add(new EqualOp());
                    break;

                case OP.EqualVerify:
                    opList.Add(new EqualVerifyOp());
                    break;

                case OP.Reserved1:
                    opList.Add(new Reserved1Op());
                    break;

                case OP.Reserved2:
                    opList.Add(new Reserved2Op());
                    break;

                case OP.ADD1:
                    opList.Add(new ADD1Op());
                    break;

                case OP.SUB1:
                    opList.Add(new SUB1Op());
                    break;

                // OP.MUL2 and OP.DIV2 are moved to top (disabled op).

                case OP.NEGATE:
                    opList.Add(new NEGATEOp());
                    break;

                case OP.ABS:
                    opList.Add(new ABSOp());
                    break;

                case OP.NOT:
                    opList.Add(new NOTOp());
                    break;

                case OP.NotEqual0:
                    opList.Add(new NotEqual0Op());
                    break;

                case OP.ADD:
                    opList.Add(new AddOp());
                    break;

                case OP.SUB:
                    opList.Add(new SUBOp());
                    break;

                // OP_ (MUL DIV MOD LSHIFT RSHIFT) are moved to top (disabled op).

                case OP.BoolAnd:
                    opList.Add(new BoolAndOp());
                    break;

                case OP.BoolOr:
                    opList.Add(new BoolOrOp());
                    break;

                case OP.NumEqual:
                    opList.Add(new NumEqualOp());
                    break;

                case OP.NumEqualVerify:
                    opList.Add(new NumEqualVerifyOp());
                    break;

                case OP.NumNotEqual:
                    opList.Add(new NumNotEqualOp());
                    break;

                case OP.LessThan:
                    opList.Add(new LessThanOp());
                    break;

                case OP.GreaterThan:
                    opList.Add(new GreaterThanOp());
                    break;

                case OP.LessThanOrEqual:
                    opList.Add(new LessThanOrEqualOp());
                    break;

                case OP.GreaterThanOrEqual:
                    opList.Add(new GreaterThanOrEqualOp());
                    break;

                case OP.MIN:
                    opList.Add(new MINOp());
                    break;

                case OP.MAX:
                    opList.Add(new MAXOp());
                    break;

                case OP.WITHIN:
                    opList.Add(new WITHINOp());
                    break;

                case OP.RIPEMD160:
                    opList.Add(new RipeMd160Op());
                    break;

                case OP.SHA1:
                    opList.Add(new Sha1Op());
                    break;

                case OP.SHA256:
                    opList.Add(new Sha256Op());
                    break;

                case OP.HASH160:
                    opList.Add(new Hash160Op());
                    break;

                case OP.HASH256:
                    opList.Add(new Hash256Op());
                    break;

                //case OP.CodeSeparator:
                //    break;
                case OP.CheckSig:
                    opList.Add(new CheckSigOp());
                    break;

                case OP.CheckSigVerify:
                    opList.Add(new CheckSigVerifyOp());
                    break;

                case OP.CheckMultiSig:
                    opList.Add(new CheckMultiSigOp());
                    break;

                case OP.CheckMultiSigVerify:
                    opList.Add(new CheckMultiSigVerifyOp());
                    break;

                case OP.NOP1:
                    opList.Add(new NOP1Op());
                    break;

                case OP.CheckLocktimeVerify:
                    opList.Add(new CheckLocktimeVerifyOp());
                    break;

                //case OP.CheckSequenceVerify:
                //    break;
                case OP.NOP4:
                    opList.Add(new NOP4Op());
                    break;

                case OP.NOP5:
                    opList.Add(new NOP5Op());
                    break;

                case OP.NOP6:
                    opList.Add(new NOP6Op());
                    break;

                case OP.NOP7:
                    opList.Add(new NOP7Op());
                    break;

                case OP.NOP8:
                    opList.Add(new NOP8Op());
                    break;

                case OP.NOP9:
                    opList.Add(new NOP9Op());
                    break;

                case OP.NOP10:
                    opList.Add(new NOP10Op());
                    break;

                default:
                    error = "Undefined OP code";
                    return(false);
                }

                offset++;
            }

            error = null;
            return(true);
        }