示例#1
0
def sendAdjudicatorCollateralSigningRequest(myself,identityInfo,collateralAmount):
    
    msigaddr,mscript = myself.createCollateralMultisig()
    if not msigaddr or not mscript:
        shared.debug(0,["Critical error: cannot create a multisignature address."])
        return False
    mypub,mypriv = multisig.getKeysFromUniqueID(myself.uniqID())
    
    shared.debug(0,["You have created this multisig address:",msigaddr])
    shared.debug(0,["Please wait while your request is sent out to the pool."])
    #broadcast
    #TODO this is slow but ..?
    for i,e in enumerate(getEscrowList()):
        
        shared.config.set("Escrow","escrow_id",value=e[0])
        shared.config.set("Escrow","escrow_pubkey",value=e[2])
        shared.config.set("Escrow","escrow_host",value=e[1])
        shared.debug(2,["Set the escrow to host:",g("Escrow","escrow_host"),"id:",g("Escrow","escrow_id"),"pubkey:",g("Escrow","escrow_pubkey")])                    
        
        #Msg.closeConnection()
        time.sleep(1)
        
        Msg.instantiateConnection()
        
        myself.sendMessage('ADJUDICATOR_APPLICATION:'+'|'.join([msigaddr,mypub,identityInfo]))
    shared.debug(0,["Your application has been sent to all pool members. Please wait for their response."])
    return True
示例#2
0
    def __init__(self, basedir, btcaddress):
        super(EscrowAgent, self).__init__(basedir=basedir, btcadd=btcaddress)
        shared.debug(1,[\
        "instantiating an escrow agent, listening for messages"])

        #messaging server should always be local for escrow
        self.host = '127.0.0.1'

        #log in to message queue server
        Msg.instantiateConnection(un=g("Agent", "agent_rabbitmq_user"),
                                  pw=g("Agent", "agent_rabbitmq_pass"))

        #hardcoded for testing TODO
        self.escrowID = btcaddress

        #self.superID = g("Escrow","super_id")

        #get the public list of escrows for propagation to RE
        self.escrowList = self.getEscrowList()

        #this  needs to be persisted as it contains
        #state information - in order to accept requests involving two parties,
        #the escrow needs to keep a record of earlier requests downloaded
        #from the MQ. The format is a list of lists, each inner list having
        #a key,message pair [k,m]
        self.requestStore = []

        d = os.path.join(g("Directories", "escrow_base_dir"), "multisig_store")
        p = g("Escrow", "escrow_pubkey")
        #initialise multisig
        multisig.initialise(p, d)
示例#3
0
 def __init__(self,basedir,btcaddress):
     super(EscrowAgent,self).__init__(basedir=basedir, btcadd=btcaddress)
     shared.debug(1,[\
     "instantiating an escrow agent, listening for messages"])
     
     #messaging server should always be local for escrow
     self.host='127.0.0.1'
     
     #log in to message queue server
     Msg.instantiateConnection(un=g("Agent","agent_rabbitmq_user"),pw=g("Agent","agent_rabbitmq_pass"))
     
     #hardcoded for testing TODO
     self.escrowID=btcaddress
     
     #self.superID = g("Escrow","super_id")
     
     #get the public list of escrows for propagation to RE
     self.escrowList = self.getEscrowList()
     
     #this  needs to be persisted as it contains
     #state information - in order to accept requests involving two parties,
     #the escrow needs to keep a record of earlier requests downloaded
     #from the MQ. The format is a list of lists, each inner list having
     #a key,message pair [k,m]
     self.requestStore=[]
     
     d = os.path.join(g("Directories","escrow_base_dir"),"multisig_store")
     p = g("Escrow","escrow_pubkey")
     #initialise multisig
     multisig.initialise(p,d)        
示例#4
0
def changeEscrow(specific=None):
    shared.debug(0, ["Current escrow:", g("Escrow", "escrow_id")])
    if specific:
        c = specific
    else:
        for i, e in enumerate(getEscrowList()):
            print "[" + str(i + 1) + "] " + e[0]
        c = shared.get_validated_input("Choose an escrow", int)

    if c not in range(1, len(escrowList) + 1):
        shared.debug(0, ["Invalid choice from escrow list"])
    else:
        #rewrite the settings file and reset the escrow
        #TODO: persist changes to config file
        shared.config.set("Escrow", "escrow_id", value=escrowList[c - 1][0])
        shared.config.set("Escrow",
                          "escrow_pubkey",
                          value=escrowList[c - 1][2])
        shared.config.set("Escrow", "escrow_host", value=escrowList[c - 1][1])
        shared.debug(2, [
            "Set the escrow to host:",
            g("Escrow", "escrow_host"), "id:",
            g("Escrow", "escrow_id"), "pubkey:",
            g("Escrow", "escrow_pubkey")
        ])

    Msg.closeConnection()
    time.sleep(1)
    Msg.instantiateConnection(un='client1', pw='client1', chanIndex=0)
