Browse Source

Merge #1142: RPC maker/start returns 409 error if no coins

bd33b6d RPC maker/start returns 409 error if no coins (Adam Gibson)
master
Adam Gibson 4 years ago
parent
commit
8b3d21f226
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 2
      jmclient/jmclient/__init__.py
  2. 3
      jmclient/jmclient/wallet-rpc-api.md
  3. 10
      jmclient/jmclient/wallet-rpc-api.yaml
  4. 36
      jmclient/jmclient/wallet_rpc.py
  5. 10
      jmclient/jmclient/yieldgenerator.py

2
jmclient/jmclient/__init__.py

@ -61,7 +61,7 @@ from .wallet_utils import (
from .wallet_service import WalletService from .wallet_service import WalletService
from .maker import Maker from .maker import Maker
from .yieldgenerator import YieldGenerator, YieldGeneratorBasic, ygmain, \ from .yieldgenerator import YieldGenerator, YieldGeneratorBasic, ygmain, \
YieldGeneratorService, YieldGeneratorServiceSetupFailed YieldGeneratorService
from .snicker_receiver import SNICKERError, SNICKERReceiver, SNICKERReceiverService from .snicker_receiver import SNICKERError, SNICKERReceiver, SNICKERReceiverService
from .payjoin import (parse_payjoin_setup, send_payjoin, from .payjoin import (parse_payjoin_setup, send_payjoin,
JMBIP78ReceiverManager) JMBIP78ReceiverManager)

3
jmclient/jmclient/wallet-rpc-api.md

@ -287,7 +287,7 @@ Start the yield generator service.
##### Description ##### Description
Start the yield generator service with the configuration settings specified in the POST request. Note that if fidelity bonds are enabled in the wallet, and a timelock address has been generated, and then funded, the fidelity bond will automatically be advertised without any specific configuration in this request. Start the yield generator service with the configuration settings specified in the POST request. Note that if fidelity bonds are enabled in the wallet, and a timelock address has been generated, and then funded, the fidelity bond will automatically be advertised without any specific configuration in this request. Note that if the wallet does not have confirmed coins, or another taker or maker coinjoin service is already running, the maker will not start.
##### Parameters ##### Parameters
@ -303,6 +303,7 @@ Start the yield generator service with the configuration settings specified in t
| 400 | Bad request format. | | 400 | Bad request format. |
| 401 | Unable to authorise the credentials that were supplied. | | 401 | Unable to authorise the credentials that were supplied. |
| 404 | Item not found. | | 404 | Item not found. |
| 409 | Maker could not start without confirmed balance. |
| 503 | The server is not ready to process the request. | | 503 | The server is not ready to process the request. |
##### Security ##### Security

10
jmclient/jmclient/wallet-rpc-api.yaml

@ -234,7 +234,7 @@ paths:
- bearerAuth: [] - bearerAuth: []
summary: Start the yield generator service. summary: Start the yield generator service.
operationId: startmaker operationId: startmaker
description: Start the yield generator service with the configuration settings specified in the POST request. Note that if fidelity bonds are enabled in the wallet, and a timelock address has been generated, and then funded, the fidelity bond will automatically be advertised without any specific configuration in this request. description: Start the yield generator service with the configuration settings specified in the POST request. Note that if fidelity bonds are enabled in the wallet, and a timelock address has been generated, and then funded, the fidelity bond will automatically be advertised without any specific configuration in this request. Note that if the wallet does not have confirmed coins, or another taker or maker coinjoin service is already running, the maker will not start.
parameters: parameters:
- name: walletname - name: walletname
in: path in: path
@ -259,6 +259,8 @@ paths:
$ref: '#/components/responses/401-Unauthorized' $ref: '#/components/responses/401-Unauthorized'
'404': '404':
$ref: '#/components/responses/404-NotFound' $ref: '#/components/responses/404-NotFound'
'409':
$ref: '#/components/responses/409-No-Coins'
'503': '503':
$ref: '#/components/responses/503-ServiceUnavailable' $ref: '#/components/responses/503-ServiceUnavailable'
/wallet/{walletname}/maker/stop: /wallet/{walletname}/maker/stop:
@ -863,6 +865,12 @@ components:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/ErrorMessage' $ref: '#/components/schemas/ErrorMessage'
409-No-Coins:
description: Maker could not start without confirmed balance.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorMessage'
404-NotFound: 404-NotFound:
description: Item not found. description: Item not found.
content: content:

36
jmclient/jmclient/wallet_rpc.py

@ -21,8 +21,7 @@ from jmclient import Taker, jm_single, \
create_wallet, get_max_cj_fee_values, \ create_wallet, get_max_cj_fee_values, \
StorageError, StoragePasswordError, JmwalletdWebSocketServerFactory, \ StorageError, StoragePasswordError, JmwalletdWebSocketServerFactory, \
JmwalletdWebSocketServerProtocol, RetryableStorageError, \ JmwalletdWebSocketServerProtocol, RetryableStorageError, \
SegwitWalletFidelityBonds, wallet_gettimelockaddress, \ SegwitWalletFidelityBonds, wallet_gettimelockaddress
YieldGeneratorServiceSetupFailed
from jmbase.support import get_log from jmbase.support import get_log
jlog = get_log() jlog = get_log()
@ -84,6 +83,11 @@ class ServiceNotStarted(Exception):
class TransactionFailed(Exception): class TransactionFailed(Exception):
pass pass
# raised when we tried to start a Maker,
# but the wallet was empty/not enough.
class NotEnoughCoinsForMaker(Exception):
pass
def get_ssl_context(cert_directory): def get_ssl_context(cert_directory):
"""Construct an SSL context factory from the user's privatekey/cert. """Construct an SSL context factory from the user's privatekey/cert.
TODO: TODO:
@ -289,6 +293,12 @@ class JMWalletDaemon(Service):
request.setResponseCode(409) request.setResponseCode(409)
return self.err(request, "Transaction failed.") return self.err(request, "Transaction failed.")
@app.handle_errors(NotEnoughCoinsForMaker)
def not_enough_coins(self, request, failure):
# as above, 409 may not be ideal
request.setResponseCode(409)
return self.err(request, "Maker could not start, no coins.")
def check_cookie(self, request): def check_cookie(self, request):
#part after bearer is what we need #part after bearer is what we need
try: try:
@ -560,14 +570,26 @@ class JMWalletDaemon(Service):
self.activate_coinjoin_state(CJ_NOT_RUNNING) self.activate_coinjoin_state(CJ_NOT_RUNNING)
def setup(): def setup():
# note this returns False if we cannot update the state. # note this returns False if we cannot update the state.
return self.activate_coinjoin_state(CJ_MAKER_RUNNING) if not self.activate_coinjoin_state(CJ_MAKER_RUNNING):
raise ServiceAlreadyStarted()
# don't even start up the service if there aren't any coins
# to offer:
def setup_sanitycheck_balance():
# note: this will only be non-zero if coins are confirmed.
# note: a call to start_maker necessarily is after a successful
# sync has already happened (this is different from CLI yg).
# note: an edge case of dusty amounts is lost here; it will get
# picked up by Maker.try_to_create_my_orders().
if not len(self.wallet_service.get_balance_by_mixdepth(
verbose=False, minconfs=1)) > 0:
raise NotEnoughCoinsForMaker()
self.services["maker"].addCleanup(cleanup) self.services["maker"].addCleanup(cleanup)
self.services["maker"].addSetup(setup) self.services["maker"].addSetup(setup)
self.services["maker"].addSetup(setup_sanitycheck_balance)
# Service startup now checks and updates coinjoin state: # Service startup now checks and updates coinjoin state:
try: self.services["maker"].startService()
self.services["maker"].startService()
except YieldGeneratorServiceSetupFailed:
raise ServiceAlreadyStarted()
return make_jmwalletd_response(request, status=202) return make_jmwalletd_response(request, status=202)
@app.route('/wallet/<string:walletname>/maker/stop', methods=['GET']) @app.route('/wallet/<string:walletname>/maker/stop', methods=['GET'])

10
jmclient/jmclient/yieldgenerator.py

@ -268,9 +268,6 @@ class YieldGeneratorBasic(YieldGenerator):
cjoutmix = (input_mixdepth + 1) % (self.wallet_service.mixdepth + 1) cjoutmix = (input_mixdepth + 1) % (self.wallet_service.mixdepth + 1)
return self.wallet_service.get_internal_addr(cjoutmix) return self.wallet_service.get_internal_addr(cjoutmix)
class YieldGeneratorServiceSetupFailed(Exception):
pass
class YieldGeneratorService(Service): class YieldGeneratorService(Service):
def __init__(self, wallet_service, daemon_host, daemon_port, yg_config): def __init__(self, wallet_service, daemon_host, daemon_port, yg_config):
self.wallet_service = wallet_service self.wallet_service = wallet_service
@ -292,8 +289,11 @@ class YieldGeneratorService(Service):
no need to check this here. no need to check this here.
""" """
for setup in self.setup_fns: for setup in self.setup_fns:
if not setup(): # we do not catch Exceptions in setup,
raise YieldGeneratorServiceSetupFailed # deliberately; this must be caught and distinguished
# by whoever started the service.
setup()
# TODO genericise to any YG class: # TODO genericise to any YG class:
self.yieldgen = YieldGeneratorBasic(self.wallet_service, self.yg_config) self.yieldgen = YieldGeneratorBasic(self.wallet_service, self.yg_config)
self.clientfactory = JMClientProtocolFactory(self.yieldgen, proto_type="MAKER") self.clientfactory = JMClientProtocolFactory(self.yieldgen, proto_type="MAKER")

Loading…
Cancel
Save