[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/truevector1/bitcore/master/Script.js [Back]  [Original]

require('classtool');

function spec(b) {
  var config = b.config || require('./config');
  var log = b.log || require('./util/log');

  var Opcode = require('./Opcode').class();

  // Make opcodes available as pseudo-constants
  for (var i in Opcode.map) {
    eval(i + " = " + Opcode.map[i] + ";");
  }

  var util = b.util || require('./util/util');
  var Parser = b.Parser || require('./util/BinaryParser').class();
  var Put = b.Put || require('bufferput');

  var TX_UNKNOWN = 0;
  var TX_PUBKEY = 1;
  var TX_PUBKEYHASH = 2;
  var TX_MULTISIG = 3;
  var TX_SCRIPTHASH = 4;

  var TX_TYPES = [
    'unknown',
    'pubkey',
    'pubkeyhash',
    'multisig',
    'scripthash'
  ];

  function Script(buffer) {
    if(buffer) {
      this.buffer = buffer;
    } else {
      this.buffer = util.EMPTY_BUFFER;
    }
    this.chunks = [];
    this.parse();
  };
  this.class = Script;

  Script.TX_UNKNOWN=TX_UNKNOWN;
  Script.TX_PUBKEY=TX_PUBKEY;
  Script.TX_PUBKEYHASH=TX_PUBKEYHASH;
  Script.TX_MULTISIG=TX_MULTISIG;
  Script.TX_SCRIPTHASH=TX_SCRIPTHASH;

  Script.prototype.parse = function () {
    this.chunks = [];

    var parser = new Parser(this.buffer);
    while (!parser.eof()) {
      var opcode = parser.word8();

      var len;
      if (opcode > 0 && opcode < OP_PUSHDATA1) {
        // Read some bytes of data, opcode value is the length of data
        this.chunks.push(parser.buffer(opcode));
      } else if (opcode == OP_PUSHDATA1) {
        len = parser.word8();
        this.chunks.push(parser.buffer(len));
      } else if (opcode == OP_PUSHDATA2) {
        len = parser.word16le();
        this.chunks.push(parser.buffer(len));
      } else if (opcode == OP_PUSHDATA4) {
        len = parser.word32le();
        this.chunks.push(parser.buffer(len));
      } else {
        this.chunks.push(opcode);
      }
    }
  };

  Script.prototype.isPushOnly = function ()
  {
    for (var i = 0; i < this.chunks.length; i++)
      if (!Buffer.isBuffer(this.chunks[i]))
        return false;

    return true;
  };

  Script.prototype.isP2SH = function ()
  {
    return (this.chunks.length == 3 &&
      this.chunks[0] == OP_HASH160 &&
      Buffer.isBuffer(this.chunks[1]) &&
      this.chunks[1].length == 20 &&
      this.chunks[2] == OP_EQUAL);
  };

  Script.prototype.isPubkey = function ()
  {
    return (this.chunks.length == 2 &&
          Buffer.isBuffer(this.chunks[0]) &&
          this.chunks[1] == OP_CHECKSIG);
  };

  Script.prototype.isPubkeyHash = function ()
  {
    return (this.chunks.length == 5 &&
            this.chunks[0] == OP_DUP &&
            this.chunks[1] == OP_HASH160 &&
      Buffer.isBuffer(this.chunks[2]) &&
      this.chunks[2].length == 20 &&
            this.chunks[3] == OP_EQUALVERIFY &&
            this.chunks[4] == OP_CHECKSIG);
  };

  function isSmallIntOp(opcode)
  {
    return ((opcode == OP_0) ||
          ((opcode >= OP_1) && (opcode  3 &&
          isSmallIntOp(this.chunks[0]) &&
          isSmallIntOp(this.chunks[this.chunks.length-2]) &&
      this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG);
  };

  Script.prototype.finishedMultiSig = function()
  {
    var nsigs = 0;
    for (var i = 0; i < this.chunks.length-1; i++)
      if (this.chunks[i] !== 0)
        nsigs++;

    var serializedScript = this.chunks[this.chunks.length-1];
    var script = new Script(serializedScript);
    var nreq = script.chunks[0] - 80; //see OP_2-OP_16

    if (nsigs == nreq)
      return true;
    else
      return false;
  }

  Script.prototype.removePlaceHolders = function()
  {
    var chunks = [];
    for (var i in this.chunks)
    {
      var chunk = this.chunks[i];
      if (chunk != 0)
        chunks.push(chunk);
    }
    this.chunks = chunks;
    this.updateBuffer();
    return this;
  }

  Script.prototype.prependOp0 = function()
  {
    var chunks = [0];
    for (i in this.chunks)
      chunks.push(this.chunks[i]);
    this.chunks = chunks;
    this.updateBuffer();
    return this;
  }

  // is this a script form we know?
  Script.prototype.classify = function ()
  {
    if (this.isPubkeyHash())
    return TX_PUBKEYHASH;
  if (this.isP2SH())
    return TX_SCRIPTHASH;
  if (this.isMultiSig())
    return TX_MULTISIG;
  if (this.isPubkey())
    return TX_PUBKEY;
  return TX_UNKNOWN;
  };

  // extract useful data items from known scripts
  Script.prototype.capture = function ()
  {
    var txType = this.classify();
  var res = [];
  switch (txType) {
  case TX_PUBKEY:
    res.push(this.chunks[0]);
    break;
  case TX_PUBKEYHASH:
    res.push(this.chunks[2]);
    break;
  case TX_MULTISIG:
    for (var i = 1; i < (this.chunks.length - 2); i++)
      res.push(this.chunks[i]);
    break;
  case TX_SCRIPTHASH:
    res.push(this.chunks[1]);
    break;

  case TX_UNKNOWN:
  default:
    // do nothing
    break;
  }

  return res;
  };

  // return first extracted data item from script
  Script.prototype.captureOne = function ()
  {
    var arr = this.capture();
  return arr[0];
  };

  Script.prototype.getOutType = function ()
  {
    var txType = this.classify();
    switch (txType) {
      case TX_PUBKEY:   return 'Pubkey';
      case TX_PUBKEYHASH: return 'Address';
      default:    return 'Strange';
    }
  };

  Script.prototype.getRawOutType = function() {
    return TX_TYPES[this.classify()];
  };

  Script.prototype.simpleOutHash = function ()
  {
    switch (this.getOutType()) {
    case 'Address':
      return this.chunks[2];
    case 'Pubkey':
      return util.sha256ripe160(this.chunks[0]);
    default:
      log.debug("Encountered non-standard scriptPubKey");
      log.debug("Strange script was: " + this.toString());
      return null;
    }
  };

  Script.prototype.getInType = function ()
  {
    if (this.chunks.length == 1) {
      // Direct IP to IP transactions only have the public key in their scriptSig.
      return 'Pubkey';
    } else if (this.chunks.length == 2 &&
               Buffer.isBuffer(this.chunks[0]) &&
               Buffer.isBuffer(this.chunks[1])) {
      return 'Address';
    } else {
      return 'Strange';
    }
  };

  Script.prototype.simpleInPubKey = function ()
  {
    switch (this.getInType()) {
    case 'Address':
      return this.chunks[1];
    case 'Pubkey':
      return null;
    default:
      log.debug("Encountered non-standard scriptSig");
      log.debug("Strange script was: " + this.toString());
      return null;
    }
  };

  Script.prototype.getBuffer = function ()
  {
    return this.buffer;
  };

  Script.prototype.getStringContent = function (truncate, maxEl)
  {
    if (truncate === null) {
      truncate = true;
    }

    if ("undefined" === typeof maxEl) {
      maxEl = 15;
    }

    var script = '';
    for (var i = 0, l = this.chunks.length; i < l; i++) {
      var chunk = this.chunks[i];

      if (i > 0) {
        script += " ";
      }

      if (Buffer.isBuffer(chunk)) {
        script += "0x"+util.formatBuffer(chunk, truncate ? null : 0);
      } else {
        script += Opcode.reverseMap[chunk];
      }

      if (maxEl && i > maxEl) {
        script += " ...";
        break;
      }
    }
    return script;
  };

  Script.prototype.toString = function (truncate, maxEl)
  {
    var script = "";
    return script;
  };


  Script.prototype.writeOp = function (opcode)
  {
    var buf = Buffer(this.buffer.length + 1);
    this.buffer.copy(buf);
    buf.writeUInt8(opcode, this.buffer.length);

    this.buffer = buf;

    this.chunks.push(opcode);
  };

  Script.prototype.writeN = function (n)
  {
    if (n < 0 || n > 16)
      throw new Error("writeN: out of range value " + n);

    if (n == 0)
      this.writeOp(OP_0);
    else
      this.writeOp(OP_1 + n - 1);
  };

  function prefixSize(data_length)
  {
    if (data_length < OP_PUSHDATA1) {
      return 1;
    } else if (data_length 

Web Proxy Viewer  |  New URL  |  Original Page