示例#5
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    
示例#6
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
示例#7
0
 def sendMessage(self,msg,recipientID='CNE',txID=None,chanIndex=0):
     '''wrapper function for sending messages
     to a counterparty. Not all messages have an associated
     transactionid, so that is allowed to be null and is
     replaced by '0'. If recipientID is not set, it defaults
     to the active CNE. A signature of the value of the 
     single dict entry is appended to the value after the last ';'
     as identity authorization.
     '''
     if not txID:
         txID='0'
     if recipientID in ['CNE','RE']:
         #TODO fix
         recipientID = recipientID+g("Escrow","escrow_id")
         
     text,sig = multisig.signText(self.uniqID(),':'.join(msg.split(':')[1:]))
     
     newMsg = {}
     newMsg[txID+'.'+self.uniqID()]=msg+';'+sig
     Msg.sendMessages(newMsg,recipientID,chanIndex) 
示例#8
0
    def sendMessage(self, msg, recipientID='CNE', txID=None, chanIndex=0):
        '''wrapper function for sending messages
        to a counterparty. Not all messages have an associated
        transactionid, so that is allowed to be null and is
        replaced by '0'. If recipientID is not set, it defaults
        to the active CNE. A signature of the value of the 
        single dict entry is appended to the value after the last ';'
        as identity authorization.
        '''
        if not txID:
            txID = '0'
        if recipientID in ['CNE', 'RE']:
            #TODO fix
            recipientID = recipientID + g("Escrow", "escrow_id")

        text, sig = multisig.signText(self.uniqID(),
                                      ':'.join(msg.split(':')[1:]))

        newMsg = {}
        newMsg[txID + '.' + self.uniqID()] = msg + ';' + sig
        Msg.sendMessages(newMsg, recipientID, chanIndex)
示例#9
0
def changeEscrow(specific=None):
    shared.debug(0,["Current escrow:",g("Escrow","escrow_id")])
    if specific:
        c = specific
    else:
        for i,e in enumerate(getEscrowList()):
            print "["+str(i+1)+"] "+e[0]    
        c = shared.get_validated_input("Choose an escrow",int)
        
    if c not in range(1,len(escrowList)+1):
        shared.debug(0,["Invalid choice from escrow list"])
    else:
        #rewrite the settings file and reset the escrow
        #TODO: persist changes to config file
        shared.config.set("Escrow","escrow_id",value=escrowList[c-1][0])
        shared.config.set("Escrow","escrow_pubkey",value=escrowList[c-1][2])
        shared.config.set("Escrow","escrow_host",value=escrowList[c-1][1])
        shared.debug(2,["Set the escrow to host:",g("Escrow","escrow_host"),"id:",g("Escrow","escrow_id"),"pubkey:",g("Escrow","escrow_pubkey")])
        
    Msg.closeConnection()
    time.sleep(1)
    Msg.instantiateConnection(un='client1',pw='client1',chanIndex=0)
示例#10
0
def sendAdjudicatorCollateralSigningRequest(myself, identityInfo,
                                            collateralAmount):

    msigaddr, mscript = myself.createCollateralMultisig()
    if not msigaddr or not mscript:
        shared.debug(
            0, ["Critical error: cannot create a multisignature address."])
        return False
    mypub, mypriv = multisig.getKeysFromUniqueID(myself.uniqID())

    shared.debug(0, ["You have created this multisig address:", msigaddr])
    shared.debug(0,
                 ["Please wait while your request is sent out to the pool."])
    #broadcast
    #TODO this is slow but ..?
    for i, e in enumerate(getEscrowList()):

        shared.config.set("Escrow", "escrow_id", value=e[0])
        shared.config.set("Escrow", "escrow_pubkey", value=e[2])
        shared.config.set("Escrow", "escrow_host", value=e[1])
        shared.debug(2, [
            "Set the escrow to host:",
            g("Escrow", "escrow_host"), "id:",
            g("Escrow", "escrow_id"), "pubkey:",
            g("Escrow", "escrow_pubkey")
        ])

        #Msg.closeConnection()
        time.sleep(1)

        Msg.instantiateConnection()

        myself.sendMessage('ADJUDICATOR_APPLICATION:' +
                           '|'.join([msigaddr, mypub, identityInfo]))
    shared.debug(0, [
        "Your application has been sent to all pool members. Please wait for their response."
    ])
    return True
