Implement the fetch-params.sh script in Python.
This commit is contained in:
parent
7f689b0a42
commit
95e9156cee
|
@ -0,0 +1,158 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
"""fetch-params.py - fetch Zcash public alpha keys
|
||||||
|
|
||||||
|
Usage: python fetch-params.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
urls = [
|
||||||
|
'https://z.cash/downloads/zc-testnet-public-alpha-proving.key',
|
||||||
|
'https://z.cash/downloads/zc-testnet-public-alpha-verification.key',
|
||||||
|
]
|
||||||
|
|
||||||
|
sizes = [
|
||||||
|
2007057094,
|
||||||
|
3478,
|
||||||
|
]
|
||||||
|
|
||||||
|
hash_algo = hashlib.sha256
|
||||||
|
|
||||||
|
hashes = [
|
||||||
|
'7844a96933979158886a5b69fb163f49de76120fa1dcfc33b16c83c134e61817',
|
||||||
|
'6902fd687bface72e572a7cda57f6da5a0c606c7b9769f30becd255e57924f41',
|
||||||
|
]
|
||||||
|
|
||||||
|
params_readme = """
|
||||||
|
This directory stores common zcash zkSNARK parameters. Note that is is
|
||||||
|
distinct from the daemon's -datadir argument because the parameters are
|
||||||
|
large and may be shared across multiple distinct -datadir's such as when
|
||||||
|
setting up test networks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
fetch_params_info = """
|
||||||
|
This script will fetch the Zcash zkSNARK parameters and verify their
|
||||||
|
integrity with sha256sum.
|
||||||
|
|
||||||
|
The parameters currently are about 2GiB in size, so plan accordingly
|
||||||
|
for your bandwidth constraints. If the files are already present and
|
||||||
|
have the correct sha256sum, no networking is used.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def which(name):
|
||||||
|
p = subprocess.Popen(['which', name], stdout=subprocess.PIPE)
|
||||||
|
p.wait()
|
||||||
|
if not p.returncode == 0:
|
||||||
|
return None
|
||||||
|
out = p.stdout.read()
|
||||||
|
return out.rstrip('\n')
|
||||||
|
|
||||||
|
|
||||||
|
# Note: This assumes cwd is set appropriately!
|
||||||
|
def fetch(url):
|
||||||
|
cmd = which('curl') or which('wget') or None
|
||||||
|
if cmd is None:
|
||||||
|
raise OSError('curl or wget is required')
|
||||||
|
options = {
|
||||||
|
'curl': [
|
||||||
|
'--remote-name',
|
||||||
|
'--insecure',
|
||||||
|
'--continue-at', '-',
|
||||||
|
'--location',
|
||||||
|
],
|
||||||
|
'wget': [
|
||||||
|
'--progress=dot:giga',
|
||||||
|
# Note: --no-check-certificate should be ok, since we rely
|
||||||
|
# on sha256 for integrity, and there's no confidentiality
|
||||||
|
# requirement. Our website uses letsencrypt certificates
|
||||||
|
# which are not supported by some wget installations,
|
||||||
|
# so we expect some cert failures.
|
||||||
|
'--no-check-certificate',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
opt = options[os.path.basename(cmd)]
|
||||||
|
ret = subprocess.call([cmd, url] + opt)
|
||||||
|
if not ret == 0:
|
||||||
|
raise OSError('%s failed with status %i' % (cmd, ret))
|
||||||
|
|
||||||
|
|
||||||
|
def verify(filename, digest):
|
||||||
|
hash = hash_algo()
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
while True:
|
||||||
|
dat = f.read(hash.block_size * 1024)
|
||||||
|
if len(dat) == 0:
|
||||||
|
break
|
||||||
|
hash.update(dat)
|
||||||
|
return hash.hexdigest() == digest
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
pass
|
||||||
|
elif len(sys.argv) == 2 and sys.argv[1] in ('-h', '--help'):
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
print(__doc__)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
home = os.environ['HOME']
|
||||||
|
|
||||||
|
# This may be the first time the user's run this script, so give
|
||||||
|
# them some info, especially about bandwidth usage:
|
||||||
|
print(fetch_params_info)
|
||||||
|
|
||||||
|
# Now create params_dir and insert a README if necessary:
|
||||||
|
print('Creating params directory...')
|
||||||
|
params_dir = os.path.join(home, '.zcash-params')
|
||||||
|
try:
|
||||||
|
os.mkdir(params_dir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
params_readme_path = os.path.join(params_dir, 'README')
|
||||||
|
if not os.path.exists(params_readme_path):
|
||||||
|
with open(params_readme_path, 'w+') as f:
|
||||||
|
print(params_readme, file=f)
|
||||||
|
print('For details about this directory, see:', params_readme_path)
|
||||||
|
|
||||||
|
regtest_dir = os.path.join(params_dir, 'regtest')
|
||||||
|
try:
|
||||||
|
os.mkdir(regtest_dir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
# This should have the same params as regtest.
|
||||||
|
# We use symlinks for now.
|
||||||
|
testnet3_dir = os.path.join(params_dir, 'testnet3')
|
||||||
|
try:
|
||||||
|
os.mkdir(testnet3_dir)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
os.chdir(regtest_dir)
|
||||||
|
for (url, size, hash) in zip(urls, sizes, hashes):
|
||||||
|
filename = url.split('/')[-1]
|
||||||
|
print('Fetching', filename, '...')
|
||||||
|
if not os.path.exists(filename) or \
|
||||||
|
not os.stat(filename).st_size == size:
|
||||||
|
fetch(url)
|
||||||
|
# Now verify their hashes:
|
||||||
|
print('Verifying', filename, '...')
|
||||||
|
assert verify(filename, hash)
|
||||||
|
try:
|
||||||
|
os.remove(os.path.join(testnet3_dir, filename))
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
os.symlink(
|
||||||
|
os.path.join(regtest_dir, filename),
|
||||||
|
os.path.join(testnet3_dir, filename),
|
||||||
|
)
|
Loading…
Reference in New Issue