示例#1
0
        public byte[] SignCompact(uint256 hash)
        {
            var sig = this._ECKey.Sign(hash);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            var recId = -1;

            for (var i = 0; i < 4; i++)
            {
                var k = ECKey.RecoverFromSignature(i, sig, hash, this.IsCompressed);
                if (k != null && k.GetPubKey(this.IsCompressed).ToHex() == this.PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }

            var headerByte = recId + 27 + (this.IsCompressed ? 4 : 0);

            var sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S

            sigData[0] = (byte)headerByte;

            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 1, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 33, 32);
            return(sigData);
        }
示例#2
0
        public byte[] SignCompact(uint256 hash, bool forceLowR)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
            AssertNotDisposed();
#if HAS_SPAN
            Span <byte> vchSig = stackalloc byte[65];
            int         rec    = -1;
            var         sig    = new Secp256k1.SecpRecoverableECDSASignature(_ECKey.Sign(hash, forceLowR, out rec), rec);
            sig.WriteToSpanCompact(vchSig.Slice(1), out int recid);
            vchSig[0] = (byte)(27 + rec + (IsCompressed ? 4 : 0));
            return(vchSig.ToArray());
#else
            var sig = _ECKey.Sign(hash, forceLowR);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;
            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash, IsCompressed);
                if (k != null && k.GetPubKey(IsCompressed).ToHex() == PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }

            int headerByte = recId + 27 + (IsCompressed ? 4 : 0);

            byte[] sigData = new byte[65];              // 1 header + 32 bytes for R + 32 bytes for S

            sigData[0] = (byte)headerByte;
#pragma warning disable 618
            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 1, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 33, 32);
#pragma warning restore 618
            return(sigData);
#endif
        }
示例#3
0
文件: Key.cs 项目: awatin/NBitcoin
        public CompactSignature SignCompact(uint256 hash, bool forceLowR)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }
            if (!IsCompressed)
            {
                throw new InvalidOperationException("This operation is only supported on compressed pubkey");
            }
            AssertNotDisposed();
#if HAS_SPAN
            byte[] sigBytes = new byte[64];
            var    sig      = new Secp256k1.SecpRecoverableECDSASignature(_ECKey.Sign(hash, forceLowR, out var rec), rec);
            sig.WriteToSpanCompact(sigBytes, out _);
            return(new CompactSignature(rec, sigBytes));
#else
            var sig = _ECKey.Sign(hash, forceLowR);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;
            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash);
                if (k != null && k.GetPubKey(true).ToHex() == PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }
#pragma warning disable 618
            byte[] sigData = new byte[64];              // 1 header + 32 bytes for R + 32 bytes for S
            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 0, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 32, 32);
#pragma warning restore 618
            return(new CompactSignature(recId, sigData));
#endif
        }
示例#4
0
文件: Key.cs 项目: buraksv/NBitcoin
        public byte[] SignCompact(uint256 hash, bool forceLowR)
        {
            if (hash is null)
            {
                throw new ArgumentNullException(nameof(hash));
            }

            var sig = _ECKey.Sign(hash, forceLowR);
            // Now we have to work backwards to figure out the recId needed to recover the signature.
            int recId = -1;

            for (int i = 0; i < 4; i++)
            {
                ECKey k = ECKey.RecoverFromSignature(i, sig, hash, IsCompressed);
                if (k != null && k.GetPubKey(IsCompressed).ToHex() == PubKey.ToHex())
                {
                    recId = i;
                    break;
                }
            }

            if (recId == -1)
            {
                throw new InvalidOperationException("Could not construct a recoverable key. This should never happen.");
            }

            int headerByte = recId + 27 + (IsCompressed ? 4 : 0);

            byte[] sigData = new byte[65];              // 1 header + 32 bytes for R + 32 bytes for S

            sigData[0] = (byte)headerByte;

            Array.Copy(Utils.BigIntegerToBytes(sig.R, 32), 0, sigData, 1, 32);
            Array.Copy(Utils.BigIntegerToBytes(sig.S, 32), 0, sigData, 33, 32);
            return(sigData);
        }
