Skip to content

Commit

Permalink
client obj integration
Browse files Browse the repository at this point in the history
  • Loading branch information
habanoz committed Feb 10, 2019
1 parent 58501e6 commit 7faf725
Show file tree
Hide file tree
Showing 13 changed files with 398 additions and 320 deletions.
3 changes: 1 addition & 2 deletions fee.ini
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ delegator_pays_xfer_fee=true
[KTTX]
storage_limit=0
gas_limit=10100
base=100

base=100
Empty file added src/cli/__init__.py
Empty file.
42 changes: 42 additions & 0 deletions src/cli/simple_client_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import subprocess

from util.client_utils import clear_terminal_chars


class SimpleClientManager:
def __init__(self, client_path, verbose=None) -> None:
super().__init__()
self.verbose = verbose
self.client_path = client_path

def send_request(self, cmd):
whole_cmd = self.client_path + cmd
if self.verbose:
print("Command is |{}|".format(whole_cmd))

# execute client
process = subprocess.Popen(whole_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

bytes = []
for b in process.stdout:
bytes.append(b)

process.wait()

buffer = b''.join(bytes).decode('utf-8')

if self.verbose:
print("Answer is |{}|".format(buffer))

return buffer

def sign(self, bytes, key_name):
response = self.send_request(" sign bytes 0x03{} for {}".format(bytes, key_name))

response = clear_terminal_chars(response)

for line in response.splitlines():
if "Signature" in line:
return line.strip("Signature:").strip()

raise Exception("Signature not found in response '{}'".format(response.replace('\n', '')))
75 changes: 75 additions & 0 deletions src/cli/test_walletClientManager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from unittest import TestCase

from cli.wallet_client_manager import WalletClientManager


class TestWalletClientManager(TestCase):
def test_parse_get_manager_for_contract_response(self):
response = """
Disclaimer:
The Tezos network is a new blockchain technology.
Users are solely responsible for any risks associated
with usage of the Tezos network. Users should do their
own research to determine if Tezos is the appropriate
platform for their needs and should apply judgement and
care in their network interactions.
tz1PJnnddwa1P5jg5sChddigxfMccK8nwLiV (known as habanoz)
"""
clientManager = WalletClientManager(None)
manager = clientManager.parse_get_manager_for_contract_response(response)
self.assertEqual('tz1PJnnddwa1P5jg5sChddigxfMccK8nwLiV', manager)

def test_parse_client_list_known_contracts_response(self):
response = """
Disclaimer:
The Tezos network is a new blockchain technology.
Users are solely responsible for any risks associated
with usage of the Tezos network. Users should do their
own research to determine if Tezos is the appropriate
platform for their needs and should apply judgement and
care in their network interactions.
newcontr: KT1XqEHigP5XumZy9i76QyVd6u93VD4HTqJK
habanoz: tz1fyvFH2pd3V9UEq5psqVokVBYkt7rHTKio
mainnetme: tz1a5GGJeyqeQ4ihZqbiRVcvj5rY5kMAt3Xa
"""
clientManager = WalletClientManager(None)
dict = clientManager.parse_client_list_known_contracts_response(response)

self.assertTrue(dict['newcontr'] == 'KT1XqEHigP5XumZy9i76QyVd6u93VD4HTqJK')
self.assertTrue(dict['habanoz'] == 'tz1fyvFH2pd3V9UEq5psqVokVBYkt7rHTKio')
self.assertTrue(dict['mainnetme'] == 'tz1a5GGJeyqeQ4ihZqbiRVcvj5rY5kMAt3Xa')

def test_parse_list_known_addresses_response(self):
response = """
Disclaimer:
The Tezos network is a new blockchain technology.
Users are solely responsible for any risks associated
with usage of the Tezos network. Users should do their
own research to determine if Tezos is the appropriate
platform for their needs and should apply judgement and
care in their network interactions.
habanoz: tz1fyvFH2pd3V9UEq5psqVokVBYkt7rHTKio (unencrypted sk known)
mainnetme: tz1a5GGJeyqeQ4ihZqbiRVcvj5rY5kMAt3Xa (tcp sk known)
zeronetme: tz1MZ72sJEVen3Qgc7uWvqKhKFJW84bNGd6T (unencrypted sk not known)
"""

clientManager = WalletClientManager(None)
dict = clientManager.parse_list_known_addresses_response(response)

habanoz = dict['tz1fyvFH2pd3V9UEq5psqVokVBYkt7rHTKio']

self.assertEqual(habanoz['alias'], 'habanoz')
self.assertEqual(habanoz['sk'], True)

mainnetme = dict['tz1a5GGJeyqeQ4ihZqbiRVcvj5rY5kMAt3Xa']

self.assertEqual(mainnetme['alias'], 'mainnetme')
self.assertEqual(mainnetme['sk'], True)

zeronetme = dict['tz1MZ72sJEVen3Qgc7uWvqKhKFJW84bNGd6T']

self.assertEqual(zeronetme['alias'], 'zeronetme')
self.assertEqual(zeronetme['sk'], False)
141 changes: 141 additions & 0 deletions src/cli/wallet_client_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from cli.simple_client_manager import SimpleClientManager
from util.address_validator import AddressValidator
from util.client_utils import clear_terminal_chars, not_indicator_line


class WalletClientManager(SimpleClientManager):

def __init__(self, client_path, contr_dict_by_alias=None,
addr_dict_by_pkh=None, managers=None, verbose=None) -> None:
super().__init__(client_path, verbose)

self.managers = managers
if self.managers is None:
self.managers = dict()

self.contr_dict_by_alias = contr_dict_by_alias
self.addr_dict_by_pkh = addr_dict_by_pkh
self.address_dict = None

def get_manager_for_contract(self, pkh):

if pkh.startswith('tz'):
return pkh

if pkh in self.managers:
return self.managers[pkh]

response = self.send_request(" get manager for " + pkh)

response = clear_terminal_chars(response)

manager = self.parse_get_manager_for_contract_response(response)

try:
AddressValidator("manager").validate(manager)
except Exception as e:
raise Exception("Invalid response from client '{}'".format(response),e)
self.managers[pkh] = manager

return manager

def parse_get_manager_for_contract_response(self, response):
manager = None
for line in response.splitlines():
line = line.strip()
if line.startswith("tz"):
line = line.replace(" (", ':')
manager, alias_plus = line.split(":", maxsplit=1)
break

if self.verbose:
print("Manager address is : {}".format(manager))

return manager

def generate_address_dict(self):
if self.address_dict is not None:
return self.address_dict

self.address_dict = {}

if self.contr_dict_by_alias is None:
self.contr_dict_by_alias = self.list_known_contracts_by_alias()

if self.addr_dict_by_pkh is None:
self.addr_dict_by_pkh = self.list_known_addresses_by_pkh()

for pkh, dict_alias_sk in self.addr_dict_by_pkh.items():
self.address_dict[pkh] = {"pkh": pkh, "originated": False, "alias": dict_alias_sk['alias'],
"sk": dict_alias_sk['sk'], "manager": pkh}

for alias, pkh in self.contr_dict_by_alias.items():
if pkh.startswith("KT"):
manager = self.get_manager_for_contract(pkh)
manager_sk = self.addr_dict_by_pkh[manager]['sk']

self.address_dict[pkh] = {"pkh": pkh, "originated": True, "alias": alias, "sk": manager_sk,
"manager": manager}

def list_known_contracts_by_alias(self):
response = self.send_request(" list known contracts")

response = clear_terminal_chars(response)

dict = self.parse_client_list_known_contracts_response(response)

return dict

def parse_client_list_known_contracts_response(self, response):
dict = {}
for line in response.splitlines():
line = line.strip()
if ":" in line and not_indicator_line(line):
alias, pkh = line.split(":", maxsplit=1)
dict[alias.strip()] = pkh.strip()
if self.verbose:
print("known contracts: {}".format(dict))
return dict

def list_known_addresses_by_pkh(self):

response = self.send_request(" list known addresses")

response = clear_terminal_chars(response)

dict = self.parse_list_known_addresses_response(response)

return dict

def get_known_contact_by_alias(self, alias):

if self.contr_dict_by_alias is None:
self.contr_dict_by_alias = self.list_known_contracts_by_alias()

return self.contr_dict_by_alias[alias]

def get_known_contacts_by_alias(self):

if self.contr_dict_by_alias is None:
self.contr_dict_by_alias = self.list_known_contracts_by_alias()

return self.contr_dict_by_alias

def parse_list_known_addresses_response(self, response):
dict = {}

for line in response.splitlines():
line = line.strip()
if ":" in line and not_indicator_line(line):
alias, pkh_plus_braces = line.split(":", maxsplit=1)
pkh_plus_braces = pkh_plus_braces.replace(' (', ':')
pkh, sk_section = pkh_plus_braces.split(":", maxsplit=1)
sk_known = "sk known" in sk_section
pkh = pkh.strip()
alias = alias.strip()
dict[pkh] = {"alias": alias, "sk": sk_known}

if self.verbose:
print("known addresses: {}".format(dict))

return dict
13 changes: 6 additions & 7 deletions src/config/yaml_app_conf_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@


class AppYamlConfParser(YamlConfParser):
def __init__(self, yaml_text, known_contracts, managers, verbose=None) -> None:
def __init__(self, yaml_text, wllt_clnt_mngr, verbose=None) -> None:
super().__init__(yaml_text, verbose)
self.known_contracts = known_contracts
self.managers = managers
self.wllt_clnt_mngr = wllt_clnt_mngr

def parse(self):
yaml_conf_dict = super().parse()
Expand Down Expand Up @@ -99,14 +98,14 @@ def __validate_payment_address(self, conf_obj):
if len(pymnt_addr) == PKH_LENGHT and (pymnt_addr.startswith("KT") or pymnt_addr.startswith("tz")):
conf_obj[('%s_type' % PAYMENT_ADDRESS)] = AddrType.KT if pymnt_addr.startswith("KT") else AddrType.TZ
conf_obj[('%s_pkh' % PAYMENT_ADDRESS)] = pymnt_addr
conf_obj[('%s_manager' % PAYMENT_ADDRESS)] = self.managers[pymnt_addr]
conf_obj[('%s_manager' % PAYMENT_ADDRESS)] = self.wllt_clnt_mngr.get_manager_for_contract(pymnt_addr)
else:
if pymnt_addr in self.known_contracts:
pkh = self.known_contracts[pymnt_addr]
if pymnt_addr in self.wllt_clnt_mngr.get_known_contacts_by_alias():
pkh = self.wllt_clnt_mngr.get_known_contact_by_alias(pymnt_addr)

conf_obj[('%s_type' % PAYMENT_ADDRESS)] = AddrType.KTALS if pkh.startswith("KT") else AddrType.TZALS
conf_obj[('%s_pkh' % PAYMENT_ADDRESS)] = pkh
conf_obj[('%s_manager' % PAYMENT_ADDRESS)] = self.managers[pkh]
conf_obj[('%s_manager' % PAYMENT_ADDRESS)] = self.wllt_clnt_mngr.get_manager_for_contract(pkh)

else:
raise Exception("Payment Address ({}) cannot be translated into a PKH or alias".format(pymnt_addr))
Expand Down
35 changes: 26 additions & 9 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
from NetworkConfiguration import network_config_map
from calc.payment_calculator import PaymentCalculator
from calc.service_fee_calculator import ServiceFeeCalculator
from cli.wallet_client_manager import WalletClientManager
from config.config_parser import ConfigParser
from config.yaml_app_conf_parser import AppYamlConfParser
from config.yaml_conf_parser import YamlConfParser
from log_config import main_logger
from model.payment_log import PaymentRecord
from pay.double_payment_check import check_past_payment
Expand Down Expand Up @@ -306,6 +308,11 @@ def main(args):
if config_dir and not os.path.exists(config_dir):
os.makedirs(config_dir)

network_config = network_config_map[args.network]
client_path = get_client_path([x.strip() for x in args.executable_dirs.split(',')], args.docker, network_config,
args.verbose)
logger.debug("Client command is {}".format(client_path))

config_file = None
for file in os.listdir(config_dir):
if file.endswith(".yaml"):
Expand All @@ -315,13 +322,27 @@ def main(args):
raise Exception(
"Unable to find any '.yaml' configuration files inside configuration directory({})".format(config_dir))

master_config_file_path = os.path.join(config_dir, "master.yaml")
config_file_path = os.path.join(config_dir, config_file)
logger.info("Loading configuration file {}".format(config_file_path))
managers = {'tz1boot1pK9h2BVGXdyvfQSv8kd1LQM6H889': 'tz1boot1pK9h2BVGXdyvfQSv8kd1LQM6H889'}

known_contracts = {}

parser = AppYamlConfParser(ConfigParser.load_file(config_file_path), known_contracts, managers)
master_cfg={}
if os.path.isfile(master_config_file_path):
master_parser = YamlConfParser(ConfigParser.load_file(master_config_file_path))
master_cfg = master_parser.parse()

managers = None
contracts_by_alias = None
addresses_by_pkh = None
if 'managers' in master_cfg:
managers = master_cfg['managers']
if 'contracts_by_alias' in master_cfg:
contracts_by_alias = master_cfg['contracts_by_alias']
if 'addresses_by_pkh' in master_cfg:
addresses_by_pkh = master_cfg['addresses_by_pkh']

wllt_clnt_mngr = WalletClientManager(client_path, contracts_by_alias, addresses_by_pkh, managers)
parser = AppYamlConfParser(ConfigParser.load_file(config_file_path), wllt_clnt_mngr)
parser.parse()
parser.validate()
cfg = parser.get_conf_obj()
Expand Down Expand Up @@ -351,10 +372,6 @@ def main(args):
run_mode = RunMode(args.run_mode)
node_addr = args.node_addr
payment_offset = args.payment_offset
network_config = network_config_map[args.network]
client_path = get_client_path([x.strip() for x in args.executable_dirs.split(',')], args.docker, network_config,
args.verbose)
logger.debug("Client command is {}".format(client_path))

validate_release_override(args.release_override)

Expand Down Expand Up @@ -391,7 +408,7 @@ def main(args):
for i in range(NB_CONSUMERS):
c = PaymentConsumer(name='consumer' + str(i), payments_dir=payments_root, key_name=payment_address,
client_path=client_path, payments_queue=payments_queue, node_addr=node_addr,
verbose=args.verbose, dry_run=dry_run)
wllt_clnt_mngr=wllt_clnt_mngr, verbose=args.verbose, dry_run=dry_run)
time.sleep(1)
c.start()
try:
Expand Down
Loading

0 comments on commit 7faf725

Please sign in to comment.