예제 #1
0
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.')
예제 #2
0
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)
예제 #3
0
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.')
예제 #4
0
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)
예제 #5
0
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))
예제 #6
0
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))
예제 #7
0
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))
예제 #8
0
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
예제 #9
0
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))
예제 #10
0
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,'>>>')
예제 #11
0
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)
예제 #12
0
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)
예제 #13
0
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))
예제 #14
0
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))
예제 #15
0
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.')
예제 #16
0
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)
예제 #17
0
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))
예제 #18
0
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))
예제 #19
0
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)
    """
예제 #20
0
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.')
예제 #21
0
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))
예제 #22
0
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))
예제 #23
0
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))