Skip to content
This repository has been archived by the owner on Jul 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #95 from CounterpartyXCP/develop
Browse files Browse the repository at this point in the history
1.1.0
  • Loading branch information
Robby Dermody committed Feb 6, 2015
2 parents cd11ccf + 488330b commit e1ca78f
Show file tree
Hide file tree
Showing 40 changed files with 370 additions and 1,805 deletions.
30 changes: 6 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
counterblockd
==============

Provides extended API functionality over counterpartyd (such as market information, asset history, etc).
Works alongside `counterpartyd`.
Provides extended API functionality over `counterparty-server` (such as market information, asset history, etc).
Works alongside `counterparty`.

Automatic Installation
------------------------

Please see the [Setting up a Federated Node](http://counterparty.io/docs/build-system/federated-node/) guide
Please see the [Setting up a Federated Node](http://counterparty.io/docs/federated-node/) guide
(under the *"Node Setup"* section) for a script that will set counterblockd up for you, automatically. When prompted
for the node type, choose "counterblockd basic".
for the node type, choose "counterblock basic".

Manual Installation on Ubuntu
Manual Installation (Linux Only)
---------------------------------

Many of the requirements for `counterblockd` are similar to those for `counterpartyd`, so if you used the
[counterpartyd installer](https://github.com/CounterpartyXCP/counterpartyd_build) to install, you already
have many requirements installed.

The first extra thing would be to install MongoDB:

```bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/10gen.list
sudo apt-get update
sudo apt-get install mongodb-10gen
```

The last couple can be added by running (from the `counterblockd` directory):

```bash
sudo apt-get install python-pip cython libxml2-dev libxslt1-dev python-dev
sudo pip install -r pip-requirements.txt
```
`sudo pip install counterblock`
9 changes: 9 additions & 0 deletions counterblock/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import os, sys

def server_main():
from counterblock import server
server.main()

def armory_utxsvr_main():
from counterblock import armory_utxsvr
armory_utxsvr.main()
7 changes: 5 additions & 2 deletions armory_utxsvr.py → counterblock/armory_utxsvr.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ def run(self):
print 'New blocks: %d (top: %d)' % (newTop-prevTop, newTop)
time.sleep(1.0) # check every 1 second

if __name__ == '__main__':
def main():
print("**** Starting up ...")
parser = argparse.ArgumentParser(description='Armory offline transaction generator daemon')
parser.add_argument('--testnet', action='store_true', help='Run for testnet')
args = parser.parse_args()
btcdir = "/home/xcp/.bitcoin%s/" % ('-testnet/testnet3' if args.testnet else '')
btcdir = "/home/xcp/.bitcoin" + ("/testnet3" if args.testnet else '')

print("**** Initializing armory ...")
#require armory to be installed, adding the configured armory path to PYTHONPATH
Expand All @@ -102,3 +102,6 @@ def run(self):
print("**** Initializing Flask (HTTP) server ...")
app.run(host="127.0.0.1", port=ARMORY_UTXSVR_PORT_MAINNET if not args.testnet else ARMORY_UTXSVR_PORT_TESTNET, threaded=True)
print("**** Ready to serve ...")

if __name__ == '__main__':
main()
File renamed without changes.
6 changes: 3 additions & 3 deletions lib/blockchain.py → counterblock/lib/blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import bitcoin.rpc as bitcoin_rpc
from pycoin import encoding

from lib import config, util
from counterblock.lib import config, util

D = decimal.Decimal
decimal.getcontext().prec = 8
Expand Down Expand Up @@ -61,7 +61,7 @@ def pubkey_to_address(pubkey_hex):
def bitcoind_rpc(command, params):
return util.call_jsonrpc_api(command,
params = params,
endpoint = config.BACKEND_RPC,
endpoint = config.BACKEND_URL_NOAUTH,
auth = config.BACKEND_AUTH,
abort_on_error = True)['result']

Expand Down Expand Up @@ -199,7 +199,7 @@ def get_cached_batch_raw_transactions(tx_hashes):

if config.TESTNET:
bitcoinlib.SelectParams('testnet')
proxy = bitcoin_rpc.Proxy(service_url=config.BACKEND_RPC_URL)
proxy = bitcoin_rpc.Proxy(service_url=config.BACKEND_URL)
return proxy._batch(call_list)

# TODO: use scriptpubkey_to_address()
Expand Down
68 changes: 34 additions & 34 deletions lib/blockfeed.py → counterblock/lib/blockfeed.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import pymongo
import gevent

from lib import config, util, blockchain, cache, database
from lib.processor import MessageProcessor, BlockProcessor, CaughtUpProcessor
from counterblock.lib import config, util, blockchain, cache, database
from counterblock.lib.processor import MessageProcessor, BlockProcessor, CaughtUpProcessor

D = decimal.Decimal
logger = logging.getLogger(__name__)
Expand All @@ -25,20 +25,20 @@ def fuzzy_is_caught_up():
"""We don't want to give users 525 errors or login errors if counterblockd/counterpartyd is in the process of
getting caught up, but we DO if counterblockd is either clearly out of date with the blockchain, or reinitializing its database"""
return config.state['caught_up'] \
or ( config.state['cpd_backend_block_index']
and config.state['my_latest_block']['block_index'] >= config.state['cpd_backend_block_index'] - 1
or ( config.state['cp_backend_block_index']
and config.state['my_latest_block']['block_index'] >= config.state['cp_backend_block_index'] - 1
)

def process_cpd_blockfeed(zmq_publisher_eventfeed):
def process_cp_blockfeed(zmq_publisher_eventfeed):
config.LATEST_BLOCK_INIT = {'block_index': config.BLOCK_FIRST, 'block_time': None, 'block_hash': None}
zmq_publisher_eventfeed = config.ZMQ_PUBLISHER_EVENTFEED

#initialize state
config.state['cur_block'] = {'block_index': 0, } #block being currently processed
config.state['my_latest_block'] = {'block_index': 0 } #last block that was successfully processed by counterblockd
config.state['last_message_index'] = -1 #initialize (last processed message index)
config.state['cpd_latest_block_index'] = 0 #last block that was successfully processed by counterparty
config.state['cpd_backend_block_index'] = 0 #the latest block height as reported by the cpd blockchain backend
config.state['cp_latest_block_index'] = 0 #last block that was successfully processed by counterparty
config.state['cp_backend_block_index'] = 0 #the latest block height as reported by the cpd blockchain backend
config.state['caught_up_started_events'] = False
#^ set after we are caught up and start up the recurring events that depend on us being caught up with the blockchain

Expand Down Expand Up @@ -132,11 +132,11 @@ def parse_block(block_data):

logger.info("Block: %i of %i [message height=%s]" % (
config.state['my_latest_block']['block_index'],
config.state['cpd_backend_block_index'] \
if config.state['cpd_backend_block_index'] else '???',
config.state['cp_backend_block_index'] \
if config.state['cp_backend_block_index'] else '???',
config.state['last_message_index'] if config.state['last_message_index'] != -1 else '???'))

if config.state['cpd_latest_block_index'] - cur_block_index < config.MAX_REORG_NUM_BLOCKS: #only when we are near the tip
if config.state['cp_latest_block_index'] - cur_block_index < config.MAX_REORG_NUM_BLOCKS: #only when we are near the tip
clean_mempool_tx()

#grab our stored preferences, and rebuild the database if necessary
Expand Down Expand Up @@ -170,7 +170,7 @@ def parse_block(block_data):
while True:
if not autopilot or autopilot_runner == 0:
try:
cpd_running_info = util.jsonrpc_api("get_running_info", abort_on_error=True)['result']
cp_running_info = util.jsonrpc_api("get_running_info", abort_on_error=True)['result']
except Exception, e:
logger.warn("Cannot contact counterpartyd get_running_info: %s" % e)
time.sleep(3)
Expand All @@ -185,51 +185,51 @@ def parse_block(block_data):
or app_config['counterpartyd_db_version_minor'] is None \
or app_config['counterpartyd_running_testnet'] is None:
updatePrefs = True
elif cpd_running_info['version_major'] != app_config['counterpartyd_db_version_major']:
elif cp_running_info['version_major'] != app_config['counterpartyd_db_version_major']:
logger.warn("counterpartyd MAJOR DB version change (we built from %s, counterpartyd is at %s)."
+ " Wiping our state data." % (
app_config['counterpartyd_db_version_major'], cpd_running_info['version_major']))
app_config['counterpartyd_db_version_major'], cp_running_info['version_major']))
wipeState = True
updatePrefs = True
elif cpd_running_info['version_minor'] != app_config['counterpartyd_db_version_minor']:
elif cp_running_info['version_minor'] != app_config['counterpartyd_db_version_minor']:
logger.warn("counterpartyd MINOR DB version change (we built from %s.%s, counterpartyd is at %s.%s)."
+ " Wiping our state data." % (
app_config['counterpartyd_db_version_major'], app_config['counterpartyd_db_version_minor'],
cpd_running_info['version_major'], cpd_running_info['version_minor']))
cp_running_info['version_major'], cp_running_info['version_minor']))
wipeState = True
updatePrefs = True
elif cpd_running_info.get('running_testnet', False) != app_config['counterpartyd_running_testnet']:
elif cp_running_info.get('running_testnet', False) != app_config['counterpartyd_running_testnet']:
logger.warn("counterpartyd testnet setting change (from %s to %s). Wiping our state data." % (
app_config['counterpartyd_running_testnet'], cpd_running_info['running_testnet']))
app_config['counterpartyd_running_testnet'], cp_running_info['running_testnet']))
wipeState = True
updatePrefs = True
if wipeState:
app_config = blow_away_db()
if updatePrefs:
app_config['counterpartyd_db_version_major'] = cpd_running_info['version_major']
app_config['counterpartyd_db_version_minor'] = cpd_running_info['version_minor']
app_config['counterpartyd_running_testnet'] = cpd_running_info['running_testnet']
app_config['counterpartyd_db_version_major'] = cp_running_info['version_major']
app_config['counterpartyd_db_version_minor'] = cp_running_info['version_minor']
app_config['counterpartyd_running_testnet'] = cp_running_info['running_testnet']
config.mongo_db.app_config.update({}, app_config)
#reset my latest block record
config.state['my_latest_block'] = config.LATEST_BLOCK_INIT
config.state['caught_up'] = False #You've Come a Long Way, Baby

