def on_JM_INIT(self, bcsource, network, irc_configs, minmakers,
                maker_timeout_sec):
     self.maker_timeout_sec = int(maker_timeout_sec)
     self.minmakers = int(minmakers)
     mcs = [DummyMC(None)]
     self.mcc = MessageChannelCollection(mcs)
     #The following is a hack to get the counterparties marked seen/active;
     #note it must happen before callign set_msgchan for OrderbookWatch
     self.mcc.on_order_seen = None
     for c in [o['counterparty'] for o in t_orderbook]:
         self.mcc.on_order_seen_trigger(mcs[0], c, "a", "b", "c", "d", "e",
                                        "f")
     OrderbookWatch.set_msgchan(self, self.mcc)
     #register taker-specific msgchan callbacks here
     self.mcc.register_taker_callbacks(self.on_error, self.on_pubkey,
                                       self.on_ioauth, self.on_sig)
     self.mcc.set_daemon(self)
     self.restart_mc_required = True
     d = self.callRemote(JMInitProto,
                         nick_hash_length=NICK_HASH_LENGTH,
                         nick_max_encoded=NICK_MAX_ENCODED,
                         joinmarket_nick_header=JOINMARKET_NICK_HEADER,
                         joinmarket_version=JM_VERSION)
     self.defaultCallbacks(d)
     return {'accepted': True}
예제 #2
0
def test_mc_run(failuretype, mcindex, wait):
    ob = OrderbookWatch()
    ob.on_welcome = dummy_on_welcome
    dmcs = [DummyMessageChannel(None, hostid="hostid"+str(x)) for x in range(3)]
    mcc = MessageChannelCollection(dmcs)
    #this sets orderbookwatch callbacks
    ob.set_msgchan(mcc)
    dummydaemon = DaemonForSigns(mcc)
    mcc.set_daemon(dummydaemon)
    #need to override thread run()
    class FIThread(MChannelThread):
        def run(self):
            self.mc.run()
    fi = FIThread(mcc)
    fi.start()
    time.sleep(wait+0.5)
def getmc(nick):
    dm = DummyDaemon()
    mc = DummyMC(get_irc_mchannels()[0], nick, dm)
    mc.register_orderbookwatch_callbacks(on_order_seen=on_order_seen)
    mc.register_taker_callbacks(on_pubkey=on_pubkey)
    mc.on_connect = on_connect
    mc.on_disconnect = on_disconnect
    mc.on_welcome = on_welcome
    mcc = MessageChannelCollection([mc])
    return dm, mc, mcc
예제 #4
0
def main():
    parser = OptionParser(
        usage='usage: %prog [options]',
        description='Runs a webservice which shows the orderbook.')
    add_base_options(parser)
    parser.add_option('-H',
                      '--host',
                      action='store',
                      type='string',
                      dest='host',
                      default='localhost',
                      help='hostname or IP to bind to, default=localhost')
    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='port to listen on, default=62601',
                      default=62601)
    (options, args) = parser.parse_args()
    load_program_config(config_path=options.datadir)
    hostport = (options.host, options.port)
    mcs = [ObIRCMessageChannel(c) for c in get_irc_mchannels()]
    mcc = MessageChannelCollection(mcs)
    mcc.set_nick(get_dummy_nick())
    taker = ObBasic(mcc, hostport)
    log.info("Starting ob-watcher")
    mcc.run()
def main():
    global bond_exponent
    parser = OptionParser(
        usage='usage: %prog [options]',
        description='Runs a webservice which shows the orderbook.')
    add_base_options(parser)
    parser.add_option('-H',
                      '--host',
                      action='store',
                      type='string',
                      dest='host',
                      default='localhost',
                      help='hostname or IP to bind to, default=localhost')
    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='port to listen on, default=62601',
                      default=62601)
    (options, args) = parser.parse_args()
    load_program_config(config_path=options.datadir)
    # needed to display notional units of FB valuation
    bond_exponent = jm_single().config.get("POLICY", "bond_value_exponent")
    try:
        float(bond_exponent)
    except ValueError:
        log.error("Invalid entry for bond_value_exponent, should be decimal "
                  "number: {}".format(bond_exponent))
        sys.exit(EXIT_FAILURE)
    check_and_start_tor()
    hostport = (options.host, options.port)
    mcs = []
    chan_configs = get_mchannels(mode="PASSIVE")
    for c in chan_configs:
        if "type" in c and c["type"] == "onion":
            mcs.append(OnionMessageChannel(c))
        else:
            # default is IRC; TODO allow others
            mcs.append(IRCMessageChannel(c))
    IRCMessageChannel.on_privmsg = on_privmsg
    OnionMessageChannel.on_privmsg = on_privmsg
    mcc = MessageChannelCollection(mcs)
    mcc.set_nick(get_dummy_nick())
    taker = ObBasic(mcc, hostport)
    log.info("Starting ob-watcher")
    mcc.run()
