Exemple #1
0
    def getSingleMessage(self,
                         timeout=1,
                         chanIndex=0,
                         prefix=None,
                         external=False):
        qname = prefix + self.uniqID() if prefix else self.uniqID()
        msg = Msg.getSingleMessage(qname, timeout, chanIndex, external)
        if not msg:
            shared.debug(5, ["Message layer returned none"])
            return None
        #all messages must be verified
        shared.logToFile(
            g("Directories",
              "agent_base_dir"), "Signed message received:" + msg.keys()[0] +
            ':' + msg.values()[0] + " at time:" + str(time.time()))
        sendingID = msg.keys()[0].split('.')[1]
        #retrieve pubkey
        msgInner = ';'.join(':'.join(
            msg.values()[0].split(':')[1:]).split(';')[:-1])
        sig = ':'.join(msg.values()[0].split(':')[1:]).split(';')[-1]
        addr = multisig.pubtoaddr(multisig.ecdsa_recover(msgInner, sig))

        if not addr == sendingID:
            #don't add anything but failure to message to prevent leaks
            shared.debug(0, ["Verification failure", sendingID, chanIndex])
            self.sendMessage({msg.keys()[0]: 'VERIFICATION_FAILED:'},
                             sendingID, chanIndex)
            return None
        else:
            #having checked the message signature, dispose of it
            v = ';'.join(msg.values()[0].split(';')[:-1])
            msg = {msg.keys()[0]: v}
            shared.debug(4, ["Returning this message:", msg])
            return msg
Exemple #2
0
 def getSingleMessage(self,timeout=1,chanIndex=0,prefix=None,external=False):
     qname = prefix+self.uniqID() if prefix else self.uniqID()
     msg = Msg.getSingleMessage(qname,timeout,chanIndex,external)
     if not msg:
         shared.debug(5,["Message layer returned none"])
         return None
     #all messages must be verified
     shared.logToFile(g("Directories","agent_base_dir"),"Signed message received:"+msg.keys()[0]+':'+msg.values()[0]+ " at time:"+str(time.time()))
     sendingID = msg.keys()[0].split('.')[1]
     #retrieve pubkey
     msgInner = ';'.join(':'.join(msg.values()[0].split(':')[1:]).split(';')[:-1])
     sig = ':'.join(msg.values()[0].split(':')[1:]).split(';')[-1]
     addr = multisig.pubtoaddr(multisig.ecdsa_recover(msgInner,sig))
     
     if not addr == sendingID:
         #don't add anything but failure to message to prevent leaks
         shared.debug(0,["Verification failure",sendingID,chanIndex])
         self.sendMessage({msg.keys()[0]:'VERIFICATION_FAILED:'},sendingID,chanIndex)
         return None
     else:
         #having checked the message signature, dispose of it
         v = ';'.join(msg.values()[0].split(';')[:-1])
         msg = {msg.keys()[0]:v}
         shared.debug(4,["Returning this message:",msg])
         return msg    
Exemple #3
0
 def getCtrprtyPubkey(self, c):
     addr = self.buyer if c else self.seller
     msg = self.contract.getContractTextOrdered()
     for sig in self.contract.signatures.values():
         pub = multisig.ecdsa_recover(msg, sig)
         if addr == multisig.pubtoaddr(pub):
             shared.debug(2, ["Got address", addr, "for pubkey,", pub])
             return pub