示例#11
0
 def processInboundMessages(self,parentThread):
     '''messages coming from the "back end" (escrow MQ server) are picked up here.
     Message syntax will be the same for front end and back end communication, 
     improving intelligibility.
     Automatic responses to MQ instructions occurs here, 
     whereas anything that needs user input or is purely informational
     is blindly passed up to the front end.'''   
     
     #need a connection to an escrow to do anything
     Msg.instantiateConnection(chanIndex=1) 
     
     #infinite loop for getting messages
     while True:
         time.sleep(1)
            
         msg = self.getSingleMessage(chanIndex=1)
         
         if not msg:
             continue
         for k,m in msg.iteritems():
             
             if 'SELF_SHUTDOWN' in m:
                 break
                 
             if 'CNE_SIGNED_CONTRACT' in m:
                 response = self.receiveContractCNE(m)
                 #let the front end know we got it etc.
                 self.qFrontEnd.put('CONTRACT RECEIVED:'+response)
                 continue
                 
             elif 'CNE_CHAT' in m:
                 self.qFrontEnd.put('CHAT RECEIVED:'+k.split('.')[1]+\
                               ':'+':'.join(m.split(':')[1:]))
                 continue
             
             elif 'QUERY_STATUS:' in m:
                 #was it RE or CNE?
                 sender = k.split('.')[1]
                 recipientID = 'RE' if sender.startswith('RE') else 'CNE'
                 requester = m.split(':')[1]
                 self.sendMessage('QUERY_STATUS_RESPONSE:ONLINE,'+requester, recipientID='CNE', chanIndex=1)
                 
             elif 'CNE_CONTRACT_SUCCESS' in m:
                 escrowAddressConfirmation,contractJSON,escrowSig =\
                     ':'.join(m.split(':')[1:]).split('|')
                 
                 #validate escrow address
                 if not escrowAddressConfirmation == \
                    multisig.pubtoaddr(g("Escrow","escrow_pubkey")):
                     raise Exception("Panic! We are talking to the wrong escrow:"\
                                     +escrowAddressConfirmation)
                 
                 testingContract = Contract.Contract(json.loads(contractJSON))
                 
                 #validate escrow's signature and append to the contract
                 if not multisig.ecdsa_verify(testingContract.getContractTextOrdered(),\
                                              escrowSig,g("Escrow","escrow_pubkey")):
                     raise Exception("Panic! We received an invalid signature from the escrow.")
                 
                 #set this as the working contract in case it isn't
                 if self.workingContract != testingContract:
                     shared.debug(0,["Warning, switched back to the contract as informed by escrow"])
                     contractLock.acquire()
                     try:
                         self.workingContract = testingContract
                     finally:
                         contractLock.release()
                 
                 self.qFrontEnd.put(m)
                 continue
             
             elif 'RE_BANK_SESSION_START_REQUEST' in m:
                 t = self.getTxByID(k.split('.')[0])
                 if self.uniqID() != t.seller:
                     shared.debug(0,["Error, received bank session request but not seller"])
                     continue
                 else:
                     self.sendMessage('RE_BANK_SESSION_START_ACCEPTED:',recipientID='RE', txID=t.uniqID(),chanIndex=1)
                     self.startBankingSession(t)
                     continue
             
             elif 'RE_BANK_SESSION_START_ACCEPTED' in m or \
                  'RE_BANK_SESSION_START_REJECTED' in m:
                 shared.debug(0,["Received an acceptance or rejection, putting to queue",k,m])
                 self.qFrontEnd.put({k:m})
                 continue
             
             elif 'RE_TRANSACTION_SYNC_RESPONSE' in m or \
                  'RE_TRANSACTION_SYNC_COMPLETE' in m:
                 self.qFrontEnd.put({k:m})
                 continue
             
             elif 'RE_BANK_SESSION_ENDED' in m:
                 transaction = self.getTxByID(k.split('.')[0])
                 if not transaction.getRole(self.uniqID()) == 'seller':
                     shared.debug(0,["Error, bank session end message received but not the seller"])
                     continue
                 rspns = m.split(':')[1]
                 self.endBankingSession(transaction, rspns)
             
             elif 'RE_SSL_KEYS_REQUEST' in m:
                 transaction = self.getTxByID(k.split('.')[0])
               
             else:
                 #catch all for messages which just go to the front end
                 shared.debug(0,["Putting this to the q,",m])
                 self.qFrontEnd.put(m)
