It was the Bitcointalk forum that inspired us to create Bitcointalksearch.org - Bitcointalk is an excellent site that should be the default page for anybody dealing in cryptocurrency, since it is a virtual gold-mine of data. However, our experience and user feedback led us create our site; Bitcointalk's search is slow, and difficult to get the results you need, because you need to log in first to find anything useful - furthermore, there are rate limiters for their search functionality.
The aim of our project is to create a faster website that yields more results and faster without having to create an account and eliminate the need to log in - your personal data, therefore, will never be in jeopardy since we are not asking for any of your data and you don't need to provide them to use our site with all of its capabilities.
We created this website with the sole purpose of users being able to search quickly and efficiently in the field of cryptocurrency so they will have access to the latest and most accurate information and thereby assisting the crypto-community at large.
# Digits are chosen to be the least ambiguous
# They all have unique seven-segment glyphs, and cannot be easily confused by humans
digits = '123456789abcdehjnrtyACEFGHJLOPUY'
radix = len(digits)
def encode(v):
if not len(v):
return ''
n = 0
bits = 0
o = []
pad = (len(v) * 8) % 5
if pad:
v = b'\0' + v
v = bytearray(v) # For Python 2.7 compatibility
for i in range(len(v) - 1, -1, -1):
n |= v[i] << bits
bits += 8
while bits >= 5:
o.insert(0, digits[n & 0x1f])
n >>= 5
bits -= 5
if i == 0 and pad:
break
return ''.join(o)
def decode(s):
n = 0
bits = 0
o = bytearray()
for i in range(len(s) - 1, -1, -1):
n |= digits.index(s[i]) << bits
bits += 5
while bits >= 8:
o.insert(0, n & 0xff)
n >>= 8
bits -= 8
return bytes(o)
def test():
from math import ceil
assert '' == encode(b'')
for (i, oc) in (
(1, '8'),
(2, '2'),
(3, 'j'),
(4, '4'),
(5, 'Y'),
(6, '8'),
(7, '2'),
(8, 'j'),
(9, '4'),
):
ol = int(ceil(i * 8 / 5.))
try:
inzero = b'\0' * i
inone = b'\xff' * i
ezero = encode(inzero)
eone = encode(inone)
dzero = decode(ezero)
done = decode(eone)
assert ezero == '1' * ol
assert eone == oc + ('Y' * (ol - 1))
assert dzero == inzero
assert done == inone
except AssertionError:
raise AssertionError('Input of length %s failed test' % (i,))
try:
for c in range(1024):
decode('111' + chr(c))
except ValueError:
pass
else:
raise AssertionError('Invalid decode input (%02x) did not throw a ValueError' % (c,))
if __name__ == '__main__':
test()
print("Tests passed")
import c32
import hashlib
import struct
def _checksum(v):
return hashlib.sha256(hashlib.sha256(v).digest()).digest()[-4:]
'''
String format:
- c32(Raw format) in reverse order
Raw format:
- 4 bytes checksum
- N bytes data (NOTE: encoded to prevent hidden changes)
- - for script:
- - - N bytes: varint preimage data length
- - - N bytes: preimage data
- - - N bytes: script data
- - for BIP32 HD parent key:
- - - 32 bytes: chain code
- - - 33 bytes: parent pubkey
- - for BIP32 serialized key:
- - - 1 byte: depth
- - - 4 bytes: child number
- - - 32 bytes: chain code
- - - One of:
- - - - 32 bytes: private key data
- - - - 33 bytes: public key data
- 1 byte flag (ignored if unknown)
- 1 byte type
- - 01 script (with preimage data)
- - 02 script hash preimage
- - 03 BIP32 HD parent key
- - 04 BIP32 serialized public key
- 2 bytes namespace (blockchain id)
- - 2d41 Bitcoin ('2bc')
- - 2e01 Namecoin ('2nc')
- - 2e37 Freicoin ('FRC')
'''
class c32d:
__slots__ = ('data', 'ns', 'dtype', 'dflag')
def __init__(self, data, ns, dtype, dflag):
self.data = data
self.ns = ns
self.dtype = dtype
self.dflag = dflag
@classmethod
def decode(cls, s, raw = False):
if not raw:
full = c32.decode(s[::-1])
else:
full = s
csum = bytearray(full[:4])
v = bytearray(full[4:])
# Encode the configuration bytes to simplify decoding
pv = 0xbf
for i in range(len(v) - 1, len(v) - 5, -1):
pv = v[i] ^ (csum[i % 4]) ^ pv
v[i] = pv
v.append(0xbf)
for i in range(len(v) - 1):
v[i] ^= csum[i % 4] ^ v[i + 1]
v.pop()
v = bytes(v)
if csum != _checksum(v):
raise ValueError('c32d checksum wrong')
o = cls(None, None, None, None)
o.data = v[:-4]
o.dflag = v[-4]
o.dtype = v[-3]
o.ns = struct.unpack('!H', v[-2:])[0]
return o
def encode(self, raw = False):
try:
v = self.data + struct.pack('!BBH', self.dflag, self.dtype, self.ns)
except struct.error as e:
raise ValueError(e)
csum = bytearray(_checksum(v))
v = bytearray(v)
pv = 0xbf
for i in range(len(v) - 1, -1, -1):
pv = v[i] ^ csum[i % 4] ^ pv
if i < len(v) - 4:
v[i] = pv
v = csum + bytes(v)
if raw:
return v
return c32.encode(v)[::-1]
decode = c32d.decode
def encode(*a, **ka):
return c32d(*a, **ka).encode()
def test():
c32.test()
for (p, s, raw) in (
((b'', 0, 0, 0), '1111115Fd9acc', b'\xb5\xa5\x0c\xb9\x00\x00\x00\x00'),
((b'test', 4232, 142, 219), '955OGe8hOGc97hH4EJj1', b'?V\x1e\\d/\x1cq\xdb\x8e\x10\x88'),
((b'\xff' * 0x100, 0xffff, 0xff, 0xff), 'YYYYYYc327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGt9n2YYbeH63jda5GnYjCEO3r8E53dGYFbchrG4c327OYcC6F9Or6r14UYCJtc5UGb2cOdG3', b'\xb0\xce,*\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xc7\x88\xb9j\xbf\xf0\xc1\x12\xff\xff\xff\xff'),
):
(kp, pp) = ({}, p)
for i in range(2):
o = c32d(*pp, **kp)
assert o.data == p[0]
assert o.ns == p[1]
assert o.dtype == p[2]
assert o.dflag == p[3]
kp = {
'data': p[0],
'ns': p[1],
'dtype': p[2],
'dflag': p[3],
}
pp = ()
assert o.encode() == s
assert o.encode(raw=True) == raw
def ensureValueError(f):
try:
f()
except ValueError:
pass
else:
raise AssertionError('Invalid decode input did not throw a ValueError')
ensureValueError(lambda: encode(b'', -1, 0, 0))
ensureValueError(lambda: encode(b'', 0x10000, 0, 0))
ensureValueError(lambda: encode(b'', 0, -1, 0))
ensureValueError(lambda: encode(b'', 0, 0x100, 0))
ensureValueError(lambda: encode(b'', 0, 0, -1))
ensureValueError(lambda: encode(b'', 0, 0, 0x100))
# Invalid c32d
ensureValueError(lambda: decode('1111115Fd9adc'))
ensureValueError(lambda: decode('11A1115Fd9acc'))
# Invalid c32
ensureValueError(lambda: decode('111x115Fd9acc'))
ensureValueError(lambda: decode('1111115Fd9acx'))
if __name__ == '__main__':
test()
print("Tests passed")