def main():
    parser = OptionParser(
        usage='usage: %prog [options]',
        description='Runs a webservice which shows the orderbook.')
    add_base_options(parser)
    parser.add_option('-H',
                      '--host',
                      action='store',
                      type='string',
                      dest='host',
                      default='localhost',
                      help='hostname or IP to bind to, default=localhost')
    parser.add_option('-p',
                      '--port',
                      action='store',
                      type='int',
                      dest='port',
                      help='port to listen on, default=62601',
                      default=62601)
    (options, args) = parser.parse_args()
    load_program_config(config_path=options.datadir)
    check_and_start_tor()
    hostport = (options.host, options.port)
    mcs = []
    chan_configs = get_mchannels(mode="PASSIVE")
    for c in chan_configs:
        if "type" in c and c["type"] == "onion":
            mcs.append(OnionMessageChannel(c))
        else:
            # default is IRC; TODO allow others
            mcs.append(IRCMessageChannel(c))
    IRCMessageChannel.on_privmsg = on_privmsg
    OnionMessageChannel.on_privmsg = on_privmsg
    mcc = MessageChannelCollection(mcs)
    mcc.set_nick(get_dummy_nick())
    taker = ObBasic(mcc, hostport)
    log.info("Starting ob-watcher")
    mcc.run()
class JMDaemonTestServerProtocol(JMDaemonServerProtocol):

    def __init__(self, factory):
        super(JMDaemonTestServerProtocol, self).__init__(factory)
        #respondtoioauths should do nothing unless jmstate = 2
        self.respondToIoauths(True)
        #calling on_JM_MAKE_TX should also do nothing in wrong state
        assert super(JMDaemonTestServerProtocol, self).on_JM_MAKE_TX(
            1, 2) == {'accepted': False}
        #calling on_JM_FILL with negative amount should reject
        assert super(JMDaemonTestServerProtocol, self).on_JM_FILL(
            -1000, 2, 3, 4) == {'accepted': False}
        #checkutxos also does nothing for rejection at the moment
        self.checkUtxosAccepted(False)
        #None should be returned requesting a cryptobox for an unknown cp
        assert self.get_crypto_box_from_nick("notrealcp") == None
        #does nothing yet
        self.on_error("dummy error")

    @JMRequestOffers.responder
    def on_JM_REQUEST_OFFERS(self):
        for o in t_orderbook:
            #counterparty, oid, ordertype, minsize, maxsize,txfee, cjfee):
            self.on_order_seen(o["counterparty"], o["oid"], o["ordertype"],
                                 o["minsize"], o["maxsize"],
                                 o["txfee"], o["cjfee"])
        return super(JMDaemonTestServerProtocol, self).on_JM_REQUEST_OFFERS()
        
    @JMInit.responder
    def on_JM_INIT(self, bcsource, network, irc_configs, minmakers,
                   maker_timeout_sec):
        self.maker_timeout_sec = int(maker_timeout_sec)
        self.minmakers = int(minmakers)
        mcs = [DummyMC(None)]
        self.mcc = MessageChannelCollection(mcs)
        #The following is a hack to get the counterparties marked seen/active;
        #note it must happen before callign set_msgchan for OrderbookWatch
        self.mcc.on_order_seen = None
        for c in [o['counterparty'] for o in t_orderbook]:
            self.mcc.on_order_seen_trigger(mcs[0], c, "a", "b", "c", "d", "e", "f")
        OrderbookWatch.set_msgchan(self, self.mcc)
        #register taker-specific msgchan callbacks here
        self.mcc.register_taker_callbacks(self.on_error, self.on_pubkey,
                                                      self.on_ioauth, self.on_sig)
        self.mcc.set_daemon(self)
        self.restart_mc_required = True
        d = self.callRemote(JMInitProto,
                                   nick_hash_length=NICK_HASH_LENGTH,
                                   nick_max_encoded=NICK_MAX_ENCODED,
                                   joinmarket_nick_header=JOINMARKET_NICK_HEADER,
                                   joinmarket_version=JM_VERSION)
        self.defaultCallbacks(d)
        return {'accepted': True}

    @JMFill.responder
    def on_JM_FILL(self, amount, commitment, revelation, filled_offers):       
        tmpfo = json.loads(filled_offers)
        dummypub = "073732a7ca60470f709f23c602b2b8a6b1ba62ee8f3f83a61e5484ab5cbf9c3d"
        #trigger invalid on_pubkey conditions
        reactor.callLater(1, self.on_pubkey, "notrealcp", dummypub)
        reactor.callLater(2, self.on_pubkey, tmpfo.keys()[0], dummypub + "deadbeef")
        #trigger invalid on_ioauth condition
        reactor.callLater(2, self.on_ioauth, "notrealcp", 1, 2, 3, 4, 5)
        #trigger msg sig verify request operation for a dummy message
        #currently a pass-through
        reactor.callLater(1, self.request_signature_verify, "1",
                          "!push abcd abc def", "3", "4",
                          str(tmpfo.keys()[0]), 6, 7, self.mcc.mchannels[0].hostid)         
        #send "valid" onpubkey, onioauth messages
        for k, v in tmpfo.iteritems():
            reactor.callLater(1, self.on_pubkey, k, dummypub)
            reactor.callLater(2, self.on_ioauth, k, ['a', 'b'], "auth_pub",
                              "cj_addr", "change_addr", "btc_sig")
        return super(JMDaemonTestServerProtocol, self).on_JM_FILL(amount,
                                            commitment, revelation, filled_offers)

    @JMMakeTx.responder
    def on_JM_MAKE_TX(self, nick_list, txhex):
        for n in nick_list:
            reactor.callLater(1, self.on_sig, n, "dummytxsig")
        return super(JMDaemonTestServerProtocol, self).on_JM_MAKE_TX(nick_list,
                                                                     txhex)
