You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

246 lines
9.0 KiB

#! /usr/bin/env python
from __future__ import absolute_import
'''test client-protocol interfacae.'''
import pytest
from jmclient import (get_schedule, load_program_config, start_reactor,
Taker, get_log, JMClientProtocolFactory, jm_single)
from jmclient.client_protocol import JMProtocolError, JMTakerClientProtocol
import os
from twisted.python.log import startLogging, err
from twisted.python.log import msg as tmsg
from twisted.internet import protocol, reactor, task
from twisted.internet.error import (ConnectionLost, ConnectionAborted,
ConnectionClosed, ConnectionDone)
from twisted.protocols.amp import UnknownRemoteError
from twisted.python import failure
from twisted.protocols import amp
from twisted.trial import unittest
from jmbase.commands import *
from taker_test_data import t_raw_signed_tx
import json
import time
import jmbitcoin as bitcoin
import twisted
twisted.internet.base.DelayedCall.debug = True
test_completed = False
clientfactory = None
runno = 0
jlog = get_log()
def dummy_taker_finished(res, fromtx, waittime=0.0):
pass
class DummyTaker(Taker):
def set_fail_init(self, val):
self.failinit = val
def set_fail_utxos(self, val):
self.failutxos = val
def default_taker_info_callback(self, infotype, msg):
jlog.debug(infotype + ":" + msg)
def initialize(self, orderbook):
"""Once the daemon is active and has returned the current orderbook,
select offers, re-initialize variables and prepare a commitment,
then send it to the protocol to fill offers.
"""
if self.failinit==-1:
return (True, -1, "aa"*32, {'dummy':'revelation'},orderbook[:2])
elif self.failinit:
return (False,)
else:
return (True, 1000000, "aa"*32, {'dummy':'revelation'},
orderbook[:2])
def receive_utxos(self, ioauth_data):
"""Triggered when the daemon returns utxo data from
makers who responded; this is the completion of phase 1
of the protocol
"""
if self.failutxos:
return (False, "dummyreason")
else:
return (True, [x*64 + ":01" for x in ["a", "b", "c"]], t_raw_signed_tx)
def on_sig(self, nick, sigb64):
"""For test, we exit 'early' on first message, since this marks the end
of client-server communication with the daemon.
"""
jlog.debug("We got a sig: " + sigb64)
end_test()
return None
class JMBaseProtocol(amp.AMP):
def checkClientResponse(self, response):
"""A generic check of client acceptance; any failure
is considered criticial.
"""
if 'accepted' not in response or not response['accepted']:
reactor.stop()
def defaultErrback(self, failure):
failure.trap(ConnectionAborted, ConnectionClosed, ConnectionDone,
ConnectionLost, UnknownRemoteError)
reactor.stop()
def defaultCallbacks(self, d):
d.addCallback(self.checkClientResponse)
d.addErrback(self.defaultErrback)
def show_receipt(name, *args):
tmsg("Received msgtype: " + name + ", args: " + ",".join([str(x) for x in args]))
def end_client(client):
pass
def end_test():
global test_completed
test_completed = True
client = clientfactory.getClient()
reactor.callLater(1, end_client, client)
class JMTestServerProtocol(JMBaseProtocol):
@JMInit.responder
def on_JM_INIT(self, bcsource, network, irc_configs, minmakers,
maker_timeout_sec):
show_receipt("JMINIT", bcsource, network, irc_configs, minmakers,
maker_timeout_sec)
d = self.callRemote(JMInitProto,
nick_hash_length=1,
nick_max_encoded=2,
joinmarket_nick_header="J",
joinmarket_version=5)
self.defaultCallbacks(d)
return {'accepted': True}
@JMStartMC.responder
def on_JM_START_MC(self, nick):
show_receipt("STARTMC", nick)
d = self.callRemote(JMUp)
self.defaultCallbacks(d)
return {'accepted': True}
@JMSetup.responder
def on_JM_SETUP(self, role, initdata):
show_receipt("JMSETUP", role, initdata)
d = self.callRemote(JMSetupDone)
self.defaultCallbacks(d)
return {'accepted': True}
@JMRequestOffers.responder
def on_JM_REQUEST_OFFERS(self):
show_receipt("JMREQUESTOFFERS")
#build a huge orderbook to test BigString Argument
orderbook = ["aaaa" for _ in range(15)]
d = self.callRemote(JMOffers,
orderbook=json.dumps(orderbook))
self.defaultCallbacks(d)
return {'accepted': True}
@JMFill.responder
def on_JM_FILL(self, amount, commitment, revelation, filled_offers):
success = False if amount == -1 else True
show_receipt("JMFILL", amount, commitment, revelation, filled_offers)
d = self.callRemote(JMFillResponse,
success=success,
ioauth_data = json.dumps(['dummy', 'list']))
return {'accepted': True}
@JMMakeTx.responder
def on_JM_MAKE_TX(self, nick_list, txhex):
show_receipt("JMMAKETX", nick_list, txhex)
d = self.callRemote(JMSigReceived,
nick="dummynick",
sig="xxxsig")
self.defaultCallbacks(d)
#add dummy calls to check message sign and message verify
d2 = self.callRemote(JMRequestMsgSig,
nick="dummynickforsign",
cmd="command1",
msg="msgforsign",
msg_to_be_signed="fullmsgforsign",
hostid="hostid1")
self.defaultCallbacks(d2)
#To test, this must include a valid ecdsa sig
fullmsg = "fullmsgforverify"
priv = "aa"*32 + "01"
pub = bitcoin.privkey_to_pubkey(priv)
sig = bitcoin.ecdsa_sign(fullmsg, priv)
d3 = self.callRemote(JMRequestMsgSigVerify,
msg="msgforverify",
fullmsg=fullmsg,
sig=sig,
pubkey=pub,
nick="dummynickforverify",
hashlen=4,
max_encoded=5,
hostid="hostid2")
self.defaultCallbacks(d3)
d4 = self.callRemote(JMSigReceived,
nick="dummynick",
sig="dummysig")
self.defaultCallbacks(d4)
return {'accepted': True}
@JMMsgSignature.responder
def on_JM_MSGSIGNATURE(self, nick, cmd, msg_to_return, hostid):
show_receipt("JMMSGSIGNATURE", nick, cmd, msg_to_return, hostid)
return {'accepted': True}
@JMMsgSignatureVerify.responder
def on_JM_MSGSIGNATURE_VERIFY(self, verif_result, nick, fullmsg, hostid):
show_receipt("JMMSGSIGVERIFY", verif_result, nick, fullmsg, hostid)
return {'accepted': True}
class JMTestServerProtocolFactory(protocol.ServerFactory):
protocol = JMTestServerProtocol
class DummyClientProtocolFactory(JMClientProtocolFactory):
def buildProtocol(self, addr):
return JMTakerClientProtocol(self, self.client, nick_priv="aa"*32)
class TrialTestJMClientProto(unittest.TestCase):
def setUp(self):
global clientfactory
print("setUp()")
params = [[False, False], [True, False], [False, True], [-1, False]]
load_program_config()
jm_single().maker_timeout_sec = 1
self.port = reactor.listenTCP(27184, JMTestServerProtocolFactory())
self.addCleanup(self.port.stopListening)
def cb(client):
self.client = client
self.addCleanup(self.client.transport.loseConnection)
clientfactories = []
takers = [DummyTaker(None, None, callbacks=(None, None, dummy_taker_finished)) for _ in range(len(params))]
for i, p in enumerate(params):
takers[i].set_fail_init(p[0])
takers[i].set_fail_utxos(p[1])
takers[i].testflag = True
if i != 0:
clientfactories.append(JMClientProtocolFactory(takers[i]))
clientconn = reactor.connectTCP("localhost", 27184, clientfactories[i])
self.addCleanup(clientconn.disconnect)
else:
clientfactories.append(DummyClientProtocolFactory(takers[i]))
clientfactory = clientfactories[0]
clientconn = reactor.connectTCP("localhost", 27184, clientfactories[0])
self.addCleanup(clientconn.disconnect)
print("Got here")
def test_waiter(self):
print("test_main()")
return task.deferLater(reactor, 3, self._called_by_deffered)
def _called_by_deffered(self):
pass