def post_shutdown(self):
        client = SawtoothClient(self.url)

        msg = shutdown_message.ShutdownMessage({})
        msg.SenderID = self._admin_node.Address
        msg.sign_from_node(self._admin_node)

        try:
            client.forward_message(msg)
        except MessageException as me:
            print me
Esempio n. 2
0
    def post_shutdown(self):
        client = SawtoothClient(self.url)

        msg = shutdown_message.ShutdownMessage({})
        msg.SenderID = self._admin_node.Address
        msg.sign_from_node(self._admin_node)

        try:
            client.forward_message(msg)
        except MessageException as me:
            print(me)
Esempio n. 3
0
class ClientController(cmd.Cmd):
    _TxnVerbMap = {'=': 'set', '+=': 'inc', '-=': 'dec'}
    pformat = 'client> '

    def __init__(self, baseurl, keystring=None):
        cmd.Cmd.__init__(self)
        self.prompt = 'client> '
        self._current_state = {}
        self._client = SawtoothClient(baseurl)

        signingkey = generate_signing_key(
            wifstr=keystring) if keystring else generate_signing_key()
        identifier = generate_identifier(signingkey)
        self._local_node = Node(identifier=identifier,
                                signingkey=signingkey,
                                name="txnclient")

    def postcmd(self, flag, line):
        return flag

    def sign_and_post(self, msg):
        msg.SenderID = self._local_node.Identifier
        msg.sign_from_node(self._local_node)

        try:
            result = self._client.forward_message(msg)
            if result:
                pretty_print_dict(result)

        except MessageException as me:
            print me

    # =================================================================
    # COMMANDS
    # =================================================================

    def do_set(self, args):
        """
        set -- Command to set properties of the interpreter
            set url --url <url>
            set nodeid --name <name> --keyfile <file>
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand url|nodeid'
            return

        try:
            if pargs[0] == 'url':
                parser = argparse.ArgumentParser()
                parser.add_argument('--url',
                                    help='url used to connect to a validator',
                                    required=True)
                options = parser.parse_args(pargs)

                self.BaseURL = options.url
                print "server URL set to {0}".format(self.BaseURL)
                return

            elif pargs[0] == 'nodeid':
                pargs = args.split()
                parser = argparse.ArgumentParser()
                parser.add_argument('--name',
                                    help='name to use for the client',
                                    default='txnclient')
                parser.add_argument('--keyfile',
                                    help='name of the file that contains '
                                    'the wif format private key')
                options = parser.parse_args(pargs[1:])

                addr = (socket.gethostbyname("localhost"), 0)
                name = options.name
                if options.keyfile:
                    signingkey = generate_signing_key(
                        wifstr=read_key_file(options.keyfile))
                else:
                    signingkey = generate_signing_key()

                identifier = generate_identifier(signingkey)

                self._local_node = Node(address=addr,
                                        identifier=identifier,
                                        signingkey=signingkey,
                                        name=name)
                print "local id set to {0}".format(self._local_node)
                return

            else:
                print "unknown subcommand; {0}".format(pargs[0])
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

    def do_state(self, args):
        """
        state -- Command to manipulate the current ledger state
            state fetch --store <store>
            state keys
            state value --path <path>
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: fetch|keys|value'
            return

        try:
            if pargs[0] == 'fetch':
                parser = argparse.ArgumentParser()
                parser.add_argument('--store',
                                    choices=TransactionTypes.keys(),
                                    default='endpoint')
                options = parser.parse_args(pargs[1:])

                self._current_state = \
                    self._client.get_store_by_name(
                        txn_type_or_name=TransactionTypes.get(options.store),
                        key='*')
            elif pargs[0] == 'keys':
                try:
                    print self._current_state.keys()
                except:
                    print '[]'

            elif pargs[0] == 'value':
                parser = argparse.ArgumentParser()
                parser.add_argument('--path', required=True)
                options = parser.parse_args(pargs[1:])
                pathargs = options.path.split('.')
                value = self._current_state
                while pathargs:
                    value = value.get(pathargs.pop(0))

                print value

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

    def do_txn(self, args):
        """
        txn -- Command to create IntegerKey transactions
            txn <expr> [ && <expr> ]*
        """
        txn = integer_key.IntegerKeyTransaction()

        # pylint: disable=line-too-long
        pattern = re.compile(
            r"^\s*(?P<name>[a-zA-Z0-9]+)\s*(?P<verb>[+-]?=)\s*(?P<value>[0-9]+)\s*$"
        )  # noqa
        expressions = args.split('&&')
        for expression in expressions:
            match = pattern.match(expression)
            if not match:
                print 'unable to parse the transaction; {0}'.format(expression)
                return

            update = integer_key.Update()
            update.Verb = self._TxnVerbMap[match.group('verb')]
            update.Name = match.group('name')
            update.Value = long(match.group('value'))
            txn.Updates.append(update)

        txn.sign_from_node(self._local_node)

        msg = integer_key.IntegerKeyTransactionMessage()
        msg.Transaction = txn

        self.sign_and_post(msg)

    def do_nodestats(self, args):
        """
        nodestats -- Command to send nodestats messages to validator pool
            nodestats reset --metrics [<metric>]+
            nodestats dump --metrics [<metric>]+ --domains [<domain>]+
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: reset|dump'
            return

        try:
            if pargs[0] == 'reset':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(
                    gossip_debug.ResetStatsMessage(
                        {'MetricList': options.metrics}))
                return

            elif pargs[0] == 'dump':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                parser.add_argument('--domains', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(
                    gossip_debug.DumpNodeStatsMessage({
                        'MetricList':
                        options.metrics,
                        'DomainList':
                        options.domains
                    }))
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

        print 'unknown nodestats command {0}'.format(args)

    def do_peerstats(self, args):
        """
        peerstats -- Command to send peerstats messages to validator pool
            peerstats reset --metrics [<metric>]+
            peerstats dump --metrics [<metric>]+ --peers [<nodeid>]+
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: reset|dump'
            return

        try:
            if pargs[0] == 'reset':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(
                    gossip_debug.ResetPeerStatsMessage(
                        {'MetricList': options.metrics}))
                return

            elif pargs[0] == 'dump':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                parser.add_argument('--peers', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(
                    gossip_debug.DumpPeerStatsMessage({
                        'MetricList':
                        options.metrics,
                        'PeerIDList':
                        options.peers
                    }))
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

        print 'unknown peerstats command {0}'.format(args)

    def do_ping(self, args):
        """
        ping -- Command to send a ping message to validator pool
        """

        self.sign_and_post(gossip_debug.PingMessage({}))

    def do_sping(self, args):
        """
        sping -- Command to send a special ping message to validator pool
        """

        parser = argparse.ArgumentParser()
        parser.add_argument('--address', default=self._local_node.Identifier)
        parser.add_argument('--count', default=2, type=int)
        options = parser.parse_args(args.split())

        msg = SpecialPingMessage()
        msg.Address = options.address
        msg.Count = options.count
        self.sign_and_post(msg)

    def do_dumpquorum(self, args):
        """
        dumpquorum -- Command to request quorum consensus node to dump quorum
            list
        """
        self.sign_and_post(quorum_debug.DumpQuorumMessage({}))

    def do_dumpcnxs(self, args):
        """
        dumpcnxs -- Command to send to the validator pool a request to dump
            current connection information
        """

        self.sign_and_post(gossip_debug.DumpConnectionsMessage({}))

    def do_dumpblks(self, args):
        """
        dumpblks -- Command to send dump blocks request to the validator pool
            dumpblks --blocks <count>
        """

        parser = argparse.ArgumentParser()
        parser.add_argument('--blocks', default=0, type=int)
        options = parser.parse_args(args.split())

        self.sign_and_post(
            gossip_debug.DumpJournalBlocksMessage({'Count': options.blocks}))

    def do_val(self, args):
        """
        val -- Command to send a dump value request to the validator pool
            val <name> [--type <transaction type>]
        """

        pargs = args.split()
        parser = argparse.ArgumentParser()
        parser.add_argument('--type',
                            help='Transaction family',
                            default='/IntegerKeyTransaction')
        options = parser.parse_args(pargs[1:])

        tinfo = {'Name': pargs[0], 'TransactionType': options.type}

        self.sign_and_post(journal_debug.DumpJournalValueMessage(tinfo))

    def do_shutdown(self, args):
        """
        shutdown -- Command to send a shutdown message to the validator pool
        """

        self.sign_and_post(shutdown_message.ShutdownMessage({}))
        return True

    def do_exit(self, args):
        """exit
        Shutdown the simulator and exit the command loop
        """
        return True

    def do_eof(self, args):
        return True
Esempio n. 4
0
class ClientController(cmd.Cmd):
    _TxnVerbMap = {'=': 'set', '+=': 'inc', '-=': 'dec'}
    pformat = 'client> '

    def __init__(self, baseurl, keystring=None):
        cmd.Cmd.__init__(self)
        self.prompt = 'client> '
        self._current_state = {}
        self._client = SawtoothClient(baseurl)

        signingkey = generate_signing_key(
            wifstr=keystring) if keystring else generate_signing_key()
        identifier = generate_identifier(signingkey)
        self._local_node = Node(identifier=identifier,
                                signingkey=signingkey,
                                name="txnclient")

    def postcmd(self, flag, line):
        return flag

    def sign_and_post(self, msg):
        msg.SenderID = self._local_node.Identifier
        msg.sign_from_node(self._local_node)

        try:
            result = self._client.forward_message(msg)
            if result:
                pretty_print_dict(result)

        except MessageException as me:
            print me

    # =================================================================
    # COMMANDS
    # =================================================================

    def do_set(self, args):
        """
        set -- Command to set properties of the interpreter
            set url --url <url>
            set nodeid --name <name> --keyfile <file>
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand url|nodeid'
            return

        try:
            if pargs[0] == 'url':
                parser = argparse.ArgumentParser()
                parser.add_argument('--url',
                                    help='url used to connect to a validator',
                                    required=True)
                options = parser.parse_args(pargs)

                self.BaseURL = options.url
                print "server URL set to {0}".format(self.BaseURL)
                return

            elif pargs[0] == 'nodeid':
                pargs = args.split()
                parser = argparse.ArgumentParser()
                parser.add_argument('--name',
                                    help='name to use for the client',
                                    default='txnclient')
                parser.add_argument('--keyfile',
                                    help='name of the file that contains '
                                         'the wif format private key')
                options = parser.parse_args(pargs[1:])

                addr = (socket.gethostbyname("localhost"), 0)
                name = options.name
                if options.keyfile:
                    signingkey = generate_signing_key(
                        wifstr=read_key_file(options.keyfile))
                else:
                    signingkey = generate_signing_key()

                identifier = generate_identifier(signingkey)

                self._local_node = Node(address=addr,
                                        identifier=identifier,
                                        signingkey=signingkey,
                                        name=name)
                print "local id set to {0}".format(self._local_node)
                return

            else:
                print "unknown subcommand; {0}".format(pargs[0])
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

    def do_state(self, args):
        """
        state -- Command to manipulate the current ledger state
            state fetch --store <store>
            state keys
            state value --path <path>
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: fetch|keys|value'
            return

        try:
            if pargs[0] == 'fetch':
                parser = argparse.ArgumentParser()
                parser.add_argument('--store',
                                    choices=TransactionTypes.keys(),
                                    default='endpoint')
                options = parser.parse_args(pargs[1:])

                self._current_state = \
                    self._client.get_store_by_name(
                        txn_type_or_name=TransactionTypes.get(options.store),
                        key='*')
            elif pargs[0] == 'keys':
                try:
                    print self._current_state.keys()
                except:
                    print '[]'

            elif pargs[0] == 'value':
                parser = argparse.ArgumentParser()
                parser.add_argument('--path', required=True)
                options = parser.parse_args(pargs[1:])
                pathargs = options.path.split('.')
                value = self._current_state
                while pathargs:
                    value = value.get(pathargs.pop(0))

                print value

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

    def do_txn(self, args):
        """
        txn -- Command to create IntegerKey transactions
            txn <expr> [ && <expr> ]*
        """
        txn = integer_key.IntegerKeyTransaction()

        # pylint: disable=line-too-long
        pattern = re.compile(r"^\s*(?P<name>[a-zA-Z0-9]+)\s*(?P<verb>[+-]?=)\s*(?P<value>[0-9]+)\s*$")  # noqa
        expressions = args.split('&&')
        for expression in expressions:
            match = pattern.match(expression)
            if not match:
                print 'unable to parse the transaction; {0}'.format(expression)
                return

            update = integer_key.Update()
            update.Verb = self._TxnVerbMap[match.group('verb')]
            update.Name = match.group('name')
            update.Value = long(match.group('value'))
            txn.Updates.append(update)

        txn.sign_from_node(self._local_node)

        msg = integer_key.IntegerKeyTransactionMessage()
        msg.Transaction = txn

        self.sign_and_post(msg)

    def do_nodestats(self, args):
        """
        nodestats -- Command to send nodestats messages to validator pool
            nodestats reset --metrics [<metric>]+
            nodestats dump --metrics [<metric>]+ --domains [<domain>]+
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: reset|dump'
            return

        try:
            if pargs[0] == 'reset':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(gossip_debug.ResetStatsMessage(
                    {'MetricList': options.metrics}))
                return

            elif pargs[0] == 'dump':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                parser.add_argument('--domains', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(gossip_debug.DumpNodeStatsMessage(
                    {'MetricList': options.metrics,
                     'DomainList': options.domains}))
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

        print 'unknown nodestats command {0}'.format(args)

    def do_peerstats(self, args):
        """
        peerstats -- Command to send peerstats messages to validator pool
            peerstats reset --metrics [<metric>]+
            peerstats dump --metrics [<metric>]+ --peers [<nodeid>]+
        """

        pargs = args.split()
        if len(pargs) == 0:
            print 'missing subcommand: reset|dump'
            return

        try:
            if pargs[0] == 'reset':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(gossip_debug.ResetPeerStatsMessage(
                    {'MetricList': options.metrics}))
                return

            elif pargs[0] == 'dump':
                parser = argparse.ArgumentParser()
                parser.add_argument('--metrics', default=[], nargs='+')
                parser.add_argument('--peers', default=[], nargs='+')
                options = parser.parse_args(pargs[1:])

                self.sign_and_post(gossip_debug.DumpPeerStatsMessage(
                    {'MetricList': options.metrics,
                     'PeerIDList': options.peers}))
                return

        except Exception as e:
            print 'an error occured processing {0}: {1}'.format(args, str(e))
            return

        print 'unknown peerstats command {0}'.format(args)

    def do_ping(self, args):
        """
        ping -- Command to send a ping message to validator pool
        """

        self.sign_and_post(gossip_debug.PingMessage({}))

    def do_sping(self, args):
        """
        sping -- Command to send a special ping message to validator pool
        """

        parser = argparse.ArgumentParser()
        parser.add_argument(
            '--address',
            default=self._local_node.Identifier)
        parser.add_argument('--count', default=2, type=int)
        options = parser.parse_args(args.split())

        msg = SpecialPingMessage()
        msg.Address = options.address
        msg.Count = options.count
        self.sign_and_post(msg)

    def do_dumpquorum(self, args):
        """
        dumpquorum -- Command to request quorum consensus node to dump quorum
            list
        """
        self.sign_and_post(quorum_debug.DumpQuorumMessage({}))

    def do_dumpcnxs(self, args):
        """
        dumpcnxs -- Command to send to the validator pool a request to dump
            current connection information
        """

        self.sign_and_post(gossip_debug.DumpConnectionsMessage({}))

    def do_dumpblks(self, args):
        """
        dumpblks -- Command to send dump blocks request to the validator pool
            dumpblks --blocks <count>
        """

        parser = argparse.ArgumentParser()
        parser.add_argument('--blocks', default=0, type=int)
        options = parser.parse_args(args.split())

        self.sign_and_post(gossip_debug.DumpJournalBlocksMessage(
            {'Count': options.blocks}))

    def do_val(self, args):
        """
        val -- Command to send a dump value request to the validator pool
            val <name> [--type <transaction type>]
        """

        pargs = args.split()
        parser = argparse.ArgumentParser()
        parser.add_argument('--type',
                            help='Transaction family',
                            default='/IntegerKeyTransaction')
        options = parser.parse_args(pargs[1:])

        tinfo = {'Name': pargs[0], 'TransactionType': options.type}

        self.sign_and_post(journal_debug.DumpJournalValueMessage(tinfo))

    def do_shutdown(self, args):
        """
        shutdown -- Command to send a shutdown message to the validator pool
        """

        self.sign_and_post(shutdown_message.ShutdownMessage({}))
        return True

    def do_exit(self, args):
        """exit
        Shutdown the simulator and exit the command loop
        """
        return True

    def do_eof(self, args):
        return True