예제 #1
0
def do_receipt_list(args, config):
    url = config.get("DEFAULT", 'url')

    client = BondClient(base_url=url, keyfile=None)
    state = client.get_all_store_objects()
    if args.org is not None:
        org_obj = try_get_then_lookup(
            state, 'organization',
            ['organization:ticker', 'organization:pricing-source'], args.org)
        if org_obj is not None:
            ListWriter(state, 'receipt', args.full,
                       args.yaml).write('PayeeId', org_obj.get('object-id'))
        else:
            raise ClientException("{} does not match an organization".format(
                args.org))
    elif args.bond is not None:
        bond_obj = try_get_then_lookup(state, 'bond',
                                       ['bond:isin', 'bond:cusip'], args.bond)
        if bond_obj is not None:
            ListWriter(state, 'receipt', args.full,
                       args.yaml).write('BondId', bond_obj.get('object-id'))
        else:
            raise ClientException("{} does not match a bond".format(args.bond))
    else:
        ListWriter(state, 'receipt', args.full, args.yaml).write()
예제 #2
0
def do_quote_list(args, config):
    url = config.get("DEFAULT", 'url')

    client = BondClient(base_url=url, keyfile=None)
    state = client.get_all_store_objects()
    if args.org is not None:
        org_obj = try_get_then_lookup(
            state, 'organization',
            ['organization:ticker', 'organization:pricing-source'], args.org)
        if org_obj is not None:
            ListWriter(state, 'quote', args.full,
                       args.yaml).write('Firm', org_obj.get('pricing-source'))
        else:
            raise ClientException("{} does not match an organization".format(
                args.org))

    elif args.user is not None:
        user_obj = try_get_then_lookup(
            state, 'participant',
            ['participant:username', 'participant:key-id'], args.user)
        if user_obj is not None:
            ListWriter(state, 'quote', args.full,
                       args.yaml).write('CreatorId', user_obj.get('object-id'))
        else:
            raise ClientException("{} does not match a user".format(args.user))

    else:
        ListWriter(state, 'quote', args.full, args.yaml).write()
예제 #3
0
def do_init(args, config):
    username = config.get('DEFAULT', 'username')
    if args.username is not None:
        if len(args.username) < 3 or len(args.username) > 16:
            raise ClientException(
                "username must be between 3 and 16 characters")
        username = args.username
        config.set('DEFAULT', 'username', username)
        print "set username: {}".format(username)
    else:
        print "Username: {}".format(username)

    http_url = config.get('DEFAULT', 'url')
    if args.url is not None:
        http_url = args.url
        config.set('DEFAULT', 'url', http_url)
        print "set url to {}".format(http_url)
    else:
        print "Validator url: {}".format(http_url)

    save_config(config)

    wif_filename = config.get('DEFAULT', 'key_file')
    if wif_filename.endswith(".wif"):
        addr_filename = wif_filename[0:-len(".wif")] + ".addr"
    else:
        addr_filename = wif_filename + ".addr"

    if not os.path.exists(wif_filename):
        try:
            if not os.path.exists(os.path.dirname(wif_filename)):
                os.makedirs(os.path.dirname(wif_filename))

            privkey = pybitcointools.random_key()
            encoded = pybitcointools.encode_privkey(privkey, 'wif')
            addr = pybitcointools.privtoaddr(privkey)

            with open(wif_filename, "w") as wif_fd:
                print "writing file: {}".format(wif_filename)
                wif_fd.write(encoded)
                wif_fd.write("\n")

            with open(addr_filename, "w") as addr_fd:
                print "writing file: {}".format(addr_filename)
                addr_fd.write(addr)
                addr_fd.write("\n")
        except IOError, ioe:
            raise ClientException("IOError: {}".format(str(ioe)))
예제 #4
0
    def state(self):
        if self._current_state is None:
            raise \
                ClientException('Client must be configured with a store name '
                                'to access its current state')

        return self._current_state.state
예제 #5
0
def main(prog_name=os.path.basename(sys.argv[0]), args=sys.argv[1:]):
    parser = create_parser(prog_name)
    args = parser.parse_args(args)

    if args.verbose is None:
        verbose_level = 0
    else:
        verbose_level = args.verbose

    setup_loggers(verbose_level=verbose_level)

    config = load_config()

    if args.command == 'init':
        do_init(args, config)
    elif args.command == 'load':
        do_load(args, config)
    elif args.command == 'bond':
        do_bond(args, config)
    elif args.command == 'org':
        do_org(args, config)
    elif args.command == 'holding':
        do_holding(args, config)
    elif args.command == 'user':
        do_user(args, config)
    elif args.command == 'order':
        do_order(args, config)
    elif args.command == 'quote':
        do_quote(args, config)
    elif args.command == 'settlement':
        do_settlement(args, config)
    elif args.command == 'receipt':
        do_receipt(args, config)
    else:
        raise ClientException("invalid command: {}".format(args.command))
예제 #6
0
def do_submit(args):
    if args.key is not None:
        key_name = args.key
    else:
        key_name = getpass.getuser()

    if args.url is not None:
        url = args.url
    else:
        url = 'http://localhost:8800'

    filename = args.filename
    family_name = args.family

    # If we have a '/' in the key name, treat it as the full path to
    # a wif file, without modification.  If it does not, then assume
    # it is in ~/.sawtooth/keys/.
    if '/' in key_name:
        key_file = key_name
    else:
        key_dir = os.path.join(os.path.expanduser('~'), '.sawtooth', 'keys')
        key_file = os.path.join(key_dir, key_name + '.wif')

    if not os.path.exists(key_file):
        raise ClientException('no such file: {}'.format(key_file))

    try:
        if filename == '-':
            json_content = sys.stdin.read()
        else:
            with open(filename) as fd:
                json_content = fd.read()
    except IOError, e:
        raise CliException(str(e))
예제 #7
0
def do_load(args, config):
    url = config.get('DEFAULT', 'url')
    key_file = config.get('DEFAULT', 'key_file')

    client = BondClient(base_url=url, keyfile=key_file)

    for filename in args.filename:
        try:
            with open(filename) as fd:
                data = yaml.load(fd)
        except IOError, ioe:
            raise ClientException("IOError: {}".format(str(ioe)))

        print "Loading file: {}".format(filename)

        with UpdateBatch(client):
            for i in xrange(0, len(data['Transactions'])):
                for j in xrange(0, len(data['Transactions'][i]["Updates"])):
                    update = data['Transactions'][i]["Updates"][j]
                    if "ObjectId" not in update:
                        update["ObjectId"] = \
                            hashlib.sha256(dict2cbor(update)).hexdigest()
                    print "Sending transaction {}, {}...".format(i, j)
                    print "Update ", update
                    client.send_bond_update(update)

        if args.wait:
            client.wait_for_commit()
예제 #8
0
    def sendtxn(self, txntype_name, msgtype_name, minfo):
        """
        Build a transaction for the update, wrap it in a message with all
        of the appropriate signatures and post it to the validator. Will
        not work with UpdatesTransaction txn families but will work with
        txn families in Arcade.
        """

        if self._signing_key is None:
            raise ClientException(
                'can not send transactions as a read-only client')

        txn = {'TransactionType': txntype_name}
        txn = dict(txn, **minfo)
        if 'Dependencies' not in txn:
            txn['Dependencies'] = []

        msg, txnid = _sign_message_with_transaction(txn, msgtype_name,
                                                    self._signing_key)
        try:
            LOGGER.debug('Posting transaction: %s', txnid)
            result = self._communication.postmsg(msgtype_name, msg)
        except MessageException as e:
            LOGGER.warn('Posting transaction failed: %s', str(e))
            return None

        # if there was no exception thrown then all transactions should return
        # a value which is a dictionary with the message that was sent
        assert result

        # if the message was successfully posted, then save the transaction
        # id for future dependencies
        self._last_transaction = txnid
        return txnid
예제 #9
0
    def __init__(self,
                 base_url,
                 store_name=None,
                 name='SawtoothClient',
                 transaction_type=None,
                 message_type=None,
                 keystring=None,
                 keyfile=None,
                 disable_client_validation=False):
        self._base_url = base_url
        self._message_type = message_type
        self._transaction_type = transaction_type

        # An explicit store name takes precedence over a store name
        # implied by the transaction type.
        self._store_name = None
        if store_name is not None:
            self._store_name = store_name.strip('/')
        elif transaction_type is not None:
            self._store_name = transaction_type.TransactionTypeName.strip('/')

        self._communication = _Communication(base_url)
        self._last_transaction = None
        self._local_node = None
        self._update_batch = None
        self._disable_client_validation = disable_client_validation

        # We only keep current state if we have a store name
        self._current_state = None
        if self._store_name is not None:
            state_type = global_store_manager.KeyValueStore
            if transaction_type is not None:
                state_type = transaction_type.TransactionStoreType

            self._current_state = \
                _ClientState(client=self, state_type=state_type)
            self.fetch_state()

        signing_key = None
        if keystring:
            LOGGER.debug("set signing key from string\n%s", keystring)
            signing_key = signed_object.generate_signing_key(wifstr=keystring)
        elif keyfile:
            LOGGER.debug("set signing key from file %s", keyfile)
            try:
                signing_key = signed_object.generate_signing_key(
                    wifstr=open(keyfile, "r").read().strip())
            except IOError as ex:
                raise ClientException("Failed to load key file: {}".format(
                    str(ex)))

        if signing_key:
            identifier = signed_object.generate_identifier(signing_key)
            self._local_node = node.Node(identifier=identifier,
                                         signingkey=signing_key,
                                         name=name)
예제 #10
0
def do_keygen(args):
    if args.key_name is not None:
        key_name = args.key_name
    else:
        key_name = getpass.getuser()

    if args.key_dir is not None:
        key_dir = args.key_dir
        if not os.path.exists(key_dir):
            raise ClientException('no such directory: {}'.format(key_dir))
    else:
        key_dir = os.path.join(os.path.expanduser('~'), '.sawtooth', 'keys')
        if not os.path.exists(key_dir):
            if not args.quiet:
                print('creating key directory: {}'.format(key_dir))
            try:
                os.makedirs(key_dir)
            except IOError, e:
                raise ClientException('IOError: {}'.format(str(e)))
예제 #11
0
    def start_batch(self):
        """
        Start a batch of updates to be sent in a single transaction to
        the validator.

        Returns:
            None

        """
        if self._update_batch is not None:
            raise ClientException("Update batch already in progress.")
        self._update_batch = {'Updates': [], 'Dependencies': []}
예제 #12
0
    def fetch_state(self):
        """
        Refresh the state for the client.

        Returns:
            Nothing
        """
        if self._current_state is None:
            raise \
                ClientException('Client must be configured with a store name '
                                'to access its current state')

        self._current_state.fetch()
예제 #13
0
def do_permissioned_validator_registry(args):

    validator_url = 'http://localhost:8800'
    if args.url is not None:
        validator_url = args.url
    client =\
        PermissionedValidatorRegistryClient(args.keyfile,
                                            base_url=validator_url)
    try:
        with open(args.whitelist) as whitelist_fd:
            permissioned_validators = json.load(whitelist_fd)
    except IOError, ex:
        raise ClientException('IOError: {}'.format(str(ex)))
예제 #14
0
def do_holding_list(args, config):
    url = config.get("DEFAULT", 'url')

    client = BondClient(base_url=url, keyfile=None)
    state = client.get_all_store_objects()
    if args.org is not None:
        org_obj = try_get_then_lookup(
            state, 'organization',
            ['organization:ticker', 'organization:pricing-source'], args.org)
        if org_obj is None:
            raise ClientException("--org did not specify an organization")

        ListWriter(state, 'holding', args.full,
                   args.yaml).write('OwnerId', org_obj.get('object-id'))
    else:
        ListWriter(state, 'holding', args.full, args.yaml).write()
예제 #15
0
    def send_batch(self):
        """
        Sends the current batch of transactions to the Validator.

        Returns:
            transaction_id of the update transaction

        """
        if len(self._update_batch) == 0:
            raise ClientException("No updates in batch.")
        msg_info = self._update_batch
        self._update_batch = None

        return self.sendtxn(minfo=msg_info,
                            txntype_name=self._transaction_type,
                            msgtype_name=self._message_type)