#work up to what block counterpartyd is at
config.state['cpd_latest_block_index'] = cpd_running_info['last_block']['block_index'] \
if isinstance(cpd_running_info['last_block'], dict) else cpd_running_info['last_block']
config.state['cpd_backend_block_index'] = cpd_running_info['bitcoin_block_count']
if not config.state['cpd_latest_block_index']:
config.state['cp_latest_block_index'] = cp_running_info['last_block']['block_index'] \
if isinstance(cp_running_info['last_block'], dict) else cp_running_info['last_block']
config.state['cp_backend_block_index'] = cp_running_info['bitcoin_block_count']
if not config.state['cp_latest_block_index']:
logger.warn("counterpartyd has no last processed block (probably is reparsing or was just restarted)."
+ " Waiting 3 seconds before trying again...")
time.sleep(3)
continue
assert config.state['cpd_latest_block_index']
if config.state['my_latest_block']['block_index'] < config.state['cpd_latest_block_index']:
assert config.state['cp_latest_block_index']
if config.state['my_latest_block']['block_index'] < config.state['cp_latest_block_index']:
#need to catch up
config.state['caught_up'] = False

#Autopilot and autopilot runner are redundant
if config.state['cpd_latest_block_index'] - config.state['my_latest_block']['block_index'] > 500: #we are safely far from the tip, switch to bulk-everything
if config.state['cp_latest_block_index'] - config.state['my_latest_block']['block_index'] > 500: #we are safely far from the tip, switch to bulk-everything
autopilot = True
if autopilot_runner == 0:
autopilot_runner = 500
Expand All @@ -240,37 +240,37 @@ def parse_block(block_data):
cur_block_index = config.state['my_latest_block']['block_index'] + 1
try:
block_data = cache.get_block_info(cur_block_index,
min(100, (config.state['cpd_latest_block_index'] - config.state['my_latest_block']['block_index'])))
min(100, (config.state['cp_latest_block_index'] - config.state['my_latest_block']['block_index'])))
except Exception, e:
logger.warn(str(e) + " Waiting 3 seconds before trying again...")
time.sleep(3)
continue

