added options to the rpc schemas, begin testing the new payment key registrations

This commit is contained in:
Aaron Blankstein
2017-09-07 17:26:17 -04:00
parent 26699c511b
commit c006610f75
4 changed files with 507 additions and 48 deletions

View File

@@ -1335,6 +1335,8 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
opt: recipient (str) 'The recipient address, if not this wallet'
opt: min_confs (int) 'The minimum number of confirmations on the initial preorder'
opt: unsafe_reg (str) 'Should we aggressively register the name (ie, use low min confs)'
opt: owner_key (str) 'Owners private key string which will receive the name'
opt: payment_key (str) 'Payers private key string'
"""
# NOTE: if force_data == True, then the zonefile will be the zonefile text itself, not a path.
@@ -1347,7 +1349,7 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
password = get_default_password(password)
conf = config.get_config(config_path)
assert conf
assert conf
res = wallet_ensure_exists(config_path=config_path)
if 'error' in res:
@@ -1372,6 +1374,17 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
else:
unsafe_reg = False
args_ownerkey = getattr(args, 'owner_key', None)
if args_ownerkey is None or len(args_ownerkey) == 0:
owner_key = None
else:
owner_key = args_ownerkey
args_paymentkey = getattr(args, 'payment_key', None)
if args_paymentkey is None or len(args_paymentkey) == 0:
payment_key = None
else:
payment_key = args_paymentkey
# name must be well-formed
error = check_valid_name(fqu)
if error:
@@ -1398,7 +1411,7 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
return {'error': 'Non-standard zone file'}
user_zonefile = zonefile_info['zonefile_str']
else:
# make a default zonefile
_, _, data_pubkey = get_addresses_from_file(config_dir=config_dir)
@@ -1428,9 +1441,16 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
wallet_keys = get_wallet_keys(config_path, password)
if 'error' in wallet_keys:
return wallet_keys
owner_privkey_info = wallet_keys['owner_privkey']
payment_privkey_info = wallet_keys['payment_privkey']
if owner_key:
owner_privkey_info = owner_key
else:
owner_privkey_info = wallet_keys['owner_privkey']
if payment_key:
payment_privkey_info = payment_key
else:
payment_privkey_info = wallet_keys['payment_privkey']
operations = ['preorder', 'register', 'update']
required_checks = ['is_name_available', 'is_payment_address_usable', 'owner_can_receive']
@@ -1499,10 +1519,16 @@ def cli_register(args, config_path=CONFIG_PATH, force_data=False,
rpc = local_api_connect(config_path=config_path)
assert rpc
additionals = {}
if payment_key:
additionals['payment_key'] = payment_key
if owner_key:
additionals['owner_key'] = owner_key
try:
resp = rpc.backend_preorder(fqu, cost_satoshis, user_zonefile, user_profile,
transfer_address, min_payment_confs,
unsafe_reg = unsafe_reg)
unsafe_reg = unsafe_reg, **additionals)
except Exception as e:
log.exception(e)
return {'error': 'Error talking to server, try again.'}
@@ -1535,7 +1561,8 @@ def cli_update(args, config_path=CONFIG_PATH, password=None,
arg: name (str) 'The name to update.'
opt: data (str) 'A path to a file with the zone file data.'
opt: nonstandard (str) 'If true, then do not validate or parse the zone file.'
opt: ownerkey (str) 'A private key string to be used for the update.'
opt: owner_key (str) 'A private key string to be used for the update.'
opt: payment_key (str) 'Payers private key string'
"""
# NOTE: if force_data == True, then the zonefile will be the zonefile text itself, not a path.
@@ -1655,13 +1682,20 @@ def cli_update(args, config_path=CONFIG_PATH, password=None,
assert rpc
try:
args_ownerkey = getattr(args, 'ownerkey', None)
# NOTE: already did safety checks
args_ownerkey = getattr(args, 'owner_key', None)
if args_ownerkey is None or len(args_ownerkey) == 0:
owner_key = None
else:
owner_key = args_ownerkey
resp = rpc.backend_update(fqu, user_data_txt, None, None, owner_key = owner_key )
args_paymentkey = getattr(args, 'payment_key', None)
if args_paymentkey is None or len(args_paymentkey) == 0:
payment_key = None
else:
payment_key = args_paymentkey
# NOTE: already did safety checks
resp = rpc.backend_update(
fqu, user_data_txt, None, None, owner_key = owner_key, payment_key = payment_key)
except Exception as e:
log.exception(e)
return {'error': 'Error talking to server, try again.'}
@@ -1685,7 +1719,8 @@ def cli_transfer(args, config_path=CONFIG_PATH, password=None, interactive=False
help: Transfer a blockchain ID to a new owner
arg: name (str) 'The name to transfer'
arg: address (str) 'The address (base58check-encoded pubkey hash) to receive the name'
opt: ownerkey (str) 'A private key string to be used for the update.'
opt: owner_key (str) 'A private key string to be used for the update.'
opt: payment_key (str) 'Payers private key string'
"""
config_dir = os.path.dirname(config_path)
@@ -1718,13 +1753,20 @@ def cli_transfer(args, config_path=CONFIG_PATH, password=None, interactive=False
assert rpc
try:
args_ownerkey = getattr(args, 'ownerkey', None)
args_ownerkey = getattr(args, 'owner_key', None)
if args_ownerkey is None or len(args_ownerkey) == 0:
owner_key = None
else:
owner_key = args_ownerkey
resp = rpc.backend_transfer(fqu, transfer_address, owner_key = owner_key)
args_paymentkey = getattr(args, 'payment_key', None)
if args_paymentkey is None or len(args_paymentkey) == 0:
payment_key = None
else:
payment_key = args_paymentkey
resp = rpc.backend_transfer(
fqu, transfer_address, owner_key = owner_key, payment_key = payment_key)
except Exception as e:
log.exception(e)
return {'error': 'Error talking to server, try again.'}
@@ -3816,7 +3858,8 @@ def cli_set_zonefile_hash(args, config_path=CONFIG_PATH, password=None):
help: Directly set the hash associated with the name in the blockchain.
arg: name (str) 'The name to update'
arg: zonefile_hash (str) 'The RIPEMD160(SHA256(zonefile)) hash'
arg: ownerkey (str) 'The key to be used if not the wallets ownerkey'
arg: owner_key (str) 'The key to be used if not the wallets ownerkey'
arg: payment_key (str) 'The key to be used if not the wallets paymentkey'
"""
password = get_default_password(password)
@@ -3840,13 +3883,21 @@ def cli_set_zonefile_hash(args, config_path=CONFIG_PATH, password=None):
assert rpc
try:
args_ownerkey = getattr(args, 'ownerkey', None)
args_ownerkey = getattr(args, 'owner_key', None)
# NOTE: already did safety checks
if args_ownerkey is None or len(args_ownerkey) == 0:
owner_key = None
else:
owner_key = args_ownerkey
resp = rpc.backend_update(fqu, None, None, zonefile_hash, owner_key = owner_key )
args_paymentkey = getattr(args, 'payment_key', None)
if args_paymentkey is None or len(args_paymentkey) == 0:
payment_key = None
else:
payment_key = args_paymentkey
# NOTE: already did safety checks
resp = rpc.backend_update(
fqu, None, None, zonefile_hash, owner_key = owner_key, payment_key = payment_key)
except Exception as e:
log.exception(e)
return {'error': 'Error talking to server, try again.'}

View File

@@ -1143,8 +1143,8 @@ def get_wallet(config_path=None, proxy=None):
# RPC method: backend_preorder
def preorder(fqu, cost_satoshis, zonefile_data, profile, transfer_address, min_payment_confs,
proxy=None, config_path=CONFIG_PATH, unsafe_reg = False, owner_privkey = None,
payment_privkey = None):
proxy = None, config_path = CONFIG_PATH, unsafe_reg = False, owner_key = None,
payment_key = None):
"""
Send preorder transaction and enter it in queue.
Queue up additional state so we can update and transfer it as well.
@@ -1171,14 +1171,10 @@ def preorder(fqu, cost_satoshis, zonefile_data, profile, transfer_address, min_p
data['error'] = "Already in queue."
return data
if payment_privkey is None:
payment_privkey_info = get_wallet_payment_privkey_info(config_path=config_path, proxy=proxy)
else:
payment_privkey_info = payment_privkey
if owner_privkey is None:
owner_privkey_info = get_wallet_owner_privkey_info(config_path=config_path, proxy=proxy)
else:
owner_privkey_info = owner_privkey
if payment_key is None:
payment_key = get_wallet_payment_privkey_info(config_path=config_path, proxy=proxy)
if owner_key is None:
owner_key = get_wallet_owner_privkey_info(config_path=config_path, proxy=proxy)
name_data = {
'transfer_address': transfer_address,
@@ -1199,15 +1195,15 @@ def preorder(fqu, cost_satoshis, zonefile_data, profile, transfer_address, min_p
passwd = get_secret('BLOCKSTACK_CLIENT_WALLET_PASSWORD')
if passwd:
name_data['owner_privkey'] = aes_encrypt(
str(owner_privkey_info), hexlify( passwd ))
str(owner_key), hexlify( passwd ))
name_data['payment_privkey'] = aes_encrypt(
str(payment_privkey_info), hexlify( passwd ))
str(payment_key), hexlify( passwd ))
else:
log.warn("Registrar couldn't access wallet password to encrypt privkey," +
" sheepishly refusing to store the private key unencrypted.")
log.debug("async_preorder({}, zonefile_data={}, profile={}, transfer_address={})".format(fqu, zonefile_data, profile, transfer_address))
resp = async_preorder(fqu, payment_privkey_info, owner_privkey_info, cost_satoshis,
resp = async_preorder(fqu, payment_key, owner_key, cost_satoshis,
name_data=name_data, min_payment_confs=min_payment_confs,
proxy=proxy, config_path=config_path, queue_path=state.queue_path)
@@ -1230,8 +1226,8 @@ def preorder(fqu, cost_satoshis, zonefile_data, profile, transfer_address, min_p
# RPC method: backend_update
def update( fqu, zonefile_txt, profile, zonefile_hash, transfer_address, config_path=CONFIG_PATH, proxy=None,
prior_name_data = None, owner_key = None, payment_key = None ):
def update(fqu, zonefile_txt, profile, zonefile_hash, transfer_address, config_path=CONFIG_PATH, proxy=None,
prior_name_data = None, owner_key = None, payment_key = None ):
"""
Send a new zonefile hash. Queue the zonefile data for subsequent replication.
zonefile_txt_b64 must be b64-encoded so we can send it over RPC sanely

View File

@@ -696,7 +696,9 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
},
'unsafe': {
'type': 'boolean'
}
},
'owner_key': PRIVKEY_INFO_SCHEMA,
'payment_key': PRIVKEY_INFO_SCHEMA
},
'required': [
'name'
@@ -719,6 +721,9 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
unsafe_reg = request.get('unsafe', False)
make_profile = request.get('make_profile', False)
owner_key = request.get('owner_key', None)
payment_key = request.get('payment_key', None)
if unsafe_reg:
unsafe_reg = 'true'
else:
@@ -762,7 +767,7 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
op = 'register'
log.debug("register {}".format(name))
res = internal.cli_register(name, zonefile_txt, recipient_address, min_confs,
unsafe_reg, interactive=False, force_data=True,
unsafe_reg, owner_key, payment_key, interactive=False, force_data=True,
cost_satoshis=cost_satoshis, make_profile = make_profile)
if 'error' in res:
@@ -944,7 +949,8 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
'minimum': 0,
'maximum': TX_MAX_FEE
},
'owner_key': PRIVKEY_INFO_SCHEMA
'owner_key': PRIVKEY_INFO_SCHEMA,
'payment_key': PRIVKEY_INFO_SCHEMA
},
'required': [
'owner'
@@ -973,8 +979,10 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
log.debug("Re-encode {} to {}".format(new_addr, recipient_address))
recipient_address = new_addr
privkey_info = request.get('owner_key', None)
res = internal.cli_transfer(name, recipient_address, privkey_info, interactive=False)
owner_key = request.get('owner_key', None)
payment_key = request.get('payment_key', None)
res = internal.cli_transfer(name, recipient_address, owner_key, payment_key, interactive=False)
if 'error' in res:
log.error("Failed to transfer {}: {}".format(name, res['error']))
self._reply_json({"error": 'Transfer failed.\n{}'.format(res['error'])}, status_code=500)
@@ -1020,7 +1028,8 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
'minimum': 0,
'maximum': TX_MAX_FEE
},
'owner_key': PRIVKEY_INFO_SCHEMA
'owner_key': PRIVKEY_INFO_SCHEMA,
'payment_key': PRIVKEY_INFO_SCHEMA
},
'additionalProperties': False,
}
@@ -1063,13 +1072,14 @@ class BlockstackAPIEndpointHandler(SimpleHTTPRequestHandler):
return
res = None
privkey_info = request.get('owner_key', None)
owner_key = request.get('owner_key', None)
payment_key = request.get('payment_key', None)
if zonefile_str is not None:
res = internal.cli_update(name, str(zonefile_str), "false", privkey_info, interactive=False,
res = internal.cli_update(name, str(zonefile_str), "false", owner_key, payment_key, interactive=False,
nonstandard=True, force_data=True)
else:
res = internal.cli_set_zonefile_hash(name, str(zonefile_hash), privkey_info)
res = internal.cli_set_zonefile_hash(name, str(zonefile_hash), owner_key, payment_key)
if 'error' in res:
log.error("Failed to update {}: {}".format(name, res['error']))
@@ -4183,15 +4193,19 @@ class BlockstackAPIEndpointClient(object):
return self.get_response(req)
def backend_preorder(self, fqu, cost_satoshis, user_zonefile, user_profile, transfer_address, min_payment_confs,
unsafe_reg = False):
def backend_preorder(self, fqu, cost_satoshis, user_zonefile, user_profile,
transfer_address, min_payment_confs, unsafe_reg = False,
payment_key = None, owner_key = None):
"""
Queue up a name for registration.
"""
if is_api_server(self.config_dir):
# directly invoke the registrar
return backend.registrar.preorder(fqu, cost_satoshis, user_zonefile, user_profile, transfer_address, min_payment_confs, config_path=self.config_path, unsafe_reg=unsafe_reg)
return backend.registrar.preorder(
fqu, cost_satoshis, user_zonefile, user_profile, transfer_address,
min_payment_confs, config_path = self.config_path, unsafe_reg = unsafe_reg,
owner_key = owner_key, payment_key = payment_key)
else:
res = self.check_version()
@@ -4215,6 +4229,11 @@ class BlockstackAPIEndpointClient(object):
if cost_satoshis is not None:
data['cost_satoshis'] = cost_satoshis
if payment_key is not None:
data['payment_key'] = payment_key
if owner_key is not None:
data['owner_key'] = owner_key
if user_profile:
# aaron: I'm making explicit a previously-baked-in assumption
# if the user_profile was given to this function, and we make an RPC
@@ -4229,15 +4248,17 @@ class BlockstackAPIEndpointClient(object):
return self.get_response(req)
def backend_update(self, fqu, zonefile_txt, profile, zonefile_hash, owner_key = None):
def backend_update(self, fqu, zonefile_txt, profile, zonefile_hash,
owner_key = None, payment_key = None):
"""
Queue an update
"""
if is_api_server(self.config_dir):
# directly invoke the registrar
return backend.registrar.update(
fqu, zonefile_txt, profile, zonefile_hash,
None, config_path = self.config_path, owner_key = owner_key)
fqu, zonefile_txt, profile, zonefile_hash, None,
config_path=self.config_path, owner_key=owner_key,
payment_key=payment_key)
else:
res = self.check_version()
@@ -4261,20 +4282,23 @@ class BlockstackAPIEndpointClient(object):
if owner_key is not None:
data['owner_key'] = owner_key
if payment_key is not None:
data['payment_key'] = payment_key
headers = self.make_request_headers()
req = requests.put( 'http://{}:{}/v1/names/{}/zonefile'.format(self.server, self.port, fqu), data=json.dumps(data), timeout=self.timeout, headers=headers)
return self.get_response(req)
def backend_transfer(self, fqu, recipient_addr, owner_key = None):
def backend_transfer(self, fqu, recipient_addr, owner_key = None, payment_key = None):
"""
Queue a transfer
"""
if is_api_server(self.config_dir):
# directly invoke the transfer
return backend.registrar.transfer(
fqu, recipient_addr, config_path=self.config_path, owner_key = owner_key)
fqu, recipient_addr, config_path=self.config_path,
owner_key = owner_key, payment_key = payment_key)
else:
res = self.check_version()
@@ -4288,6 +4312,8 @@ class BlockstackAPIEndpointClient(object):
if owner_key is not None:
data['owner_key'] = owner_key
if payment_key is not None:
data['payment_key'] = payment_key
headers = self.make_request_headers()
req = requests.put('http://{}:{}/v1/names/{}/owner'.format(self.server, self.port, fqu),