Permalink
Browse files

Get transactions from raw block rather than getrawtx

Setting verbose=false, getblock returns raw block data including all
transactions it contains. This removes the need for getrawtransaction
rpc which requires txindex=1. It's also much faster on blocks with many
transactions.
  • Loading branch information...
dermoth committed Dec 3, 2016
1 parent 0eed296 commit 359ff6ad3bf680fd104aa42a25f7eaeca96a3526
Showing with 15 additions and 41 deletions.
  1. +15 −38 Abe/DataStore.py
  2. +0 −3 abe.conf
View
@@ -2573,9 +2573,9 @@ def catch_up(store):
def catch_up_rpc(store, dircfg):
"""
Load new blocks using RPC. Requires running *coind supporting
- getblockhash, getblock, and getrawtransaction. Bitcoind v0.8
- requires the txindex configuration option. Requires chain_id
- in the datadir table.
+ getblockhash, getblock with verbose=false, and optionally
+ getrawmempool/getrawtransaction (to load mempool tx). Requires
+ chain_id in the datadir table.
"""
chain_id = dircfg['chain_id']
if chain_id is None:
@@ -2601,6 +2601,7 @@ def catch_up_rpc(store, dircfg):
rpcport = conf.get("rpcport", chain.datadir_rpcport)
url = "http://" + rpcuser + ":" + rpcpassword + "@" + rpcconnect \
+ ":" + str(rpcport)
+ ds = BCDataStream.BCDataStream()
def rpc(func, *params):
store.rpclog.info("RPC>> %s %s", func, params)
@@ -2743,46 +2744,22 @@ def catch_up_mempool(height):
if store.offer_existing_block(hash, chain.id):
rpc_hash = get_blockhash(height + 1)
else:
- rpc_block = rpc("getblock", rpc_hash)
- assert rpc_hash == rpc_block['hash']
-
- prev_hash = \
- rpc_block['previousblockhash'].decode('hex')[::-1] \
- if 'previousblockhash' in rpc_block \
- else chain.genesis_hash_prev
-
- block = {
- 'hash': hash,
- 'version': int(rpc_block['version']),
- 'hashPrev': prev_hash,
- 'hashMerkleRoot':
- rpc_block['merkleroot'].decode('hex')[::-1],
- 'nTime': int(rpc_block['time']),
- 'nBits': int(rpc_block['bits'], 16),
- 'nNonce': int(rpc_block['nonce']),
- 'transactions': [],
- 'size': int(rpc_block['size']),
- 'height': height,
- }
-
+ # get full RPC block with "getblock <hash> False"
+ ds.write(rpc("getblock", rpc_hash, False).decode('hex'))
+ block_hash = chain.ds_block_header_hash(ds)
+ block = chain.ds_parse_block(ds)
+ assert hash == block_hash
+ block['hash'] = block_hash
+
+ # XXX Shouldn't be needed since we deserialize a valid block already
if chain.block_header_hash(chain.serialize_block_header(
block)) != hash:
raise InvalidBlock('block hash mismatch')
- for rpc_tx_hash in rpc_block['tx']:
- tx = store.export_tx(tx_hash = str(rpc_tx_hash),
- format = "binary")
- if tx is None:
- tx = get_tx(rpc_tx_hash)
- if tx is None:
- store.log.error("RPC service lacks full txindex")
- return False
-
- block['transactions'].append(tx)
-
store.import_block(block, chain = chain)
- store.imported_bytes(block['size'])
- rpc_hash = rpc_block.get('nextblockhash')
+ store.imported_bytes(ds.read_cursor)
+ ds.clear()
+ rpc_hash = get_blockhash(height + 1)
height += 1
if rpc_hash is None:
View
@@ -327,9 +327,6 @@
#
# * HTTP access to bitcoind (SSL is not yet supported.)
#
-# * Bitcoin 0.8 or newer with the -txindex option. (Run bitcoind
-# once with -reindex if you previously ran it without -txindex.)
-#
# * A "datadir" option with "chain":"Bitcoin" (or other chain
# name)
#

0 comments on commit 359ff6a

Please sign in to comment.