Merge pull request #86 from majestrate/vanity

loki vanity address script demo thingy
This commit is contained in:
Jeff 2018-11-27 09:26:52 -05:00 committed by GitHub
commit b9a41e380f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 261 additions and 0 deletions

2
contrib/py/vanity/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
__pycache__
*.private

View File

@ -0,0 +1,112 @@
#
# super freaking dead simple wicked awesome bencode library
#
from io import BytesIO
class BCodec:
encoding = 'utf-8'
def __init__(self, fd):
self._fd = fd
def _write_bytestring(self, bs):
self._fd.write('{}:'.format(len(bs)).encode('ascii'))
self._fd.write(bs)
def _write_list(self, l):
self._fd.write(b'l')
for item in l:
self.encode(item)
self._fd.write(b'e')
def _write_dict(self, d):
self._fd.write(b'd')
keys = list(d.keys())
keys.sort()
for k in keys:
if isinstance(k, str):
self._write_bytestring(k.encode(self.encoding))
elif isinstance(k, bytes):
self._write_bytestring(k)
else:
self._write_bytestring('{}'.format(k).encode(self.encoding))
self.encode(d[k])
self._fd.write(b'e')
def _write_int(self, i):
self._fd.write('i{}e'.format(i).encode(self.encoding))
def encode(self, obj):
if isinstance(obj, dict):
self._write_dict(obj)
elif isinstance(obj, list):
self._write_list(obj)
elif isinstance(obj, int):
self._write_int(obj)
elif isinstance(obj, str):
self._write_bytestring(obj.encode(self.encoding))
elif isinstance(obj, bytes):
self._write_bytestring(obj)
elif hasattr(obj, bencode):
obj.bencode(self._fd)
else:
raise ValueError("invalid object type")
def _readuntil(self, delim):
b = bytes()
while True:
ch = self._fd.read(1)
if ch == delim:
return b
b += ch
def _decode_list(self):
l = list()
while True:
b = self._fd.read(1)
if b == b'e':
return l
l.append(self._decode(b))
def _decode_dict(self):
d = dict()
while True:
ch = self._fd.read(1)
if ch == b'e':
return d
k = self._decode_bytestring(ch)
d[k] = self.decode()
def _decode_int(self):
return int(self._readuntil(b'e'), 10)
def _decode_bytestring(self, ch):
ch += self._readuntil(b':')
l = int(ch, base=10)
return self._fd.read(l)
def _decode(self, ch):
if ch == b'd':
return self._decode_dict()
elif ch == b'l':
return self._decode_list()
elif ch == b'i':
return self._decode_int()
elif ch in [b'0',b'1',b'2',b'3',b'4',b'5',b'6',b'7',b'8',b'9']:
return self._decode_bytestring(ch)
else:
raise ValueError(ch)
def decode(self):
return self._decode(self._fd.read(1))
def bencode(obj):
buf = BytesIO()
b = BCodec(buf)
b.encode(obj)
return buf.bytes()
def bdecode(bytestring):
buf = BytesIO()
buf.write(bytestring)
return BCodec(buf).decode()

View File

@ -0,0 +1,136 @@
#!/usr/bin/env python3
import bencode
import sys
import libnacl
import base64
import struct
from io import BytesIO
import time
from multiprocessing import Process, Array, Value
def print_help():
print('usage: {} keyfile.private prefix numthreads'.format(sys.argv[0]))
return 1
_zalpha = ['y', 'b', 'n', 'd', 'r', 'f', 'g', '8',
'e', 'j', 'k', 'm', 'c', 'p', 'q', 'x',
'o', 't', '1', 'u', 'w', 'i', 's', 'z',
'a', '3', '4', '5', 'h', '7', '6', '9']
def zb32_encode(buf):
s = str()
bits = 0
l = len(buf)
idx = 0
tmp = buf[idx]
while bits > 0 or idx < l:
if bits < 5:
if idx < l:
tmp <<= 8
tmp |= buf[idx] & 0xff
idx += 1
bits += 8
else:
tmp <<= 5 - bits
bits = 5
bits -= 5
s += _zalpha[(tmp >> bits) & 0x1f]
return s
def _gen_si(keys):
e = keys[b'e'][32:]
s = keys[b's'][32:]
v = keys[b'v']
return {'e': e, 's':s, 'v':v}
class AddrGen:
def __init__(self, threads, keys, prefix):
self._inc = threads
self._keys = keys
self._c = Value('i')
self.sync = Array('i', 3)
self._procs = []
self.prefix = prefix
def runit(self):
for ch in self.prefix:
if ch not in _zalpha:
print("invalid prefix, {} not a valid character".format(ch))
return None, None
print("find ^{}.loki".format(self.prefix))
i = self._inc
while i > 0:
p = Process(target=self._gen_addr_tick, args=(self.prefix, abs(libnacl.randombytes_random()), abs(libnacl.randombytes_random()), _gen_si(self._keys)))
p.start()
self._procs.append(p)
i -=1
return self._runner()
def _gen_addr_tick(self, prefix, lo, hi, si):
print(prefix)
fd = BytesIO()
addr = ''
enc = bencode.BCodec(fd)
while self.sync[2] == 0:
si['x'] = struct.pack('>QQ', lo, hi)
fd.seek(0,0)
enc.encode(si)
pub = bytes(fd.getbuffer())
addr = zb32_encode(libnacl.crypto_generichash(pub))
if addr.startswith(prefix):
self.sync[2] = 1
self.sync[0] = hi
self.sync[1] = lo
return
hi += self._inc
if hi == 0:
lo += 1
self._c.value += 1
def _print_stats(self):
print('{} H/s'.format(self._c.value))
self._c.value = 0
def _joinall(self):
for p in self._procs:
p.join()
def _runner(self):
while self.sync[2] == 0:
time.sleep(1)
self._print_stats()
self._joinall()
fd = BytesIO()
enc = bencode.BCodec(fd)
hi = self.sync[0]
lo = self.sync[1]
si = _gen_si(self._keys)
si['x'] = struct.pack('>QQ', lo, hi)
enc.encode(si)
pub = bytes(fd.getbuffer())
addr = zb32_encode(libnacl.crypto_generichash(pub))
return si['x'], addr
def main(args):
if len(args) != 3:
return print_help()
keys = None
with open(args[0], 'rb') as fd:
dec = bencode.BCodec(fd)
keys = dec.decode()
runner = AddrGen(int(args[2]), keys, args[1])
keys[b'x'], addr = runner.runit()
if addr:
print("found {}.loki".format(addr))
with open(args[0], 'wb') as fd:
enc = bencode.BCodec(fd)
enc.encode(keys)
if __name__ == '__main__':
main(sys.argv[1:])

View File

@ -0,0 +1,10 @@
# lokinet vanity address generator
installing deps:
sudo apt install libsodium-dev
pip3 install --user -r requirements.txt
to generate a nonce with a prefix `^7oki` using 8 cpu threads:
python3 lokinet-vanity.py keyfile.private 7oki 8

View File

@ -0,0 +1 @@
libnacl