Exemple #4
0
    def receiveContractCNE(self, msg):
        '''When receiving a contract, first check it's signed and
            throw it out if not. Otherwise, store it in the list of contracts 
            that have been proposed by possible counterparties
            We can choose to accept at anytime, within the process/session.
            However we will not persist contract 'suggestions' across sessions. '''

        allContractDetails = ':'.join(msg.split(':')[1:]).split('|')
        contractDetails = allContractDetails[0]
        #the contract is in json; need to change it to a Contract object
        contractDetailsDict = json.loads(contractDetails)
        tmpContract = Contract.Contract(contractDetailsDict)

        ca = tmpContract.getCounterparty(self.uniqID())

        if not ca:
            return 'Contract invalid: does not contain this identity'

        for s in allContractDetails[1:]:
            ad = multisig.pubtoaddr(
                multisig.ecdsa_recover(tmpContract.getContractTextOrdered(),
                                       s))
            shared.debug(2, ["\n recovery produced this address: ", ad, "\n"])
            tmpContract.signatures[ad] = s

        #now the temporary contract object is fully populated;
        #we can check the signatures match the IDs in the contract
        for k, v in tmpContract.signatures.iteritems():
            if k not in [
                    tmpContract.text['Buyer BTC Address'],
                    tmpContract.text['Seller BTC Address']
            ]:
                shared.debug(1,
                             ['Error: signature', v, 'from', k, 'was invalid'])
                return 'Invalid contract signature'

        self.contractLock.acquire()
        try:
            #note that this represents an override for
            #repeated sending of contracts; one cp can only
            #be suggesting one contract at a time
            self.pendingContracts[ca] = tmpContract
        finally:
            self.contractLock.release()
        #if the contract is already signed by me AND ctrprty, send it to escrow
        if len(tmpContract.signatures.keys()) > 1:
            self.contractLock.acquire()
            try:
                self.workingContract = tmpContract
                #wipe the pending contract list; we are only
                #interested in the live contract now
                self.pendingContracts = {}
            finally:
                self.contractLock.release()

        return 'Signed contract successfully received from counterparty: ' + ca
Exemple #5
0
    def receiveContractCNE(self, msg):
        '''acting as CNE, the escrow can receive a doubly-signed
        contract at any time from any party. After verifying that the signatures are valid, and that the deposits 
        are specified correctly in the contract, the address
        for deposits is reported and the contract signed for the third time by the escrow.
        Messages sent to both parties giving them a deadline for deposit. '''
        sender = msg[0].split('.')[1]
        #this special message is delimited by |
        allContractDetails = ':'.join(msg[1].split(':')[1:]).split('|')

        #the contract is in json format
        contractDetails = allContractDetails[0]
        tmpContract = Contract.Contract(json.loads(contractDetails))
        pubs = {}
        for s in allContractDetails[1:]:
            tmpPub = multisig.ecdsa_recover(
                tmpContract.getContractTextOrdered(), s)
            ad = multisig.pubtoaddr(tmpPub)
            shared.debug(2, ["\n recovery produced this address: ", ad, "\n"])
            tmpContract.signatures[ad] = s
            #store the pubkeys for later use
            pubs[ad] = tmpPub

        #immediately check for 2 signatures; otherwise dump immediately
        if len(allContractDetails) != 3:
            return (False, 'Not a valid and fully signed contract, ignoring',
                    tmpContract)

        #now the temporary contract object is fully populated;
        #we can check the signatures match the IDs in the contract
        for k, v in tmpContract.signatures.iteritems():
            if k not in [
                    tmpContract.text['Buyer BTC Address'],
                    tmpContract.text['Seller BTC Address']
            ]:
                shared.debug(1,
                             ['Error: signature', v, 'from', k, 'was invalid'])
                return (False, 'Invalid contract signature', tmpContract)

        #need to check that the proposed deposits follow the business rules
        verdict, reason = self.checkBusinessRulesCNE(tmpContract)
        if not verdict: return (verdict, reason, tmpContract)

        #removed for now.
        #now we're happy that the contract is valid we build the dep multisig
        #multisig.initialise(g("Escrow","escrow_pubkey"),g("Directories","escrow_base_dir"))
        #for a,p in pubs.iteritems():
        #multisig.store_share(p,a)
        #msigaddr, mscript = multisig.create_multisig_address(*pubs.keys())

        return (True, multisig.pubtoaddr(g("Escrow",
                                           "escrow_pubkey")), tmpContract)
