diff --git a/blockstack_cli_0.14.1/rpc/__init__.py b/blockstack_cli_0.14.1/rpc/__init__.py new file mode 100644 index 000000000..f94575abc --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/__init__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" +namecoin-python - Easy-to-use Namecoin API client +""" + + +def connect_to_local(filename=None): + """ + Connect to default namecoin instance owned by this user, on this machine. + + Returns a :class:`~namecoinrpc.connection.NamecoinConnection` object. + + Arguments: + + - `filename`: Path to a configuration file in a non-standard location (optional) + """ + from .connection import NamecoinConnection + from .config import read_default_config + + cfg = read_default_config(filename) + port = int(cfg.get('rpcport', '18332' if cfg.get('testnet') else '8332')) + rcpuser = cfg.get('rpcuser', '') + + return NamecoinConnection(rcpuser, cfg['rpcpassword'], 'localhost', port) + + +def connect_to_remote(user, password, host='localhost', port=8332, + use_https=False): + """ + Connect to remote or alternative local namecoin client instance. + + Returns a :class:`~namecoinrpc.connection.NamecoinConnection` object. + """ + from .connection import NamecoinConnection + + return NamecoinConnection(user, password, host, port, use_https) diff --git a/blockstack_cli_0.14.1/rpc/config.py b/blockstack_cli_0.14.1/rpc/config.py new file mode 100644 index 000000000..0e2624ff4 --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/config.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +Utilities for reading namecoin configuration files. +""" + +def read_config_file(filename): + """ + Read a simple ``'='``-delimited config file. + Raises :const:`IOError` if unable to open file, or :const:`ValueError` + if an parse error occurs. + """ + f = open(filename) + try: + cfg = {} + for line in f: + line = line.strip() + if line and not line.startswith("#"): + try: + (key, value) = line.split('=', 1) + cfg[key] = value + except ValueError: + pass # Happens when line has no '=', ignore + finally: + f.close() + return cfg + + +def read_default_config(filename=None): + """ + Read namecoin default configuration from the current user's home directory. + + Arguments: + + - `filename`: Path to a configuration file in a non-standard location (optional) + """ + if filename is None: + import os + import platform + home = os.getenv("HOME") + if not home: + raise IOError("Home directory not defined, don't know where to look for config file") + + if platform.system() == "Darwin": + location = 'Library/Application Support/Namecoin/namecoin.conf' + else: + location = '.namecoin/namecoin.conf' + filename = os.path.join(home, location) + + elif filename.startswith("~"): + import os + filename = os.path.expanduser(filename) + + try: + return read_config_file(filename) + except (IOError, ValueError): + pass # Cannot read config file, ignore diff --git a/blockstack_cli_0.14.1/rpc/connection.py b/blockstack_cli_0.14.1/rpc/connection.py new file mode 100644 index 000000000..b8686a106 --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/connection.py @@ -0,0 +1,792 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +Connect to Namecoin server via JSON-RPC. +""" +from .proxy import JSONRPCException, AuthServiceProxy +from .exceptions import _wrap_exception, WalletPassphraseIncorrect, WalletAlreadyUnlocked +from .data import (ServerInfo, AccountInfo, AddressInfo, TransactionInfo, + AddressValidation, WorkItem, MiningInfo) + + +class NamecoinConnection(object): + """ + A NamecoinConnection object defines a connection to a namecoin server. + It is a thin wrapper around a JSON-RPC API connection. + + Up-to-date for SVN revision 198. + + Arguments to constructor: + + - *user* -- Authenticate as user. + - *password* -- Authentication password. + - *host* -- Namecoin JSON-RPC host. + - *port* -- Namecoin JSON-RPC port. + """ + def __init__(self, user, password, host='localhost', port=8332, + use_https=False): + """ + Create a new namecoin server connection. + """ + url = 'http{s}://{user}:{password}@{host}:{port}/'.format( + s='s' if use_https else '', + user=user, password=password, host=host, port=port) + self.url = url + try: + self.proxy = AuthServiceProxy(url) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def stop(self): + """ + Stop namecoin server. + """ + try: + self.proxy.stop() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getblock(self, hash): + """ + Returns information about the given block hash. + """ + try: + return self.proxy.getblock(hash) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getblockcount(self): + """ + Returns the number of blocks in the longest block chain. + """ + try: + return self.proxy.getblockcount() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getblockhash(self, index): + """ + Returns hash of block in best-block-chain at index. + + :param index: index ob the block + + """ + try: + return self.proxy.getblockhash(index) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getblocknumber(self): + """ + Returns the block number of the latest block in the longest block chain. + Deprecated. Use getblockcount instead. + """ + return self.getblockcount() + + def getconnectioncount(self): + """ + Returns the number of connections to other nodes. + """ + try: + return self.proxy.getconnectioncount() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getdifficulty(self): + """ + Returns the proof-of-work difficulty as a multiple of the minimum difficulty. + """ + try: + return self.proxy.getdifficulty() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getgenerate(self): + """ + Returns :const:`True` or :const:`False`, depending on whether generation is enabled. + """ + try: + return self.proxy.getgenerate() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def setgenerate(self, generate, genproclimit=None): + """ + Enable or disable generation (mining) of coins. + + Arguments: + + - *generate* -- is :const:`True` or :const:`False` to turn generation on or off. + - *genproclimit* -- Number of processors that are used for generation, -1 is unlimited. + + """ + try: + if genproclimit is None: + return self.proxy.setgenerate(generate) + else: + return self.proxy.setgenerate(generate, genproclimit) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def gethashespersec(self): + """ + Returns a recent hashes per second performance measurement while generating. + """ + try: + return self.proxy.gethashespersec() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getinfo(self): + """ + Returns an :class:`~namecoinrpc.data.ServerInfo` object containing various state info. + """ + try: + return ServerInfo(**self.proxy.getinfo()) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getmininginfo(self): + """ + Returns an :class:`~namecoinrpc.data.MiningInfo` object containing various + mining state info. + """ + try: + return MiningInfo(**self.proxy.getmininginfo()) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getnewaddress(self, account=None): + """ + Returns a new namecoin address for receiving payments. + + Arguments: + + - *account* -- If account is specified (recommended), it is added to the address book + so that payments received with the address will be credited to it. + + """ + try: + if account is None: + return self.proxy.getnewaddress() + else: + return self.proxy.getnewaddress(account) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getaccountaddress(self, account): + """ + Returns the current namecoin address for receiving payments to an account. + + Arguments: + + - *account* -- Account for which the address should be returned. + + """ + try: + return self.proxy.getaccountaddress(account) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def setaccount(self, namecoinaddress, account): + """ + Sets the account associated with the given address. + + Arguments: + + - *namecoinaddress* -- Namecoin address to associate. + - *account* -- Account to associate the address to. + + """ + try: + return self.proxy.setaccount(namecoinaddress, account) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getaccount(self, namecoinaddress): + """ + Returns the account associated with the given address. + + Arguments: + + - *namecoinaddress* -- Namecoin address to get account for. + """ + try: + return self.proxy.getaccount(namecoinaddress) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getaddressesbyaccount(self, account): + """ + Returns the list of addresses for the given account. + + Arguments: + + - *account* -- Account to get list of addresses for. + """ + try: + return self.proxy.getaddressesbyaccount(account) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def sendtoaddress(self, namecoinaddress, amount, comment=None, comment_to=None): + """ + Sends *amount* from the server's available balance to *namecoinaddress*. + + Arguments: + + - *namecoinaddress* -- Namecoin address to send to. + - *amount* -- Amount to send (float, rounded to the nearest 0.01). + - *minconf* -- Minimum number of confirmations required for transferred balance. + - *comment* -- Comment for transaction. + - *comment_to* -- Comment for to-address. + + """ + try: + if comment is None: + return self.proxy.sendtoaddress(namecoinaddress, amount) + elif comment_to is None: + return self.proxy.sendtoaddress(namecoinaddress, amount, comment) + else: + return self.proxy.sendtoaddress(namecoinaddress, amount, comment, comment_to) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getreceivedbyaddress(self, namecoinaddress, minconf=1): + """ + Returns the total amount received by a namecoin address in transactions with at least a + certain number of confirmations. + + Arguments: + + - *namecoinaddress* -- Address to query for total amount. + + - *minconf* -- Number of confirmations to require, defaults to 1. + """ + try: + return self.proxy.getreceivedbyaddress(namecoinaddress, minconf) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getreceivedbyaccount(self, account, minconf=1): + """ + Returns the total amount received by addresses with an account in transactions with + at least a certain number of confirmations. + + Arguments: + + - *account* -- Account to query for total amount. + - *minconf* -- Number of confirmations to require, defaults to 1. + + """ + try: + return self.proxy.getreceivedbyaccount(account, minconf) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def gettransaction(self, txid): + """ + Get detailed information about transaction + + Arguments: + + - *txid* -- Transactiond id for which the info should be returned + + """ + try: + return TransactionInfo(**self.proxy.gettransaction(txid)) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getrawtransaction(self, txid, verbose=True): + """ + Get transaction raw info + + Arguments: + + - *txid* -- Transactiond id for which the info should be returned. + - *verbose* -- If False, return only the "hex" of the transaction. + + """ + try: + if verbose: + return TransactionInfo(**self.proxy.getrawtransaction(txid, 1)) + return self.proxy.getrawtransaction(txid, 0) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def createrawtransaction(self, inputs, outputs): + """ + Creates a raw transaction spending given inputs + (a list of dictionaries, each containing a transaction id and an output number), + sending to given address(es). + + Returns hex-encoded raw transaction. + + Example usage: + >>> conn.createrawtransaction( + [{"txid": "a9d4599e15b53f3eb531608ddb31f48c695c3d0b3538a6bda871e8b34f2f430c", + "vout": 0}], + {"mkZBYBiq6DNoQEKakpMJegyDbw2YiNQnHT":50}) + + + Arguments: + + - *inputs* -- A list of {"txid": txid, "vout": n} dictionaries. + - *outputs* -- A dictionary mapping (public) addresses to the amount + they are to be paid. + """ + try: + return self.proxy.createrawtransaction(inputs, outputs) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def signrawtransaction(self, hexstring, previous_transactions=None, private_keys=None): + """ + Sign inputs for raw transaction (serialized, hex-encoded). + + Returns a dictionary with the keys: + "hex": raw transaction with signature(s) (hex-encoded string) + "complete": 1 if transaction has a complete set of signature(s), 0 if not + + Arguments: + + - *hexstring* -- A hex string of the transaction to sign. + - *previous_transactions* -- A (possibly empty) list of dictionaries of the form: + {"txid": txid, "vout": n, "scriptPubKey": hex, "redeemScript": hex}, representing + previous transaction outputs that this transaction depends on but may not yet be + in the block chain. + - *private_keys* -- A (possibly empty) list of base58-encoded private + keys that, if given, will be the only keys used to sign the transaction. + """ + try: + return dict(self.proxy.signrawtransaction(hexstring, previous_transactions, private_keys)) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def decoderawtransaction(self, hexstring): + """ + Produces a human-readable JSON object for a raw transaction. + + Arguments: + + - *hexstring* -- A hex string of the transaction to be decoded. + """ + try: + return dict(self.proxy.decoderawtransaction(hexstring)) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listsinceblock(self, block_hash): + try: + res = self.proxy.listsinceblock(block_hash) + res['transactions'] = [TransactionInfo(**x) for x in res['transactions']] + return res + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listreceivedbyaddress(self, minconf=1, includeempty=False): + """ + Returns a list of addresses. + + Each address is represented with a :class:`~namecoinrpc.data.AddressInfo` object. + + Arguments: + + - *minconf* -- Minimum number of confirmations before payments are included. + - *includeempty* -- Whether to include addresses that haven't received any payments. + + """ + try: + return [AddressInfo(**x) for x in + self.proxy.listreceivedbyaddress(minconf, includeempty)] + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listaccounts(self, minconf=1, as_dict=False): + """ + Returns a list of account names. + + Arguments: + + - *minconf* -- Minimum number of confirmations before payments are included. + - *as_dict* -- Returns a dictionary of account names, with their balance as values. + """ + try: + if as_dict: + return dict(self.proxy.listaccounts(minconf)) + else: + return self.proxy.listaccounts(minconf).keys() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listreceivedbyaccount(self, minconf=1, includeempty=False): + """ + Returns a list of accounts. + + Each account is represented with a :class:`~namecoinrpc.data.AccountInfo` object. + + Arguments: + + - *minconf* -- Minimum number of confirmations before payments are included. + + - *includeempty* -- Whether to include addresses that haven't received any payments. + """ + try: + return [AccountInfo(**x) for x in + self.proxy.listreceivedbyaccount(minconf, includeempty)] + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listtransactions(self, account=None, count=10, from_=0, address=None): + """ + Returns a list of the last transactions for an account. + + Each transaction is represented with a :class:`~namecoinrpc.data.TransactionInfo` object. + + Arguments: + + - *account* -- Account to list transactions from. Return transactions from + all accounts if None. + - *count* -- Number of transactions to return. + - *from_* -- Skip the first transactions. + - *address* -- Receive address to consider + """ + accounts = [account] if account is not None else self.listaccounts(as_dict=True).iterkeys() + try: + return [TransactionInfo(**tx) for acc in accounts for + tx in self.proxy.listtransactions(acc, count, from_) if + address is None or tx["address"] == address] + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def backupwallet(self, destination): + """ + Safely copies ``wallet.dat`` to *destination*, which can be a directory or a path + with filename. + + Arguments: + - *destination* -- directory or path with filename to backup wallet to. + + """ + try: + return self.proxy.backupwallet(destination) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + """def validateaddress(self, validateaddress): + Validate a namecoin address and return information for it. + + The information is represented by a :class:`~namecoinrpc.data.AddressValidation` object. + + Arguments: -- Address to validate. + + + - *validateaddress* + + try: + return AddressValidation(**self.proxy.validateaddress(validateaddress)) + except JSONRPCException as e: + raise _wrap_exception(e.error) + """ + + def getbalance(self, account=None, minconf=None): + """ + Get the current balance, either for an account or the total server balance. + + Arguments: + - *account* -- If this parameter is specified, returns the balance in the account. + - *minconf* -- Minimum number of confirmations required for transferred balance. + + """ + args = [] + if account: + args.append(account) + if minconf is not None: + args.append(minconf) + try: + return self.proxy.getbalance(*args) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def move(self, fromaccount, toaccount, amount, minconf=1, comment=None): + """ + Move from one account in your wallet to another. + + Arguments: + + - *fromaccount* -- Source account name. + - *toaccount* -- Destination account name. + - *amount* -- Amount to transfer. + - *minconf* -- Minimum number of confirmations required for transferred balance. + - *comment* -- Comment to add to transaction log. + + """ + try: + if comment is None: + return self.proxy.move(fromaccount, toaccount, amount, minconf) + else: + return self.proxy.move(fromaccount, toaccount, amount, minconf, comment) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def sendfrom(self, fromaccount, tonamecoinaddress, amount, minconf=1, comment=None, + comment_to=None): + """ + Sends amount from account's balance to namecoinaddress. This method will fail + if there is less than amount namecoins with minconf confirmations in the account's + balance (unless account is the empty-string-named default account; it + behaves like the sendtoaddress method). Returns transaction ID on success. + + Arguments: + + - *fromaccount* -- Account to send from. + - *tonamecoinaddress* -- Namecoin address to send to. + - *amount* -- Amount to send (float, rounded to the nearest 0.01). + - *minconf* -- Minimum number of confirmations required for transferred balance. + - *comment* -- Comment for transaction. + - *comment_to* -- Comment for to-address. + + """ + try: + if comment is None: + return self.proxy.sendfrom(fromaccount, tonamecoinaddress, amount, minconf) + elif comment_to is None: + return self.proxy.sendfrom(fromaccount, tonamecoinaddress, amount, minconf, comment) + else: + return self.proxy.sendfrom(fromaccount, tonamecoinaddress, amount, minconf, + comment, comment_to) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def sendmany(self, fromaccount, todict, minconf=1, comment=None): + """ + Sends specified amounts from account's balance to namecoinaddresses. This method will fail + if there is less than total amount namecoins with minconf confirmations in the account's + balance (unless account is the empty-string-named default account; Returns transaction ID + on success. + + Arguments: + + - *fromaccount* -- Account to send from. + - *todict* -- Dictionary with Namecoin addresses as keys and amounts as values. + - *minconf* -- Minimum number of confirmations required for transferred balance. + - *comment* -- Comment for transaction. + + """ + try: + if comment is None: + return self.proxy.sendmany(fromaccount, todict, minconf) + else: + return self.proxy.sendmany(fromaccount, todict, minconf, comment) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def verifymessage(self, namecoinaddress, signature, message): + """ + Verifies a signature given the namecoinaddress used to sign, + the signature itself, and the message that was signed. + Returns :const:`True` if the signature is valid, and :const:`False` if it is invalid. + + Arguments: + + - *namecoinaddress* -- the namecoinaddress used to sign the message + - *signature* -- the signature to be verified + - *message* -- the message that was originally signed + + """ + try: + return self.proxy.verifymessage(namecoinaddress, signature, message) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def getwork(self, data=None): + """ + Get work for remote mining, or submit result. + If data is specified, the server tries to solve the block + using the provided data and returns :const:`True` if it was successful. + If not, the function returns formatted hash data (:class:`~namecoinrpc.data.WorkItem`) + to work on. + + Arguments: + + - *data* -- Result from remote mining. + + """ + try: + if data is None: + # Only if no data provided, it returns a WorkItem + return WorkItem(**self.proxy.getwork()) + else: + return self.proxy.getwork(data) + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def listunspent(self, minconf=1, maxconf=999999): + """ + Returns a list of unspent transaction inputs in the wallet. + + Arguments: + + - *minconf* -- Minimum number of confirmations required to be listed. + + - *maxconf* -- Maximal number of confirmations allowed to be listed. + + + """ + try: + return [TransactionInfo(**tx) for tx in + self.proxy.listunspent(minconf, maxconf)] + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def keypoolrefill(self): + "Fills the keypool, requires wallet passphrase to be set." + try: + self.proxy.keypoolrefill() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def walletpassphrase(self, passphrase, timeout, dont_raise=False): + """ + Stores the wallet decryption key in memory for seconds. + + - *passphrase* -- The wallet passphrase. + + - *timeout* -- Time in seconds to keep the wallet unlocked + (by keeping the passphrase in memory). + + - *dont_raise* -- instead of raising `~namecoinrpc.exceptions.WalletPassphraseIncorrect` + return False. + """ + try: + self.proxy.walletpassphrase(passphrase, timeout) + return True + except JSONRPCException as e: + json_exception = _wrap_exception(e.error) + if dont_raise: + if isinstance(json_exception, WalletPassphraseIncorrect): + return False + elif isinstance(json_exception, WalletAlreadyUnlocked): + return True + raise json_exception + + def walletlock(self): + """ + Removes the wallet encryption key from memory, locking the wallet. + After calling this method, you will need to call walletpassphrase + again before being able to call any methods which require the wallet + to be unlocked. + """ + try: + return self.proxy.walletlock() + except JSONRPCException as e: + raise _wrap_exception(e.error) + + def walletpassphrasechange(self, oldpassphrase, newpassphrase, dont_raise=False): + """ + Changes the wallet passphrase from to . + + Arguments: + + - *dont_raise* -- instead of raising `~namecoinrpc.exceptions.WalletPassphraseIncorrect` + return False. + """ + try: + self.proxy.walletpassphrasechange(oldpassphrase, newpassphrase) + return True + except JSONRPCException as e: + json_exception = _wrap_exception(e.error) + if dont_raise and isinstance(json_exception, WalletPassphraseIncorrect): + return False + raise json_exception + + +#------------------------------------------------------------------------ +# +#################### Added commands for Namecoind read-only server ###### +# +#------------------------------------------------------------------------ + + def name_scan(self, start_name = None, max_returned = 500): + """namecoind command 'name_scan': scan all names, starting at start-name and returning a + maximum number of entries (default 500) + + Arguments: + + - *start_name* -- listing starts from the start_name upto max_returned + if None: results are returned from start + + - *max_returned* -- max number of results to return + + """ + + try: + if start_name == None: + return self.proxy.name_scan() + else: + return self.proxy.name_scan(start_name, max_returned) + except JSONRPCException as e: + return e.error + + + def name_history(self, name): + """namecoind command 'name_history': List all name values of a name + + Arguments: + + - *name* -- the name whose history is to be returned + """ + + try: + return self.proxy.name_history(name) + except JSONRPCException as e: + return e.error + + def name_show(self, name): + """namecoind command 'name_show': show values of a name + + Arguments: + + - *name* -- the name whose details is to be returned + """ + + try: + return self.proxy.name_show(name) + except JSONRPCException as e: + return e.error + + def name_list(self): + """namecoind command 'name_list': list my own names""" + + try: + return self.proxy.name_list() + except JSONRPCException as e: + return e.error + diff --git a/blockstack_cli_0.14.1/rpc/data.py b/blockstack_cli_0.14.1/rpc/data.py new file mode 100644 index 000000000..c56339431 --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/data.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +Namecoin RPC service, data objects. +""" +from .util import DStruct + + +class ServerInfo(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.getinfo`. + + - *errors* -- Number of errors. + + - *blocks* -- Number of blocks. + + - *paytxfee* -- Amount of transaction fee to pay. + + - *keypoololdest* -- Oldest key in keypool. + + - *genproclimit* -- Processor limit for generation. + + - *connections* -- Number of connections to other clients. + + - *difficulty* -- Current generating difficulty. + + - *testnet* -- True if connected to testnet, False if on real network. + + - *version* -- Namecoin client version. + + - *proxy* -- Proxy configured in client. + + - *hashespersec* -- Number of hashes per second (if generation enabled). + + - *balance* -- Total current server balance. + + - *generate* -- True if generation enabled, False if not. + + - *unlocked_until* -- Timestamp (seconds since epoch) after which the wallet + will be/was locked (if wallet encryption is enabled). + + """ + + +class AccountInfo(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.listreceivedbyaccount`. + + - *account* -- The account of the receiving address. + + - *amount* -- Total amount received by the address. + + - *confirmations* -- Number of confirmations of the most recent transaction included. + + """ + + +class AddressInfo(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.listreceivedbyaddress`. + + - *address* -- Receiving address. + + - *account* -- The account of the receiving address. + + - *amount* -- Total amount received by the address. + + - *confirmations* -- Number of confirmations of the most recent transaction included. + + """ + + +class TransactionInfo(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.listtransactions`. + + - *account* -- account name. + + - *address* -- the address namecoins were sent to, or received from. + + - *category* -- will be generate, send, receive, or move. + + - *amount* -- amount of transaction. + + - *fee* -- Fee (if any) paid (only for send transactions). + + - *confirmations* -- number of confirmations (only for generate/send/receive). + + - *txid* -- transaction ID (only for generate/send/receive). + + - *otheraccount* -- account funds were moved to or from (only for move). + + - *message* -- message associated with transaction (only for send). + + - *to* -- message-to associated with transaction (only for send). + """ + + +class AddressValidation(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.validateaddress`. + + - *isvalid* -- Validatity of address (:const:`True` or :const:`False`). + + - *ismine* -- :const:`True` if the address is in the server's wallet. + + - *address* -- Namecoin address. + + """ + + +class WorkItem(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.getwork`. + + - *midstate* -- Precomputed hash state after hashing the first half of the data. + + - *data* -- Block data. + + - *hash1* -- Formatted hash buffer for second hash. + + - *target* -- Little endian hash target. + + """ + + +class MiningInfo(DStruct): + """ + Information object returned by :func:`~namecoinrpc.connection.NamecoinConnection.getmininginfo`. + + - *blocks* -- Number of blocks. + + - *currentblocksize* -- Size of current block. + + - *currentblocktx* -- Number of transactions in current block. + + - *difficulty* -- Current generating difficulty. + + - *errors* -- Number of errors. + + - *generate* -- True if generation enabled, False if not. + + - *genproclimit* -- Processor limit for generation. + + - *hashespersec* -- Number of hashes per second (if generation enabled). + + - *pooledtx* -- Number of pooled transactions. + + - *testnet* -- True if connected to testnet, False if on real network. + + """ diff --git a/blockstack_cli_0.14.1/rpc/exceptions.py b/blockstack_cli_0.14.1/rpc/exceptions.py new file mode 100644 index 000000000..2eb45354d --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/exceptions.py @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" +Exception definitions. +""" + + +class NamecoinException(Exception): + """ + Base class for exceptions received from Namecoin server. + + - *code* -- Error code from ``namecoind``. + """ + # Standard JSON-RPC 2.0 errors + INVALID_REQUEST = -32600, + METHOD_NOT_FOUND = -32601, + INVALID_PARAMS = -32602, + INTERNAL_ERROR = -32603, + PARSE_ERROR = -32700, + + # General application defined errors + MISC_ERROR = -1 # std::exception thrown in command handling + FORBIDDEN_BY_SAFE_MODE = -2 # Server is in safe mode, and command is not allowed in safe mode + TYPE_ERROR = -3 # Unexpected type was passed as parameter + INVALID_ADDRESS_OR_KEY = -5 # Invalid address or key + OUT_OF_MEMORY = -7 # Ran out of memory during operation + INVALID_PARAMETER = -8 # Invalid, missing or duplicate parameter + DATABASE_ERROR = -20 # Database error + DESERIALIZATION_ERROR = -22 # Error parsing or validating structure in raw format + + # P2P client errors + CLIENT_NOT_CONNECTED = -9 # Namecoin is not connected + CLIENT_IN_INITIAL_DOWNLOAD = -10 # Still downloading initial blocks + + # Wallet errors + WALLET_ERROR = -4 # Unspecified problem with wallet (key not found etc.) + WALLET_INSUFFICIENT_FUNDS = -6 # Not enough funds in wallet or account + WALLET_INVALID_ACCOUNT_NAME = -11 # Invalid account name + WALLET_KEYPOOL_RAN_OUT = -12 # Keypool ran out, call keypoolrefill first + WALLET_UNLOCK_NEEDED = -13 # Enter the wallet passphrase with walletpassphrase first + WALLET_PASSPHRASE_INCORRECT = -14 # The wallet passphrase entered was incorrect + WALLET_WRONG_ENC_STATE = -15 # Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + WALLET_ENCRYPTION_FAILED = -16 # Failed to encrypt the wallet + WALLET_ALREADY_UNLOCKED = -17 # Wallet is already unlocked + + def __init__(self, error): + Exception.__init__(self, error['message']) + self.code = error['code'] + + +##### General application defined errors +class SafeMode(NamecoinException): + """ + Operation denied in safe mode (run ``namecoind`` with ``-disablesafemode``). + """ + + +class JSONTypeError(NamecoinException): + """ + Unexpected type was passed as parameter + """ +InvalidAmount = JSONTypeError # Backwards compatibility + + +class InvalidAddressOrKey(NamecoinException): + """ + Invalid address or key. + """ +InvalidTransactionID = InvalidAddressOrKey # Backwards compatibility + + +class OutOfMemory(NamecoinException): + """ + Out of memory during operation. + """ + + +class InvalidParameter(NamecoinException): + """ + Invalid parameter provided to RPC call. + """ + + +##### Client errors +class ClientException(NamecoinException): + """ + P2P network error. + This exception is never raised but functions as a superclass + for other P2P client exceptions. + """ + + +class NotConnected(ClientException): + """ + Not connected to any peers. + """ + + +class DownloadingBlocks(ClientException): + """ + Client is still downloading blocks. + """ + + +##### Wallet errors +class WalletError(NamecoinException): + """ + Unspecified problem with wallet (key not found etc.) + """ +SendError = WalletError # Backwards compatibility + +class InsufficientFunds(WalletError): + """ + Insufficient funds to complete transaction in wallet or account + """ + +class InvalidAccountName(WalletError): + """ + Invalid account name + """ + + +class KeypoolRanOut(WalletError): + """ + Keypool ran out, call keypoolrefill first + """ + + +class WalletUnlockNeeded(WalletError): + """ + Enter the wallet passphrase with walletpassphrase first + """ + + +class WalletPassphraseIncorrect(WalletError): + """ + The wallet passphrase entered was incorrect + """ + + +class WalletWrongEncState(WalletError): + """ + Command given in wrong wallet encryption state (encrypting an encrypted wallet etc.) + """ + + +class WalletEncryptionFailed(WalletError): + """ + Failed to encrypt the wallet + """ + + +class WalletAlreadyUnlocked(WalletError): + """ + Wallet is already unlocked + """ + + +# For convenience, we define more specific exception classes +# for the more common errors. +_exception_map = { + NamecoinException.FORBIDDEN_BY_SAFE_MODE: SafeMode, + NamecoinException.TYPE_ERROR: JSONTypeError, + NamecoinException.WALLET_ERROR: WalletError, + NamecoinException.INVALID_ADDRESS_OR_KEY: InvalidAddressOrKey, + NamecoinException.WALLET_INSUFFICIENT_FUNDS: InsufficientFunds, + NamecoinException.OUT_OF_MEMORY: OutOfMemory, + NamecoinException.INVALID_PARAMETER: InvalidParameter, + NamecoinException.CLIENT_NOT_CONNECTED: NotConnected, + NamecoinException.CLIENT_IN_INITIAL_DOWNLOAD: DownloadingBlocks, + NamecoinException.WALLET_INSUFFICIENT_FUNDS: InsufficientFunds, + NamecoinException.WALLET_INVALID_ACCOUNT_NAME: InvalidAccountName, + NamecoinException.WALLET_KEYPOOL_RAN_OUT: KeypoolRanOut, + NamecoinException.WALLET_UNLOCK_NEEDED: WalletUnlockNeeded, + NamecoinException.WALLET_PASSPHRASE_INCORRECT: WalletPassphraseIncorrect, + NamecoinException.WALLET_WRONG_ENC_STATE: WalletWrongEncState, + NamecoinException.WALLET_ENCRYPTION_FAILED: WalletEncryptionFailed, + NamecoinException.WALLET_ALREADY_UNLOCKED: WalletAlreadyUnlocked, +} + + +def _wrap_exception(error): + """ + Convert a JSON error object to a more specific Namecoin exception. + """ + return _exception_map.get(error['code'], NamecoinException)(error) diff --git a/blockstack_cli_0.14.1/rpc/proxy.py b/blockstack_cli_0.14.1/rpc/proxy.py new file mode 100644 index 000000000..bd81f7b1d --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/proxy.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: + +""" + Copyright 2011 Jeff Garzik + + AuthServiceProxy has the following improvements over python-jsonrpc's + ServiceProxy class: + + - HTTP connections persist for the life of the AuthServiceProxy object + (if server supports HTTP/1.1) + - sends protocol 'version', per JSON-RPC 1.1 + - sends proper, incrementing 'id' + - sends Basic HTTP authentication headers + - parses all JSON numbers that look like floats as Decimal + - uses standard Python json lib + + Previous copyright, from python-jsonrpc/jsonrpc/proxy.py: + + Copyright (c) 2007 Jan-Klaas Kollhof + + This file is part of jsonrpc. + + jsonrpc is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This software is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this software; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + +try: + import http.client as httplib +except ImportError: + import httplib +import base64 +import json +import decimal +try: + import urllib.parse as urlparse +except ImportError: + import urlparse + +USER_AGENT = "AuthServiceProxy/0.1" + +HTTP_TIMEOUT = 30 + + +class JSONRPCException(Exception): + def __init__(self, rpcError): + Exception.__init__(self) + self.error = rpcError + + +class AuthServiceProxy(object): + def __init__(self, serviceURL, serviceName=None): + self.__serviceURL = serviceURL + self.__serviceName = serviceName + self.__url = urlparse.urlparse(serviceURL) + if self.__url.port is None: + port = 80 + else: + port = self.__url.port + self.__idcnt = 0 + authpair = "%s:%s" % (self.__url.username, self.__url.password) + authpair = authpair.encode('utf8') + self.__authhdr = "Basic ".encode('utf8') + base64.b64encode(authpair) + if self.__url.scheme == 'https': + self.__conn = httplib.HTTPSConnection(self.__url.hostname, port, None, None,False, + HTTP_TIMEOUT) + else: + self.__conn = httplib.HTTPConnection(self.__url.hostname, port, False, + HTTP_TIMEOUT) + + def __getattr__(self, name): + if self.__serviceName != None: + name = "%s.%s" % (self.__serviceName, name) + return AuthServiceProxy(self.__serviceURL, name) + + def __call__(self, *args): + self.__idcnt += 1 + + postdata = json.dumps({ + 'version': '1.1', + 'method': self.__serviceName, + 'params': args, + 'id': self.__idcnt}) + self.__conn.request('POST', self.__url.path, postdata, + { 'Host' : self.__url.hostname, + 'User-Agent' : USER_AGENT, + 'Authorization' : self.__authhdr, + 'Content-type' : 'application/json' }) + + httpresp = self.__conn.getresponse() + if httpresp is None: + raise JSONRPCException({ + 'code' : -342, 'message' : 'missing HTTP response from server'}) + + resp = httpresp.read() + resp = resp.decode('utf8') + resp = json.loads(resp, parse_float=decimal.Decimal) + if 'error' in resp and resp['error'] != None: + raise JSONRPCException(resp['error']) + elif 'result' not in resp: + raise JSONRPCException({ + 'code' : -343, 'message' : 'missing JSON-RPC result'}) + else: + return resp['result'] + + def _batch(self, rpc_call_list): + postdata = json.dumps(list(rpc_call_list)) + self.__conn.request('POST', self.__url.path, postdata, + { 'Host' : self.__url.hostname, + 'User-Agent' : USER_AGENT, + 'Authorization' : self.__authhdr, + 'Content-type' : 'application/json' }) + + httpresp = self.__conn.getresponse() + if httpresp is None: + raise JSONRPCException({ + 'code' : -342, 'message' : 'missing HTTP response from server'}) + + resp = httpresp.read() + resp = resp.decode('utf8') + resp = json.loads(resp, parse_float=decimal.Decimal) + return resp diff --git a/blockstack_cli_0.14.1/rpc/util.py b/blockstack_cli_0.14.1/rpc/util.py new file mode 100644 index 000000000..ec5320391 --- /dev/null +++ b/blockstack_cli_0.14.1/rpc/util.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +#----------------------- +# Open Name System +# ~~~~~ +# +# :copyright: (c) 2014 by opennamesystem.org +# :license: MIT, see LICENSE for more details. +#----------------------- +# Previous copyright, from bitcoin-python: +# Copyright (c) 2010 Witchspace +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +"""Generic utilities used by namecoin client library.""" +from copy import copy + + +class DStruct(object): + """ + Simple dynamic structure, like :const:`collections.namedtuple` but more flexible + (and less memory-efficient) + """ + # Default arguments. Defaults are *shallow copied*, to allow defaults such as []. + _fields = [] + _defaults = {} + + def __init__(self, *args_t, **args_d): + # order + if len(args_t) > len(self._fields): + raise TypeError("Number of arguments is larger than of predefined fields") + # Copy default values + for (k, v) in self._defaults.iteritems(): + self.__dict__[k] = copy(v) + # Set pass by value arguments + self.__dict__.update(zip(self._fields, args_t)) + # dict + self.__dict__.update(args_d) + + def __repr__(self): + return '{module}.{classname}({slots})'.format( + module=self.__class__.__module__, classname=self.__class__.__name__, + slots=", ".join('{k}={v!r}'.format(k=k, v=v) for k, v in + self.__dict__.iteritems()))