# clean api cache
if config.state['cpd_latest_block_index'] - cur_block_index <= config.MAX_REORG_NUM_BLOCKS: #only when we are near the tip
if config.state['cp_latest_block_index'] - cur_block_index <= config.MAX_REORG_NUM_BLOCKS: #only when we are near the tip
cache.clean_block_cache(cur_block_index)

parse_block(block_data)

elif config.state['my_latest_block']['block_index'] > config.state['cpd_latest_block_index']:
elif config.state['my_latest_block']['block_index'] > config.state['cp_latest_block_index']:
# should get a reorg message. Just to be on the safe side, prune back MAX_REORG_NUM_BLOCKS blocks
# before what counterpartyd is saying if we see this
logger.error("Very odd: Ahead of counterpartyd with block indexes! Pruning back %s blocks to be safe."
% config.MAX_REORG_NUM_BLOCKS)
config.state['my_latest_block'] = database.rollback(
config.state['cpd_latest_block_index'] - config.MAX_REORG_NUM_BLOCKS)
config.state['cp_latest_block_index'] - config.MAX_REORG_NUM_BLOCKS)
else:
#...we may be caught up (to counterpartyd), but counterpartyd may not be (to the blockchain). And if it isn't, we aren't
config.state['caught_up'] = cpd_running_info['db_caught_up']
config.state['caught_up'] = cp_running_info['db_caught_up']

