Beispiel #1
0
def read_block(db_cursor, hash):
  (key,value) = db_cursor.set_range("\x0ablockindex"+hash)
  vds = BCDataStream()
  vds.clear(); vds.write(value)
  block_data = _parse_block_index(vds)
  block_data['hash256'] = hash
  return block_data
Beispiel #2
0
def dump_all_transactions(datadir, db_env):
  """ Dump all transactions.
  """
  blockfile = open(os.path.join(datadir, "blk%04d.dat"%(1,)), "rb")
  block_datastream = BCDataStream()
  block_datastream.map_file(blockfile, 0)
  def for_each_block(block_data):
    block_datastream.seek_file(block_data['nBlockPos'])
    data = parse_Block(block_datastream)
    block_datetime = datetime.fromtimestamp(data['nTime'])
    dt = "%d-%02d-%02d-%02d-%02d-%02d"%(block_datetime.year, block_datetime.month, block_datetime.day, block_datetime.hour, block_datetime.minute, block_datetime.second)
    for txn in data['transactions']:
      try:
        for txIn in txn['txIn']:
          if txIn['prevout_hash'] == "\x00"*32:
            print 'in\t' + txn['hash'] + '\tcoinbase\t' + dt 
          else:
            pk = extract_public_key(txIn['scriptSig'])
            print 'in\t' + txn['hash'] + '\t' + long_hex(txIn['prevout_hash'][::-1]) + '\t' + str(txIn['prevout_n']) + '\t' + pk + '\t' + dt 
        index = 0
        for txOut in txn['txOut']:
          pk = extract_public_key(txOut['scriptPubKey'])
          print 'out\t' + txn['hash'] + '\t' + str(index) + '\t' + pk + '\t' + str(txOut['value']/1.0e8) + '\t' + dt 
          index += 1
      except:
        pass
    return True
  scan_blocks(datadir, db_env, for_each_block)
  db_env.close()
Beispiel #3
0
def scan_blocks(datadir, db_env, callback_fn):
  """ Scan through blocks, from last through genesis block,
      calling callback_fn(block_data) for each.
      callback_fn should return False if scanning should
      stop, True if it should continue.
      Returns last block_data scanned.
  """
  db = _open_blkindex(db_env)

  kds = BCDataStream()
  vds = BCDataStream()
  
  # Read the hashBestChain record:
  cursor = db.cursor()
  (key, value) = cursor.set_range("\x0dhashBestChain")
  vds.write(value)
  hashBestChain = vds.read_bytes(32)

  block_data = read_block(cursor, hashBestChain)

  while callback_fn(block_data):
    if block_data['nHeight'] == 0:
      break;
    block_data = read_block(cursor, block_data['hashPrev'])
  return block_data
Beispiel #4
0
def search_blocks(datadir, db_env, pattern):
  """ Dump a block given block number (== height, genesis block is 0)
  """
  db = _open_blkindex(db_env)
  kds = BCDataStream()
  vds = BCDataStream()
  
  # Read the hashBestChain record:
  cursor = db.cursor()
  (key, value) = cursor.set_range("\x0dhashBestChain")
  vds.write(value)
  hashBestChain = vds.read_bytes(32)
  block_data = read_block(cursor, hashBestChain)

  if pattern == "NONSTANDARD_CSCRIPTS": # Hack to look for non-standard transactions
    search_odd_scripts(datadir, cursor, block_data)
    return

  while True:
    block_string = _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'],
                               block_data['hash256'], block_data['hashNext'], False)
    
    if re.search(pattern, block_string) is not None:
      print "MATCH: Block height: "+str(block_data['nHeight'])
      print block_string

    if block_data['nHeight'] == 0:
      break
    block_data = read_block(cursor, block_data['hashPrev'])
