summaryrefslogtreecommitdiff
path: root/tools/merge_dist.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/merge_dist.py')
-rw-r--r--tools/merge_dist.py130
1 files changed, 130 insertions, 0 deletions
diff --git a/tools/merge_dist.py b/tools/merge_dist.py
new file mode 100644
index 0000000..2b2f259
--- /dev/null
+++ b/tools/merge_dist.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2014-2015, NORDUnet A/S.
+# See LICENSE for licensing information.
+
+import sys
+import urllib2
+import base64
+import select
+from certtools import timing_point, check_sth_signature, \
+ get_public_key_from_file
+from mergetools import get_curpos, get_logorder, chunks, get_missingentries, \
+ sendsth, create_sth_signature, hexencode, sendlog, sendentry, read_chain
+
+def merge_dist(args, config, localconfig, sth_in):
+ paths = localconfig["paths"]
+ own_key = (localconfig["nodename"],
+ "%s/%s-private.pem" % (paths["privatekeys"],
+ localconfig["nodename"]))
+ frontendnodes = config["frontendnodes"]
+ signingnodes = config["signingnodes"]
+ ctbaseurl = config["baseurl"]
+ logpublickey = get_public_key_from_file(paths["logpublickey"])
+ mergedb = paths["mergedb"]
+ chainsdir = mergedb + "/chains"
+ logorderfile = mergedb + "/logorder"
+ timing = timing_point()
+
+ logorder = get_logorder(logorderfile)
+ timing_point(timing, "get logorder")
+
+ (tree_size, root_hash, timestamp) = sth_in
+ tree_head_signature = None
+ for signingnode in signingnodes:
+ try:
+ tree_head_signature = \
+ create_sth_signature(tree_size, timestamp,
+ root_hash,
+ "https://%s/" % signingnode["address"],
+ key=own_key)
+ break
+ except urllib2.URLError, err:
+ print >>sys.stderr, err
+ sys.stderr.flush()
+ if tree_head_signature == None:
+ print >>sys.stderr, "Could not contact any signing nodes"
+ sys.exit(1)
+
+ sth = {"tree_size": tree_size, "timestamp": timestamp,
+ "sha256_root_hash": base64.b64encode(root_hash),
+ "tree_head_signature": base64.b64encode(tree_head_signature)}
+
+ check_sth_signature(ctbaseurl, sth, publickey=logpublickey)
+
+ timing_point(timing, "build sth")
+
+ if args.timing:
+ print >>sys.stderr, timing["deltatimes"]
+ sys.stderr.flush()
+
+ print hexencode(root_hash)
+ sys.stdout.flush()
+
+ for frontendnode in frontendnodes:
+ nodeaddress = "https://%s/" % frontendnode["address"]
+ nodename = frontendnode["name"]
+ timing = timing_point()
+ print >>sys.stderr, "distributing for node", nodename
+ sys.stderr.flush()
+ curpos = get_curpos(nodename, nodeaddress, own_key, paths)
+ timing_point(timing, "get curpos")
+ print >>sys.stderr, "current position", curpos
+ sys.stderr.flush()
+ entries = [base64.b64encode(entry) for entry in logorder[curpos:]]
+ print >>sys.stderr, "sending log:",
+ sys.stderr.flush()
+ for chunk in chunks(entries, 1000):
+ for trynumber in range(5, 0, -1):
+ sendlogresult = sendlog(nodename, nodeaddress,
+ own_key, paths,
+ {"start": curpos, "hashes": chunk})
+ if sendlogresult == None:
+ if trynumber == 1:
+ sys.exit(1)
+ select.select([], [], [], 10.0)
+ print >>sys.stderr, "tries left:", trynumber
+ sys.stderr.flush()
+ continue
+ break
+ if sendlogresult["result"] != "ok":
+ print >>sys.stderr, "sendlog:", sendlogresult
+ sys.exit(1)
+ curpos += len(chunk)
+ print >>sys.stderr, curpos,
+ sys.stderr.flush()
+ print >>sys.stderr
+ timing_point(timing, "sendlog")
+ print >>sys.stderr, "log sent"
+ sys.stderr.flush()
+ missingentries = get_missingentries(nodename, nodeaddress, own_key,
+ paths)
+ timing_point(timing, "get missing")
+ print >>sys.stderr, "missing entries:", len(missingentries)
+ sys.stderr.flush()
+ fetched_entries = 0
+ print >>sys.stderr, "fetching missing entries",
+ sys.stderr.flush()
+ for missingentry in missingentries:
+ ehash = base64.b64decode(missingentry)
+ sendentryresult = sendentry(nodename, nodeaddress, own_key, paths,
+ read_chain(chainsdir, ehash), ehash)
+ if sendentryresult["result"] != "ok":
+ print >>sys.stderr, "send sth:", sendentryresult
+ sys.exit(1)
+ fetched_entries += 1
+ if fetched_entries % 1000 == 0:
+ print >>sys.stderr, fetched_entries,
+ sys.stderr.flush()
+ print >>sys.stderr
+ sys.stderr.flush()
+ timing_point(timing, "send missing")
+ sendsthresult = sendsth(nodename, nodeaddress, own_key, paths, sth)
+ if sendsthresult["result"] != "ok":
+ print >>sys.stderr, "send sth:", sendsthresult
+ sys.exit(1)
+ timing_point(timing, "send sth")
+ if args.timing:
+ print >>sys.stderr, timing["deltatimes"]
+ sys.stderr.flush()