Exemple #6
0
 def receiveContractCNE(self,msg):
     '''When receiving a contract, first check it's signed and
         throw it out if not. Otherwise, store it in the list of contracts 
         that have been proposed by possible counterparties
         We can choose to accept at anytime, within the process/session.
         However we will not persist contract 'suggestions' across sessions. '''        
     
     allContractDetails = ':'.join(msg.split(':')[1:]).split('|')
     contractDetails = allContractDetails[0]
     #the contract is in json; need to change it to a Contract object
     contractDetailsDict = json.loads(contractDetails)
     tmpContract = Contract.Contract(contractDetailsDict)
     
     ca = tmpContract.getCounterparty(self.uniqID())
     
     if not ca:
         return 'Contract invalid: does not contain this identity'
     
     for s in allContractDetails[1:]:
         ad = multisig.pubtoaddr(multisig.ecdsa_recover(tmpContract.getContractTextOrdered(),s))
         shared.debug(2,["\n recovery produced this address: ",ad,"\n"])
         tmpContract.signatures[ad]=s
     
     #now the temporary contract object is fully populated; 
     #we can check the signatures match the IDs in the contract
     for k,v in tmpContract.signatures.iteritems():
         if k not in [tmpContract.text['Buyer BTC Address'],tmpContract.text['Seller BTC Address']]:
             shared.debug(1,['Error: signature',v,'from',k,'was invalid'])
             return 'Invalid contract signature'
     
     self.contractLock.acquire()
     try:
         #note that this represents an override for
         #repeated sending of contracts; one cp can only
         #be suggesting one contract at a time
         self.pendingContracts[ca] = tmpContract
     finally:
         self.contractLock.release()
     #if the contract is already signed by me AND ctrprty, send it to escrow
     if len(tmpContract.signatures.keys())>1:
         self.contractLock.acquire()
         try:
             self.workingContract = tmpContract
             #wipe the pending contract list; we are only
             #interested in the live contract now
             self.pendingContracts = {}
         finally:
             self.contractLock.release()
         
     return 'Signed contract successfully received from counterparty: '+ca
Exemple #7
0
 def receiveContractCNE(self,msg):
     '''acting as CNE, the escrow can receive a doubly-signed
     contract at any time from any party. After verifying that the signatures are valid, and that the deposits 
     are specified correctly in the contract, the address
     for deposits is reported and the contract signed for the third time by the escrow.
     Messages sent to both parties giving them a deadline for deposit. '''       
     sender = msg[0].split('.')[1]
     #this special message is delimited by |
     allContractDetails = ':'.join(msg[1].split(':')[1:]).split('|')
     
     #the contract is in json format
     contractDetails = allContractDetails[0]
     tmpContract = Contract.Contract(json.loads(contractDetails))
     pubs = {}
     for s in allContractDetails[1:]:
         tmpPub = multisig.ecdsa_recover(tmpContract.getContractTextOrdered(),s)
         ad = multisig.pubtoaddr(tmpPub)
         shared.debug(2,["\n recovery produced this address: ",ad,"\n"])
         tmpContract.signatures[ad]=s
         #store the pubkeys for later use
         pubs[ad]= tmpPub
     
     #immediately check for 2 signatures; otherwise dump immediately
     if len(allContractDetails) != 3:
         return (False,'Not a valid and fully signed contract, ignoring',tmpContract)        
     
     #now the temporary contract object is fully populated; 
     #we can check the signatures match the IDs in the contract
     for k,v in tmpContract.signatures.iteritems():
         if k not in [tmpContract.text['Buyer BTC Address'],tmpContract.text['Seller BTC Address']]:
             shared.debug(1,['Error: signature',v,'from',k,'was invalid'])
             return (False,'Invalid contract signature',tmpContract)
     
     #need to check that the proposed deposits follow the business rules
     verdict,reason = self.checkBusinessRulesCNE(tmpContract)
     if not verdict: return (verdict, reason,tmpContract)
     
     #removed for now.
     #now we're happy that the contract is valid we build the dep multisig
     #multisig.initialise(g("Escrow","escrow_pubkey"),g("Directories","escrow_base_dir"))
     #for a,p in pubs.iteritems():
         #multisig.store_share(p,a)
     #msigaddr, mscript = multisig.create_multisig_address(*pubs.keys())
     
     return (True,multisig.pubtoaddr(g("Escrow","escrow_pubkey")),tmpContract)     
