docs: def btc_tx_deserialize(_tx, **blockchain_opts):
      """
      Given a hex-encoded transaction, decode it into an object
      with the following structure:
      {
          ins: [
              {
                  outpoint: { hash: ..., index: ... }, 
                  script: ...,
                  sequence: ...,
                  witness_script: ...,        # not included if not segwit
              }, ...
          ]
          outs: [
              {
                  value: ...,
                  script: ...
              }, ...
          ],
          version: ..., 
          locktime: ...
      }
      
      Derived from pybitcointools (https://github.com/vbuterin/pybitcointools) written by Vitalik Buterin
      Throws an exception if there are remaining bytes
      """
  
      tx = None
      if isinstance(_tx, str) and re.match('^[0-9a-fA-F]*$', _tx):
          # convert from hex to bin, safely
          tx = binascii.unhexlify(_tx)
      else:
          tx = _tx[:]
  
      # pointer to byte offset in _tx (as an array due to Python scoping rules)
      ptr = [0]
      
      # top-level tx
      obj = {"ins": [], "outs": [], 'version': None, 'locktime': None}
  
      # get version
      obj["version"] = read_as_int(ptr, tx, 4)
  
      # segwit? (bip143)
      # 5th byte will be 0 and 6th byte will be flags (nonzero) if so
      bip143 = peek_bytes(ptr, tx, 2)
      if ord(bip143[0]) == 0 and ord(bip143[1]) != 0:
          # segwit
          # consume marker
          read_bytes(ptr, tx, 2)
  
          # get the rest of the body
          body = read_tx_body(ptr, tx)
          obj['ins'] = body['ins']
          obj['outs'] = body['outs']
       
          # read witnesses for each input
          witness_scripts = read_tx_witnesses(ptr, tx, len(obj['ins']))
        
          if len(witness_scripts) != len(obj['ins']):
              raise ValueError('Invald number of witnesses in {}'.format(_tx))
  
          for i in xrange(0, len(witness_scripts)):
              obj['ins'][i]['witness_script'] = witness_scripts[i]
          
      else:
          # non-segwit
          body = read_tx_body(ptr, tx)
          obj['ins'] = body['ins']
          obj['outs'] = body['outs']
  
      # locktime
      obj["locktime"] = read_as_int(ptr, tx, 4)
  
      if not ptr[0] == len(tx):
          # log.warning('Did not parse entire tx ({} bytes remaining)'.format(len(tx) - ptr[0]))
          raise ValueError('Did not parse entire tx ({} bytes remaining)'.format(len(tx) - ptr[0]))
  
      # hexlify each byte field 
      obj = encoding.json_changebase(obj, lambda x: encoding.safe_hexlify(x))
      return obj