예제 #16
0
    def sendtxn(self, txn_type, txn_msg_type, minfo):
        """
        Build a transaction for the update, wrap it in a message with all
        of the appropriate signatures and post it to the validator
        """

        if self._local_node is None:
            raise ClientException(
                'can not send transactions as a read-only client')

        txn_type = txn_type or self._transaction_type
        txn_msg_type = txn_msg_type or self._message_type

        txn = txn_type(minfo=minfo)

        if len(minfo.get('Dependencies', [])) == 0:
            # add the last transaction submitted to ensure that the ordering
            # in the journal matches the order in which we generated them
            if self._last_transaction:
                txn.Dependencies = [self._last_transaction]

        txn.sign_from_node(self._local_node)
        txnid = txn.Identifier

        txn.check_valid(self._current_state.state)

        msg = txn_msg_type()
        msg.Transaction = txn
        msg.SenderID = self._local_node.Identifier
        msg.sign_from_node(self._local_node)

        try:
            LOGGER.debug('Posting transaction: %s', txnid)
            result = self._communication.postmsg(msg.MessageType, msg.dump())
        except MessageException:
            return None

        # if there was no exception thrown then all transactions should return
        # a value which is a dictionary with the message that was sent
        assert result

        # if the message was successfully posted, then save the transaction
        # id for future dependencies this could be a problem if the transaction
        # fails during application
        self._last_transaction = txnid
        txn.apply(self._current_state.state)
        return txnid
예제 #17
0
def do_settlement_list(args, config):
    url = config.get("DEFAULT", 'url')

    client = BondClient(base_url=url, keyfile=None)
    state = client.get_all_store_objects()
    if args.creator is not None:
        user_obj = try_get_then_lookup(
            state, 'participant',
            ['participant:username', 'participant:key-id'], args.creator)
        if user_obj is not None:
            ListWriter(state, 'settlement', args.full,
                       args.yaml).write('CreatorId', user_obj.get('object-id'))
        else:
            raise ClientException("{} does not match a user".format(
                args.creator))
    else:
        ListWriter(state, 'settlement', args.full, args.yaml).write()
예제 #18
0
    def __init__(self,
                 base_url,
                 store_name=None,
                 name='SawtoothClient',
                 txntype_name=None,
                 msgtype_name=None,
                 keystring=None,
                 keyfile=None,
                 disable_client_validation=False):
        self._base_url = base_url
        self._message_type = msgtype_name
        self._transaction_type = txntype_name

        # an explicit store name takes precedence over a store name
        # implied by the transaction type
        self._store_name = None
        if store_name is not None:
            self._store_name = store_name.strip('/')
        elif txntype_name is not None:
            self._store_name = txntype_name.strip('/')

        self._communication = _Communication(base_url)
        self._last_transaction = None
        self._signing_key = None
        self._identifier = None
        self._update_batch = None
        self._disable_client_validation = disable_client_validation

        if keystring:
            LOGGER.debug("set signing key from string\n%s", keystring)
            self._signing_key = signing.encode_privkey(
                signing.decode_privkey(keystring, 'wif'), 'hex')
        elif keyfile:
            LOGGER.debug("set signing key from file %s", keyfile)
            try:
                self._signing_key = signing.encode_privkey(
                    signing.decode_privkey(
                        open(keyfile, "r").read().strip(), 'wif'), 'hex')
            except IOError as ex:
                raise ClientException("Failed to load key file: {}".format(
                    str(ex)))

        if self._signing_key is not None:
            self._identifier = signing.generate_identifier(
                signing.generate_pubkey(self._signing_key))
예제 #19
0
    def get_store(self, key=None, block_id=None, delta=False):
        """
        Generic store retrieval method.  This allows complete flexibility
        in specifying the parameters to the HTTP request.

        This function should only be used when you need absolute control
        over the HTTP request being made to the store.  Otherwise, the
        store convenience methods should be used instead.

        Args:
            key: (optional) The object to retrieve from the store.  If None,
                will returns keys instead of objects.
            block_id: (optional) The block ID to use as ending or starting
                point of retrieval.
            delta: (optional) A flag to indicate of only a delta should be
                returned.  If key is None, this is ignored.

        Returns:
            Either a list of keys, a dictionary of name/value pairs that
            represent one or more objects, or a delta representation of the
            store.

        Notes:
            Reference the Sawtooth Lake Web API documentation for the
            behavior for the key/block_id/delta combinations.

        Raises ClientException if the client object was not created with a
        store name or transaction type.
        """
        if self._store_name is None:
            raise \
                ClientException(
                    'The client must be configured with a store name or '
                    'transaction type')

        return \
            self.get_store_by_name(
                txn_type_or_name=self._store_name,
                key=key,
                block_id=block_id,
                delta=delta)
