Skip to content

Instantly share code, notes, and snippets.

@hclivess
Last active October 2, 2019 10:49
Show Gist options
  • Save hclivess/c4a0dea4cd9c9da877d3265f96e7c79e to your computer and use it in GitHub Desktop.
Save hclivess/c4a0dea4cd9c9da877d3265f96e7c79e to your computer and use it in GitHub Desktop.
"""
Generic helpers Bismuth
"""
import re
import hashlib
import base64
from decimal import Decimal
__version__ = '0.0.5'
def protocol_version_check(url):
""" Returns version of protocol. v1 = base85 and command, v2 = just base64, no command"""
split = url.split("/")
if split[2] == "pay":
return 1
else:
return 2
def checksum(string):
""" Base 64 checksum of MD5. Used by bisurl"""
m = hashlib.md5()
m.update(string.encode("utf-8"))
return base64.b85encode(m.digest()).decode("utf-8")
def checksum_b64(string):
""" Base 64 checksum of blake2b. Used by bisurl v2"""
m = hashlib.blake2b(digest_size=4)
m.update(string.encode("utf-8"))
return base64.b64encode(m.digest()).decode("utf-8")
RE_RSA_ADDRESS = re.compile(r"^[abcdef0123456789]{56}$")
# TODO: improve that ECDSA one
RE_ECDSA_ADDRESS = re.compile(r"^Bis")
class BismuthUtil():
"""Static helper utils"""
@staticmethod
def valid_address(address: str):
"""Says if that address looks ok"""
# Dup from polysign - https://github.com/bismuthfoundation/Bismuth/blob/postfork/polysign/signerfactory.py
# TODO: polysign as module for future versions.
if RE_RSA_ADDRESS.match(address):
# RSA, 56 hex
return True
elif RE_ECDSA_ADDRESS.match(address):
if 50 < len(address) < 60:
# ED25519, around 54
return True
if 30 < len(address) < 50:
# ecdsa, around 37
return True
return False
@staticmethod
def fee_for_tx(openfield: str = '', operation: str = '', block: int = 0) -> Decimal:
# block var will be removed after HF
fee = Decimal("0.01") + (Decimal(len(openfield)) / Decimal("100000")) # 0.01 dust
if operation == "token:issue":
fee = Decimal(fee) + Decimal("10")
if openfield.startswith("alias="):
fee = Decimal(fee) + Decimal("1")
# if operation == "alias:register": #add in the future, careful about forking
# fee = Decimal(fee) + Decimal("1")
return fee.quantize(Decimal('0.00000000'))
@staticmethod
def height_to_supply(height):
"""Gives total supply at a given block height"""
R0 = 11680000.4
delta = 2e-6
pos = 0.8
pow = 12.6
N = height - 8e5
dev_rew = 1.1
R = dev_rew * R0 + N * (pos + dev_rew * (pow - N / 2 * delta))
return R
@staticmethod
def create_bis_url(recipient, amount, operation, openfield):
"""
Constructs a bis url from tx elements
"""
# Only command supported so far.
command = "pay"
openfield_b85_encode = base64.b85encode(openfield.encode("utf-8")).decode("utf-8")
operation_b85_encode = base64.b85encode(operation.encode("utf-8")).decode("utf-8")
url_partial = "bis://{}/{}/{}/{}/{}/".format(command,recipient,amount,operation_b85_encode,openfield_b85_encode)
url_constructed = url_partial + checksum(url_partial)
return url_constructed
@staticmethod
def read_url(url):
"""
Takes a bis url, checks its checksum and gives the components
"""
url_split = url.split("/")
reconstruct = "bis://{}/{}/{}/{}/{}/".format(url_split[2],url_split[3],url_split[4],url_split[5],url_split[6],url_split[7])
operation_b85_decode = base64.b85decode(url_split[5]).decode("utf-8")
openfield_b85_decode = base64.b85decode(url_split[6]).decode("utf-8")
if checksum(reconstruct) == url_split[7]:
url_deconstructed = {"recipient": url_split[3], "amount": url_split[4], "operation": operation_b85_decode,
"openfield": openfield_b85_decode}
return url_deconstructed
else:
return {'Error': 'Checksum failed'}
@staticmethod
def create_bis_url_b64(recipient, amount, operation, openfield):
"""
Constructs a bis url from tx elements, v2
"""
openfield_b64_encode = base64.b64encode(openfield.encode("utf-8")).decode("utf-8")
operation_b64_encode = base64.b64encode(operation.encode("utf-8")).decode("utf-8")
url_partial = "bis://{}/{}/{}/{}/".format(recipient, amount, operation_b64_encode, openfield_b64_encode)
url_constructed = url_partial + checksum_b64(url_partial)
return url_constructed
@staticmethod
def read_url_b64(url):
"""
Takes a bis url, checks its checksum and gives the components, v2
"""
url_split = url.split("/")
reconstruct = "bis://{}/{}/{}/{}/".format(url_split[2], url_split[3], url_split[4], url_split[5], url_split[6])
operation_b64_decode = base64.b64decode(url_split[4]).decode("utf-8")
openfield_b64_decode = base64.b64decode(url_split[5]).decode("utf-8")
if checksum_b64(reconstruct) == url_split[6]:
url_deconstructed = {"recipient": url_split[2], "amount": url_split[3], "operation": operation_b64_decode,
"openfield": openfield_b64_decode}
return url_deconstructed
else:
return {'Error': 'Checksum failed'}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment