def unforge_signature(data: bytes) -> str: """ Decode signature from byte form. :param data: encoded signature. :returns: base58 encoded signature (generic) """ return base58_encode(data, b'sig').decode()
def fill_context(self, script, context: ExecutionContext) -> None: sender = context.get_sender_expr() if sender: context.sender = SenderSection.match( sender).args[0].get_string() # type: ignore amount = context.get_amount_expr() if amount: context.amount = AmountSection.match( amount).args[0].get_int() # type: ignore balance = context.get_balance_expr() if balance: context.balance = BalanceSection.match( balance).args[0].get_int() # type: ignore _self = context.get_self_expr() if _self: context.address = SelfSection.match( _self).args[0].get_string() # type: ignore now = context.get_now_expr() if now: context.now = NowSection.match( now).args[0].get_int() # type: ignore source = context.get_source_expr() if source: context.source = SourceSection.match( source).args[0].get_string() # type: ignore chain_id = context.get_chain_id_expr() if chain_id: # FIXME: Move to some common place context.chain_id = base58_encode( cast(bytes, ChainIdSection.match(chain_id).args[0].literal), prefix=b'Net', ).decode()
def unforge_chain_id(data: bytes) -> str: """ Decode chain id from byte form. :param data: encoded chain id. :returns: base58 encoded chain id """ return base58_encode(data, b'Net').decode()
def get_keys(mnemonic, email, password): salt = unicodedata.normalize("NFKD", (email + password)) seed = m.to_seed(mnemonic.encode('utf-8'), salt.encode('utf-8')) pk, sk = pysodium.crypto_sign_seed_keypair(seed[0:32]) pkh = blake2b(pk, 20).digest() pkhb58 = base58_encode(pkh, prefix=b'tz1').decode('utf-8') return (sk, pk, pkh, pkhb58)
def public_key_hash(self): """ Creates base58 encoded public key hash for this key. :returns: the public key hash for this key """ pkh = blake2b(data=self.public_point, digest_size=20).digest() prefix = {b'ed': b'tz1', b'sp': b'tz2', b'p2': b'tz3'}[self.curve] return base58_encode(pkh, prefix).decode()
def unforge_public_key(data: bytes) -> str: """ Decode public key from byte form. :param data: encoded public key. :returns: base58 encoded public key """ key_prefix = {b'\x00': b'edpk', b'\x01': b'sppk', b'\x02': b'p2pk'} return base58_encode(data[1:], key_prefix[data[:1]]).decode()
def unforge_address(data: bytes): """ Decode address or key_hash from bytes. :param data: encoded address or key_hash :returns: base58 encoded address """ tz_prefixes = { b'\x00\x00': b'tz1', b'\x00\x01': b'tz2', b'\x00\x02': b'tz3' } for bin_prefix, tz_prefix in tz_prefixes.items(): if data.startswith(bin_prefix): return base58_encode(data[2:], tz_prefix).decode() if data.startswith(b'\x01') and data.endswith(b'\x00'): return base58_encode(data[1:-1], b'KT1').decode() else: return base58_encode(data[1:], tz_prefixes[b'\x00' + data[:1]]).decode()
def blinded_public_key_hash(self) -> str: """Creates base58 encoded commitment out of activation code (required) and public key hash :return: blinded public key hash """ if not self.activation_code: raise ValueError("Activation code is undefined") pkh = blake2b(data=self.public_point, digest_size=20).digest() key = bytes.fromhex(self.activation_code) blinded_pkh = blake2b(data=pkh, key=key, digest_size=20).digest() return base58_encode(blinded_pkh, b'btz1').decode()
def run(self, block_id='head'): """ Simulate operation without signature checks. :param block_id: Specify a level at which this operation should be applied (default is head) :returns: RPC response from `run_operation` """ return self.shell.blocks[block_id].helpers.scripts.run_operation.post({ 'operation': { 'branch': self.branch, 'contents': self.contents, 'signature': base58_encode(b'0' * 64, b'sig').decode() }, 'chain_id': self.chain_id })
def genesis_commitments(wallets, blind): commitments = [] for pkh_b58, amount in wallets.items(): # Public key hash corresponding to this Tezos address. pkh = base58_decode(pkh_b58.encode('utf-8')) # The redemption code is unique to the public key hash and deterministically # constructed using a secret blinding value. secret = secret_code(pkh, blind) # The redemption code is used to blind the pkh blinded_pkh = blake2b(pkh, 20, key=secret).digest() commitment = { 'blinded_pkh': base58_encode(blinded_pkh, prefix=b'btz1').decode(), 'amount': amount } commitments.append(commitment) return commitments
def secret_key( self, passphrase: PassphraseInput = None, ed25519_seed: bool = True, ): """Creates base58 encoded private key representation. :param passphrase: encryption phrase for the private key :param ed25519_seed: encode seed rather than full key for ed25519 curve (True by default) :returns: the secret key associated with this key, if available """ if not self.secret_exponent: raise ValueError("Secret key is undefined") if self.curve == b'ed' and ed25519_seed: key = pysodium.crypto_sign_sk_to_seed(self.secret_exponent) else: key = self.secret_exponent if passphrase: if not ed25519_seed: raise NotImplementedError if isinstance(passphrase, str): passphrase = passphrase.encode() assert isinstance( passphrase, bytes ), f'expected bytes or str, got {type(passphrase).__name__}' salt = pysodium.randombytes(8) encryption_key = hashlib.pbkdf2_hmac( hash_name="sha512", password=passphrase, salt=salt, iterations=32768, dklen=32, ) encrypted_sk = pysodium.crypto_secretbox(msg=key, nonce=b'\000' * 24, k=encryption_key) key = salt + encrypted_sk # we have to combine salt and encrypted key in order to decrypt later prefix = self.curve + b'esk' else: prefix = self.curve + b'sk' return base58_encode(key, prefix).decode()
def get_genesis_vanity_chain_id(seed_len=16): print("Generating vanity chain id") if not use_docker: return base58_encode(token_bytes(32), b"B").decode("utf-8") seed = "".join( random.choice(string.ascii_uppercase + string.digits) for _ in range(seed_len)) return (run_docker( "registry.gitlab.com/tezos/flextesa:01e3f596-run", "flextesa", "vani", '""', "--seed", seed, "--first", "--machine-readable", "csv", ).decode("utf-8").split(",")[1])
def sign(self, message, generic=False): """ Sign a raw sequence of bytes. :param message: sequence of bytes, raw format or hexadecimal notation :param generic: do not specify elliptic curve if set to True :returns: signature in base58 encoding """ message = scrub_input(message) if not self.secret_exponent: raise ValueError("Cannot sign without a secret key.") # Ed25519 if self.curve == b"ed": digest = pysodium.crypto_generichash(message) signature = pysodium.crypto_sign_detached(digest, self.secret_exponent) # Secp256k1 elif self.curve == b"sp": pk = secp256k1.PrivateKey(self.secret_exponent) signature = pk.ecdsa_serialize_compact( pk.ecdsa_sign(message, digest=blake2b_32)) # P256 elif self.curve == b"p2": r, s = fastecdsa.ecdsa.sign(msg=message, d=bytes_to_int(self.secret_exponent), hashfunc=blake2b_32) signature = r.to_bytes(32, 'big') + s.to_bytes(32, 'big') else: assert False if generic: prefix = b'sig' else: prefix = self.curve + b'sig' return base58_encode(signature, prefix).decode()
def forge_script_expr(packed_key: bytes) -> str: data = blake2b_32(packed_key).digest() return base58_encode(data, b'expr').decode()
def fill(self, block_id='head', timestamp: Optional[int] = None) -> 'BlockHeader': """Fill missing fields essential for preapply :param block_id: head or genesis :param timestamp: override header timestamp (unix seconds). NOTE that the minimal block granularity in Tezos is 1 sec, so you cannot bake faster that once per second. You also cannot bake with timestamp in the future, it will end with error. The workaround is to set the genesis block timestamp to zero (or very old date) so that you can continuously increase it by 1 sec. :rtype: BlockHeader """ pred_shell_header = self.shell.blocks[block_id].header.shell() if timestamp is None: timestamp = optimize_timestamp(pred_shell_header['timestamp']) + 1 protocol = self.shell.blocks[block_id].protocols()['next_protocol'] level = int(pred_shell_header['level']) + 1 dummy_signature = base58_encode(b'\x00' * 64, b'sig').decode() protocol_data = { 'protocol': protocol, **self.protocol_data, } if level % int(sandbox_params['blocks_per_commitment']) == 0: # type: ignore protocol_data['seed_nonce_hash'] = base58_encode(b'\x00' * 32, b'nce').decode() if 'priority' in protocol_data: baker = self.key.public_key_hash() baking_rights = self.shell.blocks[block_id].helpers.baking_rights(delegate=baker) # NOTE: Fails if baker has no baking rights protocol_data['priority'] = next(item['priority'] for item in baking_rights if item['delegate'] == baker) operations = [ [ { 'protocol': protocol, 'branch': operation['branch'], 'contents': operation['contents'], 'signature': operation['signature'], } for operation in operation_list ] for operation_list in self.operations ] payload = { 'protocol_data': { **protocol_data, 'signature': dummy_signature, }, 'operations': operations, } res = self.shell.blocks[block_id].helpers.preapply.block.post( block=payload, sort=True, timestamp=timestamp, ) forged_operations = [ [ { 'branch': operation['branch'], 'data': operation['data'], } for operation in operation_list['applied'] ] for operation_list in res['operations'] ] return self._spawn( shell_header=res['shell_header'], operations=forged_operations, protocol_data=protocol_data, signature=dummy_signature, )
def get_dummy_public_key(self) -> str: if self.key: return self.key.public_key() else: return base58_encode(b'\x00' * 32, b'edpk').decode()
def hash(self): hash_digest = blake2b_32(proto_to_bytes(self._proto)).digest() return base58_encode(hash_digest, b'P').decode()
def get_originated_address(index: int, opg_hash=None): prefix = base58_decode(opg_hash) if opg_hash else b'\x00' * 32 nonce = prefix + index.to_bytes(4, 'big') nonce_hash = blake2b(data=nonce, digest_size=20).digest() return base58_encode(nonce_hash, b'KT1').decode()
def test_b58_decode_encode(self, string, prefix): data = base58_decode(string) result = base58_encode(data, prefix) self.assertEqual(string, result)
def get_dummy_chain_id(self) -> str: return base58_encode(b'\x00' * 4, b'Net').decode()
def hash(self) -> str: hash_digest = blake2b_32(self.binary_payload()).digest() return base58_encode(hash_digest, b'B').decode()
def public_key(self): """ Creates base58 encoded public key representation. :returns: the public key associated with the private key """ return base58_encode(self.public_point, self.curve + b'pk').decode()
def fill(self, block_id='head') -> 'BlockHeader': """Fill missing fields essential for preapply :param block_id: head or genesis :rtype: BlockHeader """ pred_shell_header = self.shell.blocks[block_id].header.shell() timestamp = optimize_timestamp(pred_shell_header['timestamp']) + 1 protocol = self.shell.blocks[block_id].protocols()['next_protocol'] level = int(pred_shell_header['level']) + 1 dummy_signature = base58_encode(b'\x00' * 64, b'sig').decode() protocol_data = { 'protocol': protocol, **self.protocol_data, } if level % int( sandbox_params['blocks_per_commitment']) == 0: # type: ignore protocol_data['seed_nonce_hash'] = base58_encode( b'\x00' * 32, b'nce').decode() if 'priority' in protocol_data: baker = self.key.public_key_hash() baking_rights = self.shell.blocks[block_id].helpers.baking_rights( delegate=baker) # NOTE: Fails if baker has no baking rights protocol_data['priority'] = next(item['priority'] for item in baking_rights if item['delegate'] == baker) operations = [[{ 'protocol': protocol, 'branch': operation['branch'], 'contents': operation['contents'], 'signature': operation['signature'], } for operation in operation_list] for operation_list in self.operations] payload = { 'protocol_data': { **protocol_data, 'signature': dummy_signature, }, 'operations': operations, } res = self.shell.blocks[block_id].helpers.preapply.block.post( block=payload, sort=True, timestamp=timestamp, ) forged_operations = [[{ 'branch': operation['branch'], 'data': operation['data'], } for operation in operation_list['applied']] for operation_list in res['operations']] return self._spawn( shell_header=res['shell_header'], operations=forged_operations, protocol_data=protocol_data, signature=dummy_signature, )
def get_dummy_key_hash(self) -> str: if self.key: return self.key.public_key_hash() else: return base58_encode(b'\x00' * 20, b'tz1').decode()
def hash(self) -> str: """Calculate the Base58 encoded operation group hash.""" hash_digest = blake2b_32(self.binary_payload()).digest() return base58_encode(hash_digest, b'o').decode()
def get_dummy_signature(self) -> str: return base58_encode(b'\x00' * 64, b'sig').decode()