Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f7ede42
Showing
13 changed files
with
745 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Update vote information | ||
|
||
- Requires a Bitcoin XT node running with this patch https://github.com/dgenr8/bitcoinxt/commit/62ec4ca3bba718668f0aab1dc5ff570f9441092f | ||
- Node must be configured with txindex=1 | ||
- RPC username and password are assumed to be located at ../.bitcoin/bitcoin.conf | ||
|
||
Depends on pygtail, jinja2 and simplejson python libraries. | ||
|
||
On ubuntu: | ||
sudo apt-get install python3-pygtail, python3-jinja2, python3-simplejson | ||
|
||
Run doublespend.py to generate double spend data and update the static website. | ||
|
||
# The website | ||
The website itself consists of only static files. Point the webserver to serve files in folder site/ | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import sys | ||
import time | ||
from respend.logparser import RespendChecker | ||
from respend.txdecoder import decode_tx | ||
from respend.blockchain import BlockchainChecker | ||
from respend.winnerupdater import update_winners | ||
from respend.txdata import store_respend | ||
from respend.websitebuilder import build_website | ||
|
||
TXDATA = "txdata" | ||
|
||
def on_respend_detected(tx1, tx2): | ||
tx1_decoded = decode_tx(tx1.hex) | ||
tx1_decoded['first_seen'] = tx1.time | ||
tx2_decoded = decode_tx(tx2.hex) | ||
tx2_decoded['first_seen'] = tx2.time | ||
|
||
print("Wrote %s" % store_respend({ | ||
'first' : tx1_decoded, | ||
'second' : tx2_decoded, | ||
'timestamp' : tx1.time, | ||
'winner' : None})) | ||
|
||
respend = RespendChecker( | ||
logpath = "debug-sample.log", | ||
on_respend = on_respend_detected) | ||
|
||
blockchain = BlockchainChecker( | ||
on_new_tip = lambda: update_winners()) | ||
|
||
while True: | ||
update_website = respend.check() | ||
update_website |= blockchain.check() | ||
if update_website: | ||
print("New changes. Updating website.") | ||
build_website() | ||
|
||
sys.stdout.write(".") | ||
sys.stdout.flush() | ||
time.sleep(1) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from respend.rpcutil import connection | ||
|
||
class BlockchainChecker: | ||
def __init__(self, on_new_tip): | ||
self.on_new_tip = on_new_tip | ||
self.tip = None | ||
|
||
def check(self): | ||
new_tip = connection().getbestblockhash() | ||
if new_tip == self.tip: | ||
return False | ||
print("New blockchain tip: %s" % new_tip) | ||
self.tip = new_tip | ||
return self.on_new_tip() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import re | ||
from pygtail import Pygtail | ||
|
||
def regex_match(regex, line): | ||
m = re.match(regex, line) | ||
if m is None: | ||
return m | ||
return m.group(1); | ||
|
||
class RespendTx: | ||
def __init__(self, time_regex, hex_regex): | ||
self.time_regex = time_regex | ||
self.hex_regex = hex_regex | ||
|
||
self.time = None | ||
self.hex = None | ||
|
||
def parse_line(self, line): | ||
t = regex_match(self.time_regex, line) | ||
if t is not None: | ||
self.time = t | ||
print("matched %s %s" % (self.time_regex, line)) | ||
|
||
h = regex_match(self.hex_regex, line) | ||
if h is not None: | ||
self.hex = h | ||
print("matched %s %s" % (self.hex_regex, line)) | ||
|
||
def done(self): | ||
return self.time != None and self.hex != None | ||
|
||
def clear(self): | ||
self.time = self.hex = None | ||
|
||
class RespendChecker(): | ||
def __init__(self, logpath, on_respend): | ||
self.logpath = logpath | ||
self.on_respend = on_respend | ||
|
||
def check(self): | ||
tx1 = RespendTx( | ||
time_regex = r'.*tx1: (\d{4}-\d{2}-\d{2} [0-9:]{8})', | ||
hex_regex = r'.*tx1 hex: ([0-9a-f]+)') | ||
|
||
tx2 = RespendTx( | ||
time_regex = r'(\d{4}-\d{2}-\d{2} [0-9:]{8}) Respend tx2', | ||
hex_regex = r'.*tx2 hex: ([0-9a-f]+)') | ||
|
||
found = False | ||
for line in Pygtail(self.logpath): | ||
# tx2 is logged before tx1 | ||
|
||
if not tx2.done(): | ||
tx2.parse_line(line) | ||
|
||
elif not tx1.done(): | ||
tx1.parse_line(line) | ||
|
||
if tx1.done() and tx2.done(): | ||
print("found double spend") | ||
self.on_respend(tx1, tx2) | ||
tx1.clear() | ||
tx2.clear() | ||
found = True | ||
return found |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import sys | ||
sys.path.append("./lib/bitcoinrpc") | ||
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException | ||
from functools import lru_cache | ||
|
||
def read_cfg(param): | ||
cfglines = open("../.bitcoin/bitcoin.conf").readlines() | ||
for c in cfglines: | ||
if c.startswith(param): | ||
return c[len(param) + 1:-1] | ||
return None | ||
|
||
rpcuser = read_cfg("rpcuser") | ||
rpcpassword = read_cfg("rpcpassword") | ||
port = 8332 | ||
|
||
url = "http://%s:%s@127.0.0.1:%s" % (rpcuser, rpcpassword, port) | ||
conn = AuthServiceProxy(url) | ||
|
||
def connection(): | ||
global conn | ||
return conn | ||
|
||
@lru_cache(maxsize = 1024) | ||
def get_cached_tx(txid): | ||
return connection().getrawtransaction(txid, 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import simplejson as json | ||
import hashlib | ||
import glob | ||
import os | ||
|
||
TXDATA = "txdata" | ||
|
||
def has_winner(respend): | ||
return respend['winner'] != None | ||
|
||
def list_respends(): | ||
return glob.glob(TXDATA + "/*.json") | ||
|
||
def load_respend(path): | ||
with open(path) as fh: | ||
return json.load(fh) | ||
|
||
def respend_id(txid_first, txid_second): | ||
h = hashlib.new('ripemd160') | ||
h.update(txid_first.encode() + txid_second.encode()) | ||
return h.hexdigest() | ||
|
||
def store_respend(respend): | ||
rid = respend_id(respend['first']['txid'], respend['second']['txid']) | ||
path = os.path.join(TXDATA, rid + ".json") | ||
with open(path, "w") as fh: | ||
json.dump(respend, fh, sort_keys = True, indent = 2 * ' ') | ||
return path |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
from respend.rpcutil import connection | ||
|
||
def decode_tx(hexstr): | ||
return connection().decoderawtransaction(hexstr) |
Oops, something went wrong.