예제 #8
0
def test_setup_mc():
    ob = OrderbookWatch()
    ob.on_welcome = dummy_on_welcome
    dmcs = [
        DummyMessageChannel(None, hostid="hostid" + str(x)) for x in range(3)
    ]
    mcc = MessageChannelCollection(dmcs)
    #this sets orderbookwatch callbacks
    ob.set_msgchan(mcc)
    #we want to set all the callbacks, maker and taker
    mcc.register_taker_callbacks(don_error, don_pubkey, don_ioauth, don_sig)
    mcc.register_maker_callbacks(
        on_orderbook_requested=don_orderbook_requested,
        on_order_fill=don_order_fill,
        on_seen_auth=don_seen_auth,
        on_seen_tx=don_seen_tx,
        on_push_tx=don_push_tx,
        on_commitment_seen=don_commitment_seen,
        on_commitment_transferred=don_commitment_transferred)
    mcc.set_nick("testnick")
    dummydaemon = DaemonForSigns(mcc)
    mcc.set_daemon(dummydaemon)
    for mc in dmcs:
        mc.on_welcome(mc)
    #instead of calling mcc.run, we'll start threads for mcs manually so we
    #can probe them
    for mc in dmcs:
        MChannelThread(mc).start()
    for m in dmcs:
        m.on_pubmsg("testmaker", "!orderbook")
    #receive invalid pubmsgs
    for msg in [
            "!orderbook!orderbook", "!notacommand a b c", "no command prefix",
            "!reloffer 0 4000 5000 100"
    ]:
        dmcs[2].on_pubmsg("testmaker", msg)

    mcc.request_orderbook()
    mcc.pubmsg("outward pubmsg")
    #now create a verifiable counterparty nick;
    #to get it into active state, need to receive an orderbook from it
    cp1 = make_valid_nick()
    #Simulate order receipt on 2 of 3 msgchans from this nick;
    #note that it will have its active chan set to mc "1" because that
    #is the last it was seen on:
    dmcs[0].on_privmsg(cp1, "!reloffer 0 4000 5000 100 0.2 abc def")
    dmcs[1].on_privmsg(cp1, "!reloffer 0 4000 5000 100 0.2 abc def")
    time.sleep(0.5)
    #send back a response
    mcc.privmsg(cp1, "fill", "0")
    #trigger failure to find nick in privmsg
    mcc.privmsg(cp1 + "XXX", "fill", "0")
    #trigger check_privmsg decorator
    mcc.send_error(cp1, "errormsg")
    mcc.push_tx(cp1, "deadbeef")
    #kill the chan on which the cp is marked active;
    #note dummychannel has no actual shutdown (call it anyway),
    #so change its status manually.
    dmcs[2].shutdown()
    mcc.mc_status[dmcs[1]] = 2
    time.sleep(0.5)
    #Flush removes references to inactive channels (in this case dmcs[1]).
    #Dynamic switching of cp1 should occur to the other seen channel (dmcs[0]).
    mcc.flush_nicks()
    #force cp1 to be unseen on mc 0:
    mcc.unsee_nick(cp1, dmcs[0])
    del mcc.active_channels[cp1]
    #try sending a privmsg again; this time it should just print a warning,
    #as cp1 is not seen anywhere
    mcc.send_error(cp1, "error")
    #simulate order cancels (even though we have none)
    mcc.cancel_orders([0, 1, 2])
    #let cp1 be seen on mc2 without having got into active channels;
    #note that this is an illegal pubmsg and is ignored for everything *except*
    #nick_seen (what we need here)
    dmcs[2].on_pubmsg(cp1, "random")
    mcc.send_error(cp1, "error")
    #Try using the proper way of setting up privsmgs
    #first try without box
    mcc.prepare_privmsg(cp1, "auth", "a b c")
    dummydaemon.crypto_boxes[cp1] = ["a", DummyBox()]
    #now conditions are correct, should succeed:
    mcc.prepare_privmsg(cp1, "auth", "a b c")
    #try again but this time there is no active channel
    del mcc.active_channels[cp1]
    mcc.prepare_privmsg(cp1, "auth", "a b c")
    #try announcing orders; first public
    mcc.announce_orders(t_orderbook)
    #try on fake mc
    mcc.announce_orders(t_orderbook, new_mc="fakemc")
    #direct to one cp
    mcc.announce_orders(t_orderbook, nick=cp1)
    #direct to one cp on one mc
    mcc.announce_orders(t_orderbook, nick=cp1, new_mc=dmcs[0])

    #Next, set up 6 counterparties and fill their offers,
    #send txs to them
    cps = [make_valid_nick(i) for i in range(1, 7)]
    #reuse t_chosen_orders data, but swap out the counterparty names
    offervals = t_chosen_orders.values()
    new_offers = dict(zip(cps, offervals))
    #first, pretend they all showed up on all 3 mcs:
    for m in dmcs:
        for cp in cps:
            m.on_privmsg(cp, "!reloffer 0 400000 500000 100 0.002 abc def")
    #next, call main fill function
    mcc.fill_orders(new_offers, 1000, "dummypubkey", "dummycommit")
    #now send a dummy transaction to this same set.
    #first fails with no crypto box.
    mcc.send_tx(cps, "deadbeef")
    #Now initialize the boxes
    for c in cps:
        dummydaemon.crypto_boxes[c] = ["a", DummyBox()]
    mcc.send_tx(cps, "deadbeef")
    #try to send the transaction to a wrong cp:
    mcc.send_tx(["notrealcp"], "deadbeef")

    #At this stage, dmcs0,2 should be "up" and 1 should have been reset to 1
    assert mcc.mc_status[dmcs[0]] == 1
    assert mcc.mc_status[dmcs[1]] == 1
    assert mcc.mc_status[dmcs[2]] == 1
    #Not currently used:
    #simulate re-connection of dmcs[1] ; note that this code isn't used atm
    #mcc.on_connect_trigger(dmcs[1])
    #assert mcc.mc_status[dmcs[1]] == 1
    #Now trigger disconnection code; each mc one by one; the last should trigger
    #on_disconnect callback
    for m in dmcs:
        mcc.on_disconnect_trigger(m)
    #reconnect; effect is all nick references are flushed
    for m in dmcs:
        mcc.on_connect_trigger(m)
    assert mcc.active_channels == {}
    #have the cps rearrive
    for m in dmcs:
        for cp in cps:
            m.on_privmsg(cp, "!reloffer 0 4000 5000 100 0.2 abc def")

    #####################################################################
    #next series of messages are to test various normal and abnormal
    #message receipts under normal connection conditions
    #####################################################################

    #simulate receipt of commitments
    #valid
    dmcs[0].on_pubmsg(cps[2], "!hp2 deadbeef")
    #invalid missing field
    dmcs[0].on_pubmsg(cps[2], "!hp2")
    #receive commitment via privmsg to trigger commitment_transferred
    dmcs[0].on_privmsg(cps[2], "!hp2 deadbeef abc def")
    #simulate receipt of order cancellation
    #valid
    dmcs[0].on_pubmsg(cps[2], "!cancel 2")
    #invalid oid
    dmcs[0].on_pubmsg(cps[2], "!cancel x")
    #too short privmsg (can't even have a signature)
    dmcs[0].on_privmsg(cps[2], COMMAND_PREFIX)
    #not using correct protocol start character
    dmcs[0].on_privmsg(cps[2], "A B C")
    #unrecognized command
    dmcs[0].on_privmsg(cps[2], "!fakecommand A B C D")
    #Perhaps dubious, but currently msg after command must be non-zero
    dmcs[0].on_privmsg(cps[2], "!reloffer sig1 sig2")
    #Simulating receipt of encrypted messages:
    #ioauth
    dummy_on_ioauth_msg = b"deadbeef:0,deadbeef:1 XauthpubX XcjaddrX XchangeaddrX XbtcsigX"
    b64dummyioauth = base64.b64encode(dummy_on_ioauth_msg).decode('ascii')
    dmcs[0].on_privmsg(cps[3], "!ioauth " + b64dummyioauth + " sig1 sig2")
    #Try with a garbage b64 (but decodable); should throw index error at least
    dmcs[0].on_privmsg(cps[3], "!ioauth _*_ sig1 sig2")
    #Try also for receipt from an unknown counterparty; should fail with no enc box
    dmcs[0].on_privmsg("notrealcp", "!ioauth " + b64dummyioauth + " sig1 sig2")
    #Try same message from valid cp but with corrupted b64
    b64dummyioauth = "999"
    dmcs[0].on_privmsg(cps[3], "!ioauth " + b64dummyioauth + " sig1 sig2")
    #sig
    dummy_on_sig_msg = b"dummysig"
    b64dummysig = base64.b64encode(dummy_on_sig_msg).decode('ascii')
    dmcs[0].on_privmsg(cps[3], "!sig " + b64dummysig + " sig1 sig2")
    #auth
    dummy_auth_msg = b"dummyauth"
    b64dummyauth = base64.b64encode(dummy_auth_msg).decode('ascii')
    dmcs[0].on_privmsg(cps[2], "!auth " + b64dummyauth + " sig1 sig2")
    #invalid auth (only no message is invalid)
    dmcs[0].on_privmsg(
        cps[3],
        "!auth " + base64.b64encode(b"").decode('ascii') + " sig1 sig2")
    #tx
    #valid
    dummy_tx = b"deadbeefdeadbeef"
    b64dummytx = base64.b64encode(dummy_tx)
    b642dummytx = base64.b64encode(b64dummytx).decode('ascii')
    dmcs[0].on_privmsg(cps[2], "!tx " + b642dummytx + " sig1 sig2")
    badbase64tx = b"999"
    badbase64tx2 = base64.b64encode(badbase64tx).decode('ascii')
    #invalid txhex; here the first round will work (msg decryption), second shouldn't
    dmcs[0].on_privmsg(cps[2], "!tx " + badbase64tx2 + " sig1 sig2")
    #push
    #valid
    dmcs[0].on_privmsg(cps[2], "!push " + b642dummytx + " sig1 sig2")
    #invalid
    dmcs[0].on_privmsg(cps[2], "!push 999 sig1 sig2")
    #fill
    #valid, no commit
    dmcs[0].on_privmsg(cps[4], "!fill 0 4000 dummypub sig1 sig2")
    #valid with commit
    dmcs[0].on_privmsg(cps[4], "!fill 0 4000 dummypub dummycommit sig1 sig2")
    #invalid length
    dmcs[0].on_privmsg(cps[4], "!fill 0 sig1 sig2")
    #pubkey
    dmcs[0].on_privmsg(cps[4], "!pubkey dummypub sig1 sig2")
    ##############################################################
    #End message receipts
    ##############################################################

    #simulate loss of conncetion to cp[0]
    for m in dmcs[::-1]:
        mcc.on_nick_leave_trigger(cps[0], m)
    #call onnickleave for something not in the ac list
    mcc.on_nick_leave_trigger("notrealcp", dmcs[0])
    #make mcs 0,1 go down so that when cp[1] tries to dynamic switch, it fails
    mcc.on_disconnect_trigger(dmcs[0])
    mcc.on_disconnect_trigger(dmcs[1])
    mcc.on_nick_leave_trigger(cps[1], dmcs[2])
    mcc.shutdown()