#this logic here will cover a case where we shut down counterblockd, then start it up again quickly...
# in that case, there are no new blocks for it to parse, so config.state['last_message_index'] would otherwise remain 0.
# With this logic, we will correctly initialize config.state['last_message_index'] to the last message ID of the last processed block
if config.state['last_message_index'] == -1 or config.state['my_latest_block']['block_index'] == 0:
if config.state['last_message_index'] == -1:
config.state['last_message_index'] = cpd_running_info['last_message_index']
config.state['last_message_index'] = cp_running_info['last_message_index']
if config.state['my_latest_block']['block_index'] == 0:
config.state['my_latest_block']['block_index'] = cpd_running_info['last_block']['block_index']
config.state['my_latest_block']['block_index'] = cp_running_info['last_block']['block_index']
logger.info("Detected blocks caught up on startup. Setting last message idx to %s, current block index to %s ..." % (
config.state['last_message_index'], config.state['my_latest_block']['block_index']))

Expand Down
2 changes: 1 addition & 1 deletion lib/cache.py → counterblock/lib/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import redis.connection
redis.connection.socket = gevent.socket #make redis play well with gevent

from lib import config, util
from counterblock.lib import config, util

logger = logging.getLogger(__name__)

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
from datetime import datetime

from lib import config, util, blockchain
from counterblock.lib import config, util, blockchain

ASSET_MAX_RETRY = 3
D = decimal.Decimal
Expand All @@ -32,7 +32,7 @@ def modify_extended_asset_info(asset, description):
else:
db.asset_extended_info.remove({ 'asset': asset })
#remove any saved asset image data
imagePath = os.path.join(config.DATA_DIR, config.SUBDIR_ASSET_IMAGES, asset + '.png')
imagePath = os.path.join(config.data_dir, config.SUBDIR_ASSET_IMAGES, asset + '.png')
if os.path.exists(imagePath):
os.remove(imagePath)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import numpy
import pymongo

from lib import config, database, util, blockchain
from counterblock.lib import config, database, util, blockchain

D = decimal.Decimal
logger = logging.getLogger(__name__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import base64
import json

from lib import config, util
from counterblock.lib import config, util

FEED_MAX_RETRY = 3
D = decimal.Decimal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import json
import time

from lib import cache, config, util
from counterblock.lib import cache, config, util

decimal.setcontext(decimal.Context(prec=8, rounding=decimal.ROUND_HALF_EVEN))
D = decimal.Decimal
Expand Down
Loading

0 comments on commit e1ca78f

Please sign in to comment.