示例#5
0
 public static Op GetPushOp(long value)
 {
     return(GetPushOp(Utils.BigIntegerToBytes(new BigInteger(value))));
 }
示例#6
0
        internal static Op GetPushOp(BigInteger data)
#endif
        {
            return(GetPushOp(Utils.BigIntegerToBytes(data)));
        }
 public static Op GetPushOp(long value)
 {
     return(GetPushOp(Utils.BigIntegerToBytes(ooo.BigInteger.ValueOf(value))));
 }
示例#8
0
 public static Script operator +(Script a, int value)
 {
     return(a + Utils.BigIntegerToBytes(value));
 }
 public static Op GetPushOp(long value)
 {
     return(GetPushOp(Utils.BigIntegerToBytes(BouncyCastle.Math.BigInteger.ValueOf(value))));
 }
示例#10
0
        public bool EvalScript(Script s, Transaction txTo, int nIn)
        {
            var script = s.CreateReader();
            int pend   = (int)script.Inner.Length;

            int            pbegincodehash = 0;
            Stack <bool>   vfExec         = new Stack <bool>();
            Stack <byte[]> altstack       = new Stack <byte[]>();
            Op             opcode         = null;

            if (s.Length > 10000)
            {
                return(false);
            }
            int nOpCount = 0;

            try
            {
                while ((opcode = script.Read()) != null)
                {
                    bool fExec = vfExec.All(o => o);                     //!count(vfExec.begin(), vfExec.end(), false);

                    //
                    // Read instruction
                    //

                    if (opcode.PushData != null && opcode.PushData.Length > 520)
                    {
                        return(false);
                    }

                    // Note how OP_RESERVED does not count towards the opcode limit.
                    if (opcode.Code > OpcodeType.OP_16 && ++nOpCount > 201)
                    {
                        return(false);
                    }

                    if (opcode.Code == OpcodeType.OP_CAT ||
                        opcode.Code == OpcodeType.OP_SUBSTR ||
                        opcode.Code == OpcodeType.OP_LEFT ||
                        opcode.Code == OpcodeType.OP_RIGHT ||
                        opcode.Code == OpcodeType.OP_INVERT ||
                        opcode.Code == OpcodeType.OP_AND ||
                        opcode.Code == OpcodeType.OP_OR ||
                        opcode.Code == OpcodeType.OP_XOR ||
                        opcode.Code == OpcodeType.OP_2MUL ||
                        opcode.Code == OpcodeType.OP_2DIV ||
                        opcode.Code == OpcodeType.OP_MUL ||
                        opcode.Code == OpcodeType.OP_DIV ||
                        opcode.Code == OpcodeType.OP_MOD ||
                        opcode.Code == OpcodeType.OP_LSHIFT ||
                        opcode.Code == OpcodeType.OP_RSHIFT)
                    {
                        return(false);                        // Disabled opcodes.
                    }
                    if (fExec && opcode.PushData != null)
                    {
                        _Stack.Push(opcode.PushData);
                    }
                    else if (fExec || (OpcodeType.OP_IF <= opcode.Code && opcode.Code <= OpcodeType.OP_ENDIF))
                    {
                        switch (opcode.Code)
                        {
                        //
                        // Push value
                        //
                        case OpcodeType.OP_1NEGATE:
                        case OpcodeType.OP_1:
                        case OpcodeType.OP_2:
                        case OpcodeType.OP_3:
                        case OpcodeType.OP_4:
                        case OpcodeType.OP_5:
                        case OpcodeType.OP_6:
                        case OpcodeType.OP_7:
                        case OpcodeType.OP_8:
                        case OpcodeType.OP_9:
                        case OpcodeType.OP_10:
                        case OpcodeType.OP_11:
                        case OpcodeType.OP_12:
                        case OpcodeType.OP_13:
                        case OpcodeType.OP_14:
                        case OpcodeType.OP_15:
                        case OpcodeType.OP_16:
                        {
                            // ( -- value)
                            BigInteger bn = new BigInteger((int)opcode.Code - (int)(OpcodeType.OP_1 - 1));
                            _Stack.Push(Utils.BigIntegerToBytes(bn));
                        }
                        break;


                        //
                        // Control
                        //
                        case OpcodeType.OP_NOP:
                        case OpcodeType.OP_NOP1:
                        case OpcodeType.OP_NOP2:
                        case OpcodeType.OP_NOP3:
                        case OpcodeType.OP_NOP4:
                        case OpcodeType.OP_NOP5:
                        case OpcodeType.OP_NOP6:
                        case OpcodeType.OP_NOP7:
                        case OpcodeType.OP_NOP8:
                        case OpcodeType.OP_NOP9:
                        case OpcodeType.OP_NOP10:
                            break;

                        case OpcodeType.OP_IF:
                        case OpcodeType.OP_NOTIF:
                        {
                            // <expression> if [statements] [else [statements]] endif
                            bool fValue = false;
                            if (fExec)
                            {
                                if (_Stack.Count < 1)
                                {
                                    return(false);
                                }
                                var vch = top(_Stack, -1);
                                fValue = CastToBool(vch);
                                if (opcode.Code == OpcodeType.OP_NOTIF)
                                {
                                    fValue = !fValue;
                                }
                                _Stack.Pop();
                            }
                            vfExec.Push(fValue);
                        }
                        break;

                        case OpcodeType.OP_ELSE:
                        {
                            if (vfExec.Count == 0)
                            {
                                return(false);
                            }
                            var v = vfExec.Pop();
                            vfExec.Push(!v);
                            //vfExec.Peek() = !vfExec.Peek();
                        }
                        break;

                        case OpcodeType.OP_ENDIF:
                        {
                            if (vfExec.Count == 0)
                            {
                                return(false);
                            }
                            vfExec.Pop();
                        }
                        break;

                        case OpcodeType.OP_VERIFY:
                        {
                            // (true -- ) or
                            // (false -- false) and return
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            bool fValue = CastToBool(top(_Stack, -1));
                            if (fValue)
                            {
                                _Stack.Pop();
                            }
                            else
                            {
                                return(false);
                            }
                        }
                        break;

                        case OpcodeType.OP_RETURN:
                        {
                            return(false);
                        }


                        //
                        // Stack ops
                        //
                        case OpcodeType.OP_TOALTSTACK:
                        {
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            altstack.Push(top(_Stack, -1));
                            _Stack.Pop();
                        }
                        break;

                        case OpcodeType.OP_FROMALTSTACK:
                        {
                            if (altstack.Count < 1)
                            {
                                return(false);
                            }
                            _Stack.Push(top(altstack, -1));
                            altstack.Pop();
                        }
                        break;

                        case OpcodeType.OP_2DROP:
                        {
                            // (x1 x2 -- )
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            _Stack.Pop();
                            _Stack.Pop();
                        }
                        break;

                        case OpcodeType.OP_2DUP:
                        {
                            // (x1 x2 -- x1 x2 x1 x2)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            var vch1 = top(_Stack, -2);
                            var vch2 = top(_Stack, -1);
                            _Stack.Push(vch1);
                            _Stack.Push(vch2);
                        }
                        break;

                        case OpcodeType.OP_3DUP:
                        {
                            // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
                            if (_Stack.Count < 3)
                            {
                                return(false);
                            }
                            var vch1 = top(_Stack, -3);
                            var vch2 = top(_Stack, -2);
                            var vch3 = top(_Stack, -1);
                            _Stack.Push(vch1);
                            _Stack.Push(vch2);
                            _Stack.Push(vch3);
                        }
                        break;

                        case OpcodeType.OP_2OVER:
                        {
                            // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
                            if (_Stack.Count < 4)
                            {
                                return(false);
                            }
                            var vch1 = top(_Stack, -4);
                            var vch2 = top(_Stack, -3);
                            _Stack.Push(vch1);
                            _Stack.Push(vch2);
                        }
                        break;

                        case OpcodeType.OP_2ROT:
                        {
                            // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
                            if (_Stack.Count < 6)
                            {
                                return(false);
                            }
                            var vch1 = top(_Stack, -6);
                            var vch2 = top(_Stack, -5);
                            erase(ref _Stack, _Stack.Count - 6, _Stack.Count - 4);
                            _Stack.Push(vch1);
                            _Stack.Push(vch2);
                        }
                        break;

                        case OpcodeType.OP_2SWAP:
                        {
                            // (x1 x2 x3 x4 -- x3 x4 x1 x2)
                            if (_Stack.Count < 4)
                            {
                                return(false);
                            }
                            swap(ref _Stack, -4, -2);
                            swap(ref _Stack, -3, -1);
                        }
                        break;

                        case OpcodeType.OP_IFDUP:
                        {
                            // (x - 0 | x x)
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            var vch = top(_Stack, -1);
                            if (CastToBool(vch))
                            {
                                _Stack.Push(vch);
                            }
                        }
                        break;

                        case OpcodeType.OP_DEPTH:
                        {
                            // -- stacksize
                            BigInteger bn = new BigInteger(_Stack.Count);
                            _Stack.Push(Utils.BigIntegerToBytes(bn));
                        }
                        break;

                        case OpcodeType.OP_DROP:
                        {
                            // (x -- )
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            _Stack.Pop();
                        }
                        break;

                        case OpcodeType.OP_DUP:
                        {
                            // (x -- x x)
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            var vch = top(_Stack, -1);
                            _Stack.Push(vch);
                        }
                        break;

                        case OpcodeType.OP_NIP:
                        {
                            // (x1 x2 -- x2)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            erase(ref _Stack, _Stack.Count - 2);
                        }
                        break;

                        case OpcodeType.OP_OVER:
                        {
                            // (x1 x2 -- x1 x2 x1)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            var vch = top(_Stack, -2);
                            _Stack.Push(vch);
                        }
                        break;

                        case OpcodeType.OP_PICK:
                        case OpcodeType.OP_ROLL:
                        {
                            // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn)
                            // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            int n = (int)CastToBigNum(top(_Stack, -1));
                            _Stack.Pop();
                            if (n < 0 || n >= _Stack.Count)
                            {
                                return(false);
                            }
                            var vch = top(_Stack, -n - 1);
                            if (opcode.Code == OpcodeType.OP_ROLL)
                            {
                                erase(ref _Stack, _Stack.Count - n - 1);
                            }
                            _Stack.Push(vch);
                        }
                        break;

                        case OpcodeType.OP_ROT:
                        {
                            // (x1 x2 x3 -- x2 x3 x1)
                            //  x2 x1 x3  after first swap
                            //  x2 x3 x1  after second swap
                            if (_Stack.Count < 3)
                            {
                                return(false);
                            }
                            swap(ref _Stack, -3, -2);
                            swap(ref _Stack, -2, -1);
                        }
                        break;

                        case OpcodeType.OP_SWAP:
                        {
                            // (x1 x2 -- x2 x1)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            swap(ref _Stack, -2, -1);
                        }
                        break;

                        case OpcodeType.OP_TUCK:
                        {
                            // (x1 x2 -- x2 x1 x2)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            var vch = top(_Stack, -1);
                            insert(ref _Stack, _Stack.Count - 2, vch);
                        }
                        break;


                        case OpcodeType.OP_SIZE:
                        {
                            // (in -- in size)
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            BigInteger bn = new BigInteger(top(_Stack, -1).Length);
                            _Stack.Push(Utils.BigIntegerToBytes(bn));
                        }
                        break;


                        //
                        // Bitwise logic
                        //
                        case OpcodeType.OP_EQUAL:
                        case OpcodeType.OP_EQUALVERIFY:
                            //case OpcodeType.OP_NOTEQUAL: // use OpcodeType.OP_NUMNOTEQUAL
                        {
                            // (x1 x2 - bool)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            var  vch1   = top(_Stack, -2);
                            var  vch2   = top(_Stack, -1);
                            bool fEqual = Utils.ArrayEqual(vch1, vch2);
                            // OpcodeType.OP_NOTEQUAL is disabled because it would be too easy to say
                            // something like n != 1 and have some wiseguy pass in 1 with extra
                            // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
                            //if (opcode == OpcodeType.OP_NOTEQUAL)
                            //    fEqual = !fEqual;
                            _Stack.Pop();
                            _Stack.Pop();
                            _Stack.Push(fEqual ? vchTrue : vchFalse);
                            if (opcode.Code == OpcodeType.OP_EQUALVERIFY)
                            {
                                if (fEqual)
                                {
                                    _Stack.Pop();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;


                        //
                        // Numeric
                        //
                        case OpcodeType.OP_1ADD:
                        case OpcodeType.OP_1SUB:
                        case OpcodeType.OP_NEGATE:
                        case OpcodeType.OP_ABS:
                        case OpcodeType.OP_NOT:
                        case OpcodeType.OP_0NOTEQUAL:
                        {
                            // (in -- out)
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            var bn = CastToBigNum(top(_Stack, -1));
                            switch (opcode.Code)
                            {
                            case OpcodeType.OP_1ADD:
                                bn += BigInteger.One;
                                break;

                            case OpcodeType.OP_1SUB:
                                bn -= BigInteger.One;
                                break;

                            case OpcodeType.OP_NEGATE:
                                bn = -bn;
                                break;

                            case OpcodeType.OP_ABS:
                                if (bn < BigInteger.Zero)
                                {
                                    bn = -bn;
                                }
                                break;

                            case OpcodeType.OP_NOT:
                                bn = CastToBigNum(bn == BigInteger.Zero);
                                break;

                            case OpcodeType.OP_0NOTEQUAL:
                                bn = CastToBigNum(bn != BigInteger.Zero);
                                break;

                            default:
                                throw new NotSupportedException("invalid opcode");
                            }
                            _Stack.Pop();
                            _Stack.Push(Utils.BigIntegerToBytes(bn));
                        }
                        break;

                        case OpcodeType.OP_ADD:
                        case OpcodeType.OP_SUB:
                        case OpcodeType.OP_BOOLAND:
                        case OpcodeType.OP_BOOLOR:
                        case OpcodeType.OP_NUMEQUAL:
                        case OpcodeType.OP_NUMEQUALVERIFY:
                        case OpcodeType.OP_NUMNOTEQUAL:
                        case OpcodeType.OP_LESSTHAN:
                        case OpcodeType.OP_GREATERTHAN:
                        case OpcodeType.OP_LESSTHANOREQUAL:
                        case OpcodeType.OP_GREATERTHANOREQUAL:
                        case OpcodeType.OP_MIN:
                        case OpcodeType.OP_MAX:
                        {
                            // (x1 x2 -- out)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }
                            var        bn1 = CastToBigNum(top(_Stack, -2));
                            var        bn2 = CastToBigNum(top(_Stack, -1));
                            BigInteger bn;
                            switch (opcode.Code)
                            {
                            case OpcodeType.OP_ADD:
                                bn = bn1 + bn2;
                                break;

                            case OpcodeType.OP_SUB:
                                bn = bn1 - bn2;
                                break;

                            case OpcodeType.OP_BOOLAND:
                                bn = CastToBigNum(bn1 != BigInteger.Zero && bn2 != BigInteger.Zero);
                                break;

                            case OpcodeType.OP_BOOLOR:
                                bn = CastToBigNum(bn1 != BigInteger.Zero || bn2 != BigInteger.Zero);
                                break;

                            case OpcodeType.OP_NUMEQUAL:
                                bn = CastToBigNum(bn1 == bn2);
                                break;

                            case OpcodeType.OP_NUMEQUALVERIFY:
                                bn = CastToBigNum(bn1 == bn2);
                                break;

                            case OpcodeType.OP_NUMNOTEQUAL:
                                bn = CastToBigNum(bn1 != bn2);
                                break;

                            case OpcodeType.OP_LESSTHAN:
                                bn = CastToBigNum(bn1 < bn2);
                                break;

                            case OpcodeType.OP_GREATERTHAN:
                                bn = CastToBigNum(bn1 > bn2);
                                break;

                            case OpcodeType.OP_LESSTHANOREQUAL:
                                bn = CastToBigNum(bn1 <= bn2);
                                break;

                            case OpcodeType.OP_GREATERTHANOREQUAL:
                                bn = CastToBigNum(bn1 >= bn2);
                                break;

                            case OpcodeType.OP_MIN:
                                bn = (bn1 < bn2 ? bn1 : bn2);
                                break;

                            case OpcodeType.OP_MAX:
                                bn = (bn1 > bn2 ? bn1 : bn2);
                                break;

                            default:
                                throw new NotSupportedException("invalid opcode");
                            }
                            _Stack.Pop();
                            _Stack.Pop();
                            _Stack.Push(Utils.BigIntegerToBytes(bn));

                            if (opcode.Code == OpcodeType.OP_NUMEQUALVERIFY)
                            {
                                if (CastToBool(top(_Stack, -1)))
                                {
                                    _Stack.Pop();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;

                        case OpcodeType.OP_WITHIN:
                        {
                            // (x min max -- out)
                            if (_Stack.Count < 3)
                            {
                                return(false);
                            }
                            var  bn1    = CastToBigNum(top(_Stack, -3));
                            var  bn2    = CastToBigNum(top(_Stack, -2));
                            var  bn3    = CastToBigNum(top(_Stack, -1));
                            bool fValue = (bn2 <= bn1 && bn1 < bn3);
                            _Stack.Pop();
                            _Stack.Pop();
                            _Stack.Pop();
                            _Stack.Push(fValue ? vchTrue : vchFalse);
                        }
                        break;


                        //
                        // Crypto
                        //
                        case OpcodeType.OP_RIPEMD160:
                        case OpcodeType.OP_SHA1:
                        case OpcodeType.OP_SHA256:
                        case OpcodeType.OP_HASH160:
                        case OpcodeType.OP_HASH256:
                        {
                            // (in -- hash)
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            var    vch     = top(_Stack, -1);
                            byte[] vchHash = null;                                            //((opcode == OpcodeType.OP_RIPEMD160 || opcode == OpcodeType.OP_SHA1 || opcode == OpcodeType.OP_HASH160) ? 20 : 32);
                            if (opcode.Code == OpcodeType.OP_RIPEMD160)
                            {
                                vchHash = Hashes.RIPEMD160(vch, vch.Length);
                            }
                            else if (opcode.Code == OpcodeType.OP_SHA1)
                            {
                                vchHash = Hashes.SHA1(vch, vch.Length);
                            }
                            else if (opcode.Code == OpcodeType.OP_SHA256)
                            {
                                vchHash = Hashes.SHA256(vch, vch.Length);
                            }
                            else if (opcode.Code == OpcodeType.OP_HASH160)
                            {
                                vchHash = Hashes.Hash160(vch, vch.Length).ToBytes();
                            }
                            else if (opcode.Code == OpcodeType.OP_HASH256)
                            {
                                vchHash = Hashes.Hash256(vch, vch.Length).ToBytes();
                            }
                            _Stack.Pop();
                            _Stack.Push(vchHash);
                        }
                        break;

                        case OpcodeType.OP_CODESEPARATOR:
                        {
                            // Hash starts after the code separator
                            pbegincodehash = (int)script.Inner.Position;
                        }
                        break;

                        case OpcodeType.OP_CHECKSIG:
                        case OpcodeType.OP_CHECKSIGVERIFY:
                        {
                            // (sig pubkey -- bool)
                            if (_Stack.Count < 2)
                            {
                                return(false);
                            }

                            var vchSig    = top(_Stack, -2);
                            var vchPubKey = top(_Stack, -1);

                            ////// debug print
                            //PrintHex(vchSig.begin(), vchSig.end(), "sig: %s\n");
                            //PrintHex(vchPubKey.begin(), vchPubKey.end(), "pubkey: %s\n");

                            // Subset of script starting at the most recent codeseparator
                            var scriptCode = new Script(s._Script.Skip(pbegincodehash).ToArray());
                            // Drop the signature, since there's no way for a signature to sign itself
                            scriptCode.FindAndDelete(vchSig);


                            bool fSuccess = IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey) &&
                                            CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn);

                            _Stack.Pop();
                            _Stack.Pop();
                            _Stack.Push(fSuccess ? vchTrue : vchFalse);
                            if (opcode.Code == OpcodeType.OP_CHECKSIGVERIFY)
                            {
                                if (fSuccess)
                                {
                                    _Stack.Pop();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;

                        case OpcodeType.OP_CHECKMULTISIG:
                        case OpcodeType.OP_CHECKMULTISIGVERIFY:
                        {
                            // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool)

                            int i = 1;
                            if ((int)_Stack.Count < i)
                            {
                                return(false);
                            }

                            int nKeysCount = (int)CastToBigNum(top(_Stack, -i));
                            if (nKeysCount < 0 || nKeysCount > 20)
                            {
                                return(false);
                            }
                            nOpCount += nKeysCount;
                            if (nOpCount > 201)
                            {
                                return(false);
                            }
                            int ikey = ++i;
                            i += nKeysCount;
                            if ((int)_Stack.Count < i)
                            {
                                return(false);
                            }

                            int nSigsCount = (int)CastToBigNum(top(_Stack, -i));
                            if (nSigsCount < 0 || nSigsCount > nKeysCount)
                            {
                                return(false);
                            }
                            int isig = ++i;
                            i += nSigsCount;
                            if ((int)_Stack.Count < i)
                            {
                                return(false);
                            }

                            // Subset of script starting at the most recent codeseparator
                            Script scriptCode = new Script(s._Script.Skip(pbegincodehash).ToArray());
                            // Drop the signatures, since there's no way for a signature to sign itself
                            for (int k = 0; k < nSigsCount; k++)
                            {
                                var vchSig = top(_Stack, -isig - k);
                                scriptCode.FindAndDelete(vchSig);
                            }

                            bool fSuccess = true;
                            while (fSuccess && nSigsCount > 0)
                            {
                                var vchSig    = top(_Stack, -isig);
                                var vchPubKey = top(_Stack, -ikey);

                                // Check signature
                                bool fOk = IsCanonicalSignature(vchSig) && IsCanonicalPubKey(vchPubKey) &&
                                           CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn);

                                if (fOk)
                                {
                                    isig++;
                                    nSigsCount--;
                                }
                                ikey++;
                                nKeysCount--;

                                // If there are more signatures left than keys left,
                                // then too many signatures have failed
                                if (nSigsCount > nKeysCount)
                                {
                                    fSuccess = false;
                                }
                            }

                            while (i-- > 1)
                            {
                                _Stack.Pop();
                            }

                            // A bug causes CHECKMULTISIG to consume one extra argument
                            // whose contents were not checked in any way.
                            //
                            // Unfortunately this is a potential source of mutability,
                            // so optionally verify it is exactly equal to zero prior
                            // to removing it from the stack.
                            if (_Stack.Count < 1)
                            {
                                return(false);
                            }
                            if (((ScriptVerify & ScriptVerify.NullDummy) != 0) && top(_Stack, -1).Length != 0)
                            {
                                return(Utils.error("CHECKMULTISIG dummy argument not null"));
                            }
                            _Stack.Pop();

                            _Stack.Push(fSuccess ? vchTrue : vchFalse);

                            if (opcode.Code == OpcodeType.OP_CHECKMULTISIGVERIFY)
                            {
                                if (fSuccess)
                                {
                                    _Stack.Pop();
                                }
                                else
                                {
                                    return(false);
                                }
                            }
                        }
                        break;

                        default:
                            return(false);
                        }
                    }

                    // Size limits
                    if (_Stack.Count + altstack.Count > 1000)
                    {
                        return(false);
                    }
                }
            }
            catch (Exception ex)
            {
                Utils.error("Error in EvalScript " + ex.Message + " on opcode " + opcode);
                return(false);
            }


            if (vfExec.Count != 0)
            {
                return(false);
            }

            return(true);
        }
示例#11
0
 public static Op GetPushOp(BigInteger data)
 {
     return(GetPushOp(Utils.BigIntegerToBytes(data)));
 }