def _do_config_proposal_create(args): """Executes the 'proposal create' subcommand. Given a key file, and a series of key/value pairs, it generates batches of sawtooth_settings transactions in a BatchList instance. The BatchList is either stored to a file or submitted to a validator, depending on the supplied CLI arguments. """ settings = [s.split('=', 1) for s in args.setting] signer = _read_signer(args.key) txns = [_create_propose_txn(signer, setting) for setting in settings] batch = _create_batch(signer, txns) batch_list = BatchList(batches=[batch]) if args.output is not None: try: with open(args.output, 'wb') as batch_file: batch_file.write(batch_list.SerializeToString()) except IOError as e: raise CliException( 'Unable to write to batch file: {}'.format(str(e))) elif args.url is not None: rest_client = RestClient(args.url) rest_client.send_batches(batch_list) else: raise AssertionError('No target for create set.')
def _do_param_topology(args): """ Executes the 'topology set' subcommand. """ signer = _read_signer(args.key) rest_client = RestClient(args.url) _param_topology(rest_client,signer,args)
def _set_topology(rest_client,signer,args): """ set topology """ param = {} if args.cls: param['cluster'] = args.cls if args.peer: param['peer'] = args.peer if args.oper: param['oper'] = args.oper if args.oper: param['list'] = args.list if args.oper: param['pid'] = args.pid val = json.dumps(param, sort_keys=True, indent=4) print('topology val',val,'>>>') txns = [_create_topology_txn(signer, (TOPOLOGY_SET_NM,val))] batch = _create_batch(signer, txns) batch_list = BatchList(batches=[batch]) if args.url is not None: rest_client = RestClient(args.url) rest_client.send_batches(batch_list) else: raise AssertionError('No target for create set.')
def _do_config_proposal_vote(args): """Executes the 'proposal vote' subcommand. Given a key file, a proposal id and a vote value, it generates a batch of bgx_settings transactions in a BatchList instance. The BatchList is file or submitted to a validator. """ signer = _read_signer(args.key) rest_client = RestClient(args.url) proposals = _get_proposals(rest_client) proposal = None for candidate in proposals.candidates: if candidate.proposal_id == args.proposal_id: proposal = candidate break if proposal is None: raise CliException('No proposal exists with the given id') for vote_record in proposal.votes: if vote_record.public_key == signer.get_public_key().as_hex(): raise CliException( 'A vote has already been recorded with this signing key') txn = _create_vote_txn( signer, args.proposal_id, proposal.proposal.setting, args.vote_value) batch = _create_batch(signer, [txn]) batch_list = BatchList(batches=[batch]) rest_client.send_batches(batch_list)
def do_batch_list(args): rest_client = RestClient(args.url, args.user) batches = rest_client.list_batches() keys = ('batch_id', 'txns', 'signer') headers = tuple(k.upper() for k in keys) def parse_batch_row(batch): return (batch['header_signature'], len(batch.get('transactions', [])), batch['header']['signer_public_key']) if args.format == 'default': fmt.print_terminal_table(headers, batches, parse_batch_row) elif args.format == 'csv': fmt.print_csv(headers, batches, parse_batch_row) elif args.format == 'json' or args.format == 'yaml': data = [{k: d for k, d in zip(keys, parse_batch_row(b))} for b in batches] if args.format == 'yaml': fmt.print_yaml(data) elif args.format == 'json': fmt.print_json(data) else: raise AssertionError('Missing handler: {}'.format(args.format)) else: raise AssertionError('Missing handler: {}'.format(args.format))
def _do_identity_policy_list(args): rest_client = RestClient(args.url) state = rest_client.list_state(subtree=IDENTITY_NAMESPACE + _POLICY_PREFIX) head = state['head'] state_values = state['data'] printable_policies = [] for state_value in state_values: policies_list = PolicyList() decoded = b64decode(state_value['data']) policies_list.ParseFromString(decoded) for policy in policies_list.policies: printable_policies.append(policy) printable_policies.sort(key=lambda p: p.name) if args.format == 'default': tty_width = tty.width() for policy in printable_policies: # Set value width to the available terminal space, or the min width width = tty_width - len(policy.name) - 3 width = width if width > _MIN_PRINT_WIDTH else _MIN_PRINT_WIDTH value = "Entries:\n" for entry in policy.entries: entry_string = (" " * 4) + Policy.EntryType.Name(entry.type) \ + " " + entry.key value += (entry_string[:width] + '...' if len(entry_string) > width else entry_string) + "\n" print('{}: \n {}'.format(policy.name, value)) elif args.format == 'csv': try: writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL) writer.writerow(['POLICY NAME', 'ENTRIES']) for policy in printable_policies: output = [policy.name] for entry in policy.entries: output.append( Policy.EntryType.Name(entry.type) + " " + entry.key) writer.writerow(output) except csv.Error: raise CliException('Error writing CSV') elif args.format == 'json' or args.format == 'yaml': output = {} for policy in printable_policies: value = "Entries: " for entry in policy.entries: entry_string = Policy.EntryType.Name(entry.type) + " " \ + entry.key value += entry_string + " " output[policy.name] = value policies_snapshot = {'head': head, 'policies': output} if args.format == 'json': print(json.dumps(policies_snapshot, indent=2, sort_keys=True)) else: print(yaml.dump(policies_snapshot, default_flow_style=False)[0:-1]) else: raise AssertionError('Unknown format {}'.format(args.format))
def _do_settings_list(args): """Lists the current on-chain configuration values. """ rest_client = RestClient(args.url) state = rest_client.list_state(subtree=SETTINGS_NAMESPACE) prefix = args.filter head = state['head'] state_values = state['data'] printable_settings = [] proposals_address = _key_to_address('sawtooth.settings.vote.proposals') for state_value in state_values: if state_value['address'] == proposals_address: # This is completely internal setting and we won't list it here continue decoded = b64decode(state_value['data']) setting = Setting() setting.ParseFromString(decoded) for entry in setting.entries: if entry.key.startswith(prefix): printable_settings.append(entry) printable_settings.sort(key=lambda s: s.key) if args.format == 'default': tty_width = tty.width() for setting in printable_settings: # Set value width to the available terminal space, or the min width width = tty_width - len(setting.key) - 3 width = width if width > _MIN_PRINT_WIDTH else _MIN_PRINT_WIDTH value = (setting.value[:width] + '...' if len(setting.value) > width else setting.value) print('{}: {}'.format(setting.key, value)) elif args.format == 'csv': try: writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL) writer.writerow(['KEY', 'VALUE']) for setting in printable_settings: writer.writerow([setting.key, setting.value]) except csv.Error: raise CliException('Error writing CSV') elif args.format == 'json' or args.format == 'yaml': settings_snapshot = { 'head': head, 'settings': {setting.key: setting.value for setting in printable_settings} } if args.format == 'json': print(json.dumps(settings_snapshot, indent=2, sort_keys=True)) else: print(yaml.dump(settings_snapshot, default_flow_style=False)[0:-1]) else: raise AssertionError('Unknown format {}'.format(args.format))
def make_rest_apis(urls, users): clients = [] for i, url in enumerate(urls): try: user = users[i] except IndexError: user = '' clients.append(RestClient(url, user)) return clients
def do_state(args): """Runs the batch list or batch show command, printing output to the console Args: args: The parsed arguments sent to the command at runtime """ rest_client = RestClient(args.url, args.user) if args.subcommand == 'list': response = rest_client.list_state(args.subtree, args.head) leaves = response['data'] head = response['head'] keys = ('address', 'size', 'data') headers = tuple(k.upper() for k in keys) def parse_leaf_row(leaf, decode=True): decoded = b64decode(leaf['data']) return (leaf['address'], len(decoded), str(decoded) if decode else leaf['data']) if args.format == 'default': fmt.print_terminal_table(headers, leaves, parse_leaf_row) print('HEAD BLOCK: "{}"'.format(head)) elif args.format == 'csv': fmt.print_csv(headers, leaves, parse_leaf_row) print('(data for head block: "{}")'.format(head)) elif args.format == 'json' or args.format == 'yaml': state_data = { 'head': head, 'data': [{k: d for k, d in zip(keys, parse_leaf_row(l, False))} for l in leaves] } if args.format == 'yaml': fmt.print_yaml(state_data) elif args.format == 'json': fmt.print_json(state_data) else: raise AssertionError('Missing handler: {}'.format(args.format)) else: raise AssertionError('Missing handler: {}'.format(args.format)) if args.subcommand == 'show': output = rest_client.get_leaf(args.address, args.head) if output is not None: print('DATA: "{}"'.format(b64decode(output['data']))) print('HEAD: "{}"'.format(output['head'])) else: raise CliException('No data available at {}'.format(args.address))
def _do_set_topology(args): """ Executes the 'topology set' subcommand. """ signer = _read_signer(args.key) rest_client = RestClient(args.url) _set_topology(rest_client,signer,args) print('topology SET',args.cls,args.peer,'>>>')
def do_peer_list(args): rest_client = RestClient(base_url=args.url) peers = sorted(rest_client.list_peers()) if args.format == 'csv' or args.format == 'default': print(','.join(peers)) elif args.format == 'json': fmt.print_json(peers) elif args.format == 'yaml': fmt.print_yaml(peers)
def do_status_show(args): rest_client = RestClient(base_url=args.url) status = rest_client.get_status() if args.format == 'csv' or args.format == 'default': print(status) elif args.format == 'json': fmt.print_json(status) elif args.format == 'yaml': fmt.print_yaml(status)
def _do_identity_role_list(args): """Lists the current on-chain configuration values. """ rest_client = RestClient(args.url) state = rest_client.list_state(subtree=IDENTITY_NAMESPACE + _ROLE_PREFIX) head = state['head'] state_values = state['data'] printable_roles = [] for state_value in state_values: role_list = RoleList() decoded = b64decode(state_value['data']) role_list.ParseFromString(decoded) for role in role_list.roles: printable_roles.append(role) printable_roles.sort(key=lambda r: r.name) if args.format == 'default': tty_width = tty.width() for role in printable_roles: # Set value width to the available terminal space, or the min width width = tty_width - len(role.name) - 3 width = width if width > _MIN_PRINT_WIDTH else _MIN_PRINT_WIDTH value = (role.policy_name[:width] + '...' if len(role.policy_name) > width else role.policy_name) print('{}: {}'.format(role.name, value)) elif args.format == 'csv': try: writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL) writer.writerow(['KEY', 'VALUE']) for role in printable_roles: writer.writerow([role.name, role.policy_name]) except csv.Error: raise CliException('Error writing CSV') elif args.format == 'json' or args.format == 'yaml': roles_snapshot = { 'head': head, 'roles': {role.name: role.policy_name for role in printable_roles} } if args.format == 'json': print(json.dumps(roles_snapshot, indent=2, sort_keys=True)) else: print(yaml.dump(roles_snapshot, default_flow_style=False)[0:-1]) else: raise AssertionError('Unknown format {}'.format(args.format))
def _do_config_proposal_list(args): """Executes the 'proposal list' subcommand. Given a url, optional filters on prefix and public key, this command lists the current pending proposals for settings changes. """ def _accept(candidate, public_key, prefix): # Check to see if the first public key matches the given public key # (if it is not None). This public key belongs to the user that # created it. has_pub_key = (not public_key or candidate.votes[0].public_key == public_key) has_prefix = candidate.proposal.setting.startswith(prefix) return has_prefix and has_pub_key candidates_payload = _get_proposals(RestClient(args.url)) candidates = [ c for c in candidates_payload.candidates if _accept(c, args.public_key, args.filter) ] if args.format == 'default': for candidate in candidates: print('{}: {} => {}'.format( candidate.proposal_id, candidate.proposal.setting, candidate.proposal.value)) elif args.format == 'csv': writer = csv.writer(sys.stdout, quoting=csv.QUOTE_ALL) writer.writerow(['PROPOSAL_ID', 'KEY', 'VALUE']) for candidate in candidates: writer.writerow([ candidate.proposal_id, candidate.proposal.setting, candidate.proposal.value]) elif args.format == 'json' or args.format == 'yaml': candidates_snapshot = \ {c.proposal_id: {c.proposal.setting: c.proposal.value} for c in candidates} if args.format == 'json': print(json.dumps(candidates_snapshot, indent=2, sort_keys=True)) else: print(yaml.dump(candidates_snapshot, default_flow_style=False)[0:-1]) else: raise AssertionError('Unknown format {}'.format(args.format))
def _do_identity_role_create(args): """Executes the 'role create' subcommand. Given a key file, a role name, and a policy name it generates a batch of sawtooth_identity transactions in a BatchList instance. The BatchList is either stored to a file or submitted to a validator, depending on the supplied CLI arguments. """ signer = _read_signer(args.key) txns = [_create_role_txn(signer, args.name, args.policy)] batch = _create_batch(signer, txns) batch_list = BatchList(batches=[batch]) if args.output is not None: try: with open(args.output, 'wb') as batch_file: batch_file.write(batch_list.SerializeToString()) except IOError as e: raise CliException('Unable to write to batch file: {}'.format( str(e))) elif args.url is not None: rest_client = RestClient(args.url) rest_client.send_batches(batch_list) if args.wait and args.wait > 0: batch_id = batch.header_signature wait_time = 0 start_time = time.time() while wait_time < args.wait: statuses = rest_client.get_statuses([batch_id], args.wait - int(wait_time)) wait_time = time.time() - start_time if statuses[0]['status'] == 'COMMITTED': print('Role committed in {:.6} sec'.format(wait_time)) return # Wait a moment so as not to hammer the Rest Api time.sleep(0.2) print('Wait timed out! Role was not committed...') print('{:128.128} {}'.format(batch_id, statuses[0]['status'])) exit(1) else: raise AssertionError('No target for create set.')
def do_batch_submit(args): try: with open(args.filename, mode='rb') as fd: batches = batch_pb2.BatchList() batches.ParseFromString(fd.read()) except IOError as e: raise CliException(e) rest_client = RestClient(args.url, args.user) start = time.time() for batch_list in _split_batch_list(args, batches): rest_client.send_batches(batch_list) stop = time.time() print('batches: {}, batch/sec: {}'.format( str(len(batches.batches)), len(batches.batches) / (stop - start))) if args.wait and args.wait > 0: batch_ids = [b.header_signature for b in batches.batches] wait_time = 0 start_time = time.time() while wait_time < args.wait: statuses = rest_client.get_statuses(batch_ids, args.wait - int(wait_time)) wait_time = time.time() - start_time if all(s['status'] == 'COMMITTED' for s in statuses): print('All batches committed in {:.6} sec'.format(wait_time)) return # Wait a moment so as not to send another request immediately time.sleep(0.2) print('Wait timed out! Some batches have not yet been committed...') for batch_id, status in statuses[0].items(): print('{} {}'.format(batch_id, status)) exit(1)
def do_batch_show(args): rest_client = RestClient(args.url, args.user) output = rest_client.get_batch(args.batch_id) if args.key: if args.key in output: output = output[args.key] elif args.key in output['header']: output = output['header'][args.key] else: raise CliException('key "{}" not found in batch or header'.format( args.key)) if args.format == 'yaml': fmt.print_yaml(output) elif args.format == 'json': fmt.print_json(output) else: raise AssertionError('Missing handler: {}'.format(args.format))
def do_batch_status(args): """Runs the batch-status command, printing output to the console Args: args: The parsed arguments sent to the command at runtime """ rest_client = RestClient(args.url, args.user) batch_ids = args.batch_ids.split(',') if args.wait and args.wait > 0: statuses = rest_client.get_statuses(batch_ids, args.wait) else: statuses = rest_client.get_statuses(batch_ids) if args.format == 'yaml': fmt.print_yaml(statuses) elif args.format == 'json': fmt.print_json(statuses) else: raise AssertionError('Missing handler: {}'.format(args.format))
def _do_list_topology(args): """ Executes the 'topology list' subcommand. """ #signer = _read_signer(args.key) rest_client = RestClient(args.url) topology = _get_topology(rest_client,args) if topology is None: raise CliException('No topology exists ') """ for vote_record in proposal.votes: if vote_record.public_key == signer.get_public_key().as_hex(): raise CliException( 'A vote has already been recorded with this signing key') """ print('topology ',args.cls,args.peer,'>>>',topology) """
def _param_topology(rest_client,signer,args): """ set topology params """ #print('_param_topology args',args,'>>>') if args.new == '': # show value _param_show(rest_client,args) else: #set value fname = ('' if args.param_name[:4] == "bgx." else "bgx.") + args.param_name txns = [_create_propose_txn(signer, (fname,args.new))] batch = _create_batch(signer, txns) batch_list = BatchList(batches=[batch]) if args.url is not None: rest_client = RestClient(args.url) rest_client.send_batches(batch_list) else: raise AssertionError('No target for create set.')
def do_dag(args): """Runs the head list or block show command, printing output to the console Args: args: The parsed arguments sent to the command at runtime """ rest_client = RestClient(args.url, args.user) if args.subcommand == 'list': heads = sorted(rest_client.list_dag()) if args.format == 'csv' or args.format == 'default': print(','.join(heads)) elif args.format == 'json': fmt.print_json(heads) elif args.format == 'yaml': fmt.print_yaml(heads) if args.subcommand == 'show': output = rest_client.get_dag(args.head_id) if args.key: if args.key in output: output = output[args.key] elif args.key in output['header']: output = output['header'][args.key] else: raise CliException( 'key "{}" not found in block or header'.format(args.key)) if args.format == 'yaml': fmt.print_yaml(output) elif args.format == 'json': fmt.print_json(output) else: raise AssertionError('Missing handler: {}'.format(args.format))
def do_block(args): """Runs the block list or block show command, printing output to the console Args: args: The parsed arguments sent to the command at runtime """ rest_client = RestClient(args.url, args.user) if args.subcommand == 'list': block_generator = rest_client.list_blocks() blocks = [] left = args.count for block in block_generator: blocks.append(block) left -= 1 if left <= 0: break keys = ('num', 'block_id', 'batches', 'txns', 'signer') headers = tuple(k.upper() if k != 'batches' else 'BATS' for k in keys) def parse_block_row(block): batches = block.get('batches', []) txns = [t for b in batches for t in b['transactions']] return ( block['header'].get('block_num', 0), block['header_signature'], len(batches), len(txns), block['header']['signer_public_key']) if args.format == 'default': fmt.print_terminal_table(headers, blocks, parse_block_row) elif args.format == 'csv': fmt.print_csv(headers, blocks, parse_block_row) elif args.format == 'json' or args.format == 'yaml': data = [{k: d for k, d in zip(keys, parse_block_row(b))} for b in blocks] if args.format == 'yaml': fmt.print_yaml(data) elif args.format == 'json': fmt.print_json(data) else: raise AssertionError('Missing handler: {}'.format(args.format)) else: raise AssertionError('Missing handler: {}'.format(args.format)) if args.subcommand == 'show': output = rest_client.get_block(args.block_id) if args.key: if args.key in output: output = output[args.key] elif args.key in output['header']: output = output['header'][args.key] else: raise CliException( 'key "{}" not found in block or header'.format(args.key)) if args.format == 'yaml': fmt.print_yaml(output) elif args.format == 'json': fmt.print_json(output) else: raise AssertionError('Missing handler: {}'.format(args.format))
def do_transaction(args): """Runs the transaction list or show command, printing to the console Args: args: The parsed arguments sent to the command at runtime """ rest_client = RestClient(args.url, args.user) if args.subcommand == 'list': transactions = rest_client.list_transactions() keys = ('transaction_id', 'family', 'version', 'size', 'payload') headers = tuple(k.upper() if k != 'version' else 'VERS' for k in keys) def parse_txn_row(transaction, decode=True): decoded = b64decode(transaction['payload']) return ( transaction['header_signature'], transaction['header']['family_name'], transaction['header']['family_version'], len(decoded), str(decoded) if decode else transaction['payload']) if args.format == 'default': fmt.print_terminal_table(headers, transactions, parse_txn_row) elif args.format == 'csv': fmt.print_csv(headers, transactions, parse_txn_row) elif args.format == 'json' or args.format == 'yaml': data = [{k: d for k, d in zip(keys, parse_txn_row(b, False))} for b in transactions] if args.format == 'yaml': fmt.print_yaml(data) elif args.format == 'json': fmt.print_json(data) else: raise AssertionError('Missing handler: {}'.format(args.format)) else: raise AssertionError('Missing handler: {}'.format(args.format)) if args.subcommand == 'show': output = rest_client.get_transaction(args.transaction_id) if args.key: if args.key == 'payload': output = b64decode(output['payload']) elif args.key in output: output = output[args.key] elif args.key in output['header']: output = output['header'][args.key] else: raise CliException( 'Key "{}" not found in transaction or header'.format( args.key)) if args.format == 'yaml': fmt.print_yaml(output) elif args.format == 'json': fmt.print_json(output) else: raise AssertionError('Missing handler: {}'.format(args.format))