示例#12
0
if __name__ == "__main__":
    #first connect to CNE
    #code for reading order books and choosing escrow here?
    myBtcAddress=None
    myself = None
    receiverThread=None
    #Load all necessary configurations:
    helper_startup.loadconfig(sys.argv[1])    
    global txRE
    myEscrow = g("Escrow","escrow_id")
    d = os.path.join(g("Directories","agent_base_dir"),"multisig_store")
    p = g("Escrow","escrow_pubkey")
    #initialise multisig
    multisig.initialise(p,d)
    #need a connection to an escrow to do anything
    Msg.instantiateConnection(un='guest', pw='guest')
    
    
    #read in contract details (for early testing only)
    contractDetails = {}
    with open("AppLayer/boilerplate.txt") as fi:
        lines = fi.readlines()
        for line in lines:
            if line.startswith('***'):
                k,v = line[3:].strip().split(':: ')
                contractDetails[k]=v
    
    boilerplateContract = Contract.Contract(contractDetails)
    
    #flag to control which menu to use for contacting which type of escrow
    #TODO: actual connection switching; could still use EscrowAccessor concept?
示例#13
0
if __name__ == "__main__":
    #first connect to CNE
    #code for reading order books and choosing escrow here?
    myBtcAddress = None
    myself = None
    receiverThread = None
    #Load all necessary configurations:
    helper_startup.loadconfig(sys.argv[1])
    global txRE
    myEscrow = g("Escrow", "escrow_id")
    d = os.path.join(g("Directories", "agent_base_dir"), "multisig_store")
    p = g("Escrow", "escrow_pubkey")
    #initialise multisig
    multisig.initialise(p, d)
    #need a connection to an escrow to do anything
    Msg.instantiateConnection(un='guest', pw='guest')

    #read in contract details (for early testing only)
    contractDetails = {}
    with open("AppLayer/boilerplate.txt") as fi:
        lines = fi.readlines()
        for line in lines:
            if line.startswith('***'):
                k, v = line[3:].strip().split(':: ')
                contractDetails[k] = v

    boilerplateContract = Contract.Contract(contractDetails)

    #flag to control which menu to use for contacting which type of escrow
    #TODO: actual connection switching; could still use EscrowAccessor concept?
    RE = False
示例#14
0
 #first connect to CNE
 #code for reading order books and choosing escrow here?
 myBtcAddress=None
 myself = None
 receiverThread=None
 #Load all necessary configurations:
 helper_startup.loadconfig(sys.argv[1])    
 global txRE
 myEscrow = g("Escrow","escrow_id")
 d = os.path.join(g("Directories","escrow_base_dir"),"multisig_store")
 #p = g("Escrow","escrow_pubkey")
 #initialise multisig
 #multisig.initialise(p,d) #TODO remove this "initialize" thing
 multisig.msd=d
 #need a connection to an escrow to do anything
 Msg.instantiateConnection()
 adjudicator = AdjudicatorAgent(d,myEscrow,txStore=False)
 while True:
     print """Please choose an option:
     [1] Read message from queue
     [2] Choose transaction
     [3] Adjudicate transaction
     [4] Review adjudicator applications
     [5] Exit
     
     """
     choice = shared.get_validated_input("Enter an integer:",int)
     
     
     if choice==1:
         msg = adjudicator.getSingleMessage(prefix='ADJ')