예제 #20
0
    def __init__(self,
                 base_url,
                 store_name,
                 name='SawtoothClient',
                 transaction_type=None,
                 message_type=None,
                 keystring=None,
                 keyfile=None):
        self._transaction_type = transaction_type
        self._message_type = message_type
        self._base_url = base_url
        self._communication = _Communication(base_url)
        self._last_transaction = None
        self._local_node = None
        state_communication = self._communication if base_url else None
        self._current_state = _ClientState(
            communication=state_communication,
            store_name=store_name,
            state_type=transaction_type.TransactionStoreType
            if transaction_type else global_store_manager.KeyValueStore)
        self._update_batch = None
        self.fetch_state()

        signing_key = None
        if keystring:
            LOGGER.debug("set signing key from string\n%s", keystring)
            signing_key = signed_object.generate_signing_key(wifstr=keystring)
        elif keyfile:
            LOGGER.debug("set signing key from file %s", keyfile)
            try:
                signing_key = signed_object.generate_signing_key(
                    wifstr=open(keyfile, "r").read().strip())
            except IOError as ex:
                raise ClientException("Failed to load key file: {}".format(
                    str(ex)))

        if signing_key:
            identifier = signed_object.generate_identifier(signing_key)
            self._local_node = node.Node(identifier=identifier,
                                         signingkey=signing_key,
                                         name=name)
예제 #21
0
    def send_update(self, updates, dependencies=None):
        """
        Send an update or list of updates to the validator or add them to an
        existing batch.

        Args:
            updates: single update or list of updates to be sent.
            dependencies: ids of transactions dependencies.

        Returns:
            transaction_id if update is sent, None if it is added to a batch.
        """

        if self._update_batch is not None:
            # if we are in batching mode.
            if isinstance(updates, dict):  # accept single update
                self._update_batch['Updates'].append(updates)
            elif isinstance(updates, (list, tuple)):  # or a list
                self._update_batch['Updates'] += updates
            else:
                raise ClientException(
                    "Unexpected updates type {}.".format(type(updates)))
            if dependencies:
                self._update_batch['Dependencies'] += dependencies
            return None  # there is no transaction id yet.
        else:
            if isinstance(updates, dict):  # accept single update
                updates = [updates]

        dependencies = dependencies or []

        return self.sendtxn(
            minfo={
                'Updates': updates,
                'Dependencies': dependencies,
            },
            txntype_name=self._transaction_type,
            msgtype_name=self._message_type)
예제 #22
0
            try:
                os.makedirs(key_dir)
            except IOError, e:
                raise ClientException('IOError: {}'.format(str(e)))

    wif_filename = os.path.join(key_dir, key_name + '.wif')
    addr_filename = os.path.join(key_dir, key_name + '.addr')

    if not args.force:
        file_exists = False
        for filename in [wif_filename, addr_filename]:
            if os.path.exists(filename):
                file_exists = True
                print('file exists: {}'.format(filename), file=sys.stderr)
        if file_exists:
            raise ClientException(
                'files exist, rerun with --force to overwrite existing files')

    privkey = signing.generate_privkey()
    encoded = signing.encode_privkey(privkey)
    pubkey = signing.generate_pubkey(privkey)
    addr = signing.generate_identifier(pubkey)

    try:
        wif_exists = os.path.exists(wif_filename)
        with open(wif_filename, 'w') as wif_fd:
            if not args.quiet:
                if wif_exists:
                    print('overwriting file: {}'.format(wif_filename))
                else:
                    print('writing file: {}'.format(wif_filename))
            wif_fd.write(encoded)
예제 #23
0
        PermissionedValidatorRegistryClient(args.keyfile,
                                            base_url=validator_url)
    try:
        with open(args.whitelist) as whitelist_fd:
            permissioned_validators = json.load(whitelist_fd)
    except IOError, ex:
        raise ClientException('IOError: {}'.format(str(ex)))

    result = {}

    whitelist = permissioned_validators["WhitelistOfPermissionedValidators"]

    if 'WhitelistName' in whitelist:
        whitelist_name = whitelist['WhitelistName']
    else:
        raise ClientException('No WhitelistName')

    if 'PermissionedValidatorPublicKeys' in whitelist:
        permissioned_public_keys =\
            whitelist['PermissionedValidatorPublicKeys']

    if 'PermissionedValidatorAddrs' in whitelist:
        permissioned_addrs = whitelist['PermissionedValidatorAddrs']

    update = {
        'whitelist_name': whitelist_name,
        'verb': 'reg',
        'permissioned_public_keys': permissioned_public_keys,
        'permissioned_addrs': permissioned_addrs
    }
    result['Update'] = update