@ -9,7 +9,7 @@ from .protocol import (COMMAND_PREFIX, ORDER_KEYS, NICK_HASH_LENGTH,
COMMITMENT_PREFIXES )
COMMITMENT_PREFIXES )
from . irc import IRCMessageChannel
from . irc import IRCMessageChannel
from jmbase import ( hextobin , is_hs_uri , get_tor_agent , JMHiddenService ,
from jmbase import ( is_hs_uri , get_tor_agent , JMHiddenService ,
get_nontor_agent , BytesProducer , wrapped_urlparse ,
get_nontor_agent , BytesProducer , wrapped_urlparse ,
bdict_sdict_convert , JMHTTPResource )
bdict_sdict_convert , JMHTTPResource )
from jmbase . commands import *
from jmbase . commands import *
@ -32,7 +32,6 @@ import os
from io import BytesIO
from io import BytesIO
import copy
import copy
from functools import wraps
from functools import wraps
from numbers import Integral
""" Joinmarket application protocol control flow.
""" Joinmarket application protocol control flow.
For documentation on protocol ( formats , message sequence ) see
For documentation on protocol ( formats , message sequence ) see
@ -101,11 +100,11 @@ class BIP78ReceiverResource(JMHTTPResource):
def __init__ ( self , info_callback , shutdown_callback , post_request_handler ) :
def __init__ ( self , info_callback , shutdown_callback , post_request_handler ) :
""" The POST request handling callback has function signature:
""" The POST request handling callback has function signature:
args : ( request - body - content - in - bytes , )
args : ( request - body - content - in - bytes , )
returns : ( errormsg , errcode , httpcode , response - in - bytes )
returns : ( errormsg , errcode , httpcode , response - in - bytes )
If the request was successful , errormsg should be true and response
If the request was successful , errormsg should be true and response
should be in bytes , to be sent in the return value of render_POST ( ) .
should be in bytes , to be sent in the return value of render_POST ( ) .
"""
"""
self . post_request_handler = post_request_handler
self . post_request_handler = post_request_handler
super ( ) . __init__ ( info_callback , shutdown_callback )
super ( ) . __init__ ( info_callback , shutdown_callback )
@ -158,6 +157,7 @@ class BIP78ReceiverResource(JMHTTPResource):
self . info_callback ( " Shutting down, payjoin negotiation failed. " )
self . info_callback ( " Shutting down, payjoin negotiation failed. " )
self . shutdown_callback ( )
self . shutdown_callback ( )
class HTTPPassThrough ( amp . AMP ) :
class HTTPPassThrough ( amp . AMP ) :
""" This class supports passing through
""" This class supports passing through
requests over HTTPS or over a socks proxy to a remote
requests over HTTPS or over a socks proxy to a remote
@ -166,15 +166,14 @@ class HTTPPassThrough(amp.AMP):
def on_INIT ( self , netconfig ) :
def on_INIT ( self , netconfig ) :
""" The network config must be passed in json
""" The network config must be passed in json
and contains these fields :
and contains these fields :
socks5_host
socks5_host
socks5_proxy
socks5_proxy
servers ( comma separated list )
servers ( comma separated list )
tls_whitelist ( comma separated list )
tls_whitelist ( comma separated list )
filterconfig ( not yet defined )
filterconfig ( not yet defined )
credentials ( not yet defined )
credentials ( not yet defined )
"""
"""
netconfig = json . loads ( netconfig )
self . socks5_host = netconfig [ " socks5_host " ]
self . socks5_host = netconfig [ " socks5_host " ]
self . socks5_port = int ( netconfig [ " socks5_port " ] )
self . socks5_port = int ( netconfig [ " socks5_port " ] )
self . servers = [ a for a in netconfig [ " servers " ] if a != " " ]
self . servers = [ a for a in netconfig [ " servers " ] if a != " " ]
@ -206,9 +205,9 @@ class HTTPPassThrough(amp.AMP):
def getRequest ( self , server , success_callback , url = None , headers = None ) :
def getRequest ( self , server , success_callback , url = None , headers = None ) :
""" Make GET request to server server, if response received OK,
""" Make GET request to server server, if response received OK,
passed to success_callback , which must have function signature
passed to success_callback , which must have function signature
( response , server ) .
( response , server ) .
"""
"""
agent , destination_url = self . getAgentDestination ( server )
agent , destination_url = self . getAgentDestination ( server )
if url :
if url :
destination_url = destination_url + url
destination_url = destination_url + url
@ -230,7 +229,7 @@ class HTTPPassThrough(amp.AMP):
def postRequest ( self , body , server , success_callback ,
def postRequest ( self , body , server , success_callback ,
url = None , params = None , headers = None ) :
url = None , params = None , headers = None ) :
""" Pass body of post request as string, will be encoded here.
""" Pass body of post request as string, will be encoded here.
"""
"""
agent , destination_url = self . getAgentDestination ( server ,
agent , destination_url = self . getAgentDestination ( server ,
params = params )
params = params )
if url :
if url :
@ -272,7 +271,6 @@ class HTTPPassThrough(amp.AMP):
class BIP78ServerProtocol ( HTTPPassThrough ) :
class BIP78ServerProtocol ( HTTPPassThrough ) :
@BIP78ReceiverInit . responder
@BIP78ReceiverInit . responder
def on_BIP78_RECEIVER_INIT ( self , netconfig ) :
def on_BIP78_RECEIVER_INIT ( self , netconfig ) :
netconfig = json . loads ( netconfig )
self . serving_port = int ( netconfig [ " port " ] )
self . serving_port = int ( netconfig [ " port " ] )
self . tor_control_host = netconfig [ " tor_control_host " ]
self . tor_control_host = netconfig [ " tor_control_host " ]
self . tor_control_port = int ( netconfig [ " tor_control_port " ] )
self . tor_control_port = int ( netconfig [ " tor_control_port " ] )
@ -304,28 +302,28 @@ class BIP78ServerProtocol(HTTPPassThrough):
def info_callback ( self , msg ) :
def info_callback ( self , msg ) :
""" Informational messages are all passed
""" Informational messages are all passed
to the client . TODO makes sense to log locally
to the client . TODO makes sense to log locally
too , in case daemon is isolated ? .
too , in case daemon is isolated ? .
"""
"""
d = self . callRemote ( BIP78InfoMsg , infomsg = msg )
d = self . callRemote ( BIP78InfoMsg , infomsg = msg )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
def onion_hostname_callback ( self , hostname ) :
def onion_hostname_callback ( self , hostname ) :
""" On successful start of HS, we pass hostname
""" On successful start of HS, we pass hostname
to client , who can use this to build the full URI .
to client , who can use this to build the full URI .
"""
"""
d = self . callRemote ( BIP78ReceiverUp ,
d = self . callRemote ( BIP78ReceiverUp ,
hostname = hostname )
hostname = hostname )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
def post_request_handler ( self , request , body , params ) :
def post_request_handler ( self , request , body , params ) :
""" Fired when a sender has sent a POST request
""" Fired when a sender has sent a POST request
to our hidden service . Argument ` body ` should be a base64
to our hidden service . Argument ` body ` should be a base64
string and params should be a dict .
string and params should be a dict .
"""
"""
self . post_request = request
self . post_request = request
d = self . callRemote ( BIP78ReceiverOriginalPSBT , body = body ,
d = self . callRemote ( BIP78ReceiverOriginalPSBT , body = body ,
params = json . dumps ( bdict_sdict_convert ( params ) ) )
params = bdict_sdict_convert ( params ) )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
@BIP78ReceiverSendProposal . responder
@BIP78ReceiverSendProposal . responder
@ -354,9 +352,9 @@ class BIP78ServerProtocol(HTTPPassThrough):
@BIP78SenderOriginalPSBT . responder
@BIP78SenderOriginalPSBT . responder
def on_BIP78_SENDER_ORIGINAL_PSBT ( self , body , params ) :
def on_BIP78_SENDER_ORIGINAL_PSBT ( self , body , params ) :
self . postRequest ( body , self . servers [ 0 ] ,
self . postRequest ( body , self . servers [ 0 ] ,
self . bip78_receiver_response ,
self . bip78_receiver_response ,
params = json . loads ( params ) ,
params = params ,
headers = Headers ( { " Content-Type " : [ " text/plain " ] } ) )
headers = Headers ( { " Content-Type " : [ " text/plain " ] } ) )
return { " accepted " : True }
return { " accepted " : True }
def bip78_receiver_response ( self , response , server ) :
def bip78_receiver_response ( self , response , server ) :
@ -384,8 +382,8 @@ class SNICKERDaemonServerProtocol(HTTPPassThrough):
@SNICKERProposerPostProposals . responder
@SNICKERProposerPostProposals . responder
def on_SNICKER_PROPOSER_POST_PROPOSALS ( self , proposals , server ) :
def on_SNICKER_PROPOSER_POST_PROPOSALS ( self , proposals , server ) :
""" Receives a list of proposals to be posted to a specific
""" Receives a list of proposals to be posted to a specific
server .
server .
"""
"""
self . postRequest ( proposals , server , self . receive_proposals_response )
self . postRequest ( proposals , server , self . receive_proposals_response )
return { " accepted " : True }
return { " accepted " : True }
@ -421,7 +419,7 @@ class SNICKERDaemonServerProtocol(HTTPPassThrough):
def receive_proposals_from_server ( self , response , server ) :
def receive_proposals_from_server ( self , response , server ) :
""" Parses the response from one server.
""" Parses the response from one server.
"""
"""
# if the response code is not 200 OK, we must let the client
# if the response code is not 200 OK, we must let the client
# know that this server is not responding as expected.
# know that this server is not responding as expected.
if int ( response . code ) != 200 :
if int ( response . code ) != 200 :
@ -475,6 +473,8 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
self . sig_lock = threading . Lock ( )
self . sig_lock = threading . Lock ( )
self . active_orders = { }
self . active_orders = { }
self . use_fidelity_bond = False
self . use_fidelity_bond = False
self . offerlist = None
self . kp = None
def checkClientResponse ( self , response ) :
def checkClientResponse ( self , response ) :
""" A generic check of client acceptance; any failure
""" A generic check of client acceptance; any failure
@ -485,7 +485,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
def defaultErrback ( self , failure ) :
def defaultErrback ( self , failure ) :
""" TODO better network error handling.
""" TODO better network error handling.
"""
"""
failure . trap ( ConnectionAborted , ConnectionClosed ,
failure . trap ( ConnectionAborted , ConnectionClosed ,
ConnectionDone , ConnectionLost )
ConnectionDone , ConnectionLost )
@ -502,11 +502,9 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
If a new message channel configuration is required , the current
If a new message channel configuration is required , the current
one is shutdown in preparation .
one is shutdown in preparation .
"""
"""
self . maker_timeout_sec = int ( maker_timeout_sec )
self . maker_timeout_sec = maker_timeout_sec
# used in OrderbookWatch:
self . minmakers = minmakers
self . dust_threshold = int ( dust_threshold )
self . dust_threshold = int ( dust_threshold )
self . minmakers = int ( minmakers )
irc_configs = json . loads ( irc_configs )
#(bitcoin) network only referenced in channel name construction
#(bitcoin) network only referenced in channel name construction
self . network = network
self . network = network
if irc_configs == self . irc_configs :
if irc_configs == self . irc_configs :
@ -554,7 +552,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
return { ' accepted ' : True }
return { ' accepted ' : True }
@JMSetup . responder
@JMSetup . responder
def on_JM_SETUP ( self , role , offers , use_fidelity_bond ) :
def on_JM_SETUP ( self , role , initdata , use_fidelity_bond ) :
assert self . jm_state == 0
assert self . jm_state == 0
self . role = role
self . role = role
self . crypto_boxes = { }
self . crypto_boxes = { }
@ -568,7 +566,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
if self . role == " TAKER " :
if self . role == " TAKER " :
self . mcc . pubmsg ( COMMAND_PREFIX + " orderbook " )
self . mcc . pubmsg ( COMMAND_PREFIX + " orderbook " )
elif self . role == " MAKER " :
elif self . role == " MAKER " :
self . offerlist = json . loads ( offers )
self . offerlist = initdata
self . use_fidelity_bond = use_fidelity_bond
self . use_fidelity_bond = use_fidelity_bond
self . mcc . announce_orders ( self . offerlist , None , None , None )
self . mcc . announce_orders ( self . offerlist , None , None , None )
self . jm_state = 1
self . jm_state = 1
@ -614,15 +612,14 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
""" Takes the necessary data from the Taker and initiates the Stage 1
""" Takes the necessary data from the Taker and initiates the Stage 1
interaction with the Makers .
interaction with the Makers .
"""
"""
if not ( self . jm_state == 1 and isinstance ( amount , Integral )
if self . jm_state != 1 or amount < 0 :
and amount > = 0 ) :
return { ' accepted ' : False }
return { ' accepted ' : False }
self . cjamount = amount
self . cjamount = amount
self . commitment = commitment
self . commitment = commitment
self . revelation = revelation
self . revelation = revelation
#Reset utxo data to null for this new transaction
#Reset utxo data to null for this new transaction
self . ioauth_data = { }
self . ioauth_data = { }
self . active_orders = json . loads ( filled_offers )
self . active_orders = filled_offers
for nick , offer_dict in self . active_orders . items ( ) :
for nick , offer_dict in self . active_orders . items ( ) :
offer_fill_msg = " " . join ( [ str ( offer_dict [ " oid " ] ) , str ( amount ) ,
offer_fill_msg = " " . join ( [ str ( offer_dict [ " oid " ] ) , str ( amount ) ,
self . kp . hex_pk ( ) . decode ( ' ascii ' ) , str ( commitment ) ] )
self . kp . hex_pk ( ) . decode ( ' ascii ' ) , str ( commitment ) ] )
@ -632,20 +629,19 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
return { ' accepted ' : True }
return { ' accepted ' : True }
@JMMakeTx . responder
@JMMakeTx . responder
def on_JM_MAKE_TX ( self , nick_list , txhex ) :
def on_JM_MAKE_TX ( self , nick_list , tx ) :
""" Taker sends the prepared unsigned transaction
""" Taker sends the prepared unsigned transaction
to all the Makers in nick_list
to all the Makers in nick_list
"""
"""
if not self . jm_state == 4 :
if not self . jm_state == 4 :
log . msg ( " Make tx was called in wrong state, rejecting " )
log . msg ( " Make tx was called in wrong state, rejecting " )
return { ' accepted ' : False }
return { ' accepted ' : False }
nick_list = json . loads ( nick_list )
self . mcc . send_tx ( nick_list , tx )
self . mcc . send_tx ( nick_list , txhex )
return { ' accepted ' : True }
return { ' accepted ' : True }
@JMPushTx . responder
@JMPushTx . responder
def on_JM_PushTx ( self , nick , txhex ) :
def on_JM_PushTx ( self , nick , tx ) :
self . mcc . push_tx ( nick , txhex )
self . mcc . push_tx ( nick , tx )
return { ' accepted ' : True }
return { ' accepted ' : True }
""" Maker specific responders
""" Maker specific responders
@ -654,14 +650,12 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@JMAnnounceOffers . responder
@JMAnnounceOffers . responder
def on_JM_ANNOUNCE_OFFERS ( self , to_announce , to_cancel , offerlist ) :
def on_JM_ANNOUNCE_OFFERS ( self , to_announce , to_cancel , offerlist ) :
""" Called by Maker to reset his current offerlist;
""" Called by Maker to reset his current offerlist;
Daemon decides what messages ( cancel , announce ) to
Daemon decides what messages ( cancel , announce ) to
send to the message channel .
send to the message channel .
"""
"""
if self . role != " MAKER " :
if self . role != " MAKER " :
return
return
to_announce = json . loads ( to_announce )
self . offerlist = offerlist
to_cancel = json . loads ( to_cancel )
self . offerlist = json . loads ( offerlist )
if len ( to_cancel ) > 0 :
if len ( to_cancel ) > 0 :
self . mcc . cancel_orders ( to_cancel )
self . mcc . cancel_orders ( to_cancel )
if len ( to_announce ) > 0 :
if len ( to_announce ) > 0 :
@ -677,19 +671,18 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@JMIOAuth . responder
@JMIOAuth . responder
def on_JM_IOAUTH ( self , nick , utxolist , pubkey , cjaddr , changeaddr , pubkeysig ) :
def on_JM_IOAUTH ( self , nick , utxolist , pubkey , cjaddr , changeaddr , pubkeysig ) :
""" Daemon constructs full !ioauth message to be sent on message
""" Daemon constructs full !ioauth message to be sent on message
channel based on data from Maker . Relevant data ( utxos , addresses )
channel based on data from Maker . Relevant data ( utxos , addresses )
are stored in the active_orders dict keyed by the nick of the Taker .
are stored in the active_orders dict keyed by the nick of the Taker .
"""
"""
if not self . role == " MAKER " :
if not self . role == " MAKER " :
return
return
if not nick in self . active_orders :
if nick not in self . active_orders :
return
return
utxos = json . loads ( utxolist )
#completed population of order/offer object
#completed population of order/offer object
self . active_orders [ nick ] [ " cjaddr " ] = cjaddr
self . active_orders [ nick ] [ " cjaddr " ] = cjaddr
self . active_orders [ nick ] [ " changeaddr " ] = changeaddr
self . active_orders [ nick ] [ " changeaddr " ] = changeaddr
self . active_orders [ nick ] [ " utxos " ] = utxos
self . active_orders [ nick ] [ " utxos " ] = utxoli st
msg = str ( " , " . join ( utxos . keys ( ) ) ) + " " + " " . join (
msg = str ( " , " . join ( utxolist ) ) + " " + " " . join (
[ pubkey , cjaddr , changeaddr , pubkeysig ] )
[ pubkey , cjaddr , changeaddr , pubkeysig ] )
self . mcc . prepare_privmsg ( nick , " ioauth " , msg )
self . mcc . prepare_privmsg ( nick , " ioauth " , msg )
#In case of *blacklisted (ie already used) commitments, we already
#In case of *blacklisted (ie already used) commitments, we already
@ -705,11 +698,10 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@JMTXSigs . responder
@JMTXSigs . responder
def on_JM_TX_SIGS ( self , nick , sigs ) :
def on_JM_TX_SIGS ( self , nick , sigs ) :
""" Signatures that the Maker has produced
""" Signatures that the Maker has produced
are passed here to the daemon as a list and
are passed here to the daemon as a list and
broadcast one by one . TODO : could shorten this ,
broadcast one by one . TODO : could shorten this ,
have more than one sig per message .
have more than one sig per message .
"""
"""
sigs = json . loads ( sigs )
for sig in sigs :
for sig in sigs :
self . mcc . prepare_privmsg ( nick , " sig " , sig )
self . mcc . prepare_privmsg ( nick , " sig " , sig )
return { " accepted " : True }
return { " accepted " : True }
@ -794,19 +786,19 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@maker_only
@maker_only
def on_seen_auth ( self , nick , commitment_revelation ) :
def on_seen_auth ( self , nick , commitment_revelation ) :
""" Passes to Maker the !auth message from the Taker,
""" Passes to Maker the !auth message from the Taker,
for processing . This will include validating the PoDLE
for processing . This will include validating the PoDLE
commitment revelation against the existing commitment ,
commitment revelation against the existing commitment ,
which was already stored in active_orders [ nick ] .
which was already stored in active_orders [ nick ] .
"""
"""
if not nick in self . active_orders :
if nick not in self . active_orders :
return
return
ao = self . active_orders [ nick ]
ao = self . active_orders [ nick ]
#ask the client to validate the commitment and prepare the utxo data
#ask the client to validate the commitment and prepare the utxo data
d = self . callRemote ( JMAuthReceived ,
d = self . callRemote ( JMAuthReceived ,
nick = nick ,
nick = nick ,
offer = json . dumps ( ao [ " offer " ] ) ,
offer = ao [ " offer " ] ,
commitment = ao [ " commit " ] ,
commitment = ao [ " commit " ] ,
revelation = json . dumps ( commitment_revelation ) ,
revelation = commitment_revelation ,
amount = ao [ " amount " ] ,
amount = ao [ " amount " ] ,
kphex = ao [ " kp " ] . hex_pk ( ) . decode ( ' ascii ' ) )
kphex = ao [ " kp " ] . hex_pk ( ) . decode ( ' ascii ' ) )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
@ -814,8 +806,8 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@maker_only
@maker_only
def on_commitment_seen ( self , nick , commitment ) :
def on_commitment_seen ( self , nick , commitment ) :
""" Triggered when we see a commitment for blacklisting
""" Triggered when we see a commitment for blacklisting
appear in the public pit channel .
appear in the public pit channel .
"""
"""
#just add if necessary, ignore return value.
#just add if necessary, ignore return value.
check_utxo_blacklist ( commitment , persist = True )
check_utxo_blacklist ( commitment , persist = True )
log . msg ( " Received commitment broadcast by other maker: " + str (
log . msg ( " Received commitment broadcast by other maker: " + str (
@ -824,30 +816,24 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
@maker_only
@maker_only
def on_commitment_transferred ( self , nick , commitment ) :
def on_commitment_transferred ( self , nick , commitment ) :
""" Triggered when a privmsg is received from another maker
""" Triggered when a privmsg is received from another maker
with a commitment to announce in public ( obfuscation of source ) .
with a commitment to announce in public ( obfuscation of source ) .
We simply post it in public ( not affected by whether we ourselves
We simply post it in public ( not affected by whether we ourselves
are * accepting * commitment broadcasts .
are * accepting * commitment broadcasts .
"""
"""
self . mcc . pubmsg ( " !hp2 " + commitment )
self . mcc . pubmsg ( " !hp2 " + commitment )
@maker_only
@maker_only
def on_push_tx ( self , nick , txhex ) :
def on_push_tx ( self , nick , tx ) :
""" Broadcast unquestioningly, except checking
""" Broadcast unquestioningly
hex format .
"""
"""
d = self . callRemote ( JMTXBroadcast , tx = tx )
try :
dummy = hextobin ( txhex )
except :
return
d = self . callRemote ( JMTXBroadcast ,
txhex = txhex )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
@maker_only
@maker_only
def on_seen_tx ( self , nick , txhex ) :
def on_seen_tx ( self , nick , tx ) :
""" Passes the txhex to the Maker for verification
""" Passes the txhex to the Maker for verification
and signing . Note the security checks occur in Maker .
and signing . Note the security checks occur in Maker .
"""
"""
if nick not in self . active_orders :
if nick not in self . active_orders :
return
return
#we send a copy of the entire "active_orders" entry except the cryptobox,
#we send a copy of the entire "active_orders" entry except the cryptobox,
@ -855,10 +841,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
ao = copy . deepcopy ( self . active_orders [ nick ] )
ao = copy . deepcopy ( self . active_orders [ nick ] )
del ao [ " crypto_box " ]
del ao [ " crypto_box " ]
del ao [ " kp " ]
del ao [ " kp " ]
d = self . callRemote ( JMTXReceived ,
d = self . callRemote ( JMTXReceived , nick = nick , tx = tx , offer = ao )
nick = nick ,
txhex = txhex ,
offer = json . dumps ( ao ) )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
@taker_only
@taker_only
@ -898,9 +881,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
def on_sig ( self , nick , sig ) :
def on_sig ( self , nick , sig ) :
""" Pass signature through to Taker.
""" Pass signature through to Taker.
"""
"""
d = self . callRemote ( JMSigReceived ,
d = self . callRemote ( JMSigReceived , nick = nick , sig = sig )
nick = nick ,
sig = sig )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
def on_error ( self , msg ) :
def on_error ( self , msg ) :
@ -920,11 +901,11 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
"""
"""
with self . sig_lock :
with self . sig_lock :
d = self . callRemote ( JMRequestMsgSig ,
d = self . callRemote ( JMRequestMsgSig ,
nick = str ( nick ) ,
nick = str ( nick ) ,
cmd = str ( cmd ) ,
cmd = str ( cmd ) ,
msg = str ( msg ) ,
msg = str ( msg ) ,
msg_to_be_signed = str ( msg_to_be_signed ) ,
msg_to_be_signed = str ( msg_to_be_signed ) ,
hostid = str ( hostid ) )
hostid = str ( hostid ) )
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
def request_signature_verify ( self , msg , fullmsg , sig , pubkey , nick , hashlen ,
def request_signature_verify ( self , msg , fullmsg , sig , pubkey , nick , hashlen ,
@ -959,8 +940,8 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
def transfer_commitment ( self , commit ) :
def transfer_commitment ( self , commit ) :
""" Send this commitment via privmsg to one (random)
""" Send this commitment via privmsg to one (random)
other maker .
other maker .
"""
"""
crow = self . db . execute (
crow = self . db . execute (
' SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
' SELECT DISTINCT counterparty FROM orderbook ORDER BY ' +
' RANDOM() LIMIT 1; '
' RANDOM() LIMIT 1; '
@ -990,12 +971,12 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
self . jm_state = 3
self . jm_state = 3
if not accepted :
if not accepted :
#use ioauth data field to return the list of non-responsive makers
#use ioauth data field to return the list of non-responsive makers
nonresponders = [ x for x in self . active_orders . keys ( ) if x not
nonresponders = [ x for x in self . active_orders
in self . ioauth_data . keys ( ) ]
if x not in self . ioauth_data ]
ioauth_data = self . ioauth_data if accepted else nonresponders
ioauth_data = self . ioauth_data if accepted else nonresponders
d = self . callRemote ( JMFillResponse ,
d = self . callRemote ( JMFillResponse ,
success = accepted ,
success = accepted ,
ioauth_data = json . dumps ( ioauth_data ) )
ioauth_data = ioauth_data )
if not accepted :
if not accepted :
#Client simply accepts failure TODO
#Client simply accepts failure TODO
self . defaultCallbacks ( d )
self . defaultCallbacks ( d )
@ -1010,7 +991,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch):
either send success + ioauth data if enough makers ,
either send success + ioauth data if enough makers ,
else send failure to client .
else send failure to client .
"""
"""
response = True if len ( self . ioauth_data . keys ( ) ) > = self . minmakers else False
response = True if len ( self . ioauth_data ) > = self . minmakers else False
self . respondToIoauths ( response )
self . respondToIoauths ( response )
def checkUtxosAccepted ( self , accepted ) :
def checkUtxosAccepted ( self , accepted ) :