예제 #1
0
파일: KzOp.cs 프로젝트: TagsRocks/KzBsv
        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
파일: KzOp.cs 프로젝트: wy000000/KzBsv
        /*
         *  // script.h lines 527-562
         *  bool GetOp2(const_iterator &pc, opcodetype &opcodeRet,
         *      std::vector<uint8_t> *pvchRet) const {
         *      opcodeRet = OP_INVALIDOPCODE;
         *      if (pvchRet) pvchRet->clear();
         *      if (pc >= end()) return false;
         *
         *      // Read instruction
         *      if (end() - pc < 1) return false;
         *      unsigned int opcode = *pc++;
         *
         *      // Immediate operand
         *      if (opcode <= OP_PUSHDATA4) {
         *          unsigned int nSize = 0;
         *          if (opcode < OP_PUSHDATA1) {
         *              nSize = opcode;
         *          } else if (opcode == OP_PUSHDATA1) {
         *              if (end() - pc < 1) return false;
         *              nSize = *pc++;
         *          } else if (opcode == OP_PUSHDATA2) {
         *              if (end() - pc < 2) return false;
         *              nSize = ReadLE16(&pc[0]);
         *              pc += 2;
         *          } else if (opcode == OP_PUSHDATA4) {
         *              if (end() - pc < 4) return false;
         *              nSize = ReadLE32(&pc[0]);
         *              pc += 4;
         *          }
         *          if (end() - pc < 0 || (unsigned int)(end() - pc) < nSize)
         *              return false;
         *          if (pvchRet) pvchRet->assign(pc, pc + nSize);
         *          pc += nSize;
         *      }
         *
         *      opcodeRet = (opcodetype)opcode;
         *      return true;
         *  }
         */

        public static (bool ok, KzOp op) TryRead(ref ReadOnlySequence <byte> ros, out long consumed)
        {
            var op = new KzOp();
            var ok = op.TryReadOp(ref ros, out consumed);

            return(ok, op);
        }
예제 #3
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
        }
예제 #4
0
        /// <summary>
        /// Decode script opcodes and push data.
        /// </summary>
        /// <returns></returns>
        public IEnumerable <KzOp> Decode()
        {
            var ros = _script;

            while (ros.Length > 0)
            {
                var op = new KzOp();
                if (!op.TryReadOp(ref ros))
                {
                    goto fail;
                }
                yield return(op);
            }

fail:
            ;
        }
예제 #5
0
        /// <summary>
        /// Return the Template String representation of script bytes.
        /// If the returned string does not include all the script opcodes, either because the scriptLen or limitLen
        /// arguments are greater than zero, or if the script sequence ends with an incomplete multibyte opcode,
        /// then "..." is appended following the last complete opcode.
        ///
        /// scriptLen argument should be used when the actual script is longer than the script sequence provided,
        /// which must then be a subsequence from the start of the script.
        /// If greater than zero it may be longer than the sequence provided in which case "..." will be appended
        /// after the last opcode.
        ///
        /// limitLen argument stops converting opcodes to their template string format after processing this many bytes.
        /// </summary>
        /// <param name="script"></param>
        /// <param name="scriptLen">How long the entire script is, or zero.</param>
        /// <param name="limitLen">How many bytes to process, or zero.</param>
        /// <returns></returns>
        public static string ToTemplateString(ReadOnlySequence <byte> script, long scriptLen = 0, long limitLen = 0)
        {
            var ros = script;

            if (limitLen == 0)
            {
                limitLen = long.MaxValue;
            }
            var ok    = true;
            var count = 0L;
            var sb    = new StringBuilder();

            while (ros.Length > 0 && ok && limitLen > count)
            {
                var op = new KzOp();
                ok     = op.TryReadOp(ref ros, out var consumed);
                count += consumed;
                if (ok && limitLen >= count)
                {
                    var len = op.Data.Length;
                    if (len == 0)
                    {
                        sb.Append($"{op.CodeName} ");
                    }
                    else
                    {
                        sb.Append($"[{op.Data.Length}] ");
                    }
                }
            }
            if (sb.Length > 0)
            {
                sb.Length--;
            }
            if (scriptLen == 0)
            {
                scriptLen = count;
            }
            if (!ok || limitLen < count || count < scriptLen)
            {
                sb.Append("...");
            }
            return(sb.ToString());
        }
예제 #6
0
파일: KzOp.cs 프로젝트: TagsRocks/KzBsv
        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);
        }
예제 #7
0
        public bool IsPushOnly()
        {
            var ros = _script;
            var op  = new KzOp();

            while (ros.Length > 0)
            {
                if (!op.TryReadOp(ref ros))
                {
                    return(false);
                }
                // Note that IsPushOnly() *does* consider OP_RESERVED to be a push-type
                // opcode, however execution of OP_RESERVED fails, so it's not relevant
                // to P2SH/BIP62 as the scriptSig would fail prior to the P2SH special
                // validation code being executed.
                if (op.Code > KzOpcode.OP_16)
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #8
0
파일: KzBOp.cs 프로젝트: TagsRocks/KzBsv
 public KzBOp(KzValType data) : this()
 {
     IsFinal = true; IsRaw = true; Op = new KzOp(KzOpcode.OP_NOP, data);
 }
예제 #9
0
파일: KzBOp.cs 프로젝트: TagsRocks/KzBsv
 public KzBOp(KzOp op) : this()
 {
     IsFinal = true; Op = op;
 }