commit
e423343e9a
|
@ -29,6 +29,7 @@ from helper_sql import *
|
|||
from class_sqlThread import *
|
||||
from class_singleCleaner import *
|
||||
from class_singleWorker import *
|
||||
from class_objectProcessor import *
|
||||
from class_outgoingSynSender import *
|
||||
from class_singleListener import *
|
||||
from class_addressGenerator import *
|
||||
|
@ -47,6 +48,7 @@ if sys.platform == 'darwin':
|
|||
sys.exit(0)
|
||||
|
||||
def connectToStream(streamNumber):
|
||||
shared.streamsInWhichIAmParticipating[streamNumber] = 'no data'
|
||||
selfInitiatedConnections[streamNumber] = {}
|
||||
shared.inventorySets[streamNumber] = set()
|
||||
queryData = sqlQuery('''SELECT hash FROM inventory WHERE streamnumber=?''', streamNumber)
|
||||
|
@ -985,6 +987,11 @@ class Main:
|
|||
sqlLookup.daemon = False # DON'T close the main program even if there are threads left. The closeEvent should command this thread to exit gracefully.
|
||||
sqlLookup.start()
|
||||
|
||||
# Start the thread that calculates POWs
|
||||
objectProcessorThread = objectProcessor()
|
||||
objectProcessorThread.daemon = False # DON'T close the main program even the thread remains. This thread checks the shutdown variable after processing each object.
|
||||
objectProcessorThread.start()
|
||||
|
||||
# Start the cleanerThread
|
||||
singleCleanerThread = singleCleaner()
|
||||
singleCleanerThread.daemon = True # close the main program even if there are threads left
|
||||
|
|
|
@ -16,6 +16,7 @@ import shared
|
|||
from bitmessageui import *
|
||||
from namecoin import namecoinConnection, ensureNamecoinOptions
|
||||
from newaddressdialog import *
|
||||
from addaddressdialog import *
|
||||
from newsubscriptiondialog import *
|
||||
from regenerateaddresses import *
|
||||
from newchandialog import *
|
||||
|
@ -2063,15 +2064,15 @@ class MyForm(QtGui.QMainWindow):
|
|||
self.ubuntuMessagingMenuUpdate(True, newItem, toLabel)
|
||||
|
||||
def click_pushButtonAddAddressBook(self):
|
||||
self.NewSubscriptionDialogInstance = NewSubscriptionDialog(self)
|
||||
if self.NewSubscriptionDialogInstance.exec_():
|
||||
if self.NewSubscriptionDialogInstance.ui.labelSubscriptionAddressCheck.text() == _translate("MainWindow", "Address is valid."):
|
||||
self.AddAddressDialogInstance = AddAddressDialog(self)
|
||||
if self.AddAddressDialogInstance.exec_():
|
||||
if self.AddAddressDialogInstance.ui.labelAddressCheck.text() == _translate("MainWindow", "Address is valid."):
|
||||
# First we must check to see if the address is already in the
|
||||
# address book. The user cannot add it again or else it will
|
||||
# cause problems when updating and deleting the entry.
|
||||
address = addBMIfNotPresent(str(
|
||||
self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))
|
||||
label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()
|
||||
self.AddAddressDialogInstance.ui.lineEditAddress.text()))
|
||||
label = self.AddAddressDialogInstance.ui.newAddressLabel.text().toUtf8()
|
||||
self.addEntryToAddressBook(address,label)
|
||||
else:
|
||||
self.statusBar().showMessage(_translate(
|
||||
|
@ -2120,7 +2121,7 @@ class MyForm(QtGui.QMainWindow):
|
|||
def click_pushButtonAddSubscription(self):
|
||||
self.NewSubscriptionDialogInstance = NewSubscriptionDialog(self)
|
||||
if self.NewSubscriptionDialogInstance.exec_():
|
||||
if self.NewSubscriptionDialogInstance.ui.labelSubscriptionAddressCheck.text() != _translate("MainWindow", "Address is valid."):
|
||||
if self.NewSubscriptionDialogInstance.ui.labelAddressCheck.text() != _translate("MainWindow", "Address is valid."):
|
||||
self.statusBar().showMessage(_translate("MainWindow", "The address you entered was invalid. Ignoring it."))
|
||||
return
|
||||
address = addBMIfNotPresent(str(self.NewSubscriptionDialogInstance.ui.lineEditSubscriptionAddress.text()))
|
||||
|
@ -2130,6 +2131,22 @@ class MyForm(QtGui.QMainWindow):
|
|||
return
|
||||
label = self.NewSubscriptionDialogInstance.ui.newsubscriptionlabel.text().toUtf8()
|
||||
self.addSubscription(address, label)
|
||||
# Now, if the user wants to display old broadcasts, let's get them out of the inventory and put them
|
||||
# in the objectProcessorQueue to be processed
|
||||
if self.NewSubscriptionDialogInstance.ui.checkBoxDisplayMessagesAlreadyInInventory.isChecked():
|
||||
status, addressVersion, streamNumber, ripe = decodeAddress(address)
|
||||
shared.flushInventory()
|
||||
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint(
|
||||
addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest()
|
||||
tag = doubleHashOfAddressData[32:]
|
||||
queryreturn = sqlQuery(
|
||||
'''select payload from inventory where objecttype='broadcast' and tag=?''', tag)
|
||||
for row in queryreturn:
|
||||
payload, = row
|
||||
objectType = 'broadcast'
|
||||
with shared.objectProcessorQueueSizeLock:
|
||||
shared.objectProcessorQueueSize += len(payload)
|
||||
shared.objectProcessorQueue.put((objectType,payload))
|
||||
|
||||
def loadBlackWhiteList(self):
|
||||
# Initialize the Blacklist or Whitelist table
|
||||
|
@ -2368,11 +2385,11 @@ class MyForm(QtGui.QMainWindow):
|
|||
self.ui.tabWidget.setTabText(6, 'Whitelist')
|
||||
|
||||
def click_pushButtonAddBlacklist(self):
|
||||
self.NewBlacklistDialogInstance = NewSubscriptionDialog(self)
|
||||
self.NewBlacklistDialogInstance = AddAddressDialog(self)
|
||||
if self.NewBlacklistDialogInstance.exec_():
|
||||
if self.NewBlacklistDialogInstance.ui.labelSubscriptionAddressCheck.text() == _translate("MainWindow", "Address is valid."):
|
||||
if self.NewBlacklistDialogInstance.ui.labelAddressCheck.text() == _translate("MainWindow", "Address is valid."):
|
||||
address = addBMIfNotPresent(str(
|
||||
self.NewBlacklistDialogInstance.ui.lineEditSubscriptionAddress.text()))
|
||||
self.NewBlacklistDialogInstance.ui.lineEditAddress.text()))
|
||||
# First we must check to see if the address is already in the
|
||||
# address book. The user cannot add it again or else it will
|
||||
# cause problems when updating and deleting the entry.
|
||||
|
@ -2386,7 +2403,7 @@ class MyForm(QtGui.QMainWindow):
|
|||
self.ui.tableWidgetBlacklist.setSortingEnabled(False)
|
||||
self.ui.tableWidgetBlacklist.insertRow(0)
|
||||
newItem = QtGui.QTableWidgetItem(unicode(
|
||||
self.NewBlacklistDialogInstance.ui.newsubscriptionlabel.text().toUtf8(), 'utf-8'))
|
||||
self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8(), 'utf-8'))
|
||||
newItem.setIcon(avatarize(address))
|
||||
self.ui.tableWidgetBlacklist.setItem(0, 0, newItem)
|
||||
newItem = QtGui.QTableWidgetItem(address)
|
||||
|
@ -2394,7 +2411,7 @@ class MyForm(QtGui.QMainWindow):
|
|||
QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
||||
self.ui.tableWidgetBlacklist.setItem(0, 1, newItem)
|
||||
self.ui.tableWidgetBlacklist.setSortingEnabled(True)
|
||||
t = (str(self.NewBlacklistDialogInstance.ui.newsubscriptionlabel.text().toUtf8()), address, True)
|
||||
t = (str(self.NewBlacklistDialogInstance.ui.newAddressLabel.text().toUtf8()), address, True)
|
||||
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black':
|
||||
sql = '''INSERT INTO blacklist VALUES (?,?,?)'''
|
||||
else:
|
||||
|
@ -3465,6 +3482,40 @@ class SpecialAddressBehaviorDialog(QtGui.QDialog):
|
|||
QtGui.QWidget.resize(self, QtGui.QWidget.sizeHint(self))
|
||||
|
||||
|
||||
class AddAddressDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
self.ui = Ui_AddAddressDialog()
|
||||
self.ui.setupUi(self)
|
||||
self.parent = parent
|
||||
QtCore.QObject.connect(self.ui.lineEditAddress, QtCore.SIGNAL(
|
||||
"textChanged(QString)"), self.addressChanged)
|
||||
|
||||
def addressChanged(self, QString):
|
||||
status, a, b, c = decodeAddress(str(QString))
|
||||
if status == 'missingbm':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address should start with ''BM-''"))
|
||||
elif status == 'checksumfailed':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address is not typed or copied correctly (the checksum failed)."))
|
||||
elif status == 'versiontoohigh':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The version number of this address is higher than this software can support. Please upgrade Bitmessage."))
|
||||
elif status == 'invalidcharacters':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address contains invalid characters."))
|
||||
elif status == 'ripetooshort':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "Some data encoded in the address is too short."))
|
||||
elif status == 'ripetoolong':
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "Some data encoded in the address is too long."))
|
||||
elif status == 'success':
|
||||
self.ui.labelAddressCheck.setText(
|
||||
_translate("MainWindow", "Address is valid."))
|
||||
|
||||
class NewSubscriptionDialog(QtGui.QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
@ -3473,31 +3524,56 @@ class NewSubscriptionDialog(QtGui.QDialog):
|
|||
self.ui.setupUi(self)
|
||||
self.parent = parent
|
||||
QtCore.QObject.connect(self.ui.lineEditSubscriptionAddress, QtCore.SIGNAL(
|
||||
"textChanged(QString)"), self.subscriptionAddressChanged)
|
||||
"textChanged(QString)"), self.addressChanged)
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText(
|
||||
_translate("MainWindow", "Enter an address above."))
|
||||
|
||||
def subscriptionAddressChanged(self, QString):
|
||||
status, a, b, c = decodeAddress(str(QString))
|
||||
def addressChanged(self, QString):
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(False)
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setChecked(False)
|
||||
status, addressVersion, streamNumber, ripe = decodeAddress(str(QString))
|
||||
if status == 'missingbm':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address should start with ''BM-''"))
|
||||
elif status == 'checksumfailed':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address is not typed or copied correctly (the checksum failed)."))
|
||||
elif status == 'versiontoohigh':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The version number of this address is higher than this software can support. Please upgrade Bitmessage."))
|
||||
elif status == 'invalidcharacters':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "The address contains invalid characters."))
|
||||
elif status == 'ripetooshort':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "Some data encoded in the address is too short."))
|
||||
elif status == 'ripetoolong':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(_translate(
|
||||
self.ui.labelAddressCheck.setText(_translate(
|
||||
"MainWindow", "Some data encoded in the address is too long."))
|
||||
elif status == 'success':
|
||||
self.ui.labelSubscriptionAddressCheck.setText(
|
||||
self.ui.labelAddressCheck.setText(
|
||||
_translate("MainWindow", "Address is valid."))
|
||||
if addressVersion <= 3:
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText(
|
||||
_translate("MainWindow", "Address is an old type. We cannot display its past broadcasts."))
|
||||
else:
|
||||
shared.flushInventory()
|
||||
doubleHashOfAddressData = hashlib.sha512(hashlib.sha512(encodeVarint(
|
||||
addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest()
|
||||
tag = doubleHashOfAddressData[32:]
|
||||
queryreturn = sqlQuery(
|
||||
'''select hash from inventory where objecttype='broadcast' and tag=?''', tag)
|
||||
if len(queryreturn) == 0:
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText(
|
||||
_translate("MainWindow", "There are no recent broadcasts from this address to display."))
|
||||
elif len(queryreturn) == 1:
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(True)
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText(
|
||||
_translate("MainWindow", "Display the %1 recent broadcast from this address.").arg(str(len(queryreturn))))
|
||||
else:
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(True)
|
||||
self.ui.checkBoxDisplayMessagesAlreadyInInventory.setText(
|
||||
_translate("MainWindow", "Display the %1 recent broadcasts from this address.").arg(str(len(queryreturn))))
|
||||
|
||||
|
||||
class NewAddressDialog(QtGui.QDialog):
|
||||
|
|
65
src/bitmessageqt/addaddressdialog.py
Normal file
65
src/bitmessageqt/addaddressdialog.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'addaddressdialog.ui'
|
||||
#
|
||||
# Created: Sat Nov 30 20:35:38 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_AddAddressDialog(object):
|
||||
def setupUi(self, AddAddressDialog):
|
||||
AddAddressDialog.setObjectName(_fromUtf8("AddAddressDialog"))
|
||||
AddAddressDialog.resize(368, 162)
|
||||
self.formLayout = QtGui.QFormLayout(AddAddressDialog)
|
||||
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_2 = QtGui.QLabel(AddAddressDialog)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.SpanningRole, self.label_2)
|
||||
self.newAddressLabel = QtGui.QLineEdit(AddAddressDialog)
|
||||
self.newAddressLabel.setObjectName(_fromUtf8("newAddressLabel"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.SpanningRole, self.newAddressLabel)
|
||||
self.label = QtGui.QLabel(AddAddressDialog)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.lineEditAddress = QtGui.QLineEdit(AddAddressDialog)
|
||||
self.lineEditAddress.setObjectName(_fromUtf8("lineEditAddress"))
|
||||
self.formLayout.setWidget(5, QtGui.QFormLayout.SpanningRole, self.lineEditAddress)
|
||||
self.labelAddressCheck = QtGui.QLabel(AddAddressDialog)
|
||||
self.labelAddressCheck.setText(_fromUtf8(""))
|
||||
self.labelAddressCheck.setWordWrap(True)
|
||||
self.labelAddressCheck.setObjectName(_fromUtf8("labelAddressCheck"))
|
||||
self.formLayout.setWidget(6, QtGui.QFormLayout.SpanningRole, self.labelAddressCheck)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(AddAddressDialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.formLayout.setWidget(7, QtGui.QFormLayout.FieldRole, self.buttonBox)
|
||||
|
||||
self.retranslateUi(AddAddressDialog)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), AddAddressDialog.accept)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), AddAddressDialog.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(AddAddressDialog)
|
||||
|
||||
def retranslateUi(self, AddAddressDialog):
|
||||
AddAddressDialog.setWindowTitle(_translate("AddAddressDialog", "Add new entry", None))
|
||||
self.label_2.setText(_translate("AddAddressDialog", "Label", None))
|
||||
self.label.setText(_translate("AddAddressDialog", "Address", None))
|
||||
|
97
src/bitmessageqt/addaddressdialog.ui
Normal file
97
src/bitmessageqt/addaddressdialog.ui
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AddAddressDialog</class>
|
||||
<widget class="QDialog" name="AddAddressDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>368</width>
|
||||
<height>162</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add new entry</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Label</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="newAddressLabel"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEditAddress"/>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelAddressCheck">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AddAddressDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>360</x>
|
||||
<y>234</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>256</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AddAddressDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>360</x>
|
||||
<y>240</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>256</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
# Form implementation generated from reading ui file 'newsubscriptiondialog.ui'
|
||||
#
|
||||
# Created: Fri Oct 19 15:30:41 2012
|
||||
# by: PyQt4 UI code generator 4.9.4
|
||||
# Created: Sat Nov 30 21:53:38 2013
|
||||
# by: PyQt4 UI code generator 4.10.3
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
|
@ -12,41 +12,49 @@ from PyQt4 import QtCore, QtGui
|
|||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
_fromUtf8 = lambda s: s
|
||||
def _fromUtf8(s):
|
||||
return s
|
||||
|
||||
try:
|
||||
_encoding = QtGui.QApplication.UnicodeUTF8
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig, _encoding)
|
||||
except AttributeError:
|
||||
def _translate(context, text, disambig):
|
||||
return QtGui.QApplication.translate(context, text, disambig)
|
||||
|
||||
class Ui_NewSubscriptionDialog(object):
|
||||
def setupUi(self, NewSubscriptionDialog):
|
||||
NewSubscriptionDialog.setObjectName(_fromUtf8("NewSubscriptionDialog"))
|
||||
NewSubscriptionDialog.resize(368, 192)
|
||||
NewSubscriptionDialog.resize(368, 173)
|
||||
self.formLayout = QtGui.QFormLayout(NewSubscriptionDialog)
|
||||
self.formLayout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
|
||||
self.formLayout.setObjectName(_fromUtf8("formLayout"))
|
||||
self.label_2 = QtGui.QLabel(NewSubscriptionDialog)
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.SpanningRole, self.label_2)
|
||||
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_2)
|
||||
self.newsubscriptionlabel = QtGui.QLineEdit(NewSubscriptionDialog)
|
||||
self.newsubscriptionlabel.setObjectName(_fromUtf8("newsubscriptionlabel"))
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.SpanningRole, self.newsubscriptionlabel)
|
||||
self.formLayout.setWidget(1, QtGui.QFormLayout.SpanningRole, self.newsubscriptionlabel)
|
||||
self.label = QtGui.QLabel(NewSubscriptionDialog)
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.LabelRole, self.label)
|
||||
spacerItem = QtGui.QSpacerItem(302, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(4, QtGui.QFormLayout.FieldRole, spacerItem)
|
||||
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label)
|
||||
self.lineEditSubscriptionAddress = QtGui.QLineEdit(NewSubscriptionDialog)
|
||||
self.lineEditSubscriptionAddress.setObjectName(_fromUtf8("lineEditSubscriptionAddress"))
|
||||
self.formLayout.setWidget(5, QtGui.QFormLayout.SpanningRole, self.lineEditSubscriptionAddress)
|
||||
self.formLayout.setWidget(3, QtGui.QFormLayout.SpanningRole, self.lineEditSubscriptionAddress)
|
||||
self.labelAddressCheck = QtGui.QLabel(NewSubscriptionDialog)
|
||||
self.labelAddressCheck.setText(_fromUtf8(""))
|
||||
self.labelAddressCheck.setWordWrap(True)
|
||||
self.labelAddressCheck.setObjectName(_fromUtf8("labelAddressCheck"))
|
||||
self.formLayout.setWidget(4, QtGui.QFormLayout.SpanningRole, self.labelAddressCheck)
|
||||
self.checkBoxDisplayMessagesAlreadyInInventory = QtGui.QCheckBox(NewSubscriptionDialog)
|
||||
self.checkBoxDisplayMessagesAlreadyInInventory.setEnabled(False)
|
||||
self.checkBoxDisplayMessagesAlreadyInInventory.setObjectName(_fromUtf8("checkBoxDisplayMessagesAlreadyInInventory"))
|
||||
self.formLayout.setWidget(5, QtGui.QFormLayout.SpanningRole, self.checkBoxDisplayMessagesAlreadyInInventory)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(NewSubscriptionDialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
|
||||
self.formLayout.setWidget(8, QtGui.QFormLayout.FieldRole, self.buttonBox)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(7, QtGui.QFormLayout.FieldRole, spacerItem1)
|
||||
self.labelSubscriptionAddressCheck = QtGui.QLabel(NewSubscriptionDialog)
|
||||
self.labelSubscriptionAddressCheck.setText(_fromUtf8(""))
|
||||
self.labelSubscriptionAddressCheck.setWordWrap(True)
|
||||
self.labelSubscriptionAddressCheck.setObjectName(_fromUtf8("labelSubscriptionAddressCheck"))
|
||||
self.formLayout.setWidget(6, QtGui.QFormLayout.SpanningRole, self.labelSubscriptionAddressCheck)
|
||||
self.formLayout.setWidget(6, QtGui.QFormLayout.FieldRole, self.buttonBox)
|
||||
|
||||
self.retranslateUi(NewSubscriptionDialog)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewSubscriptionDialog.accept)
|
||||
|
@ -54,7 +62,8 @@ class Ui_NewSubscriptionDialog(object):
|
|||
QtCore.QMetaObject.connectSlotsByName(NewSubscriptionDialog)
|
||||
|
||||
def retranslateUi(self, NewSubscriptionDialog):
|
||||
NewSubscriptionDialog.setWindowTitle(QtGui.QApplication.translate("NewSubscriptionDialog", "Add new entry", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label_2.setText(QtGui.QApplication.translate("NewSubscriptionDialog", "Label", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setText(QtGui.QApplication.translate("NewSubscriptionDialog", "Address", None, QtGui.QApplication.UnicodeUTF8))
|
||||
NewSubscriptionDialog.setWindowTitle(_translate("NewSubscriptionDialog", "Add new entry", None))
|
||||
self.label_2.setText(_translate("NewSubscriptionDialog", "Label", None))
|
||||
self.label.setText(_translate("NewSubscriptionDialog", "Address", None))
|
||||
self.checkBoxDisplayMessagesAlreadyInInventory.setText(_translate("NewSubscriptionDialog", "CheckBox", None))
|
||||
|
||||
|
|
|
@ -7,50 +7,54 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>368</width>
|
||||
<height>192</height>
|
||||
<height>173</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add new entry</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Label</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="newsubscriptionlabel"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>302</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLineEdit" name="lineEditSubscriptionAddress"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelAddressCheck">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxDisplayMessagesAlreadyInInventory">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CheckBox</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -60,29 +64,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QLabel" name="labelSubscriptionAddressCheck">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
|
1228
src/class_objectProcessor.py
Normal file
1228
src/class_objectProcessor.py
Normal file
|
@ -0,0 +1,1228 @@
|
|||
import time
|
||||
import threading
|
||||
import shared
|
||||
import hashlib
|
||||
import random
|
||||
from struct import unpack, pack
|
||||
import sys
|
||||
import string
|
||||
from subprocess import call # used when the API must execute an outside program
|
||||
from pyelliptic.openssl import OpenSSL
|
||||
|
||||
import highlevelcrypto
|
||||
from addresses import *
|
||||
import helper_generic
|
||||
import helper_bitcoin
|
||||
import helper_inbox
|
||||
import helper_sent
|
||||
from helper_sql import *
|
||||
import tr
|
||||
from debug import logger
|
||||
|
||||
|
||||
class objectProcessor(threading.Thread):
|
||||
"""
|
||||
The objectProcessor thread, of which there is only one, receives network
|
||||
objecs (msg, broadcast, pubkey, getpubkey) from the receiveDataThreads.
|
||||
"""
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
"""
|
||||
It may be the case that the last time Bitmessage was running, the user
|
||||
closed it before it finished processing everything in the
|
||||
objectProcessorQueue. Assuming that Bitmessage wasn't closed forcefully,
|
||||
it should have saved the data in the queue into the objectprocessorqueue
|
||||
table. Let's pull it out.
|
||||
"""
|
||||
queryreturn = sqlQuery(
|
||||
'''SELECT objecttype, data FROM objectprocessorqueue''')
|
||||
with shared.objectProcessorQueueSizeLock:
|
||||
for row in queryreturn:
|
||||
objectType, data = row
|
||||
shared.objectProcessorQueueSize += len(data)
|
||||
shared.objectProcessorQueue.put((objectType,data))
|
||||
sqlExecute('''DELETE FROM objectprocessorqueue''')
|
||||
logger.debug('Loaded %s objects from disk into the objectProcessorQueue.' % str(len(queryreturn)))
|
||||
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
objectType, data = shared.objectProcessorQueue.get()
|
||||
|
||||
if objectType == 'getpubkey':
|
||||
self.processgetpubkey(data)
|
||||
elif objectType == 'pubkey':
|
||||
self.processpubkey(data)
|
||||
elif objectType == 'msg':
|
||||
self.processmsg(data)
|
||||
elif objectType == 'broadcast':
|
||||
self.processbroadcast(data)
|
||||
elif objectType == 'checkShutdownVariable': # is more of a command, not an object type. Is used to get this thread past the queue.get() so that it will check the shutdown variable.
|
||||
pass
|
||||
else:
|
||||
logger.critical('Error! Bug! The class_objectProcessor was passed an object type it doesn\'t recognize: %s' % str(objectType))
|
||||
|
||||
with shared.objectProcessorQueueSizeLock:
|
||||
shared.objectProcessorQueueSize -= len(data) # We maintain objectProcessorQueueSize so that we will slow down requesting objects if too much data accumulates in the queue.
|
||||
|
||||
if shared.shutdown:
|
||||
time.sleep(.5) # Wait just a moment for most of the connections to close
|
||||
numberOfObjectsThatWereInTheObjectProcessorQueue = 0
|
||||
with SqlBulkExecute() as sql:
|
||||
while shared.objectProcessorQueueSize > 1:
|
||||
objectType, data = shared.objectProcessorQueue.get()
|
||||
sql.execute('''INSERT INTO objectprocessorqueue VALUES (?,?)''',
|
||||
objectType,data)
|
||||
with shared.objectProcessorQueueSizeLock:
|
||||
shared.objectProcessorQueueSize -= len(data) # We maintain objectProcessorQueueSize so that we will slow down requesting objects if too much data accumulates in the queue.
|
||||
numberOfObjectsThatWereInTheObjectProcessorQueue += 1
|
||||
logger.debug('Saved %s objects from the objectProcessorQueue to disk. objectProcessorThread exiting.' % str(numberOfObjectsThatWereInTheObjectProcessorQueue))
|
||||
shared.shutdown = 2
|
||||
break
|
||||
|
||||
def processgetpubkey(self, data):
|
||||
readPosition = 8 # bypass the nonce
|
||||
embeddedTime, = unpack('>I', data[readPosition:readPosition + 4])
|
||||
|
||||
# This section is used for the transition from 32 bit time to 64 bit
|
||||
# time in the protocol.
|
||||
if embeddedTime == 0:
|
||||
embeddedTime, = unpack('>Q', data[readPosition:readPosition + 8])
|
||||
readPosition += 8
|
||||
else:
|
||||
readPosition += 4
|
||||
|
||||
requestedAddressVersionNumber, addressVersionLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += addressVersionLength
|
||||
streamNumber, streamNumberLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += streamNumberLength
|
||||
|
||||
if requestedAddressVersionNumber == 0:
|
||||
print 'The requestedAddressVersionNumber of the pubkey request is zero. That doesn\'t make any sense. Ignoring it.'
|
||||
return
|
||||
elif requestedAddressVersionNumber == 1:
|
||||
print 'The requestedAddressVersionNumber of the pubkey request is 1 which isn\'t supported anymore. Ignoring it.'
|
||||
return
|
||||
elif requestedAddressVersionNumber > 4:
|
||||
print 'The requestedAddressVersionNumber of the pubkey request is too high. Can\'t understand. Ignoring it.'
|
||||
return
|
||||
|
||||
myAddress = ''
|
||||
if requestedAddressVersionNumber <= 3 :
|
||||
requestedHash = data[readPosition:readPosition + 20]
|
||||
if len(requestedHash) != 20:
|
||||
print 'The length of the requested hash is not 20 bytes. Something is wrong. Ignoring.'
|
||||
return
|
||||
with shared.printLock:
|
||||
print 'the hash requested in this getpubkey request is:', requestedHash.encode('hex')
|
||||
if requestedHash in shared.myAddressesByHash: # if this address hash is one of mine
|
||||
myAddress = shared.myAddressesByHash[requestedHash]
|
||||
elif requestedAddressVersionNumber >= 4:
|
||||
requestedTag = data[readPosition:readPosition + 32]
|
||||
if len(requestedTag) != 32:
|
||||
print 'The length of the requested tag is not 32 bytes. Something is wrong. Ignoring.'
|
||||
return
|
||||
with shared.printLock:
|
||||
print 'the tag requested in this getpubkey request is:', requestedTag.encode('hex')
|
||||
if requestedTag in shared.myAddressesByTag:
|
||||
myAddress = shared.myAddressesByTag[requestedTag]
|
||||
|
||||
if myAddress == '':
|
||||
with shared.printLock:
|
||||
print 'This getpubkey request is not for any of my keys.'
|
||||
return
|
||||
|
||||
if decodeAddress(myAddress)[1] != requestedAddressVersionNumber:
|
||||
with shared.printLock:
|
||||
sys.stderr.write(
|
||||
'(Within the recgetpubkey function) Someone requested one of my pubkeys but the requestedAddressVersionNumber doesn\'t match my actual address version number. Ignoring.\n')
|
||||
return
|
||||
if decodeAddress(myAddress)[2] != streamNumber:
|
||||
with shared.printLock:
|
||||
sys.stderr.write(
|
||||
'(Within the recgetpubkey function) Someone requested one of my pubkeys but the stream number on which we heard this getpubkey object doesn\'t match this address\' stream number. Ignoring.\n')
|
||||
return
|
||||
if shared.safeConfigGetBoolean(myAddress, 'chan'):
|
||||
with shared.printLock:
|
||||
print 'Ignoring getpubkey request because it is for one of my chan addresses. The other party should already have the pubkey.'
|
||||
return
|
||||
try:
|
||||
lastPubkeySendTime = int(shared.config.get(
|
||||
myAddress, 'lastpubkeysendtime'))
|
||||
except:
|
||||
lastPubkeySendTime = 0
|
||||
if lastPubkeySendTime > time.time() - shared.lengthOfTimeToHoldOnToAllPubkeys: # If the last time we sent our pubkey was more recent than 28 days ago...
|
||||
with shared.printLock:
|
||||
print 'Found getpubkey-requested-item in my list of EC hashes BUT we already sent it recently. Ignoring request. The lastPubkeySendTime is:', lastPubkeySendTime
|
||||
return
|
||||
|
||||
with shared.printLock:
|
||||
print 'Found getpubkey-requested-hash in my list of EC hashes. Telling Worker thread to do the POW for a pubkey message and send it out.'
|
||||
if requestedAddressVersionNumber == 2:
|
||||
shared.workerQueue.put((
|
||||
'doPOWForMyV2Pubkey', requestedHash))
|
||||
elif requestedAddressVersionNumber == 3:
|
||||
shared.workerQueue.put((
|
||||
'sendOutOrStoreMyV3Pubkey', requestedHash))
|
||||
elif requestedAddressVersionNumber == 4:
|
||||
shared.workerQueue.put((
|
||||
'sendOutOrStoreMyV4Pubkey', myAddress))
|
||||
|
||||
def processpubkey(self, data):
|
||||
pubkeyProcessingStartTime = time.time()
|
||||
shared.numberOfPubkeysProcessed += 1
|
||||
shared.UISignalQueue.put((
|
||||
'updateNumberOfPubkeysProcessed', 'no data'))
|
||||
readPosition = 8 # bypass the nonce
|
||||
embeddedTime, = unpack('>I', data[readPosition:readPosition + 4])
|
||||
|
||||
# This section is used for the transition from 32 bit time to 64 bit
|
||||
# time in the protocol.
|
||||
if embeddedTime == 0:
|
||||
embeddedTime, = unpack('>Q', data[readPosition:readPosition + 8])
|
||||
readPosition += 8
|
||||
else:
|
||||
readPosition += 4
|
||||
|
||||
addressVersion, varintLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += varintLength
|
||||
streamNumber, varintLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += varintLength
|
||||
if addressVersion == 0:
|
||||
print '(Within processpubkey) addressVersion of 0 doesn\'t make sense.'
|
||||
return
|
||||
if addressVersion > 4 or addressVersion == 1:
|
||||
with shared.printLock:
|
||||
print 'This version of Bitmessage cannot handle version', addressVersion, 'addresses.'
|
||||
return
|
||||
if addressVersion == 2:
|
||||
if len(data) < 146: # sanity check. This is the minimum possible length.
|
||||
print '(within processpubkey) payloadLength less than 146. Sanity check failed.'
|
||||
return
|
||||
bitfieldBehaviors = data[readPosition:readPosition + 4]
|
||||
readPosition += 4
|
||||
publicSigningKey = data[readPosition:readPosition + 64]
|
||||
# Is it possible for a public key to be invalid such that trying to
|
||||
# encrypt or sign with it will cause an error? If it is, we should
|
||||
# probably test these keys here.
|
||||
readPosition += 64
|
||||
publicEncryptionKey = data[readPosition:readPosition + 64]
|
||||
if len(publicEncryptionKey) < 64:
|
||||
print 'publicEncryptionKey length less than 64. Sanity check failed.'
|
||||
return
|
||||
sha = hashlib.new('sha512')
|
||||
sha.update(
|
||||
'\x04' + publicSigningKey + '\x04' + publicEncryptionKey)
|
||||
ripeHasher = hashlib.new('ripemd160')
|
||||
ripeHasher.update(sha.digest())
|
||||
ripe = ripeHasher.digest()
|
||||
|
||||
with shared.printLock:
|
||||
print 'within recpubkey, addressVersion:', addressVersion, ', streamNumber:', streamNumber
|
||||
print 'ripe', ripe.encode('hex')
|
||||
print 'publicSigningKey in hex:', publicSigningKey.encode('hex')
|
||||
print 'publicEncryptionKey in hex:', publicEncryptionKey.encode('hex')
|
||||
|
||||
|
||||
queryreturn = sqlQuery(
|
||||
'''SELECT usedpersonally FROM pubkeys WHERE hash=? AND addressversion=? AND usedpersonally='yes' ''', ripe, addressVersion)
|
||||
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
||||
print 'We HAVE used this pubkey personally. Updating time.'
|
||||
t = (ripe, addressVersion, data, embeddedTime, 'yes')
|
||||
else:
|
||||
print 'We have NOT used this pubkey personally. Inserting in database.'
|
||||
t = (ripe, addressVersion, data, embeddedTime, 'no')
|
||||
# This will also update the embeddedTime.
|
||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||
# shared.workerQueue.put(('newpubkey',(addressVersion,streamNumber,ripe)))
|
||||
self.possibleNewPubkey(ripe = ripe)
|
||||
if addressVersion == 3:
|
||||
if len(data) < 170: # sanity check.
|
||||
print '(within processpubkey) payloadLength less than 170. Sanity check failed.'
|
||||
return
|
||||
bitfieldBehaviors = data[readPosition:readPosition + 4]
|
||||
readPosition += 4
|
||||
publicSigningKey = '\x04' + data[readPosition:readPosition + 64]
|
||||
# Is it possible for a public key to be invalid such that trying to
|
||||
# encrypt or sign with it will cause an error? If it is, we should
|
||||
# probably test these keys here.
|
||||
readPosition += 64
|
||||
publicEncryptionKey = '\x04' + data[readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
specifiedNonceTrialsPerByte, specifiedNonceTrialsPerByteLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += specifiedNonceTrialsPerByteLength
|
||||
specifiedPayloadLengthExtraBytes, specifiedPayloadLengthExtraBytesLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += specifiedPayloadLengthExtraBytesLength
|
||||
endOfSignedDataPosition = readPosition
|
||||
signatureLength, signatureLengthLength = decodeVarint(
|
||||
data[readPosition:readPosition + 10])
|
||||
readPosition += signatureLengthLength
|
||||
signature = data[readPosition:readPosition + signatureLength]
|
||||
try:
|
||||
if not highlevelcrypto.verify(data[8:endOfSignedDataPosition], signature, publicSigningKey.encode('hex')):
|
||||
print 'ECDSA verify failed (within processpubkey)'
|
||||
return
|
||||
print 'ECDSA verify passed (within processpubkey)'
|
||||
except Exception as err:
|
||||
print 'ECDSA verify failed (within processpubkey)', err
|
||||
return
|
||||
|
||||
sha = hashlib.new('sha512')
|
||||
sha.update(publicSigningKey + publicEncryptionKey)
|
||||
ripeHasher = hashlib.new('ripemd160')
|
||||
ripeHasher.update(sha.digest())
|
||||
ripe = ripeHasher.digest()
|
||||
|
||||
with shared.printLock:
|
||||
print 'within recpubkey, addressVersion:', addressVersion, ', streamNumber:', streamNumber
|
||||
print 'ripe', ripe.encode('hex')
|
||||
print 'publicSigningKey in hex:', publicSigningKey.encode('hex')
|
||||
print 'publicEncryptionKey in hex:', publicEncryptionKey.encode('hex')
|
||||
|
||||
|
||||
queryreturn = sqlQuery('''SELECT usedpersonally FROM pubkeys WHERE hash=? AND addressversion=? AND usedpersonally='yes' ''', ripe, addressVersion)
|
||||
if queryreturn != []: # if this pubkey is already in our database and if we have used it personally:
|
||||
print 'We HAVE used this pubkey personally. Updating time.'
|
||||
t = (ripe, addressVersion, data, embeddedTime, 'yes')
|
||||
else:
|
||||
print 'We have NOT used this pubkey personally. Inserting in database.'
|
||||
t = (ripe, addressVersion, data, embeddedTime, 'no')
|
||||
# This will also update the embeddedTime.
|
||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||
self.possibleNewPubkey(ripe = ripe)
|
||||
|
||||
if addressVersion == 4:
|
||||
"""
|
||||
There exist a function: shared.decryptAndCheckPubkeyPayload which does something almost
|
||||
the same as this section of code. There are differences, however; one being that
|
||||
decryptAndCheckPubkeyPayload requires that a cryptor object be created each time it is
|
||||
run which is an expensive operation. This, on the other hand, keeps them saved in
|
||||
the shared.neededPubkeys dictionary so that if an attacker sends us many
|
||||
incorrectly-tagged pubkeys, which would force us to try to decrypt them, this code
|
||||
would run and handle that event quite quickly.
|
||||
"""
|
||||
if len(data) < 350: # sanity check.
|
||||
print '(within processpubkey) payloadLength less than 350. Sanity check failed.'
|
||||
return
|
||||
signedData = data[8:readPosition] # Some of the signed data is not encrypted so let's keep it for now.
|
||||
tag = data[readPosition:readPosition + 32]
|
||||
readPosition += 32
|
||||
encryptedData = data[readPosition:]
|
||||
if tag not in shared.neededPubkeys:
|
||||
with shared.printLock:
|
||||
print 'We don\'t need this v4 pubkey. We didn\'t ask for it.'
|
||||
return
|
||||
|
||||
# Let us try to decrypt the pubkey
|
||||
cryptorObject = shared.neededPubkeys[tag]
|
||||
try:
|
||||
decryptedData = cryptorObject.decrypt(encryptedData)
|
||||
except:
|
||||
# Someone must have encrypted some data with a different key
|
||||
# but tagged it with a tag for which we are watching.
|
||||
with shared.printLock:
|
||||
print 'Pubkey decryption was unsuccessful.'
|
||||
return
|
||||
|
||||
readPosition = 0
|
||||
bitfieldBehaviors = decryptedData[readPosition:readPosition + 4]
|
||||
readPosition += 4
|
||||
publicSigningKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
||||
# Is it possible for a public key to be invalid such that trying to
|
||||
# encrypt or check a sig with it will cause an error? If it is, we
|
||||
# should probably test these keys here.
|
||||
readPosition += 64
|
||||
publicEncryptionKey = '\x04' + decryptedData[readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
specifiedNonceTrialsPerByte, specifiedNonceTrialsPerByteLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += specifiedNonceTrialsPerByteLength
|
||||
specifiedPayloadLengthExtraBytes, specifiedPayloadLengthExtraBytesLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += specifiedPayloadLengthExtraBytesLength
|
||||
signedData += decryptedData[:readPosition]
|
||||
signatureLength, signatureLengthLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += signatureLengthLength
|
||||
signature = decryptedData[readPosition:readPosition + signatureLength]
|
||||
try:
|
||||
if not highlevelcrypto.verify(signedData, signature, publicSigningKey.encode('hex')):
|
||||
print 'ECDSA verify failed (within processpubkey)'
|
||||
return
|
||||
print 'ECDSA verify passed (within processpubkey)'
|
||||
except Exception as err:
|
||||
print 'ECDSA verify failed (within processpubkey)', err
|
||||
return
|
||||
|
||||
sha = hashlib.new('sha512')
|
||||
sha.update(publicSigningKey + publicEncryptionKey)
|
||||
ripeHasher = hashlib.new('ripemd160')
|
||||
ripeHasher.update(sha.digest())
|
||||
ripe = ripeHasher.digest()
|
||||
|
||||
# We need to make sure that the tag on the outside of the encryption
|
||||
# is the one generated from hashing these particular keys.
|
||||
if tag != hashlib.sha512(hashlib.sha512(encodeVarint(addressVersion) + encodeVarint(streamNumber) + ripe).digest()).digest()[32:]:
|
||||
with shared.printLock:
|
||||
print 'Someone was trying to act malicious: tag doesn\'t match the keys in this pubkey message. Ignoring it.'
|
||||
return
|
||||
else:
|
||||
print 'Tag successfully matches keys in pubkey message' # testing. Will remove soon.
|
||||
|
||||
with shared.printLock:
|
||||
print 'within recpubkey, addressVersion:', addressVersion, ', streamNumber:', streamNumber
|
||||
print 'ripe', ripe.encode('hex')
|
||||
print 'publicSigningKey in hex:', publicSigningKey.encode('hex')
|
||||
print 'publicEncryptionKey in hex:', publicEncryptionKey.encode('hex')
|
||||
|
||||
t = (ripe, addressVersion, signedData, embeddedTime, 'yes')
|
||||
sqlExecute('''INSERT INTO pubkeys VALUES (?,?,?,?,?)''', *t)
|
||||
|
||||
fromAddress = encodeAddress(addressVersion, streamNumber, ripe)
|
||||
# That this point we know that we have been waiting on this pubkey.
|
||||
# This function will command the workerThread to start work on
|
||||
# the messages that require it.
|
||||
self.possibleNewPubkey(address = fromAddress)
|
||||
|
||||
# Display timing data
|
||||
timeRequiredToProcessPubkey = time.time(
|
||||
) - pubkeyProcessingStartTime
|
||||
with shared.printLock:
|
||||
print 'Time required to process this pubkey:', timeRequiredToProcessPubkey
|
||||
|
||||
|
||||
def processmsg(self, data):
|
||||
messageProcessingStartTime = time.time()
|
||||
shared.numberOfMessagesProcessed += 1
|
||||
shared.UISignalQueue.put((
|
||||
'updateNumberOfMessagesProcessed', 'no data'))
|
||||
readPosition = 8 # bypass the nonce
|
||||
embeddedTime, = unpack('>I', data[readPosition:readPosition + 4])
|
||||
|
||||
# This section is used for the transition from 32 bit time to 64 bit
|
||||
# time in the protocol.
|
||||
if embeddedTime == 0:
|
||||
embeddedTime, = unpack('>Q', data[readPosition:readPosition + 8])
|
||||
readPosition += 8
|
||||
else:
|
||||
readPosition += 4
|
||||
streamNumberAsClaimedByMsg, streamNumberAsClaimedByMsgLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
readPosition += streamNumberAsClaimedByMsgLength
|
||||
inventoryHash = calculateInventoryHash(data)
|
||||
initialDecryptionSuccessful = False
|
||||
# Let's check whether this is a message acknowledgement bound for us.
|
||||
if data[readPosition:] in shared.ackdataForWhichImWatching:
|
||||
with shared.printLock:
|
||||
print 'This msg IS an acknowledgement bound for me.'
|
||||
|
||||
del shared.ackdataForWhichImWatching[data[readPosition:]]
|
||||
sqlExecute('UPDATE sent SET status=? WHERE ackdata=?',
|
||||
'ackreceived', data[readPosition:])
|
||||
shared.UISignalQueue.put(('updateSentItemStatusByAckdata', (data[readPosition:], tr.translateText("MainWindow",'Acknowledgement of the message received. %1').arg(unicode(
|
||||
time.strftime(shared.config.get('bitmessagesettings', 'timeformat'), time.localtime(int(time.time()))), 'utf-8')))))
|
||||
return
|
||||
else:
|
||||
with shared.printLock:
|
||||
print 'This was NOT an acknowledgement bound for me.'
|
||||
# print 'shared.ackdataForWhichImWatching', shared.ackdataForWhichImWatching
|
||||
|
||||
|
||||
# This is not an acknowledgement bound for me. See if it is a message
|
||||
# bound for me by trying to decrypt it with my private keys.
|
||||
for key, cryptorObject in shared.myECCryptorObjects.items():
|
||||
try:
|
||||
decryptedData = cryptorObject.decrypt(
|
||||
data[readPosition:])
|
||||
toRipe = key # This is the RIPE hash of my pubkeys. We need this below to compare to the destination_ripe included in the encrypted data.
|
||||
initialDecryptionSuccessful = True
|
||||
with shared.printLock:
|
||||
print 'EC decryption successful using key associated with ripe hash:', key.encode('hex')
|
||||
break
|
||||
except Exception as err:
|
||||
pass
|
||||
# print 'cryptorObject.decrypt Exception:', err
|
||||
if not initialDecryptionSuccessful:
|
||||
# This is not a message bound for me.
|
||||
with shared.printLock:
|
||||
print 'Length of time program spent failing to decrypt this message:', time.time() - messageProcessingStartTime, 'seconds.'
|
||||
return
|
||||
|
||||
# This is a message bound for me.
|
||||
toAddress = shared.myAddressesByHash[
|
||||
toRipe] # Look up my address based on the RIPE hash.
|
||||
readPosition = 0
|
||||
messageVersion, messageVersionLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += messageVersionLength
|
||||
if messageVersion != 1:
|
||||
print 'Cannot understand message versions other than one. Ignoring message.'
|
||||
return
|
||||
sendersAddressVersionNumber, sendersAddressVersionNumberLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += sendersAddressVersionNumberLength
|
||||
if sendersAddressVersionNumber == 0:
|
||||
print 'Cannot understand sendersAddressVersionNumber = 0. Ignoring message.'
|
||||
return
|
||||
if sendersAddressVersionNumber > 4:
|
||||
print 'Sender\'s address version number', sendersAddressVersionNumber, 'not yet supported. Ignoring message.'
|
||||
return
|
||||
if len(decryptedData) < 170:
|
||||
print 'Length of the unencrypted data is unreasonably short. Sanity check failed. Ignoring message.'
|
||||
return
|
||||
sendersStreamNumber, sendersStreamNumberLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
if sendersStreamNumber == 0:
|
||||
print 'sender\'s stream number is 0. Ignoring message.'
|
||||
return
|
||||
readPosition += sendersStreamNumberLength
|
||||
behaviorBitfield = decryptedData[readPosition:readPosition + 4]
|
||||
readPosition += 4
|
||||
pubSigningKey = '\x04' + decryptedData[
|
||||
readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
pubEncryptionKey = '\x04' + decryptedData[
|
||||
readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
if sendersAddressVersionNumber >= 3:
|
||||
requiredAverageProofOfWorkNonceTrialsPerByte, varintLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += varintLength
|
||||
print 'sender\'s requiredAverageProofOfWorkNonceTrialsPerByte is', requiredAverageProofOfWorkNonceTrialsPerByte
|
||||
requiredPayloadLengthExtraBytes, varintLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += varintLength
|
||||
print 'sender\'s requiredPayloadLengthExtraBytes is', requiredPayloadLengthExtraBytes
|
||||
endOfThePublicKeyPosition = readPosition # needed for when we store the pubkey in our database of pubkeys for later use.
|
||||
if toRipe != decryptedData[readPosition:readPosition + 20]:
|
||||
with shared.printLock:
|
||||
print 'The original sender of this message did not send it to you. Someone is attempting a Surreptitious Forwarding Attack.'
|
||||
print 'See: http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html'
|
||||
print 'your toRipe:', toRipe.encode('hex')
|
||||
print 'embedded destination toRipe:', decryptedData[readPosition:readPosition + 20].encode('hex')
|
||||
return
|
||||
readPosition += 20
|
||||
messageEncodingType, messageEncodingTypeLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += messageEncodingTypeLength
|
||||
messageLength, messageLengthLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += messageLengthLength
|
||||
message = decryptedData[readPosition:readPosition + messageLength]
|
||||
# print 'First 150 characters of message:', repr(message[:150])
|
||||
readPosition += messageLength
|
||||
ackLength, ackLengthLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += ackLengthLength
|
||||
ackData = decryptedData[readPosition:readPosition + ackLength]
|
||||
readPosition += ackLength
|
||||
positionOfBottomOfAckData = readPosition # needed to mark the end of what is covered by the signature
|
||||
signatureLength, signatureLengthLength = decodeVarint(
|
||||
decryptedData[readPosition:readPosition + 10])
|
||||
readPosition += signatureLengthLength
|
||||
signature = decryptedData[
|
||||
readPosition:readPosition + signatureLength]
|
||||
try:
|
||||
if not highlevelcrypto.verify(decryptedData[:positionOfBottomOfAckData], signature, pubSigningKey.encode('hex')):
|
||||
print 'ECDSA verify failed'
|
||||
return
|
||||
print 'ECDSA verify passed'
|
||||
except Exception as err:
|
||||
print 'ECDSA verify failed', err
|
||||
return
|
||||
with shared.printLock:
|
||||
print 'As a matter of intellectual curiosity, here is the Bitcoin address associated with the keys owned by the other person:', helper_bitcoin.calculateBitcoinAddressFromPubkey(pubSigningKey), ' ..and here is the testnet address:', helper_bitcoin.calculateTestnetAddressFromPubkey(pubSigningKey), '. The other person must take their private signing key from Bitmessage and import it into Bitcoin (or a service like Blockchain.info) for it to be of any use. Do not use this unless you know what you are doing.'
|
||||
|
||||
# calculate the fromRipe.
|
||||
sha = hashlib.new('sha512')
|
||||
sha.update(pubSigningKey + pubEncryptionKey)
|
||||
ripe = hashlib.new('ripemd160')
|
||||
ripe.update(sha.digest())
|
||||
fromAddress = encodeAddress(
|
||||
sendersAddressVersionNumber, sendersStreamNumber, ripe.digest())
|
||||
# Let's store the public key in case we want to reply to this
|
||||
# person.
|
||||
if sendersAddressVersionNumber <= 3:
|
||||
sqlExecute(
|
||||
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
||||
ripe.digest(),
|
||||
sendersAddressVersionNumber,
|
||||
'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF' + '\xFF\xFF\xFF\xFF' + decryptedData[messageVersionLength:endOfThePublicKeyPosition],
|
||||
int(time.time()),
|
||||
'yes')
|
||||
# This will check to see whether we happen to be awaiting this
|
||||
# pubkey in order to send a message. If we are, it will do the POW
|
||||
# and send it.
|
||||
self.possibleNewPubkey(ripe=ripe.digest())
|
||||
elif sendersAddressVersionNumber >= 4:
|
||||
sqlExecute(
|
||||
'''INSERT INTO pubkeys VALUES (?,?,?,?,?)''',
|
||||
ripe.digest(),
|
||||
sendersAddressVersionNumber,
|
||||
'\x00\x00\x00\x00\x00\x00\x00\x01' + decryptedData[messageVersionLength:endOfThePublicKeyPosition],
|
||||
int(time.time()),
|
||||
'yes')
|
||||
# This will check to see whether we happen to be awaiting this
|
||||
# pubkey in order to send a message. If we are, it will do the POW
|
||||
# and send it.
|
||||
self.possibleNewPubkey(address = fromAddress)
|
||||
# If this message is bound for one of my version 3 addresses (or
|
||||
# higher), then we must check to make sure it meets our demanded
|
||||
# proof of work requirement.
|
||||
if decodeAddress(toAddress)[1] >= 3: # If the toAddress version number is 3 or higher:
|
||||
if not shared.isAddressInMyAddressBookSubscriptionsListOrWhitelist(fromAddress): # If I'm not friendly with this person:
|
||||
requiredNonceTrialsPerByte = shared.config.getint(
|
||||
toAddress, 'noncetrialsperbyte')
|
||||
requiredPayloadLengthExtraBytes = shared.config.getint(
|
||||
toAddress, 'payloadlengthextrabytes')
|
||||
if not shared.isProofOfWorkSufficient(data, requiredNonceTrialsPerByte, requiredPayloadLengthExtraBytes):
|
||||
print 'Proof of work in msg message insufficient only because it does not meet our higher requirement.'
|
||||
return
|
||||
blockMessage = False # Gets set to True if the user shouldn't see the message according to black or white lists.
|
||||
if shared.config.get('bitmessagesettings', 'blackwhitelist') == 'black': # If we are using a blacklist
|
||||
queryreturn = sqlQuery(
|
||||
'''SELECT label FROM blacklist where address=? and enabled='1' ''',
|
||||
fromAddress)
|
||||
if queryreturn != []:
|
||||
with shared.printLock:
|
||||
print 'Message ignored because address is in blacklist.'
|
||||
|
||||
blockMessage = True
|
||||
else: # We're using a whitelist
|
||||
queryreturn = sqlQuery(
|
||||
'''SELECT label FROM whitelist where address=? and enabled='1' ''',
|
||||
fromAddress)
|
||||
if queryreturn == []:
|
||||
print 'Message ignored because address not in whitelist.'
|
||||
blockMessage = True
|
||||
if not blockMessage:
|
||||
toLabel = shared.config.get(toAddress, 'label')
|
||||
if toLabel == '':
|
||||
toLabel = toAddress
|
||||
|
||||
if messageEncodingType == 2:
|
||||
subject, body = self.decodeType2Message(message)
|
||||
elif messageEncodingType == 1:
|
||||
body = message
|
||||
subject = ''
|
||||
elif messageEncodingType == 0:
|
||||
print 'messageEncodingType == 0. Doing nothing with the message. They probably just sent it so that we would store their public key or send their ack data for them.'
|
||||
else:
|
||||
body = 'Unknown encoding type.\n\n' + repr(message)
|
||||
subject = ''
|
||||
if messageEncodingType != 0:
|
||||
t = (inventoryHash, toAddress, fromAddress, subject, int(
|
||||
time.time()), body, 'inbox', messageEncodingType, 0)
|
||||
helper_inbox.insert(t)
|
||||
|
||||
shared.UISignalQueue.put(('displayNewInboxMessage', (
|
||||
inventoryHash, toAddress, fromAddress, subject, body)))
|
||||
|
||||
# If we are behaving as an API then we might need to run an
|
||||
# outside command to let some program know that a new message
|
||||
# has arrived.
|
||||
if shared.safeConfigGetBoolean('bitmessagesettings', 'apienabled'):
|
||||
try:
|
||||
apiNotifyPath = shared.config.get(
|
||||
'bitmessagesettings', 'apinotifypath')
|
||||
except:
|
||||
apiNotifyPath = ''
|
||||
if apiNotifyPath != '':
|
||||
call([apiNotifyPath, "newMessage"])
|
||||
|
||||
# Let us now check and see whether our receiving address is
|
||||
# behaving as a mailing list
|
||||
if shared.safeConfigGetBoolean(toAddress, 'mailinglist'):
|
||||
try:
|
||||
mailingListName = shared.config.get(
|
||||
toAddress, 'mailinglistname')
|
||||
except:
|
||||
mailingListName = ''
|
||||
# Let us send out this message as a broadcast
|
||||
subject = self.addMailingListNameToSubject(
|
||||
subject, mailingListName)
|
||||
# Let us now send this message out as a broadcast
|
||||
message = time.strftime("%a, %Y-%m-%d %H:%M:%S UTC", time.gmtime(
|
||||
)) + ' Message ostensibly from ' + fromAddress + ':\n\n' + body
|
||||
fromAddress = toAddress # The fromAddress for the broadcast that we are about to send is the toAddress (my address) for the msg message we are currently processing.
|
||||
ackdataForBroadcast = OpenSSL.rand(
|
||||
32) # We don't actually need the ackdataForBroadcast for acknowledgement since this is a broadcast message but we can use it to update the user interface when the POW is done generating.
|
||||
toAddress = '[Broadcast subscribers]'
|
||||
ripe = ''
|
||||
|
||||
t = ('', toAddress, ripe, fromAddress, subject, message, ackdataForBroadcast, int(
|
||||
time.time()), 'broadcastqueued', 1, 1, 'sent', 2)
|
||||
helper_sent.insert(t)
|
||||
|
||||
shared.UISignalQueue.put(('displayNewSentMessage', (
|
||||
toAddress, '[Broadcast subscribers]', fromAddress, subject, message, ackdataForBroadcast)))
|
||||
shared.workerQueue.put(('sendbroadcast', ''))
|
||||
|
||||
if self.ackDataHasAVaildHeader(ackData):
|
||||
if ackData[4:16] == 'getpubkey\x00\x00\x00':
|
||||
shared.checkAndSharegetpubkeyWithPeers(ackData[24:])
|
||||
elif ackData[4:16] == 'pubkey\x00\x00\x00\x00\x00\x00':
|
||||
shared.checkAndSharePubkeyWithPeers(ackData[24:])
|
||||
elif ackData[4:16] == 'msg\x00\x00\x00\x00\x00\x00\x00\x00\x00':
|
||||
shared.checkAndShareMsgWithPeers(ackData[24:])
|
||||
elif ackData[4:16] == 'broadcast\x00\x00\x00':
|
||||
shared.checkAndShareBroadcastWithPeers(ackData[24:])
|
||||
|
||||
# Display timing data
|
||||
timeRequiredToAttemptToDecryptMessage = time.time(
|
||||
) - messageProcessingStartTime
|
||||
shared.successfullyDecryptMessageTimings.append(
|
||||
timeRequiredToAttemptToDecryptMessage)
|
||||
sum = 0
|
||||
for item in shared.successfullyDecryptMessageTimings:
|
||||
sum += item
|
||||
with shared.printLock:
|
||||
print 'Time to decrypt this message successfully:', timeRequiredToAttemptToDecryptMessage
|
||||
print 'Average time for all message decryption successes since startup:', sum / len(shared.successfullyDecryptMessageTimings)
|
||||
|
||||
|
||||
def processbroadcast(self, data):
|
||||
messageProcessingStartTime = time.time()
|
||||
shared.numberOfBroadcastsProcessed += 1
|
||||
shared.UISignalQueue.put((
|
||||
'updateNumberOfBroadcastsProcessed', 'no data'))
|
||||
inventoryHash = calculateInventoryHash(data)
|
||||
readPosition = 8 # bypass the nonce
|
||||
embeddedTime, = unpack('>I', data[readPosition:readPosition + 4])
|
||||
|
||||
# This section is used for the transition from 32 bit time to 64 bit
|
||||
# time in the protocol.
|
||||
if embeddedTime == 0:
|
||||
embeddedTime, = unpack('>Q', data[readPosition:readPosition + 8])
|
||||
readPosition += 8
|
||||
else:
|
||||
readPosition += 4
|
||||
|
||||
broadcastVersion, broadcastVersionLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
readPosition += broadcastVersionLength
|
||||
if broadcastVersion < 1 or broadcastVersion > 3:
|
||||
print 'Cannot decode incoming broadcast versions higher than 3. Assuming the sender isn\'t being silly, you should upgrade Bitmessage because this message shall be ignored.'
|
||||
return
|
||||
if broadcastVersion == 1:
|
||||
beginningOfPubkeyPosition = readPosition # used when we add the pubkey to our pubkey table
|
||||
sendersAddressVersion, sendersAddressVersionLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
if sendersAddressVersion <= 1 or sendersAddressVersion >= 3:
|
||||
# Cannot decode senderAddressVersion higher than 2. Assuming
|
||||
# the sender isn\'t being silly, you should upgrade Bitmessage
|
||||
# because this message shall be ignored.
|
||||
return
|
||||
readPosition += sendersAddressVersionLength
|
||||
if sendersAddressVersion == 2:
|
||||
sendersStream, sendersStreamLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
readPosition += sendersStreamLength
|
||||
behaviorBitfield = data[readPosition:readPosition + 4]
|
||||
readPosition += 4
|
||||
sendersPubSigningKey = '\x04' + \
|
||||
data[readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
sendersPubEncryptionKey = '\x04' + \
|
||||
data[readPosition:readPosition + 64]
|
||||
readPosition += 64
|
||||
endOfPubkeyPosition = readPosition
|
||||
sendersHash = data[readPosition:readPosition + 20]
|
||||
if sendersHash not in shared.broadcastSendersForWhichImWatching:
|
||||
# Display timing data
|
||||
with shared.printLock:
|
||||
print 'Time spent deciding that we are not interested in this v1 broadcast:', time.time() - messageProcessingStartTime
|
||||
|
||||
return
|
||||
# At this point, this message claims to be from sendersHash and
|
||||
# we are interested in it. We still have to hash the public key
|
||||
# to make sure it is truly the key that matches the hash, and
|
||||
# also check the signiture.
|
||||
readPosition += 20
|
||||
|
||||
sha = hashlib.new('sha512')
|
||||
sha.update(sendersPubSigningKey + sendersPubEncryptionKey)
|
||||
ripe = hashlib.new('ripemd160')
|
||||
ripe.update(sha.digest())
|
||||
if ripe.digest() != sendersHash:
|
||||
# The sender of this message lied.
|
||||
return
|
||||
messageEncodingType, messageEncodingTypeLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
if messageEncodingType == 0:
|
||||
return
|
||||
readPosition += messageEncodingTypeLength
|
||||
messageLength, messageLengthLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
readPosition += messageLengthLength
|
||||
message = data[readPosition:readPosition + messageLength]
|
||||
readPosition += messageLength
|
||||
readPositionAtBottomOfMessage = readPosition
|
||||
signatureLength, signatureLengthLength = decodeVarint(
|
||||
data[readPosition:readPosition + 9])
|
||||
readPosition += signatureLengthLength
|
||||
signature = data[readPosition:readPosition + signatureLength]
|
||||
try:
|