Skip to content

Instantly share code, notes, and snippets.

@jdp
Created March 7, 2014 02:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jdp/9404289 to your computer and use it in GitHub Desktop.
Save jdp/9404289 to your computer and use it in GitHub Desktop.
gitcoin miner
#!/usr/bin/env python
import calendar
import datetime
import hashlib
import multiprocessing
import os
import re
import signal
import subprocess
import sys
CORES = multiprocessing.cpu_count()
USERNAME = 'user-iguqnxej'
CLONE_URL = 'lvl1-jtdjmntc@stripe-ctf.com:current-round'
# CLONE_URL = 'lvl1-jtdjmntc@stripe-ctf.com:level1'
COMMIT_FORMAT = """tree {}
parent {}
author jdp <jp@i.tv> {} +0000
committer jdp <jp@.itv> {} +0000
"""
local_repo = CLONE_URL.split(':')[-1]
def prepare_index():
with open('LEDGER.txt') as f:
ledger = f.read()
pattern = '{}: (\d+)'.format(USERNAME)
match = re.search(pattern, ledger)
if match:
gitcoins = int(match.groups()[0]) + 1
ledger = re.sub(pattern, '{}: {}'.format(USERNAME, gitcoins), ledger)
else:
ledger += '{}: 1\n'.format(USERNAME)
with open('LEDGER.txt', 'w') as f:
f.write(ledger)
subprocess.call(['git', 'add', 'LEDGER.txt'])
def solve(solver_id, repo_lock, commit_queue):
print "solver", solver_id, "at work!"
repo_lock.acquire()
tree_hex = subprocess.check_output(['git', 'write-tree']).strip()
parent_hex = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
repo_lock.release()
timestamp = calendar.timegm(datetime.datetime.utcnow().utctimetuple())
commit = COMMIT_FORMAT.format(tree_hex, parent_hex, timestamp, timestamp)
with open('difficulty.txt') as f:
difficulty = f.read().strip()
counter = solver_id
while True:
h = hashlib.sha1()
contents = commit + str(counter)
header = "commit " + str(len(contents)) + "\0"
h.update(header + contents)
sha1 = h.hexdigest()
if sha1 < difficulty:
commit_queue.put((solver_id, sha1, contents))
counter += CORES
def submit(repo_lock, commit_queue):
while True:
solver_id, sha1, contents = commit_queue.get()
print "mined a gitcoin!", sha1, "from", solver_id
repo_lock.acquire()
p = subprocess.Popen(['git', 'hash-object', '-t', 'commit', '--stdin', '-w'], stdin=subprocess.PIPE)
p.communicate(contents)
subprocess.call(['git', 'reset', '--hard', sha1])
result = subprocess.call(['git', 'push', 'origin', 'master'])
subprocess.call(['git', 'fetch', 'origin', 'master'])
subprocess.call(['git', 'reset', '--hard', 'origin/master'])
repo_lock.release()
def init_worker():
signal.signal(signal.SIGINT, signal.SIG_IGN)
if __name__ == '__main__':
print "starting up..."
if not os.path.isdir(local_repo):
print "cloning git repo..."
subprocess.call(['git', 'clone', CLONE_URL])
os.chdir(local_repo)
prepare_index()
manager = multiprocessing.Manager()
repo_lock = manager.Lock()
commit_queue = manager.Queue()
try:
producer_pool = multiprocessing.Pool(CORES, init_worker)
for i in range(CORES):
producer_pool.apply_async(solve, (i, repo_lock, commit_queue))
producer_pool.close()
consumer = multiprocessing.Process(target=submit, args=(repo_lock, commit_queue))
consumer.start()
producer_pool.join()
consumer.join()
except KeyboardInterrupt:
producer_pool.terminate()
producer_pool.join()
consumer.terminate()
consumer.join()
sys.exit(0)
if submit():
print "success!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment