Пример #1
0
        public static KzOp Push(ReadOnlySpan <byte> data)
        {
            var code = KzOpcode.OP_INVALIDOPCODE;
            var val  = KzValType.None;

            if (data.Length == 1 && data[0] <= 16)
            {
                code = data[0] == 0 ? KzOpcode.OP_0 : (KzOpcode)(data[0] - 1 + (int)KzOpcode.OP_1);
            }
            else
            {
                if (data.Length < (int)KzOpcode.OP_PUSHDATA1)
                {
                    code = (KzOpcode)data.Length;
                }
                else if (data.Length <= 0xff)
                {
                    code = KzOpcode.OP_PUSHDATA1;
                }
                else if (data.Length <= 0xffff)
                {
                    code = KzOpcode.OP_PUSHDATA2;
                }
                else
                {
                    code = KzOpcode.OP_PUSHDATA4;
                }
                val = new KzValType(data.ToArray());
            }
            var op = new KzOp(code, val);

            return(op);
        }
Пример #2
0
        public int FindAndDelete(KzValType vchSig)
        {
            int nFound = 0;
            var s      = _script;
            var r      = s;

            if (vchSig.Length == 0)
            {
                return(nFound);
            }

            var op       = new KzOp();
            var consumed = 0L;
            var offset   = 0L;

            var o    = vchSig.Sequence;
            var oLen = o.Length;

            do
            {
                offset += consumed;
                while (s.StartsWith(o))
                {
                    r = r.RemoveSlice(offset, oLen);
                    s = s.Slice(oLen);
                    ++nFound;
                }
            } while (op.TryReadOp(ref s, out consumed));

            _script = r;
            return(nFound);

#if false
            CScript    result;
            iterator   pc = begin(), pc2 = begin();
            opcodetype opcode;

            do
            {
                result.insert(result.end(), pc2, pc);
                while (static_cast <size_t>(end() - pc) >= b.size() &&
                       std::equal(b.begin(), b.end(), pc))
                {
                    pc = pc + b.size();
                    ++nFound;
                }
                pc2 = pc;
            } while (GetOp(pc, opcode));

            if (nFound > 0)
            {
                result.insert(result.end(), pc2, end());
                *this = result;
            }
#endif
        }
Пример #3
0
        public KzValType BitXor(KzValType b)
        {
            if (Length != b.Length)
            {
                throw new InvalidOperationException();
            }
            var sa = ToSpan();
            var sb = b.ToSpan();
            var r  = new byte[sa.Length];

            for (var i = 0; i < sa.Length; i++)
            {
                r[i] = (byte)(sa[i] ^ sb[i]);
            }
            return(new KzValType(r));
        }
Пример #4
0
        public bool BitEquals(KzValType x2)
        {
            if (Length != x2.Length)
            {
                return(false);
            }
            var s1 = ToSpan();
            var s2 = x2.ToSpan();

            for (var i = 0; i < s1.Length; i++)
            {
                if (s1[i] != s2[i])
                {
                    return(false);
                }
            }
            return(true);
        }
Пример #5
0
        public static KzOp Push(long v)
        {
            var code = KzOpcode.OP_INVALIDOPCODE;
            var val  = KzValType.None;

            if (v == -1)
            {
                code = KzOpcode.OP_1NEGATE;
            }
            else if (v >= 0 && v <= 16)
            {
                code = v == 0 ? KzOpcode.OP_0 : (KzOpcode)(v - 1 + (int)KzOpcode.OP_1);
            }
            else
            {
                var bytes = BitConverter.GetBytes(v).AsSpan();
                if (v <= 0xff)
                {
                    code = KzOpcode.OP_PUSH1;
                    val  = new KzValType(bytes.Slice(0, 1).ToArray());
                }
                else if (v <= 0xffff)
                {
                    code = KzOpcode.OP_PUSH2;
                    val  = new KzValType(bytes.Slice(0, 2).ToArray());
                }
                else if (v <= 0xffffff)
                {
                    code = KzOpcode.OP_PUSH3;
                    val  = new KzValType(bytes.Slice(0, 3).ToArray());
                }
                else
                {
                    code = KzOpcode.OP_PUSH4;
                    val  = new KzValType(bytes.Slice(0, 4).ToArray());
                }
            }
            var op = new KzOp(code, val);

            return(op);
        }
Пример #6
0
 public KzBOp(KzValType data) : this()
 {
     IsFinal = true; IsRaw = true; Op = new KzOp(KzOpcode.OP_NOP, data);
 }
Пример #7
0
 public KzOp(KzOpcode code)
 {
     _code = code; _data = KzValType.None;
 }
Пример #8
0
 public KzOp(KzOpcode code, KzValType data)
 {
     _code = code; _data = data;
 }
Пример #9
0
        public bool TryReadOp(ref SequenceReader <byte> r)
        {
            _code = KzOpcode.OP_INVALIDOPCODE;
            _data = KzValType.None;

            if (!r.TryRead(out byte opcode))
            {
                goto fail;
            }

            _code = (KzOpcode)opcode;

            // Opcodes OP_0 and OP_1 to OP_16 are single byte opcodes that push the corresponding value.
            // Opcodes from zero to 0x4b [0..75] are single byte push commands where the value is the number of bytes to push.
            // Opcode 0x4c (76) takes the next byte as the count and should be used for pushing [76..255] bytes.
            // Opcode 0x4d (77) takes the next two bytes. Used for pushing [256..65536] bytes.
            // Opcode 0x4e (78) takes the next four bytes. Used for pushing [65537..4,294,967,296] bytes.

            if (opcode <= (byte)KzOpcode.OP_PUSHDATA4)
            {
                var nSize = 0U;
                if (opcode < (byte)KzOpcode.OP_PUSHDATA1)
                {
                    nSize = opcode;
                }
                else if (opcode == (byte)KzOpcode.OP_PUSHDATA1)
                {
                    if (!r.TryRead(out byte size1))
                    {
                        goto fail;
                    }
                    nSize = size1;
                }
                else if (opcode == (byte)KzOpcode.OP_PUSHDATA2)
                {
                    if (!r.TryReadLittleEndian(out UInt16 size2))
                    {
                        goto fail;
                    }
                    nSize = size2;
                }
                else if (opcode == (byte)KzOpcode.OP_PUSHDATA4)
                {
                    if (!r.TryReadLittleEndian(out UInt32 size4))
                    {
                        goto fail;
                    }
                    nSize = size4;
                }
                if (nSize >= 0)
                {
                    if (r.Remaining < nSize)
                    {
                        goto fail;
                    }
                    _data = new KzValType(r.Sequence.Slice(r.Position, (Int32)nSize));
                    r.Advance(nSize);
                }
            }
            return(true);

fail:
            return(false);
        }