Beispiel #5
0
def check_block_chain(db_env):
  """ Make sure hashPrev/hashNext pointers are consistent through block chain """
  db = _open_blkindex(db_env)

  kds = BCDataStream()
  vds = BCDataStream()
  
  # Read the hashBestChain record:
  cursor = db.cursor()
  (key, value) = cursor.set_range("\x0dhashBestChain")
  vds.write(value)
  hashBestChain = vds.read_bytes(32)

  back_blocks = []

  block_data = read_block(cursor, hashBestChain)

  while block_data['nHeight'] > 0:
    back_blocks.append( (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext']) )
    block_data = read_block(cursor, block_data['hashPrev'])

  back_blocks.append( (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext']) )
  genesis_block = block_data
  
  print("check block chain: genesis block merkle hash is: %s"%(block_data['hashMerkle'][::-1].encode('hex_codec')))

  while block_data['hashNext'] != ('\0'*32):
    forward = (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext'])
    back = back_blocks.pop()
    if forward != back:
      print("Forward/back block mismatch at height %d!"%(block_data['nHeight'],))
      print(" Forward: "+str(forward))
      print(" Back: "+str(back))
    block_data = read_block(cursor, block_data['hashNext'])
Beispiel #6
0
 def process_tx(self):
     hash = self.tx
     tx_broadcast = dict(hash=hash, value=0);
     logging.info("processing tx hash: "+hash)
     template = self.daemon.conn.proxy.getblocktemplate()
     txns = template["transactions"];
     txdata = None
     for tx in txns:
         if tx["hash"] == hash:
             logging.info("tx found in mempool")
             txdata = tx["data"]
             break
     if txdata:
         raw = BCDataStream()
         raw.write(txdata.decode('hex_codec'))
         tx = parse_Transaction(raw)
         for out in tx["txOut"]:
             tx_broadcast["value"] += out["value"] 
     else:
         logging.info("unable to find tx in mempool")
         try:
             tx = self.daemon.conn.gettransaction(hash)
             tx = tx.transaction[0]
             logging.debug(tx)
             for out in tx["outpoints"]:
                 tx_broadcast["value"] += long(out["value"])
         except bitcoinrpc.exceptions.InvalidAddressOrKey:
             logging.info("tx not found in blockchain")
             sys.exit(1)
     date = datetime.datetime.fromtimestamp(tx["time"]).replace(tzinfo=tzlocal())
     tx_broadcast["time"] = date.strftime('%Y-%m-%d %H:%M:%S%z')
     tx_broadcast["value"] = format(tx_broadcast["value"] / 1e6,'.6f')
     self.txnotify.post(tx_broadcast)
Beispiel #7
0
def _dump_tx(datadir, tx_hash, tx_pos):
  blockfile = open(os.path.join(datadir, "blk%04d.dat"%(tx_pos[0],)), "rb")
  ds = BCDataStream()
  ds.map_file(blockfile, tx_pos[2])
  d = parse_Transaction(ds)
  print deserialize_Transaction(d)
  ds.close_file()
  blockfile.close()
Beispiel #8
0
def _dump_tx(datadir, tx_hash, tx_pos):
  BLOCK_HEADER_SIZE = 80
  blockfile = open(os.path.join(datadir, "blocks","blk%05d.dat"%(tx_pos[0],)), "rb")
  ds = BCDataStream()
  ds.map_file(blockfile, tx_pos[1]+BLOCK_HEADER_SIZE+tx_pos[2])
  tx = parse_Transaction(ds)
  tx['hash'] = tx_hash[::-1]
  ds.close_file()
  blockfile.close()
  return tx
Beispiel #9
0
def _dump_block(datadir, nFile, nBlockPos, blkhash):
  blockfile = open(os.path.join(datadir,"blocks","blk%05d.dat"%(nFile,)), "rb")
  ds = BCDataStream()
  ds.map_file(blockfile, nBlockPos)
  block_start = ds.read_cursor
  block = parse_Block(ds)
  block_end = ds.read_cursor
  block['blk_size'] = (block_end - block_start)
  ds.close_file()
  blockfile.close()
  return block
def main():
  import optparse
  parser = optparse.OptionParser(usage="%prog [options]")
  parser.add_option("--datadir", dest="datadir", default=None,
                    help="Look for files here (defaults to bitcoin default)")
  parser.add_option("--regex", dest="lookfor", default="/P2SH/",
                    help="Look for string/regular expression (default: %default)")
  parser.add_option("--n", dest="howmany", default=999999, type="int",
                    help="Look back this many blocks (default: all)")
  parser.add_option("--start", dest="start", default=0, type="int",
                    help="Skip this many blocks to start (default: 0)")
  parser.add_option("--verbose", dest="verbose", default=False, action="store_true",
                    help="Print blocks that match")
  (options, args) = parser.parse_args()

  if options.datadir is None:
    db_dir = determine_db_dir()
  else:
    db_dir = options.datadir

  try:
    db_env = create_env(db_dir)
  except DBNoSuchFileError:
    logging.error("Couldn't open " + db_dir)
    sys.exit(1)

  blockfile = open(os.path.join(db_dir, "blk%04d.dat"%(1,)), "rb")
  block_datastream = BCDataStream()
  block_datastream.map_file(blockfile, 0)

  results = defaultdict(int)

  def count_matches(block_data):
    block_datastream.seek_file(block_data['nBlockPos'])
    data = parse_Block(block_datastream)
    coinbase = data['transactions'][0]
    scriptSig = coinbase['txIn'][0]['scriptSig']
    if results['skipped'] < options.start:
      results['skipped'] += 1
    else:
      results['checked'] += 1
      if re.search(options.lookfor, scriptSig) is not None:
        results['matched'] += 1
        if options.verbose: print("Block %d : %s"%(block_data['nHeight'], scriptSig.encode('string_escape')) )

    results['searched'] += 1
    return results['searched'] < options.howmany

  scan_blocks(db_dir, db_env, count_matches)

  db_env.close()

  percent = (100.0*results['matched'])/results['checked']
  print("Found %d matches in %d blocks (%.1f percent)"%(results['matched'], results['checked'], percent))
Beispiel #11
0
def sendbitcoin(address, amount=0, comment="", comment_to=""):
    txid = sendtoaddress(address, amount, comment, comment_to)
    if txid['result']:
        _raw = getrawtransaction(txid['result'])
        if _raw['result']:
            ds = BCDataStream()
            ds.write(binascii.unhexlify(_raw['result']))
            _raw['result'] = deserialize.deserialize_TransactionRaw(deserialize.parse_Transaction(ds))
        return _raw
    else:
        if txid['error']['code']==-4:
            txid['error']['message']="Insufficient funds"
    return txid
Beispiel #12
0
def _dump_block(datadir, nFile, nBlockPos, hash256, hashNext, do_print=True):
    blockfile = open(os.path.join(datadir, "blk%04d.dat" % (nFile,)), "rb")
    ds = BCDataStream()
    ds.map_file(blockfile, nBlockPos)
    d = parse_Block(ds)
    block_string = deserialize_Block(d)
    ds.close_file()
    blockfile.close()
    if do_print:
        print "BLOCK " + long_hex(hash256[::-1])
        print "Next block: " + long_hex(hashNext[::-1])
        print block_string
    return block_string
Beispiel #13
0
def main():
  import optparse
  parser = optparse.OptionParser(usage="%prog [options]")
  parser.add_option("--datadir", dest="datadir", default=None,
                    help="Look for files here (defaults to bitcoin default)")
  (options, args) = parser.parse_args()

  if options.datadir is None:
    db_dir = determine_db_dir()
  else:
    db_dir = options.datadir

  try:
    db_env = create_env(db_dir)
  except DBNoSuchFileError:
    logging.error("Couldn't open " + db_dir)
    sys.exit(1)

  blockfile = open(os.path.join(db_dir, "blk%04d.dat"%(1,)), "rb")
  block_datastream = BCDataStream()
  block_datastream.map_file(blockfile, 0)

  n_transactions = { }
  v_transactions = { }
  def gather_stats(block_data):
    block_datastream.seek_file(block_data['nBlockPos'])
    data = parse_Block(block_datastream)
    block_date = date.fromtimestamp(data['nTime'])
    key = "%d-%02d"%(block_date.year, block_date.month)
    for txn in data['transactions'][1:]:
      for txout in txn['txOut']:
        if key in n_transactions:
          n_transactions[key] += 1
          v_transactions[key] += txout['value'] 
        else:
          n_transactions[key] = 1
          v_transactions[key] = txout['value'] 
    return True

  scan_blocks(db_dir, db_env, gather_stats)

  db_env.close()

  keys = n_transactions.keys()
  keys.sort()
  for k in keys:
    v = v_transactions[k]/1.0e8
    print "%s,%d,%.2f"%(k, n_transactions[k], v)
def main():
    import optparse

    parser = optparse.OptionParser(usage="%prog [options]")
    parser.add_option(
        "--datadir", dest="datadir", default=None, help="Look for files here (defaults to bitcoin default)"
    )
    (options, args) = parser.parse_args()

    if options.datadir is None:
        db_dir = determine_db_dir()
    else:
        db_dir = options.datadir

    try:
        db_env = create_env(db_dir)
    except DBNoSuchFileError:
        logging.error("Couldn't open " + db_dir)
        sys.exit(1)

    blockfile = open(os.path.join(db_dir, "blk%04d.dat" % (1,)), "rb")
    block_datastream = BCDataStream()
    block_datastream.map_file(blockfile, 0)

    def gather(block_data):
        block_datastream.seek_file(block_data["nBlockPos"])
        data = parse_Block(block_datastream)
        height = block_data["nHeight"]
        coinbase = data["transactions"][0]
        scriptSig = coinbase["txIn"][0]["scriptSig"]
        if len(scriptSig) < 4:
            return True
        (n,) = struct.unpack_from("<I", scriptSig[0:4])
        if n < 6 * 24 * 365.25 * 100:  # 200 years of blocks:
            print("%d: %d (%s)" % (height, n, approx_date(n)))

        if ord(scriptSig[0]) == 0x03:
            (n,) = struct.unpack_from("<I", scriptSig[1:4] + "\0")
            if n < 6 * 24 * 365.25 * 100:  # 200 years of blocks:
                print("%d: PUSH %d (%s)" % (height, n, approx_date(n)))

        return True

    scan_blocks(db_dir, db_env, gather)

    db_env.close()
Beispiel #15
0
 def get_tx(self,txhash,skip=0):
     # validation txhash here
     txhash = txhash.lower()
     if not re.match(r'^[a-f0-9]{64}$',txhash):
         return {"error" : "invalid transaction hash format"}
     try:
         print "trying ppcoind"
         tx = self.conn.gettransaction(txhash)
         confirmations = tx.confirmations;
         tx = tx.transaction[0]
         del tx['coindays']
         tx['confirmations'] = confirmations
         for out in tx["outpoints"]:
             out["value"] = format(int(out["value"]) / 1e6,'.6f')
         for inp in tx["inpoints"]:
             inp["value"] = format(int(inp["value"]) / 1e6,'.6f')
         tx['time'] = datetime.datetime.utcfromtimestamp(tx["time"]).strftime("%Y-%m-%d %H:%M:%S+0000")
         return tx
     except bitcoinrpc.exceptions.InvalidAddressOrKey:
         print "checking elsewhere";
     template = self.conn.proxy.getblocktemplate()
     txns = template["transactions"];
     txdata = None
     for tx in txns:
         if tx["hash"] == txhash:
             txdata = tx["data"]
             break
     if txdata:
         raw = BCDataStream()
         raw.write(txdata.decode('hex_codec'))
         tx = parse_Transaction(raw)
         dtx = deserialize_Transaction_json(tx)
         dtx["confirmations"] = 0
         dtx["txid"] = txhash;
         dtx['time'] = datetime.datetime.utcfromtimestamp(tx["time"]).strftime("%Y-%m-%d %H:%M:%S+0000")
         #print dtx
         for inp in dtx["inpoints"]:
             old_tx = self.get_tx(inp["previoustx"])
             #print old_tx
             inp['value'] = old_tx['outpoints'][inp["previoustxindex"]]['value']
             inp['scriptpubkey'] = old_tx['outpoints'][inp["previoustxindex"]]['scriptpubkey']
             inp['peercoinaddress'] = old_tx['outpoints'][inp["previoustxindex"]]['peercoinaddress']
         return dtx;
     cherrypy.response.status = 500
     return {'error' : 'tx not found'}
Beispiel #16
0
def _read_block(db, blkhash):
  key_prefix = "b"+(blkhash.decode('hex_codec')[::-1])
  cursor = db.iterator(prefix=key_prefix)
  (key, value) = cursor.next()
  vds = BCDataStream()
  vds.clear(); vds.write(value)
  block_data = _parse_block_index(vds)

  print block_data

  if block_data['nStatus'] & 8 == False:
    raise 'no block data, maybe data is downloaded?'
    return
  
  block = _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'], blkhash)
  block['hash256'] = blkhash
  block['nHeight'] = block_data['nHeight']
  return block
Beispiel #17
0
class CachedBlockFile(object):
  def __init__(self, db_dir):
    self.datastream = None
    self.file = None
    self.n = None
    self.db_dir = db_dir

  def get_stream(self, n):
    if self.n == n:
      return self.datastream
    if self.datastream is not None:
      self.datastream.close_file()
      self.file.close()
    self.n = n
    self.file = open(os.path.join(self.db_dir, "blk%04d.dat"%(n,)), "rb")
    self.datastream = BCDataStream()
    self.datastream.map_file(self.file, 0)
    return self.datastream
Beispiel #18
0
 def get_stream(self, n):
   if self.n == n:
     return self.datastream
   if self.datastream is not None:
     self.datastream.close_file()
     self.file.close()
   self.n = n
   self.file = open(os.path.join(self.db_dir, "blk%04d.dat"%(n,)), "rb")
   self.datastream = BCDataStream()
   self.datastream.map_file(self.file, 0)
   return self.datastream
Beispiel #19
0
def dump_block_n(datadir, db_env, block_number):
    """ Dump a block given block number (== height, genesis block is 0)
  """
    db = _open_blkindex(db_env)

    kds = BCDataStream()
    vds = BCDataStream()

    # Read the hashBestChain record:
    cursor = db.cursor()
    (key, value) = cursor.set_range("\x0dhashBestChain")
    vds.write(value)
    hashBestChain = vds.read_bytes(32)

    block_data = read_block(cursor, hashBestChain)

    while block_data["nHeight"] > block_number:
        block_data = read_block(cursor, block_data["hashPrev"])

    print "Block height: " + str(block_data["nHeight"])
    _dump_block(datadir, block_data["nFile"], block_data["nBlockPos"], block_data["hash256"], block_data["hashNext"])
Beispiel #20
0
def _dump_block(datadir, nFile, nBlockPos, hash256, hashNext, do_print=True, print_raw_tx=False, print_json=False):
  blockfile = open(os.path.join(datadir, "blk%04d.dat"%(nFile,)), "rb")
  ds = BCDataStream()
  ds.map_file(blockfile, nBlockPos)
  d = parse_Block(ds)
  block_string = deserialize_Block(d, print_raw_tx)
  ds.close_file()
  blockfile.close()
  if do_print:
    print "BLOCK "+long_hex(hash256[::-1])
    print "Next block: "+long_hex(hashNext[::-1])
    print block_string
  elif print_json:
    import json
    print json.dumps({
                        'version': d['version'],
                        'previousblockhash': d['hashPrev'][::-1].encode('hex'),
                        'transactions' : [ tx_hex['__data__'].encode('hex') for tx_hex in d['transactions'] ],
                        'time' : d['nTime'],
                        'bits' : hex(d['nBits']).lstrip("0x"),
                        'nonce' : d['nNonce']
                      })

  return block_string
Beispiel #21
0
 def serialize_transaction(chain, tx):
     ds = BCDataStream.BCDataStream()
     chain.ds_serialize_transaction(ds, tx)
     return ds.input
Beispiel #22
0
def dump_transaction(datadir, db_env, tx_id):
  """ Dump a transaction, given hexadecimal tx_id-- either the full ID
      OR a short_hex version of the id.
  """
  db = DB(db_env)
  try:
    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
  except DBError:
    r = True

  if r is not None:
    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
    sys.exit(1)

  kds = BCDataStream()
  vds = BCDataStream()

  n_tx = 0
  n_blockindex = 0

  key_prefix = "\x02tx"+(tx_id[-4:].decode('hex_codec')[::-1])
  cursor = db.cursor()
  (key, value) = cursor.set_range(key_prefix)

  while key.startswith(key_prefix):
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()
    hash256 = (kds.read_bytes(32))
    hash_hex = long_hex(hash256[::-1])
    version = vds.read_uint32()
    tx_pos = _read_CDiskTxPos(vds)
    if (hash_hex.startswith(tx_id) or short_hex(hash256[::-1]).startswith(tx_id)):
      _dump_tx(datadir, hash256, tx_pos)

    (key, value) = cursor.next()

  db.close()
Beispiel #23
0
def update_wallet(db, type, data):
  """Write a single item to the wallet.
  db must be open with writable=True.
  type and data are the type code and data dictionary as parse_wallet would
  give to item_callback.
  data's __key__, __value__ and __type__ are ignored; only the primary data
  fields are used.
  """
  d = data
  kds = BCDataStream()
  vds = BCDataStream()

  # Write the type code to the key
  kds.write_string(type)
  vds.write("")             # Ensure there is something

  try:
    if type == "tx":
      raise NotImplementedError("Writing items of type 'tx'")
      kds.write(d['tx_id'])
      #d.update(parse_WalletTx(vds))
    elif type == "name":
      kds.write(d['hash'])
      vds.write(d['name'])
    elif type == "version":
      vds.write_uint32(d['version'])
    elif type == "setting":
      raise NotImplementedError("Writing items of type 'setting'")
      kds.write_string(d['setting'])
      #d['value'] = parse_setting(d['setting'], vds)
    elif type == "key":
      kds.write_string(d['public_key'])
      vds.write_string(d['private_key'])
    elif type == "wkey":
      kds.write_string(d['public_key'])
      vds.write_string(d['private_key'])
      vds.write_int64(d['created'])
      vds.write_int64(d['expires'])
      vds.write_string(d['comment'])
    elif type == "ckey":
      kds.write_string(d['public_key'])
      kds.write_string(d['crypted_key'])
    elif type == "mkey":
      kds.write_int32(d['nID'])
      vds.write_string(d['crypted_key'])
      vds.write_string(d['salt'])
      vds.write_int32(d['nDeriveIterations'])
      vds.write_int32(d['nDerivationMethod'])
      vds.write_string(d['vchOtherDerivationParameters'])
    elif type == "defaultkey":
      vds.write_string(d['key'])
    elif type == "pool":
      kds.write_int64(d['n'])
      vds.write_int32(d['nVersion'])
      vds.write_int64(d['nTime'])
      vds.write_string(d['public_key'])
    elif type == "acc":
      kds.write_string(d['account'])
      vds.write_int32(d['nVersion'])
      vds.write_string(d['public_key'])
    elif type == "acentry":
      kds.write_string(d['account'])
      kds.write_uint64(d['n'])
      vds.write_int32(d['nVersion'])
      vds.write_int64(d['nCreditDebit'])
      vds.write_int64(d['nTime'])
      vds.write_string(d['otherAccount'])
      vds.write_string(d['comment'])
    elif type == "bestblock":
      vds.write_int32(d['nVersion'])
      vds.write_compact_size(len(d['hashes']))
      for h in d['hashes']:
        vds.write(h)
    else:
      print "Unknown key type: "+type

    # Write the key/value pair to the database
    db.put(kds.input, vds.input)

  except Exception, e:
    print("ERROR writing to wallet.dat, type %s"%type)
    print("data dictionary: %r"%data)
Beispiel #24
0
def dump_accounts(db_env):
  db = open_wallet(db_env)

  kds = BCDataStream()
  vds = BCDataStream()

  accounts = set()

  for (key, value) in db.items():
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()

    if type == "acc":
      accounts.add(kds.read_string())
    elif type == "name":
      accounts.add(vds.read_string())
    elif type == "acentry":
      accounts.add(kds.read_string())
      # Note: don't need to add otheraccount, because moves are
      # always double-entry

  for name in sorted(accounts):
    print(name)

  db.close()
Beispiel #25
0
def parse_wallet(db, item_callback):
  kds = BCDataStream()
  vds = BCDataStream()

  for (key, value) in db.items():
    d = { }

    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    try:
      type = kds.read_string()

      d["__key__"] = key
      d["__value__"] = value
      d["__type__"] = type

    except Exception, e:
      print("ERROR attempting to read data from wallet.dat, type %s"%type)
      continue

    try:
      if type == "tx":
        d["tx_id"] = kds.read_bytes(32)
        d.update(parse_WalletTx(vds))
      elif type == "name":
        d['hash'] = kds.read_string()
        d['name'] = vds.read_string()
      elif type == "version":
        d['version'] = vds.read_uint32()
      elif type == "setting":
        d['setting'] = kds.read_string()
        d['value'] = parse_setting(d['setting'], vds)
      elif type == "key":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "wkey":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
        d['created'] = vds.read_int64()
        d['expires'] = vds.read_int64()
        d['comment'] = vds.read_string()
      elif type == "ckey":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "mkey":
        d['nID'] = kds.read_int32()
        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
        d['salt'] = vds.read_bytes(vds.read_compact_size())
        d['nDerivationMethod'] = vds.read_int32()
        d['nDeriveIterations'] = vds.read_int32()
        d['vchOtherDerivationParameters'] = vds.read_bytes(vds.read_compact_size())
      elif type == "defaultkey":
        d['key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "pool":
        d['n'] = kds.read_int64()
        d['nVersion'] = vds.read_int32()
        d['nTime'] = vds.read_int64()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acc":
        d['account'] = kds.read_string()
        d['nVersion'] = vds.read_int32()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acentry":
        d['account'] = kds.read_string()
        d['n'] = kds.read_uint64()
        d['nVersion'] = vds.read_int32()
        d['nCreditDebit'] = vds.read_int64()
        d['nTime'] = vds.read_int64()
        d['otherAccount'] = vds.read_string()
        d['comment'] = vds.read_string()
      elif type == "bestblock":
        d['nVersion'] = vds.read_int32()
        d.update(parse_BlockLocator(vds))
      elif type == "cscript":
        d['scriptHash'] = kds.read_bytes(20)
        d['script'] = vds.read_bytes(vds.read_compact_size())
      else:
        print "Skipping item of type "+type
        continue
      
      item_callback(type, d)

    except Exception, e:
      print("ERROR parsing wallet.dat, type %s"%type)
      print("key data in hex: %s"%key.encode('hex_codec'))
      print("value data in hex: %s"%value.encode('hex_codec'))
Beispiel #26
0
def main():
  import optparse
  parser = optparse.OptionParser(usage="%prog [options]")
  parser.add_option("--datadir", dest="datadir", default=None,
                    help="Look for files here (defaults to bitcoin default)")
  parser.add_option("--week", dest="week", default=False,
                    action="store_true",
                    help="Dump day-by-day for the last week's worth of blocks")
  (options, args) = parser.parse_args()

  if options.datadir is None:
    db_dir = determine_db_dir()
  else:
    db_dir = options.datadir

  try:
    db_env = create_env(db_dir)
  except DBNoSuchFileError:
    logging.error("Couldn't open " + db_dir)
    sys.exit(1)

  blockfile = open(os.path.join(db_dir, "blk%04d.dat"%(1,)), "rb")
  block_datastream = BCDataStream()
  block_datastream.map_file(blockfile, 0)

  n_transactions = defaultdict(int)
  v_transactions = defaultdict(float)
  v_transactions_min = defaultdict(float)
  v_transactions_max = defaultdict(float)
  def gather_stats(block_data):
    block_datastream.seek_file(block_data['nBlockPos'])
    data = parse_Block(block_datastream)
    block_date = date.fromtimestamp(data['nTime'])
    key = "%d-%02d"%(block_date.year, block_date.month)
    for txn in data['transactions'][1:]:
      values = []
      for txout in txn['txOut']:
        n_transactions[key] += 1
        v_transactions[key] += txout['value'] 
        values.append(txout['value'])
      v_transactions_min[key] += min(values)
      v_transactions_max[key] += max(values)
    return True

  def gather_stats_week(block_data, lastDate):
    block_datastream.seek_file(block_data['nBlockPos'])
    data = parse_Block(block_datastream)
    block_date = date.fromtimestamp(data['nTime'])
    if block_date < lastDate:
      return False
    key = "%d-%02d-%02d"%(block_date.year, block_date.month, block_date.day)
    for txn in data['transactions'][1:]:
      values = []
      for txout in txn['txOut']:
        n_transactions[key] += 1
        v_transactions[key] += txout['value'] 
        values.append(txout['value'])
      v_transactions_min[key] += min(values)
      v_transactions_max[key] += max(values)
    return True

  if options.week:
    lastDate = date.fromordinal(date.today().toordinal()-7)
    scan_blocks(db_dir, db_env, lambda x: gather_stats_week(x, lastDate) )
  else:
    scan_blocks(db_dir, db_env, gather_stats)

  db_env.close()

  print "date,nTransactions,minBTC,maxBTC,totalBTC"

  keys = n_transactions.keys()
  keys.sort()
  for k in keys:
    v = v_transactions[k]/1.0e8
    v_min = v_transactions_min[k]/1.0e8
    v_max = v_transactions_max[k]/1.0e8
    # Columns are:
    # month n_transactions min max total
    # ... where min and max add up just the smallest or largest
    # output in each transaction; the true value of bitcoins
    # transferred will be somewhere between min and max.
    # We don't know how many are transfers-to-self, though, and
    # this will undercount multi-txout-transactions (which is good
    # right now, because they're mostly used for mining pool
    # payouts that arguably shouldn't count).
    print "%s,%d,%.2f,%.2f,%.2f"%(k, n_transactions[k], v_min, v_max, v)
Beispiel #27
0
 def serialize_block_header(chain, block):
     ds = BCDataStream.BCDataStream()
     chain.ds_serialize_block_header(ds, block)
     return ds.input
Beispiel #28
0
def dump_block(datadir, db_env, block_hash):
    """ Dump a block, given hexadecimal hash-- either the full hash
      OR a short_hex version of the it.
  """
    db = _open_blkindex(db_env)

    kds = BCDataStream()
    vds = BCDataStream()

    n_blockindex = 0

    key_prefix = "\x0ablockindex"
    cursor = db.cursor()
    (key, value) = cursor.set_range(key_prefix)

    while key.startswith(key_prefix):
        kds.clear()
        kds.write(key)
        vds.clear()
        vds.write(value)

        type = kds.read_string()
        hash256 = kds.read_bytes(32)
        hash_hex = long_hex(hash256[::-1])
        block_data = _parse_block_index(vds)

        if hash_hex.startswith(block_hash) or short_hex(hash256[::-1]).startswith(block_hash):
            print "Block height: " + str(block_data["nHeight"])
            _dump_block(datadir, block_data["nFile"], block_data["nBlockPos"], hash256, block_data["hashNext"])

        (key, value) = cursor.next()

    db.close()
Beispiel #29
0
def dump_addresses(db_env):
  db = DB(db_env)
  try:
    r = db.open("addr.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
  except DBError:
    r = True

  if r is not None:
    logging.error("Couldn't open addr.dat/main. Try quitting Bitcoin and running this again.")
    sys.exit(1)

  kds = BCDataStream()
  vds = BCDataStream()

  for (key, value) in db.items():
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()

    if type == "addr":
      d = parse_CAddress(vds)
      print(deserialize_CAddress(d))

  db.close()
Beispiel #30
0
def dump_blkindex_summary(db_env):
  db = DB(db_env)
  try:
    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
  except DBError:
    r = True

  if r is not None:
    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
    sys.exit(1)

  kds = BCDataStream()
  vds = BCDataStream()

  n_tx = 0
  n_blockindex = 0

  print("blkindex file summary:")
  for (key, value) in db.items():
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()

    if type == "tx":
      n_tx += 1
    elif type == "blockindex":
      n_blockindex += 1
    elif type == "version":
      version = vds.read_int32()
      print(" Version: %d"%(version,))
    elif type == "hashBestChain":
      hash = vds.read_bytes(32)
      print(" HashBestChain: %s"%(hash.encode('hex_codec'),))
    else:
      logging.warn("blkindex: unknown type '%s'"%(type,))
      continue

  print(" %d transactions, %d blocks."%(n_tx, n_blockindex))
  db.close()
Beispiel #31
0
def dump_transaction(datadir, db_env, tx_id):
  """ Dump a transaction, given hexadecimal tx_id-- either the full ID
      OR a short_hex version of the id.
  """
  db = DB(db_env)
  try:
    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
  except DBError:
    r = True

  if r is not None:
    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
    sys.exit(1)

  kds = BCDataStream()
  vds = BCDataStream()

  n_tx = 0
  n_blockindex = 0

  key_prefix = "\x02tx"+(tx_id[-4:].decode('hex_codec')[::-1])
  cursor = db.cursor()
  (key, value) = cursor.set_range(key_prefix)

  while key.startswith(key_prefix):
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()
    hash256 = (kds.read_bytes(32))
    hash_hex = long_hex(hash256[::-1])
    version = vds.read_uint32()
    tx_pos = _read_CDiskTxPos(vds)
    if (hash_hex.startswith(tx_id) or short_hex(hash256[::-1]).startswith(tx_id)):
      _dump_tx(datadir, hash256, tx_pos)

    (key, value) = cursor.next()

  db.close()
Beispiel #32
0
def dump_accounts(db_env):
  db = open_wallet(db_env)

  kds = BCDataStream()
  vds = BCDataStream()

  accounts = set()

  for (key, value) in db.items():
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()

    if type == "acc":
      accounts.add(kds.read_string())
    elif type == "name":
      accounts.add(vds.read_string())
    elif type == "acentry":
      accounts.add(kds.read_string())
      # Note: don't need to add otheraccount, because moves are
      # always double-entry

  for name in sorted(accounts):
    print(name)

  db.close()
Beispiel #33
0
def dump_block(datadir, db_env, block_hash, print_raw_tx=False, print_json=False):
  """ Dump a block, given hexadecimal hash-- either the full hash
      OR a short_hex version of the it.
  """
  db = _open_blkindex(db_env)

  kds = BCDataStream()
  vds = BCDataStream()

  n_blockindex = 0

  key_prefix = "\x0ablockindex"
  cursor = db.cursor()
  (key, value) = cursor.set_range(key_prefix)

  while key.startswith(key_prefix):
    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()
    hash256 = kds.read_bytes(32)
    hash_hex = long_hex(hash256[::-1])
    block_data = _parse_block_index(vds)

    if (hash_hex.startswith(block_hash) or short_hex(hash256[::-1]).startswith(block_hash)):
      if print_json == False:
          print "Block height: "+str(block_data['nHeight'])
          _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'], hash256, block_data['hashNext'], print_raw_tx=print_raw_tx)
      else:
          _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'], hash256, block_data['hashNext'], print_json=print_json, do_print=False)

    (key, value) = cursor.next()

  db.close()
Beispiel #34
0
def str_to_ds(s):
    import BCDataStream
    ds = BCDataStream.BCDataStream()
    ds.write(s)
    return ds
Beispiel #35
0
def update_wallet(db, type, data):
  """Write a single item to the wallet.
  db must be open with writable=True.
  type and data are the type code and data dictionary as parse_wallet would
  give to item_callback.
  data's __key__, __value__ and __type__ are ignored; only the primary data
  fields are used.
  """
  d = data
  kds = BCDataStream()
  vds = BCDataStream()

  # Write the type code to the key
  kds.write_string(type)
  vds.write("")             # Ensure there is something

  try:
    if type == "tx":
      raise NotImplementedError("Writing items of type 'tx'")
      kds.write(d['tx_id'])
      #d.update(parse_WalletTx(vds))
    elif type == "name":
      kds.write(d['hash'])
      vds.write(d['name'])
    elif type == "version":
      vds.write_uint32(d['version'])
    elif type == "setting":
      raise NotImplementedError("Writing items of type 'setting'")
      kds.write_string(d['setting'])
      #d['value'] = parse_setting(d['setting'], vds)
    elif type == "key":
      kds.write_string(d['public_key'])
      vds.write_string(d['private_key'])
    elif type == "wkey":
      kds.write_string(d['public_key'])
      vds.write_string(d['private_key'])
      vds.write_int64(d['created'])
      vds.write_int64(d['expires'])
      vds.write_string(d['comment'])
    elif type == "ckey":
      kds.write_string(d['public_key'])
      kds.write_string(d['crypted_key'])
    elif type == "mkey":
      kds.write_int32(d['nID'])
      vds.write_string(d['crypted_key'])
      vds.write_string(d['salt'])
      vds.write_int32(d['nDeriveIterations'])
      vds.write_int32(d['nDerivationMethod'])
      vds.write_string(d['vchOtherDerivationParameters'])
    elif type == "defaultkey":
      vds.write_string(d['key'])
    elif type == "pool":
      kds.write_int64(d['n'])
      vds.write_int32(d['nVersion'])
      vds.write_int64(d['nTime'])
      vds.write_string(d['public_key'])
    elif type == "acc":
      kds.write_string(d['account'])
      vds.write_int32(d['nVersion'])
      vds.write_string(d['public_key'])
    elif type == "acentry":
      kds.write_string(d['account'])
      kds.write_uint64(d['n'])
      vds.write_int32(d['nVersion'])
      vds.write_int64(d['nCreditDebit'])
      vds.write_int64(d['nTime'])
      vds.write_string(d['otherAccount'])
      vds.write_string(d['comment'])
    elif type == "bestblock":
      vds.write_int32(d['nVersion'])
      vds.write_compact_size(len(d['hashes']))
      for h in d['hashes']:
        vds.write(h)
    else:
      print "Unknown key type: "+type

    # Write the key/value pair to the database
    db.put(kds.input, vds.input)

  except Exception, e:
    print("ERROR writing to wallet.dat, type %s"%type)
    print("data dictionary: %r"%data)
Beispiel #36
0
def _read_tx(db, txhash):
  kds = BCDataStream()
  vds = BCDataStream()

  key_prefix = "t"+txhash
  cursor = db.iterator(prefix=key_prefix)
  (key, value) = cursor.next()
  kds.clear(); kds.write(key)
  vds.clear(); vds.write(value)

  kds.read_bytes(1)
  hash256 = (kds.read_bytes(32))
  tx_pos = _read_CDiskTxPos(vds)
  return _dump_tx(datadir, hash256, tx_pos)
Beispiel #37
0
def parse_wallet(db, item_callback):
  kds = BCDataStream()
  vds = BCDataStream()

  for (key, value) in db.items():
    d = { }

    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    try:
      type = kds.read_string()

      d["__key__"] = key
      d["__value__"] = value
      d["__type__"] = type

    except Exception, e:
      print("ERROR attempting to read data from wallet.dat, type %s"%type)
      continue

    try:
      if type == "tx":
        d["tx_id"] = kds.read_bytes(32)
        d.update(parse_WalletTx(vds))
      elif type == "name":
        d['hash'] = kds.read_string()
        d['name'] = vds.read_string()
      elif type == "version":
        d['version'] = vds.read_uint32()
      elif type == "setting":
        d['setting'] = kds.read_string()
        d['value'] = parse_setting(d['setting'], vds)
      elif type == "key":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "wkey":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
        d['created'] = vds.read_int64()
        d['expires'] = vds.read_int64()
        d['comment'] = vds.read_string()
      elif type == "ckey":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "mkey":
        d['nID'] = kds.read_int32()
        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
        d['salt'] = vds.read_bytes(vds.read_compact_size())
        d['nDerivationMethod'] = vds.read_int32()
        d['nDeriveIterations'] = vds.read_int32()
        d['vchOtherDerivationParameters'] = vds.read_bytes(vds.read_compact_size())
      elif type == "defaultkey":
        d['key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "pool":
        d['n'] = kds.read_int64()
        d['nVersion'] = vds.read_int32()
        d['nTime'] = vds.read_int64()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acc":
        d['account'] = kds.read_string()
        d['nVersion'] = vds.read_int32()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acentry":
        d['account'] = kds.read_string()
        d['n'] = kds.read_uint64()
        d['nVersion'] = vds.read_int32()
        d['nCreditDebit'] = vds.read_int64()
        d['nTime'] = vds.read_int64()
        d['otherAccount'] = vds.read_string()
        d['comment'] = vds.read_string()
      elif type == "bestblock":
        d['nVersion'] = vds.read_int32()
        d.update(parse_BlockLocator(vds))
      elif type == "cscript":
        d['scriptHash'] = kds.read_bytes(20)
        d['script'] = vds.read_bytes(vds.read_compact_size())
      else:
        print "Skipping item of type "+type
        continue
      
      item_callback(type, d)

    except Exception, e:
      print("ERROR parsing wallet.dat, type %s"%type)
      print("key data in hex: %s"%key.encode('hex_codec'))
      print("value data in hex: %s"%value.encode('hex_codec'))
Beispiel #38
0
def parse_wallet(db, item_callback):
  kds = BCDataStream()
  vds = BCDataStream()

  for (key, value) in db.items():
    d = { }

    kds.clear(); kds.write(key)
    vds.clear(); vds.write(value)

    type = kds.read_string()

    d["__key__"] = key
    d["__value__"] = value
    d["__type__"] = type

    try:
      if type == "tx":
        d["tx_id"] = kds.read_bytes(32)
        d.update(parse_WalletTx(vds))
      elif type == "name":
        d['hash'] = kds.read_string()
        d['name'] = vds.read_string()
      elif type == "version":
        d['version'] = vds.read_uint32()
      elif type == "setting":
        d['setting'] = kds.read_string()
        d['value'] = parse_setting(d['setting'], vds)
      elif type == "key":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "wkey":
        d['public_key'] = kds.read_bytes(kds.read_compact_size())
        d['private_key'] = vds.read_bytes(vds.read_compact_size())
        d['created'] = vds.read_int64()
        d['expires'] = vds.read_int64()
        d['comment'] = vds.read_string()
      elif type == "defaultkey":
        d['key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "pool":
        d['n'] = kds.read_int64()
        d['nVersion'] = vds.read_int32()
        d['nTime'] = vds.read_int64()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acc":
        d['account'] = kds.read_string()
        d['nVersion'] = vds.read_int32()
        d['public_key'] = vds.read_bytes(vds.read_compact_size())
      elif type == "acentry":
        d['account'] = kds.read_string()
        d['n'] = kds.read_uint64()
        d['nVersion'] = vds.read_int32()
        d['nCreditDebit'] = vds.read_int64()
        d['nTime'] = vds.read_int64()
        d['otherAccount'] = vds.read_string()
        d['comment'] = vds.read_string()
      else:
        print "Unknown key type: "+type
      
      item_callback(type, d)

    except Exception, e:
      print("ERROR parsing wallet.dat, type %s"%type)
      print("key data in hex: %s"%key.encode('hex_codec'))
      print("value data in hex: %s"%value.encode('hex_codec'))