Exemple #8
0
 def processNewTxRE(self,msg):
     
     txHash,sender = msg[0].split('.')
     txString,buyerSig,sellerSig,escrowSig,btcTxhash = \
         ':'.join(msg[1].split(':')[1:]).split('|')
     
     print txString
     print buyerSig
     print sellerSig
     print btcTxhash
     
     #shared.debug(2,["We received a transaction string:",txString])
     #instantiate the transaction
     tx = pickle.loads(txString)
     if tx.uniqID() != txHash:
         shared.debug(0,["Alert: transaction object passed with inconsistent hash, given",txHash,"should be:",tx.uniqID()])
         self.sendMessage('RE_CNE_TX_REJECT_RECEIPT:',recipientID='CNE'+sender,txID=tx.uniqID())
         return None
     #initiate the new multisig address for this transaction
     tx.msigAddr,tx.mscript = self.getMultisigAddress(tx,g("Escrow","escrow_pubkey"))
     
     #allow us to keep track of where the deposits are (fees also collected here) 
     tx.depositHash = btcTxhash       
     
     #permanent record of identity of CNE
     tx.CNE = sender
     
     #validate the signatures
     for i,j in zip([buyerSig,sellerSig,escrowSig],[tx.buyer,tx.seller,sender]):
         testaddress = multisig.pubtoaddr(multisig.ecdsa_recover(tx.contract.getContractTextOrdered(),i))
         shared.debug(4,["Recovery produced this address:",multisig.pubtoaddr(testaddress)])
         if not testaddress == j:
             shared.debug(0,["Alert: this transaction is not correctly signed by",j,"- ignoring"])
             self.sendMessage('RE_CNE_TX_REJECT_RECEIPT:',recipientID='CNE'+sender,txID=tx.uniqID())
             return None
         else:
             shared.debug(1,["Correct signature from:",j])
     
     #add the transaction to the persistent store
     #at this point, a valid transaction has been initialised but not funded in any way.
     self.transactionUpdate(tx=tx,new_state=400)
     
     #send back confirmation message (on THIS message queue)
     self.sendMessage('RE_CNE_TX_CONFIRM_RECEIPT:',recipientID='CNE'+sender,txID=tx.uniqID())
Exemple #9
0
    def processNewTxRE(self, msg):

        txHash, sender = msg[0].split('.')
        txString,buyerSig,sellerSig,escrowSig,btcTxhash = \
            ':'.join(msg[1].split(':')[1:]).split('|')

        print txString
        print buyerSig
        print sellerSig
        print btcTxhash

        #shared.debug(2,["We received a transaction string:",txString])
        #instantiate the transaction
        tx = pickle.loads(txString)
        if tx.uniqID() != txHash:
            shared.debug(0, [
                "Alert: transaction object passed with inconsistent hash, given",
                txHash, "should be:",
                tx.uniqID()
            ])
            self.sendMessage('RE_CNE_TX_REJECT_RECEIPT:',
                             recipientID='CNE' + sender,
                             txID=tx.uniqID())
            return None
        #initiate the new multisig address for this transaction
        tx.msigAddr, tx.mscript = self.getMultisigAddress(
            tx, g("Escrow", "escrow_pubkey"))

        #allow us to keep track of where the deposits are (fees also collected here)
        tx.depositHash = btcTxhash

        #permanent record of identity of CNE
        tx.CNE = sender

        #validate the signatures
        for i, j in zip([buyerSig, sellerSig, escrowSig],
                        [tx.buyer, tx.seller, sender]):
            testaddress = multisig.pubtoaddr(
                multisig.ecdsa_recover(tx.contract.getContractTextOrdered(),
                                       i))
            shared.debug(4, [
                "Recovery produced this address:",
                multisig.pubtoaddr(testaddress)
            ])
            if not testaddress == j:
                shared.debug(0, [
                    "Alert: this transaction is not correctly signed by", j,
                    "- ignoring"
                ])
                self.sendMessage('RE_CNE_TX_REJECT_RECEIPT:',
                                 recipientID='CNE' + sender,
                                 txID=tx.uniqID())
                return None
            else:
                shared.debug(1, ["Correct signature from:", j])

        #add the transaction to the persistent store
        #at this point, a valid transaction has been initialised but not funded in any way.
        self.transactionUpdate(tx=tx, new_state=400)

        #send back confirmation message (on THIS message queue)
        self.sendMessage('RE_CNE_TX_CONFIRM_RECEIPT:',
                         recipientID='CNE' + sender,
                         txID=tx.uniqID())