Пример #1
0
 def send_poll(self, method, callback):
     nonce = self.get_msg_nonce()
     msg_to_sign = prepare_ecdsa_msg(nonce, method)
     sig = btc.ecdsa_sign(msg_to_sign, self.keyset["key_session"][0])
     noncesig = {"nonce": nonce, "sig": sig}
     return self.jsonrpcclient.send_poll(
         method, callback, noncesig, self.coinswap_parameters.session_id)
Пример #2
0
 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}
 def sign_message(privkey, message):
     """
     args:
         privkey: bytes
         message: bytes
     returns:
         base64-encoded signature
     """
     return btc.ecdsa_sign(message, privkey, True, False)
Пример #4
0
 def on_JM_REQUEST_MSGSIG(self, nick, cmd, msg, msg_to_be_signed, hostid):
     sig = btc.ecdsa_sign(str(msg_to_be_signed), self.nick_priv)
     msg_to_return = str(msg) + " " + self.nick_pubkey + " " + sig
     d = self.callRemote(commands.JMMsgSignature,
                         nick=nick,
                         cmd=cmd,
                         msg_to_return=msg_to_return,
                         hostid=hostid)
     self.defaultCallbacks(d)
     return {'accepted': True}
 def test_JMRequestMsgSigVerify(self):
     fullmsg = 'fullmsgforverify'
     priv = b"\xaa"*32 + b"\x01"
     pub = bintohex(bitcoin.privkey_to_pubkey(priv))
     sig = bitcoin.ecdsa_sign(fullmsg, priv)
     yield self.init_client()
     yield self.callClient(
         JMRequestMsgSigVerify, msg='msgforverify', fullmsg=fullmsg,
         sig=sig, pubkey=pub, nick='dummynickforverify', hashlen=4,
         max_encoded=5, hostid='hostid2')
    def get_fidelity_bond_template(self):
        if not isinstance(self.wallet_service.wallet, FidelityBondMixin):
            jlog.info(
                "Not a fidelity bond wallet, not announcing fidelity bond")
            return None
        blocks = jm_single().bc_interface.get_current_block_height()
        mediantime = jm_single().bc_interface.get_best_block_median_time()

        BLOCK_COUNT_SAFETY = 2  #use this safety number to reduce chances of the proof expiring
        #before the taker gets a chance to verify it
        RETARGET_INTERVAL = 2016
        CERT_MAX_VALIDITY_TIME = 1
        cert_expiry = ((blocks + BLOCK_COUNT_SAFETY) //
                       RETARGET_INTERVAL) + CERT_MAX_VALIDITY_TIME

        utxos = self.wallet_service.wallet.get_utxos_by_mixdepth(
            include_disabled=True,
            includeheight=True)[FidelityBondMixin.FIDELITY_BOND_MIXDEPTH]
        timelocked_utxos = [
            (outpoint, info) for outpoint, info in utxos.items()
            if FidelityBondMixin.is_timelocked_path(info["path"])
        ]
        if len(timelocked_utxos) == 0:
            jlog.info(
                "No timelocked coins in wallet, not announcing fidelity bond")
            return
        timelocked_utxos_with_confirmation_time = [
            (outpoint, info, jm_single().bc_interface.get_block_time(
                jm_single().bc_interface.get_block_hash(info["height"])))
            for (outpoint, info) in timelocked_utxos
        ]

        interest_rate = get_interest_rate()
        max_valued_bond = max(
            timelocked_utxos_with_confirmation_time,
            key=lambda x: FidelityBondMixin.
            calculate_timelocked_fidelity_bond_value(x[1]["value"], x[2], x[1][
                "path"][-1], mediantime, interest_rate))
        (utxo_priv,
         locktime), engine = self.wallet_service.wallet._get_key_from_path(
             max_valued_bond[1]["path"])
        utxo_pub = engine.privkey_to_pubkey(utxo_priv)
        cert_priv = os.urandom(32) + b"\x01"
        cert_pub = btc.privkey_to_pubkey(cert_priv)
        cert_msg = b"fidelity-bond-cert|" + cert_pub + b"|" + str(
            cert_expiry).encode("ascii")
        cert_sig = base64.b64decode(btc.ecdsa_sign(cert_msg, utxo_priv))
        utxo = (max_valued_bond[0][0], max_valued_bond[0][1])
        fidelity_bond = FidelityBond(utxo, utxo_pub, locktime, cert_expiry,
                                     cert_priv, cert_pub, cert_sig)
        jlog.info("Announcing fidelity bond coin {}".format(fmt_utxo(utxo)))
        return fidelity_bond
