import time, threading
-SQL_LIMIT=200
-
class AbeStore(Datastore_class):
def __init__(self, config):
elif args.dbtype == 'psycopg2':
args.connect_args = { 'database' : config.get('database','database') }
+ coin = config.get('server', 'coin')
+ self.addrtype = 0
+ if coin == 'litecoin':
+ print 'Litecoin settings:'
+ datadir = config.get('server','datadir')
+ print ' datadir = ' + datadir
+ args.datadir = [{"dirname":datadir,"chain":"Litecoin","code3":"LTC","address_version":"\u0030"}]
+ print ' addrtype = 48'
+ self.addrtype = 48
+
Datastore_class.__init__(self,args)
+ # Use 1 (Bitcoin) if chain_id is not sent
+ self.chain_id = self.datadirs[0]["chain_id"] or 1
+ print 'Coin chain_id = %d' % self.chain_id
+
+ self.sql_limit = int( config.get('database','limit') )
+
self.tx_cache = {}
self.bitcoind_url = 'http://%s:%s@%s:%s/' % ( config.get('bitcoind','user'), config.get('bitcoind','password'), config.get('bitcoind','host'), config.get('bitcoind','port'))
self.address_queue = Queue()
self.dblock = thread.allocate_lock()
+ self.last_tx_id = 0
+
+
+ def import_tx(self, tx, is_coinbase):
+ tx_id = super(AbeStore, self).import_tx(tx, is_coinbase)
+ self.last_tx_id = tx_id
+ return tx_id
+
#print "WARNING: missing tx_in for tx", txid
continue
- address = hash_to_address(chr(0), _hash)
+ address = hash_to_address(chr(self.addrtype), _hash)
if self.tx_cache.has_key(address):
print "cache: invalidating", address
self.tx_cache.pop(address)
#print "WARNING: missing tx_out for tx", txid
continue
- address = hash_to_address(chr(0), _hash)
+ address = hash_to_address(chr(self.addrtype), _hash)
if self.tx_cache.has_key(address):
print "cache: invalidating", address
self.tx_cache.pop(address)
ret = self.selectall(sql,params)
except:
error = True
+ traceback.print_exc(file=sys.stdout)
finally:
if lock: self.dblock.release()
JOIN txout prevout ON (txin.txout_id = prevout.txout_id)
JOIN pubkey ON (pubkey.pubkey_id = prevout.pubkey_id)
WHERE pubkey.pubkey_hash = ?
+ AND cc.chain_id = ?
AND cc.in_longest = 1
- LIMIT ? """, (dbhash,SQL_LIMIT))
+ LIMIT ? """, (dbhash, self.chain_id, self.sql_limit))
- if len(out)==SQL_LIMIT:
+ if len(out)==self.sql_limit:
raise BaseException('limit reached')
return out
JOIN txout prevout ON (txin.txout_id = prevout.txout_id)
JOIN pubkey ON (pubkey.pubkey_id = prevout.pubkey_id)
WHERE pubkey.pubkey_hash = ?
- LIMIT ? """, (dbhash,SQL_LIMIT))
+ LIMIT ? """, (dbhash,self.sql_limit))
- if len(out)==SQL_LIMIT:
+ if len(out)==self.sql_limit:
raise BaseException('limit reached')
return out
JOIN txout ON (txout.tx_id = tx.tx_id)
JOIN pubkey ON (pubkey.pubkey_id = txout.pubkey_id)
WHERE pubkey.pubkey_hash = ?
+ AND cc.chain_id = ?
AND cc.in_longest = 1
- LIMIT ? """, (dbhash,SQL_LIMIT))
+ LIMIT ? """, (dbhash, self.chain_id, self.sql_limit))
- if len(out)==SQL_LIMIT:
+ if len(out)==self.sql_limit:
raise BaseException('limit reached')
return out
JOIN txout ON (txout.tx_id = tx.tx_id)
JOIN pubkey ON (pubkey.pubkey_id = txout.pubkey_id)
WHERE pubkey.pubkey_hash = ?
- LIMIT ? """, (dbhash,SQL_LIMIT))
+ LIMIT ? """, (dbhash,self.sql_limit))
- if len(out)==SQL_LIMIT:
+ if len(out)==self.sql_limit:
raise BaseException('limit reached')
return out
rows += self.get_address_out_rows_memorypool( dbhash )
address_has_mempool = False
- current_id = self.new_id("tx")
-
for row in rows:
is_in, tx_hash, tx_id, pos, value = row
tx_hash = self.hashout_hex(tx_hash)
if tx_hash in known_tx:
continue
- # this means that pending transactions were added to the db, even if they are not returned by getmemorypool
- address_has_mempool = True
-
- # fixme: we need to detect transactions that became invalid
- if current_id - tx_id > 10000:
+ # discard transactions that are too old
+ if self.last_tx_id - tx_id > 50000:
+ print "discarding tx id", tx_id
continue
+ # this means that pending transactions were added to the db, even if they are not returned by getmemorypool
+ address_has_mempool = True
#print "mempool", tx_hash
txpoint = {
if not _hash:
#print "WARNING: missing tx_in for tx", tx_id, addr
continue
- address = hash_to_address(chr(0), _hash)
+ address = hash_to_address(chr(self.addrtype), _hash)
txinputs.append(address)
txpoint['inputs'] = txinputs
txoutputs = []
if not _hash:
#print "WARNING: missing tx_out for tx", tx_id, addr
continue
- address = hash_to_address(chr(0), _hash)
+ address = hash_to_address(chr(self.addrtype), _hash)
txoutputs.append(address)
txpoint['outputs'] = txoutputs
if row:
if not row[4]: txpoint['raw_output_script'] = row[1]
+ txpoint.pop('tx_id')
+
# cache result
# do not cache mempool results because statuses are ambiguous
if not address_has_mempool:
else:
tx_id = store.import_tx(tx, False)
store.update_tx_cache(tx_id)
+ #print tx_hash
store.commit()
def main_iteration(store):
- try:
- store.dblock.acquire()
+ with store.dblock:
store.catch_up()
store.memorypool_update()
- block_number = store.get_block_number(1)
+ block_number = store.get_block_number(store.chain_id)
+ return block_number
- except IOError:
- print "IOError: cannot reach bitcoind"
- block_number = 0
- except:
- traceback.print_exc(file=sys.stdout)
- block_number = 0
- finally:
- store.dblock.release()
- return block_number
def catch_up(store):
self.store = AbeStore(config)
self.block_number = -1
self.watched_addresses = []
+
+ # catch_up first
+ n = self.store.main_iteration()
+ print "blockchain: %d blocks"%n
+
threading.Timer(10, self.run_store_iteration).start()
def process(self, request):
result = self.store.get_status(address)
self.watch_address(address)
except BaseException, e:
- error = str(e)
+ error = str(e) + ': ' + address
+ print "error:", error
elif method == 'blockchain.address.get_history':
try:
address = params[0]
result = self.store.get_history( address )
except BaseException, e:
- error = str(e)
+ error = str(e) + ': ' + address
+ print "error:", error
elif method == 'blockchain.transaction.broadcast':
txo = self.store.send_tx(params[0])
def run_store_iteration(self):
+
+ try:
+ block_number = self.store.main_iteration()
+ except:
+ traceback.print_exc(file=sys.stdout)
+ print "terminating"
+ self.shared.stop()
+
if self.shared.stopped():
print "exit timer"
return
-
- block_number = self.store.main_iteration()
+
if self.block_number != block_number:
self.block_number = block_number
print "block number:", self.block_number
- self.push_response({ 'method':'blockchain.numblocks.subscribe', 'params':[self.block_number] })
+ self.push_response({ 'id': None, 'method':'blockchain.numblocks.subscribe', 'params':[self.block_number] })
while True:
try:
break
if addr in self.watched_addresses:
status = self.store.get_status( addr )
- self.push_response({ 'method':'blockchain.address.subscribe', 'params':[addr, status] })
+ self.push_response({ 'id': None, 'method':'blockchain.address.subscribe', 'params':[addr, status] })
threading.Timer(10, self.run_store_iteration).start()