mirror of
https://github.com/aljazceru/python-teos.git
synced 2025-12-18 14:44:21 +01:00
pisa-btc initial commit
Contains basic structure, zmq so subscribe to blockid messages, api and so on. Still WIP
This commit is contained in:
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
*~
|
||||
\#*\#
|
||||
.\#*
|
||||
build/
|
||||
dist/
|
||||
node_modules/
|
||||
.vscode/
|
||||
*.log
|
||||
.nyc_output
|
||||
logs/
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
conf.py
|
||||
bitcoin.conf
|
||||
__pycache__/*
|
||||
.pending*
|
||||
|
||||
2
pisa-btc/apps/__init__.py
Normal file
2
pisa-btc/apps/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
PISA_API_SERVER = 'localhost'
|
||||
PISA_API_PORT = 2222
|
||||
1
pisa-btc/apps/messages.py
Normal file
1
pisa-btc/apps/messages.py
Normal 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
53
pisa-btc/apps/pisa-cli.py
Normal 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()
|
||||
|
||||
2
pisa-btc/pisa/__init__.py
Normal file
2
pisa-btc/pisa/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
HOST = 'localhost'
|
||||
PORT = 2222
|
||||
34
pisa-btc/pisa/api.py
Normal file
34
pisa-btc/pisa/api.py
Normal 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
25
pisa-btc/pisa/pisad.py
Normal 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
8
pisa-btc/pisa/shared.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from queue import Queue
|
||||
|
||||
|
||||
def init():
|
||||
global block_queue, registered_txs
|
||||
|
||||
block_queue = Queue()
|
||||
registered_txs = dict()
|
||||
23
pisa-btc/pisa/tx_watcher.py
Normal file
23
pisa-btc/pisa/tx_watcher.py
Normal 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)
|
||||
37
pisa-btc/pisa/zmq_subscriber.py
Normal file
37
pisa-btc/pisa/zmq_subscriber.py
Normal 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
11
pisa-btc/sample_conf.py
Normal 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
|
||||
Reference in New Issue
Block a user