pisa-btc initial commit

Contains basic structure, zmq so subscribe to blockid messages, api and so on. Still WIP
This commit is contained in:
Sergi Delgado
2019-03-29 18:54:31 +00:00
committed by Sergi Delgado Segura
commit 39a9a92bdb
11 changed files with 214 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@@ -0,0 +1,18 @@
*~
\#*\#
.\#*
build/
dist/
node_modules/
.vscode/
*.log
.nyc_output
logs/
.DS_Store
.idea
conf.py
bitcoin.conf
__pycache__/*
.pending*

View File

@@ -0,0 +1,2 @@
PISA_API_SERVER = 'localhost'
PISA_API_PORT = 2222

View File

@@ -0,0 +1 @@
wrong_txid = "You should provide the 16 MSB (in base58 hex) of the txid you'd like to be monitored."

53
pisa-btc/apps/pisa-cli.py Normal file
View File

@@ -0,0 +1,53 @@
from multiprocessing.connection import Client
from getopt import getopt
from sys import argv
from apps import PISA_API_SERVER, PISA_API_PORT
import apps.messages as msg
from base58 import b58decode
commands = ['register_tx']
def check_txid_format(txid):
if len(txid) != 32:
raise Exception("txid does not matches the expected size (16-byte / 32 hex chars). " + msg.wrong_txid)
try:
b58decode(txid)
except ValueError:
raise Exception("The provided txid is not in base58. " + msg.wrong_txid)
def show_usage():
print("usage: python pisa-cli.py argument [additional_arguments]."
"\nArguments:"
"\nregister_tx half_txid: \tregisters a txid to be monitored by PISA using the 16 MSB of the txid (in hex)."
"\nhelp: \t\tshows this message.")
if __name__ == '__main__':
opts, args = getopt(argv[1:], '', commands)
# Get args
if len(args) > 0:
command = args[0]
else:
raise Exception("Argument missing. Use help for usage information.")
if command in commands:
if command == 'register_tx':
if len(args) != 2:
raise Exception("txid missing. " + msg.wrong_txid)
arg = args[1]
check_txid_format(arg)
conn = Client((PISA_API_SERVER, PISA_API_PORT))
# Argv could be undefined, but we only have one command for now so safe
conn.send((command, arg))
else:
show_usage()

View File

@@ -0,0 +1,2 @@
HOST = 'localhost'
PORT = 2222

34
pisa-btc/pisa/api.py Normal file
View File

@@ -0,0 +1,34 @@
import threading
from multiprocessing.connection import Listener
from pisa import *
def manage_api(debug, host=HOST, port=PORT):
listener = Listener((host, port))
while True:
conn = listener.accept()
if debug:
print('Connection accepted from', listener.last_accepted)
# Maintain metadata up to date.
t_serve = threading.Thread(target=serve_data, args=[debug, conn, listener.last_accepted])
t_serve.start()
def serve_data(debug, conn, remote_addr):
while not conn.closed:
try:
msg = conn.recv()
if type(msg) == tuple:
if len(msg) is 2:
command, arg = msg
print(command, arg)
except (IOError, EOFError):
if debug:
print('Disconnecting from', remote_addr)
conn.close()

25
pisa-btc/pisa/pisad.py Normal file
View File

@@ -0,0 +1,25 @@
from getopt import getopt
from sys import argv
from threading import Thread
from pisa import shared
from pisa.zmq_subscriber import run_subscribe
from pisa.tx_watcher import watch_txs
from pisa.api import manage_api
if __name__ == '__main__':
debug = False
opts, _ = getopt(argv[1:], 'd', ['debug'])
for opt, arg in opts:
if opt in ['-d', '--debug']:
debug = True
shared.init()
zmq_thread = Thread(target=run_subscribe, args=[debug])
tx_watcher_thread = Thread(target=watch_txs, args=[debug])
api_thread = Thread(target=manage_api, args=[debug])
zmq_thread.start()
tx_watcher_thread.start()
api_thread.start()

8
pisa-btc/pisa/shared.py Normal file
View File

@@ -0,0 +1,8 @@
from queue import Queue
def init():
global block_queue, registered_txs
block_queue = Queue()
registered_txs = dict()

View File

@@ -0,0 +1,23 @@
from pisa import shared
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
from conf import BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT
def watch_txs(debug):
bitcoin_cli = AuthServiceProxy("http://%s:%s@%s:%d" % (BTC_RPC_USER, BTC_RPC_PASSWD, BTC_RPC_HOST, BTC_RPC_PORT))
while True:
block_hash = shared.block_queue.get()
try:
block = bitcoin_cli.getblock(block_hash)
prev_tx_id = block.get('previousblockhash')
txs = block.get('tx')
if debug:
# Log shit
print(prev_tx_id, txs)
except JSONRPCException as e:
print(e)

View File

@@ -0,0 +1,37 @@
"""
Adapted from https://github.com/bitcoin/bitcoin/blob/master/contrib/zmq/zmq_sub.py
"""
import binascii
import zmq
import conf
from pisa import shared
class ZMQHandler:
def __init__(self):
self.zmqContext = zmq.Context()
self.zmqSubSocket = self.zmqContext.socket(zmq.SUB)
self.zmqSubSocket.setsockopt(zmq.RCVHWM, 0)
self.zmqSubSocket.setsockopt_string(zmq.SUBSCRIBE, "hashblock")
self.zmqSubSocket.connect("%s://%s:%s" % (conf.FEED_PROTOCOL, conf.FEED_ADDR, conf.FEED_PORT))
def handle(self, debug):
msg = self.zmqSubSocket.recv_multipart()
topic = msg[0]
body = msg[1]
if topic == b"hashblock":
block_hash = binascii.hexlify(body).decode('UTF-8')
shared.block_queue.put(block_hash)
if debug:
# Log shit
pass
def run_subscribe(debug):
daemon = ZMQHandler()
daemon.handle(debug)

11
pisa-btc/sample_conf.py Normal file
View File

@@ -0,0 +1,11 @@
# bitcoind
BTC_RPC_USER = None
BTC_RPC_PASSWD = None
BTC_RPC_HOST = None
BTC_RPC_PORT = None
# ZMQ
FEED_PROTOCOL = None
FEED_ADDR = None
FEED_PORT = None