Пример #7
0
 def send(self, *args):
     """The state machine state maps to a specific call in the
     JSON RPC API. The return value is passed to the callback, which
     is the statemachine .tick() function, which passes that return
     value to the next state transition function. All method calls
     must be prefaced by the sessionid for distinction of client, other
     than the handshake which inits the session.
     """
     mn = self.jsonrpcclient.method_names[self.sm.state]
     nonce = self.get_msg_nonce()
     msg_to_sign = prepare_ecdsa_msg(nonce, mn, *args)
     sig = btc.ecdsa_sign(msg_to_sign, self.keyset["key_session"][0])
     noncesig = {"nonce": nonce, "sig": sig}
     params = [self.coinswap_parameters.session_id, noncesig, mn
               ] + list(args)
     if mn != "handshake":
         return self.jsonrpcclient.send("coinswap", *params)
     else:
         return self.jsonrpcclient.send("handshake", *params)
Пример #8
0
    def on_auth_received(self, nick, offer, commitment, cr, amount, kphex):
        """Receives data on proposed transaction offer from daemon, verifies
        commitment, returns necessary data to send ioauth message (utxos etc)
        """
        # special case due to cjfee passed as string: it can accidentally parse
        # as hex:
        if not isinstance(offer["cjfee"], str):
            offer["cjfee"] = bintohex(offer["cjfee"])
        #check the validity of the proof of discrete log equivalence
        tries = jm_single().config.getint("POLICY", "taker_utxo_retries")

        def reject(msg):
            jlog.info("Counterparty commitment not accepted, reason: " + msg)
            return (False, )

        # deserialize the commitment revelation
        try:
            cr_dict = PoDLE.deserialize_revelation(cr)
        except PoDLEError as e:
            reason = repr(e)
            return reject(reason)

        if not verify_podle(cr_dict['P'],
                            cr_dict['P2'],
                            cr_dict['sig'],
                            cr_dict['e'],
                            commitment,
                            index_range=range(tries)):
            reason = "verify_podle failed"
            return reject(reason)
        #finally, check that the proffered utxo is real, old enough, large enough,
        #and corresponds to the pubkey
        res = jm_single().bc_interface.query_utxo_set([cr_dict['utxo']],
                                                      includeconf=True)
        if len(res) != 1 or not res[0]:
            reason = "authorizing utxo is not valid"
            return reject(reason)
        age = jm_single().config.getint("POLICY", "taker_utxo_age")
        if res[0]['confirms'] < age:
            reason = "commitment utxo not old enough: " + str(
                res[0]['confirms'])
            return reject(reason)
        reqd_amt = int(
            amount *
            jm_single().config.getint("POLICY", "taker_utxo_amtpercent") /
            100.0)
        if res[0]['value'] < reqd_amt:
            reason = "commitment utxo too small: " + str(res[0]['value'])
            return reject(reason)

        try:
            if not self.wallet_service.pubkey_has_script(
                    cr_dict['P'], res[0]['script']):
                raise EngineError()
        except EngineError:
            reason = "Invalid podle pubkey: " + str(cr_dict['P'])
            return reject(reason)

        # authorisation of taker passed
        # Find utxos for the transaction now:
        utxos, cj_addr, change_addr = self.oid_to_order(offer, amount)
        if not utxos:
            #could not find funds
            return (False, )
        # for index update persistence:
        self.wallet_service.save_wallet()
        # Construct data for auth request back to taker.
        # Need to choose an input utxo pubkey to sign with
        # (no longer using the coinjoin pubkey from 0.2.0)
        # Just choose the first utxo in self.utxos and retrieve key from wallet.
        auth_address = utxos[list(utxos.keys())[0]]['address']
        auth_key = self.wallet_service.get_key_from_addr(auth_address)
        auth_pub = btc.privkey_to_pubkey(auth_key)
        # kphex was auto-converted by @hexbin but we actually need to sign the
        # hex version to comply with pre-existing JM protocol:
        btc_sig = btc.ecdsa_sign(bintohex(kphex), auth_key)
        return (True, utxos, auth_pub, cj_addr, change_addr, btc_sig)
Пример #9
0
 def create_proof_msg(self, cert_priv):
     nick_sig = ecdsa_sign(self.nick_msg, cert_priv)
     # FIXME: remove stupid base64
     nick_sig = base64.b64decode(nick_sig)
     return self._serialize_proof_msg(nick_sig)