示例#15
0
    def processInboundMessages(self, parentThread):
        '''messages coming from the "back end" (escrow MQ server) are picked up here.
        Message syntax will be the same for front end and back end communication, 
        improving intelligibility.
        Automatic responses to MQ instructions occurs here, 
        whereas anything that needs user input or is purely informational
        is blindly passed up to the front end.'''

        #need a connection to an escrow to do anything
        Msg.instantiateConnection(chanIndex=1)

        #infinite loop for getting messages
        while True:
            time.sleep(1)

            msg = self.getSingleMessage(chanIndex=1)

            if not msg:
                continue
            for k, m in msg.iteritems():

                if 'SELF_SHUTDOWN' in m:
                    break

                if 'CNE_SIGNED_CONTRACT' in m:
                    response = self.receiveContractCNE(m)
                    #let the front end know we got it etc.
                    self.qFrontEnd.put('CONTRACT RECEIVED:' + response)
                    continue

                elif 'CNE_CHAT' in m:
                    self.qFrontEnd.put('CHAT RECEIVED:'+k.split('.')[1]+\
                                  ':'+':'.join(m.split(':')[1:]))
                    continue

                elif 'QUERY_STATUS:' in m:
                    #was it RE or CNE?
                    sender = k.split('.')[1]
                    recipientID = 'RE' if sender.startswith('RE') else 'CNE'
                    requester = m.split(':')[1]
                    self.sendMessage('QUERY_STATUS_RESPONSE:ONLINE,' +
                                     requester,
                                     recipientID='CNE',
                                     chanIndex=1)

                elif 'CNE_CONTRACT_SUCCESS' in m:
                    escrowAddressConfirmation,contractJSON,escrowSig =\
                        ':'.join(m.split(':')[1:]).split('|')

                    #validate escrow address
                    if not escrowAddressConfirmation == \
                       multisig.pubtoaddr(g("Escrow","escrow_pubkey")):
                        raise Exception("Panic! We are talking to the wrong escrow:"\
                                        +escrowAddressConfirmation)

                    testingContract = Contract.Contract(
                        json.loads(contractJSON))

                    #validate escrow's signature and append to the contract
                    if not multisig.ecdsa_verify(testingContract.getContractTextOrdered(),\
                                                 escrowSig,g("Escrow","escrow_pubkey")):
                        raise Exception(
                            "Panic! We received an invalid signature from the escrow."
                        )

                    #set this as the working contract in case it isn't
                    if self.workingContract != testingContract:
                        shared.debug(0, [
                            "Warning, switched back to the contract as informed by escrow"
                        ])
                        contractLock.acquire()
                        try:
                            self.workingContract = testingContract
                        finally:
                            contractLock.release()

                    self.qFrontEnd.put(m)
                    continue

                elif 'RE_BANK_SESSION_START_REQUEST' in m:
                    t = self.getTxByID(k.split('.')[0])
                    if self.uniqID() != t.seller:
                        shared.debug(0, [
                            "Error, received bank session request but not seller"
                        ])
                        continue
                    else:
                        self.sendMessage('RE_BANK_SESSION_START_ACCEPTED:',
                                         recipientID='RE',
                                         txID=t.uniqID(),
                                         chanIndex=1)
                        self.startBankingSession(t)
                        continue

                elif 'RE_BANK_SESSION_START_ACCEPTED' in m or \
                     'RE_BANK_SESSION_START_REJECTED' in m:
                    shared.debug(0, [
                        "Received an acceptance or rejection, putting to queue",
                        k, m
                    ])
                    self.qFrontEnd.put({k: m})
                    continue

                elif 'RE_TRANSACTION_SYNC_RESPONSE' in m or \
                     'RE_TRANSACTION_SYNC_COMPLETE' in m:
                    self.qFrontEnd.put({k: m})
                    continue

                elif 'RE_BANK_SESSION_ENDED' in m:
                    transaction = self.getTxByID(k.split('.')[0])
                    if not transaction.getRole(self.uniqID()) == 'seller':
                        shared.debug(0, [
                            "Error, bank session end message received but not the seller"
                        ])
                        continue
                    rspns = m.split(':')[1]
                    self.endBankingSession(transaction, rspns)

                elif 'RE_SSL_KEYS_REQUEST' in m:
                    transaction = self.getTxByID(k.split('.')[0])

                else:
                    #catch all for messages which just go to the front end
                    shared.debug(0, ["Putting this to the q,", m])
                    self.qFrontEnd.put(m)
示例#16
0
    #first connect to CNE
    #code for reading order books and choosing escrow here?
    myBtcAddress = None
    myself = None
    receiverThread = None
    #Load all necessary configurations:
    helper_startup.loadconfig(sys.argv[1])
    global txRE
    myEscrow = g("Escrow", "escrow_id")
    d = os.path.join(g("Directories", "escrow_base_dir"), "multisig_store")
    #p = g("Escrow","escrow_pubkey")
    #initialise multisig
    #multisig.initialise(p,d) #TODO remove this "initialize" thing
    multisig.msd = d
    #need a connection to an escrow to do anything
    Msg.instantiateConnection()
    adjudicator = AdjudicatorAgent(d, myEscrow, txStore=False)
    while True:
        print """Please choose an option:
        [1] Read message from queue
        [2] Choose transaction
        [3] Adjudicate transaction
        [4] Review adjudicator applications
        [5] Exit
        
        """
        choice = shared.get_validated_input("Enter an integer:", int)

        if choice == 1:
            msg = adjudicator.getSingleMessage(prefix='ADJ')
            print msg