Mobile message & behavior bitfield support #808

Open
kyucrane wants to merge 3 commits from kyucrane/mobileRecv into master
11 changed files with 137 additions and 35 deletions

View File

@ -220,24 +220,34 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
elif len(params) == 1: elif len(params) == 1:
label, = params label, = params
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 2: elif len(params) == 2:
label, eighteenByteRipe = params label, eighteenByteRipe = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 3: elif len(params) == 3:
label, eighteenByteRipe, totalDifficulty = params label, eighteenByteRipe, totalDifficulty = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 4: elif len(params) == 4:
label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = int(
shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
elif len(params) == 5:
label, eighteenByteRipe, totalDifficulty, smallMessageDifficulty, behaviorBits = params
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = int( payloadLengthExtraBytes = int(
@ -252,7 +262,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
shared.apiAddressGeneratorReturnQueue.queue.clear() shared.apiAddressGeneratorReturnQueue.queue.clear()
streamNumberForAddress = 1 streamNumberForAddress = 1
shared.addressGeneratorQueue.put(( shared.addressGeneratorQueue.put((
'createRandomAddress', 4, streamNumberForAddress, label, 1, "", eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes)) 'createRandomAddress', 4, streamNumberForAddress, label, 1, "", eighteenByteRipe, behaviorBits, nonceTrialsPerByte, payloadLengthExtraBytes))
return shared.apiAddressGeneratorReturnQueue.get() return shared.apiAddressGeneratorReturnQueue.get()
def HandleCreateDeterministicAddresses(self, params): def HandleCreateDeterministicAddresses(self, params):
@ -264,6 +274,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
addressVersionNumber = 0 addressVersionNumber = 0
streamNumber = 0 streamNumber = 0
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
@ -273,6 +284,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
addressVersionNumber = 0 addressVersionNumber = 0
streamNumber = 0 streamNumber = 0
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
@ -281,6 +293,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
passphrase, numberOfAddresses, addressVersionNumber = params passphrase, numberOfAddresses, addressVersionNumber = params
streamNumber = 0 streamNumber = 0
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
@ -288,24 +301,34 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
elif len(params) == 4: elif len(params) == 4:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params passphrase, numberOfAddresses, addressVersionNumber, streamNumber = params
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 5: elif len(params) == 5:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = shared.config.get( nonceTrialsPerByte = shared.config.get(
'bitmessagesettings', 'defaultnoncetrialsperbyte') 'bitmessagesettings', 'defaultnoncetrialsperbyte')
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 6: elif len(params) == 6:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = shared.config.get( payloadLengthExtraBytes = shared.config.get(
'bitmessagesettings', 'defaultpayloadlengthextrabytes') 'bitmessagesettings', 'defaultpayloadlengthextrabytes')
elif len(params) == 7: elif len(params) == 7:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty = params
behaviorBits = shared.BEHAVIOR_SENDACK,
nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = int(
shared.networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
elif len(params) == 8:
passphrase, numberOfAddresses, addressVersionNumber, streamNumber, eighteenByteRipe, totalDifficulty, smallMessageDifficulty, behaviorBits = params
nonceTrialsPerByte = int( nonceTrialsPerByte = int(
shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty) shared.networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
payloadLengthExtraBytes = int( payloadLengthExtraBytes = int(
@ -333,7 +356,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses) logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
shared.addressGeneratorQueue.put( shared.addressGeneratorQueue.put(
('createDeterministicAddresses', addressVersionNumber, streamNumber, ('createDeterministicAddresses', addressVersionNumber, streamNumber,
'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes)) 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, behaviorBits, nonceTrialsPerByte, payloadLengthExtraBytes))
data = '{"addresses":[' data = '{"addresses":['
queueReturn = shared.apiAddressGeneratorReturnQueue.get() queueReturn = shared.apiAddressGeneratorReturnQueue.get()
for item in queueReturn: for item in queueReturn:
@ -349,6 +372,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
passphrase, addressVersionNumber, streamNumber = params passphrase, addressVersionNumber, streamNumber = params
numberOfAddresses = 1 numberOfAddresses = 1
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = shared.BEHAVIOR_SENDACK,
if len(passphrase) == 0: if len(passphrase) == 0:
raise APIError(1, 'The specified passphrase is blank.') raise APIError(1, 'The specified passphrase is blank.')
passphrase = self._decode(passphrase, "base64") passphrase = self._decode(passphrase, "base64")
@ -360,7 +384,7 @@ class MySimpleXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses) logger.debug('Requesting that the addressGenerator create %s addresses.', numberOfAddresses)
shared.addressGeneratorQueue.put( shared.addressGeneratorQueue.put(
('getDeterministicAddress', addressVersionNumber, ('getDeterministicAddress', addressVersionNumber,
streamNumber, 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe)) streamNumber, 'unused API address', numberOfAddresses, passphrase, eighteenByteRipe, behaviorBits))
return shared.apiAddressGeneratorReturnQueue.get() return shared.apiAddressGeneratorReturnQueue.get()
def HandleCreateChan(self, params): def HandleCreateChan(self, params):

View File

@ -427,11 +427,15 @@ def handlech(c, stdscr):
if r == d.DIALOG_OK: if r == d.DIALOG_OK:
stream = decodeAddress(addrs[int(t)][1])[2] stream = decodeAddress(addrs[int(t)][1])[2]
shorten = False shorten = False
behaviorBits = shared.BEHAVIOR_SENDACK,
r, t = d.checklist("Miscellaneous options", r, t = d.checklist("Miscellaneous options",
choices=[("1", "Spend time shortening the address", shorten)]) choices=[("1", "Spend time shortening the address", shorten), ("2", "Create a mobile address")])
if r == d.DIALOG_OK and "1" in t: if r == d.DIALOG_OK:
if "1" in t:
shorten = True shorten = True
shared.addressGeneratorQueue.put(("createRandomAddress", 4, stream, label, 1, "", shorten)) if "2" in t:
behaviorBits += shared.BEHAVIOR_NEEDRIPE,
shared.addressGeneratorQueue.put(("createRandomAddress", 4, stream, label, 1, "", shorten, behaviorBits))
elif t == "2": elif t == "2":
d.set_background_title("Make deterministic addresses") d.set_background_title("Make deterministic addresses")
r, t = d.passwordform("Enter passphrase", r, t = d.passwordform("Enter passphrase",
@ -447,15 +451,19 @@ def handlech(c, stdscr):
number = t number = t
stream = 1 stream = 1
shorten = False shorten = False
behaviorBits = shared.BEHAVIOR_SENDACK,
r, t = d.checklist("Miscellaneous options", r, t = d.checklist("Miscellaneous options",
choices=[("1", "Spend time shortening the address", shorten)]) choices=[("1", "Spend time shortening the address", shorten), ("2", "Create a mobile address")])
if r == d.DIALOG_OK and "1" in t: if r == d.DIALOG_OK:
if "1" in t:
shorten = True shorten = True
if "2" in t:
behaviorBits += shared.BEHAVIOR_NEEDRIPE,
d.scrollbox(unicode("In addition to your passphrase, be sure to remember the following numbers:\n" d.scrollbox(unicode("In addition to your passphrase, be sure to remember the following numbers:\n"
"\n * Address version number: "+str(4)+"\n" "\n * Address version number: "+str(4)+"\n"
" * Stream number: "+str(stream)), " * Stream number: "+str(stream)),
exit_label="Continue") exit_label="Continue")
shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, stream, "unused deterministic address", number, str(passphrase), shorten)) shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, stream, "unused deterministic address", number, str(passphrase), shorten, behaviorBits))
else: else:
d.scrollbox(unicode("Passphrases do not match"), exit_label="Continue") d.scrollbox(unicode("Passphrases do not match"), exit_label="Continue")
elif t == "2": # Send a message elif t == "2": # Send a message

View File

@ -1405,8 +1405,11 @@ class MyForm(QtGui.QMainWindow):
QMessageBox.about(self, _translate("MainWindow", "Bad address version number"), _translate( QMessageBox.about(self, _translate("MainWindow", "Bad address version number"), _translate(
"MainWindow", "Your address version number must be either 3 or 4.")) "MainWindow", "Your address version number must be either 3 or 4."))
return return
behaviorBits = shared.BEHAVIOR_SENDACK,
if self.dialog.ui.checkBoxMobile.isChecked():
behaviorBits += shared.BEHAVIOR_NEEDRIPE,
shared.addressGeneratorQueue.put(('createDeterministicAddresses', addressVersionNumber, streamNumberForAddress, "regenerated deterministic address", self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value( shared.addressGeneratorQueue.put(('createDeterministicAddresses', addressVersionNumber, streamNumberForAddress, "regenerated deterministic address", self.regenerateAddressesDialogInstance.ui.spinBoxNumberOfAddressesToMake.value(
), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked())) ), self.regenerateAddressesDialogInstance.ui.lineEditPassphrase.text().toUtf8(), self.regenerateAddressesDialogInstance.ui.checkBoxEighteenByteRipe.isChecked(), behaviorBits))
self.ui.tabWidget.setCurrentIndex(3) self.ui.tabWidget.setCurrentIndex(3)
def click_actionJoinChan(self): def click_actionJoinChan(self):
@ -2635,8 +2638,11 @@ more work your computer must do to send the message. A Time-To-Live of four or f
# address.' # address.'
streamNumberForAddress = decodeAddress( streamNumberForAddress = decodeAddress(
self.dialog.ui.comboBoxExisting.currentText())[2] self.dialog.ui.comboBoxExisting.currentText())[2]
behaviorBits = shared.BEHAVIOR_SENDACK,
if self.dialog.ui.checkBoxMobile.isChecked():
behaviorBits += shared.BEHAVIOR_NEEDRIPE,
shared.addressGeneratorQueue.put(('createRandomAddress', 4, streamNumberForAddress, str( shared.addressGeneratorQueue.put(('createRandomAddress', 4, streamNumberForAddress, str(
self.dialog.ui.newaddresslabel.text().toUtf8()), 1, "", self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) self.dialog.ui.newaddresslabel.text().toUtf8()), 1, "", self.dialog.ui.checkBoxEighteenByteRipe.isChecked(), behaviorBits))
else: else:
if self.dialog.ui.lineEditPassphrase.text() != self.dialog.ui.lineEditPassphraseAgain.text(): if self.dialog.ui.lineEditPassphrase.text() != self.dialog.ui.lineEditPassphraseAgain.text():
QMessageBox.about(self, _translate("MainWindow", "Passphrase mismatch"), _translate( QMessageBox.about(self, _translate("MainWindow", "Passphrase mismatch"), _translate(
@ -2646,8 +2652,11 @@ more work your computer must do to send the message. A Time-To-Live of four or f
"MainWindow", "Choose a passphrase"), _translate("MainWindow", "You really do need a passphrase.")) "MainWindow", "Choose a passphrase"), _translate("MainWindow", "You really do need a passphrase."))
else: else:
streamNumberForAddress = 1 # this will eventually have to be replaced by logic to determine the most available stream number. streamNumberForAddress = 1 # this will eventually have to be replaced by logic to determine the most available stream number.
behaviorBits = shared.BEHAVIOR_SENDACK,
if self.dialog.ui.checkBoxMobile.isChecked():
behaviorBits += shared.BEHAVIOR_NEEDRIPE,
shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value( shared.addressGeneratorQueue.put(('createDeterministicAddresses', 4, streamNumberForAddress, "unused deterministic address", self.dialog.ui.spinBoxNumberOfAddressesToMake.value(
), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked())) ), self.dialog.ui.lineEditPassphrase.text().toUtf8(), self.dialog.ui.checkBoxEighteenByteRipe.isChecked(), behaviorBits))
else: else:
print 'new address dialog box rejected' print 'new address dialog box rejected'

View File

@ -64,6 +64,9 @@ class Ui_NewAddressDialog(object):
self.checkBoxEighteenByteRipe = QtGui.QCheckBox(NewAddressDialog) self.checkBoxEighteenByteRipe = QtGui.QCheckBox(NewAddressDialog)
self.checkBoxEighteenByteRipe.setObjectName(_fromUtf8("checkBoxEighteenByteRipe")) self.checkBoxEighteenByteRipe.setObjectName(_fromUtf8("checkBoxEighteenByteRipe"))
self.formLayout.setWidget(9, QtGui.QFormLayout.SpanningRole, self.checkBoxEighteenByteRipe) self.formLayout.setWidget(9, QtGui.QFormLayout.SpanningRole, self.checkBoxEighteenByteRipe)
self.checkBoxMobile = QtGui.QCheckBox(NewAddressDialog)
self.checkBoxMobile.setObjectName(_fromUtf8("checkBoxMobile"))
self.formLayout.setWidget(10, QtGui.QFormLayout.SpanningRole, self.checkBoxMobile)
self.groupBoxDeterministic = QtGui.QGroupBox(NewAddressDialog) self.groupBoxDeterministic = QtGui.QGroupBox(NewAddressDialog)
self.groupBoxDeterministic.setObjectName(_fromUtf8("groupBoxDeterministic")) self.groupBoxDeterministic.setObjectName(_fromUtf8("groupBoxDeterministic"))
self.gridLayout = QtGui.QGridLayout(self.groupBoxDeterministic) self.gridLayout = QtGui.QGridLayout(self.groupBoxDeterministic)
@ -149,7 +152,7 @@ class Ui_NewAddressDialog(object):
self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(_fromUtf8("buttonBox")) self.buttonBox.setObjectName(_fromUtf8("buttonBox"))
self.formLayout.setWidget(10, QtGui.QFormLayout.SpanningRole, self.buttonBox) self.formLayout.setWidget(11, QtGui.QFormLayout.SpanningRole, self.buttonBox)
self.retranslateUi(NewAddressDialog) self.retranslateUi(NewAddressDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewAddressDialog.accept) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), NewAddressDialog.accept)
@ -167,7 +170,8 @@ class Ui_NewAddressDialog(object):
NewAddressDialog.setTabOrder(self.lineEditPassphrase, self.lineEditPassphraseAgain) NewAddressDialog.setTabOrder(self.lineEditPassphrase, self.lineEditPassphraseAgain)
NewAddressDialog.setTabOrder(self.lineEditPassphraseAgain, self.spinBoxNumberOfAddressesToMake) NewAddressDialog.setTabOrder(self.lineEditPassphraseAgain, self.spinBoxNumberOfAddressesToMake)
NewAddressDialog.setTabOrder(self.spinBoxNumberOfAddressesToMake, self.checkBoxEighteenByteRipe) NewAddressDialog.setTabOrder(self.spinBoxNumberOfAddressesToMake, self.checkBoxEighteenByteRipe)
NewAddressDialog.setTabOrder(self.checkBoxEighteenByteRipe, self.buttonBox) NewAddressDialog.setTabOrder(self.checkBoxEighteenByteRipe, self.checkBoxMobile)
NewAddressDialog.setTabOrder(self.checkBoxMobile, self.buttonBox)
def retranslateUi(self, NewAddressDialog): def retranslateUi(self, NewAddressDialog):
NewAddressDialog.setWindowTitle(_translate("NewAddressDialog", "Create new Address", None)) NewAddressDialog.setWindowTitle(_translate("NewAddressDialog", "Create new Address", None))
@ -177,6 +181,7 @@ class Ui_NewAddressDialog(object):
self.radioButtonRandomAddress.setText(_translate("NewAddressDialog", "Use a random number generator to make an address", None)) self.radioButtonRandomAddress.setText(_translate("NewAddressDialog", "Use a random number generator to make an address", None))
self.radioButtonDeterministicAddress.setText(_translate("NewAddressDialog", "Use a passphrase to make addresses", None)) self.radioButtonDeterministicAddress.setText(_translate("NewAddressDialog", "Use a passphrase to make addresses", None))
self.checkBoxEighteenByteRipe.setText(_translate("NewAddressDialog", "Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter", None)) self.checkBoxEighteenByteRipe.setText(_translate("NewAddressDialog", "Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter", None))
self.checkBoxMobile.setText(_translate("NewAddressDialog", "Require messages sent to you include your address unencrypted (saves resources, for mobile)", None))
self.groupBoxDeterministic.setTitle(_translate("NewAddressDialog", "Make deterministic addresses", None)) self.groupBoxDeterministic.setTitle(_translate("NewAddressDialog", "Make deterministic addresses", None))
self.label_9.setText(_translate("NewAddressDialog", "Address version number: 4", None)) self.label_9.setText(_translate("NewAddressDialog", "Address version number: 4", None))
self.label_8.setText(_translate("NewAddressDialog", "In addition to your passphrase, you must remember these numbers:", None)) self.label_8.setText(_translate("NewAddressDialog", "In addition to your passphrase, you must remember these numbers:", None))

View File

@ -90,6 +90,13 @@ The 'Random Number' option is selected by default but deterministic addresses ha
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="0" colspan="2">
<widget class="QCheckBox" name="checkBoxMobile">
<property name="text">
<string>Require messages sent to you include your address(es) unencrypted (saves resources, for mobile)</string>
</propert>
</widget>
</item>
<item row="8" column="0"> <item row="8" column="0">
<widget class="QGroupBox" name="groupBoxDeterministic"> <widget class="QGroupBox" name="groupBoxDeterministic">
<property name="title"> <property name="title">
@ -284,7 +291,7 @@ The 'Random Number' option is selected by default but deterministic addresses ha
<zorder>horizontalSpacer_3</zorder> <zorder>horizontalSpacer_3</zorder>
</widget> </widget>
</item> </item>
<item row="10" column="0" colspan="2"> <item row="11" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox"> <widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">

View File

@ -94,11 +94,14 @@ class Ui_regenerateAddressesDialog(object):
self.gridLayout.addItem(spacerItem2, 5, 2, 1, 3) self.gridLayout.addItem(spacerItem2, 5, 2, 1, 3)
self.checkBoxEighteenByteRipe = QtGui.QCheckBox(self.groupBox) self.checkBoxEighteenByteRipe = QtGui.QCheckBox(self.groupBox)
self.checkBoxEighteenByteRipe.setObjectName(_fromUtf8("checkBoxEighteenByteRipe")) self.checkBoxEighteenByteRipe.setObjectName(_fromUtf8("checkBoxEighteenByteRipe"))
self.gridLayout.addWidget(self.checkBoxEighteenByteRipe, 6, 0, 1, 5) self.gridLayout.addWidget(self.checkBoxEighteenByteRipe, 7, 0, 1, 5)
self.checkBoxMobile = QtGui.QCheckBox(self.groupBox)
self.checkBoxMobile.setObjectName(_fromUtf8("checkBoxMobile"))
self.gridLayout.addWidget(self.checkBoxMobile, 6, 0, 1, 5)
self.label_4 = QtGui.QLabel(self.groupBox) self.label_4 = QtGui.QLabel(self.groupBox)
self.label_4.setWordWrap(True) self.label_4.setWordWrap(True)
self.label_4.setObjectName(_fromUtf8("label_4")) self.label_4.setObjectName(_fromUtf8("label_4"))
self.gridLayout.addWidget(self.label_4, 7, 0, 1, 5) self.gridLayout.addWidget(self.label_4, 8, 0, 1, 5)
self.label = QtGui.QLabel(self.groupBox) self.label = QtGui.QLabel(self.groupBox)
self.label.setWordWrap(True) self.label.setWordWrap(True)
self.label.setObjectName(_fromUtf8("label")) self.label.setObjectName(_fromUtf8("label"))
@ -119,6 +122,7 @@ class Ui_regenerateAddressesDialog(object):
self.label_3.setText(_translate("regenerateAddressesDialog", "Stream number:", None)) self.label_3.setText(_translate("regenerateAddressesDialog", "Stream number:", None))
self.lineEditStreamNumber.setText(_translate("regenerateAddressesDialog", "1", None)) self.lineEditStreamNumber.setText(_translate("regenerateAddressesDialog", "1", None))
self.checkBoxEighteenByteRipe.setText(_translate("regenerateAddressesDialog", "Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter", None)) self.checkBoxEighteenByteRipe.setText(_translate("regenerateAddressesDialog", "Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter", None))
self.checkBoxMobile.setText(_translate("regenerateAddressesDialog", "Require messages sent to you include your address(es) unencrypted (saves resources, for mobile)", None))
self.label_4.setText(_translate("regenerateAddressesDialog", "You must check (or not check) this box just like you did (or didn\'t) when you made your addresses the first time.", None)) self.label_4.setText(_translate("regenerateAddressesDialog", "You must check (or not check) this box just like you did (or didn\'t) when you made your addresses the first time.", None))
self.label.setText(_translate("regenerateAddressesDialog", "If you have previously made deterministic addresses but lost them due to an accident (like hard drive failure), you can regenerate them here. If you used the random number generator to make your addresses then this form will be of no use to you.", None)) self.label.setText(_translate("regenerateAddressesDialog", "If you have previously made deterministic addresses but lost them due to an accident (like hard drive failure), you can regenerate them here. If you used the random number generator to make your addresses then this form will be of no use to you.", None))

View File

@ -168,13 +168,20 @@
</spacer> </spacer>
</item> </item>
<item row="6" column="0" colspan="5"> <item row="6" column="0" colspan="5">
<widget class="QCheckBox" name="checkBoxMobile">
<property name="text">
<string>Require messages sent to you include your address(es) unencrypted (saves resources, for mobile)</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="5">
<widget class="QCheckBox" name="checkBoxEighteenByteRipe"> <widget class="QCheckBox" name="checkBoxEighteenByteRipe">
<property name="text"> <property name="text">
<string>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</string> <string>Spend several minutes of extra computing time to make the address(es) 1 or 2 characters shorter</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="0" colspan="5"> <item row="8" column="0" colspan="5">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="text"> <property name="text">
<string>You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time.</string> <string>You must check (or not check) this box just like you did (or didn't) when you made your addresses the first time.</string>

View File

@ -25,17 +25,19 @@ class addressGenerator(threading.Thread):
if queueValue[0] == 'createChan': if queueValue[0] == 'createChan':
command, addressVersionNumber, streamNumber, label, deterministicPassphrase = queueValue command, addressVersionNumber, streamNumber, label, deterministicPassphrase = queueValue
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = ()
numberOfAddressesToMake = 1 numberOfAddressesToMake = 1
numberOfNullBytesDemandedOnFrontOfRipeHash = 1 numberOfNullBytesDemandedOnFrontOfRipeHash = 1
elif queueValue[0] == 'joinChan': elif queueValue[0] == 'joinChan':
command, chanAddress, label, deterministicPassphrase = queueValue command, chanAddress, label, deterministicPassphrase = queueValue
eighteenByteRipe = False eighteenByteRipe = False
behaviorBits = ()
addressVersionNumber = decodeAddress(chanAddress)[1] addressVersionNumber = decodeAddress(chanAddress)[1]
streamNumber = decodeAddress(chanAddress)[2] streamNumber = decodeAddress(chanAddress)[2]
numberOfAddressesToMake = 1 numberOfAddressesToMake = 1
numberOfNullBytesDemandedOnFrontOfRipeHash = 1 numberOfNullBytesDemandedOnFrontOfRipeHash = 1
elif len(queueValue) == 7: elif len(queueValue) == 8:
command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe = queueValue command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe, behaviorBits = queueValue
try: try:
numberOfNullBytesDemandedOnFrontOfRipeHash = shared.config.getint( numberOfNullBytesDemandedOnFrontOfRipeHash = shared.config.getint(
'bitmessagesettings', 'numberofnullbytesonaddress') 'bitmessagesettings', 'numberofnullbytesonaddress')
@ -44,8 +46,8 @@ class addressGenerator(threading.Thread):
numberOfNullBytesDemandedOnFrontOfRipeHash = 2 numberOfNullBytesDemandedOnFrontOfRipeHash = 2
else: else:
numberOfNullBytesDemandedOnFrontOfRipeHash = 1 # the default numberOfNullBytesDemandedOnFrontOfRipeHash = 1 # the default
elif len(queueValue) == 9: elif len(queueValue) == 10:
command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe, nonceTrialsPerByte, payloadLengthExtraBytes = queueValue command, addressVersionNumber, streamNumber, label, numberOfAddressesToMake, deterministicPassphrase, eighteenByteRipe, behaviorBits, nonceTrialsPerByte, payloadLengthExtraBytes = queueValue
try: try:
numberOfNullBytesDemandedOnFrontOfRipeHash = shared.config.getint( numberOfNullBytesDemandedOnFrontOfRipeHash = shared.config.getint(
'bitmessagesettings', 'numberofnullbytesonaddress') 'bitmessagesettings', 'numberofnullbytesonaddress')
@ -119,6 +121,7 @@ class addressGenerator(threading.Thread):
shared.config.set(address, 'label', label) shared.config.set(address, 'label', label)
shared.config.set(address, 'enabled', 'true') shared.config.set(address, 'enabled', 'true')
shared.config.set(address, 'decoy', 'false') shared.config.set(address, 'decoy', 'false')
shared.setConfigFromBehaviorBitfield(address, shared.createBitfield(*behaviorBits))
shared.config.set(address, 'noncetrialsperbyte', str( shared.config.set(address, 'noncetrialsperbyte', str(
nonceTrialsPerByte)) nonceTrialsPerByte))
shared.config.set(address, 'payloadlengthextrabytes', str( shared.config.set(address, 'payloadlengthextrabytes', str(
@ -236,6 +239,7 @@ class addressGenerator(threading.Thread):
shared.config.set(address, 'label', label) shared.config.set(address, 'label', label)
shared.config.set(address, 'enabled', 'true') shared.config.set(address, 'enabled', 'true')
shared.config.set(address, 'decoy', 'false') shared.config.set(address, 'decoy', 'false')
shared.setConfigFromBehaviorBitfield(address, shared.createBitfield(*behaviorBits))
if command == 'joinChan' or command == 'createChan': if command == 'joinChan' or command == 'createChan':
shared.config.set(address, 'chan', 'true') shared.config.set(address, 'chan', 'true')
shared.config.set(address, 'noncetrialsperbyte', str( shared.config.set(address, 'noncetrialsperbyte', str(

View File

@ -342,6 +342,11 @@ class objectProcessor(threading.Thread):
for key, cryptorObject in shared.myECCryptorObjects.items(): for key, cryptorObject in shared.myECCryptorObjects.items():
try: try:
mobileRipe = key.lstrip('\x00')
if data[readPosition:readPosition+len(mobileRipe)] == mobileRipe:
decryptedData = cryptorObject.decrypt(data[readPosition+len(mobileRipe):])
logger.info('Received a mobile message containing our unencrypted address.')
else:
decryptedData = cryptorObject.decrypt(data[readPosition:]) 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. 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 initialDecryptionSuccessful = True
@ -575,6 +580,9 @@ class objectProcessor(threading.Thread):
shared.workerQueue.put(('sendbroadcast', '')) shared.workerQueue.put(('sendbroadcast', ''))
if self.ackDataHasAVaildHeader(ackData): if self.ackDataHasAVaildHeader(ackData):
if shared.config.getboolean(toAddress, 'notsendack'):
logger.info('Ack data was provided even though we do not send it. Ignoring.')
else:
shared.checkAndShareObjectWithPeers(ackData[24:]) shared.checkAndShareObjectWithPeers(ackData[24:])
# Display timing data # Display timing data

View File

@ -106,7 +106,7 @@ class singleWorker(threading.Thread):
payload += '\x00\x00\x00\x01' # object type: pubkey payload += '\x00\x00\x00\x01' # object type: pubkey
payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(addressVersionNumber) # Address version number
payload += encodeVarint(streamNumber) payload += encodeVarint(streamNumber)
payload += '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). payload += shared.createBehaviorBitfieldFromConfig(myAddress) # bitfield of features supported by me (see the wiki).
try: try:
privSigningKeyBase58 = shared.config.get( privSigningKeyBase58 = shared.config.get(
@ -191,7 +191,7 @@ class singleWorker(threading.Thread):
payload += '\x00\x00\x00\x01' # object type: pubkey payload += '\x00\x00\x00\x01' # object type: pubkey
payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(addressVersionNumber) # Address version number
payload += encodeVarint(streamNumber) payload += encodeVarint(streamNumber)
payload += '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). payload += shared.createBehaviorBitfieldFromConfig(myAddress) # bitfield of features supported by me (see the wiki).
try: try:
privSigningKeyBase58 = shared.config.get( privSigningKeyBase58 = shared.config.get(
@ -277,7 +277,7 @@ class singleWorker(threading.Thread):
payload += encodeVarint(addressVersionNumber) # Address version number payload += encodeVarint(addressVersionNumber) # Address version number
payload += encodeVarint(streamNumber) payload += encodeVarint(streamNumber)
dataToEncrypt = '\x00\x00\x00\x01' # bitfield of features supported by me (see the wiki). dataToEncrypt = shared.createBehaviorBitfieldFromConfig(myAddress) # bitfield of features supported by me (see the wiki).
try: try:
privSigningKeyBase58 = shared.config.get( privSigningKeyBase58 = shared.config.get(
@ -410,7 +410,7 @@ class singleWorker(threading.Thread):
dataToEncrypt = encodeVarint(addressVersionNumber) dataToEncrypt = encodeVarint(addressVersionNumber)
dataToEncrypt += encodeVarint(streamNumber) dataToEncrypt += encodeVarint(streamNumber)
dataToEncrypt += '\x00\x00\x00\x01' # behavior bitfield dataToEncrypt += shared.createBehaviorBitfieldFromConfig(fromaddress) # behavior bitfield
dataToEncrypt += pubSigningKey[1:] dataToEncrypt += pubSigningKey[1:]
dataToEncrypt += pubEncryptionKey[1:] dataToEncrypt += pubEncryptionKey[1:]
if addressVersionNumber >= 3: if addressVersionNumber >= 3:
@ -641,7 +641,7 @@ class singleWorker(threading.Thread):
# Mobile users may ask us to include their address's RIPE hash on a message # Mobile users may ask us to include their address's RIPE hash on a message
# unencrypted. Before we actually do it the sending human must check a box # unencrypted. Before we actually do it the sending human must check a box
# in the settings menu to allow it. # in the settings menu to allow it.
if shared.isBitSetWithinBitfield(behaviorBitfield,30): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message.. if shared.isBitSetWithinBitfield(behaviorBitfield,shared.BEHAVIOR_NEEDRIPE): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message..
if not shared.safeConfigGetBoolean('bitmessagesettings','willinglysendtomobile'): # if we are Not willing to include the receiver's RIPE hash on the message.. if not shared.safeConfigGetBoolean('bitmessagesettings','willinglysendtomobile'): # if we are Not willing to include the receiver's RIPE hash on the message..
logger.info('The receiver is a mobile user but the sender (you) has not selected that you are willing to send to mobiles. Aborting send.') logger.info('The receiver is a mobile user but the sender (you) has not selected that you are willing to send to mobiles. Aborting send.')
shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(l10n.formatTimestamp())))) shared.UISignalQueue.put(('updateSentItemStatusByAckdata',(ackdata,tr.translateText("MainWindow",'Problem: Destination is a mobile device who requests that the destination be included in the message but this is disallowed in your settings. %1').arg(l10n.formatTimestamp()))))
@ -687,7 +687,7 @@ class singleWorker(threading.Thread):
else: # if we are sending a message to ourselves or a chan.. else: # if we are sending a message to ourselves or a chan..
with shared.printLock: with shared.printLock:
print 'Sending a message. First 150 characters of message:', repr(message[:150]) print 'Sending a message. First 150 characters of message:', repr(message[:150])
behaviorBitfield = '\x00\x00\x00\x01' behaviorBitfield = shared.createBehaviorBitfieldFromConfig(toaddress)
try: try:
privEncryptionKeyBase58 = shared.config.get( privEncryptionKeyBase58 = shared.config.get(
@ -710,7 +710,7 @@ class singleWorker(threading.Thread):
# Now we can start to assemble our message. # Now we can start to assemble our message.
payload = encodeVarint(fromAddressVersionNumber) payload = encodeVarint(fromAddressVersionNumber)
payload += encodeVarint(fromStreamNumber) payload += encodeVarint(fromStreamNumber)
payload += '\x00\x00\x00\x01' # Bitfield of features and behaviors that can be expected from me. (See https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features ) payload += shared.createBehaviorBitfieldFromConfig(fromaddress) # Bitfield of features and behaviors that can be expected from me. (See https://bitmessage.org/wiki/Protocol_specification#Pubkey_bitfield_features )
# We need to convert our private keys to public keys in order # We need to convert our private keys to public keys in order
# to include them. # to include them.
@ -764,7 +764,7 @@ class singleWorker(threading.Thread):
with shared.printLock: with shared.printLock:
print 'Not bothering to include ackdata because we are sending to ourselves or a chan.' print 'Not bothering to include ackdata because we are sending to ourselves or a chan.'
fullAckPayload = '' fullAckPayload = ''
elif not shared.isBitSetWithinBitfield(behaviorBitfield,31): elif not shared.isBitSetWithinBitfield(behaviorBitfield,shared.BEHAVIOR_SENDACK):
with shared.printLock: with shared.printLock:
print 'Not bothering to include ackdata because the receiver said that they won\'t relay it anyway.' print 'Not bothering to include ackdata because the receiver said that they won\'t relay it anyway.'
fullAckPayload = '' fullAckPayload = ''
@ -789,7 +789,10 @@ class singleWorker(threading.Thread):
encryptedPayload = pack('>Q', embeddedTime) encryptedPayload = pack('>Q', embeddedTime)
encryptedPayload += '\x00\x00\x00\x02' # object type: msg encryptedPayload += '\x00\x00\x00\x02' # object type: msg
encryptedPayload += encodeVarint(1) # msg version encryptedPayload += encodeVarint(1) # msg version
encryptedPayload += encodeVarint(toStreamNumber) + encrypted encryptedPayload += encodeVarint(toStreamNumber)
if shared.isBitSetWithinBitfield(behaviorBitfield,shared.BEHAVIOR_NEEDRIPE): # if receiver is a mobile device who expects that their address RIPE is included unencrypted on the front of the message..
encryptedPayload += toRipe.lstrip('\x00')
encryptedPayload += encrypted
target = 2 ** 64 / (requiredAverageProofOfWorkNonceTrialsPerByte*(len(encryptedPayload) + 8 + requiredPayloadLengthExtraBytes + ((TTL*(len(encryptedPayload)+8+requiredPayloadLengthExtraBytes))/(2 ** 16)))) target = 2 ** 64 / (requiredAverageProofOfWorkNonceTrialsPerByte*(len(encryptedPayload) + 8 + requiredPayloadLengthExtraBytes + ((TTL*(len(encryptedPayload)+8+requiredPayloadLengthExtraBytes))/(2 ** 16))))
with shared.printLock: with shared.printLock:
print '(For msg message) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes print '(For msg message) Doing proof of work. Total required difficulty:', float(requiredAverageProofOfWorkNonceTrialsPerByte) / shared.networkDefaultProofOfWorkNonceTrialsPerByte, 'Required small message difficulty:', float(requiredPayloadLengthExtraBytes) / shared.networkDefaultPayloadLengthExtraBytes

View File

@ -116,6 +116,10 @@ frozen = getattr(sys,'frozen', None)
# security. # security.
trustedPeer = None trustedPeer = None
# Behavior bitfield constants
BEHAVIOR_SENDACK = 31
BEHAVIOR_NEEDRIPE = 30
#Compiled struct for packing/unpacking headers #Compiled struct for packing/unpacking headers
#New code should use CreatePacket instead of Header.pack #New code should use CreatePacket instead of Header.pack
Header = Struct('!L12sL4s') Header = Struct('!L12sL4s')
@ -473,6 +477,25 @@ def isBitSetWithinBitfield(fourByteString, n):
x, = unpack('>L', fourByteString) x, = unpack('>L', fourByteString)
return x & 2**n != 0 return x & 2**n != 0
def createBitfield(*fields):
x = 0
for n in fields:
n = 31 - n
x |= 2**n
return pack('>L', x)
def createBehaviorBitfieldFromConfig(myAddress):
fields = ()
if not config.getboolean(myAddress, 'notsendack'):
fields += BEHAVIOR_SENDACK,
if config.getboolean(myAddress, 'needripe'):
fields += BEHAVIOR_NEEDRIPE,
return createBitfield(*fields)
def setConfigFromBehaviorBitfield(address, bitfield):
config.set(address, 'notsendack', str(not isBitSetWithinBitfield(bitfield, BEHAVIOR_SENDACK)))
config.set(address, 'needripe', str(isBitSetWithinBitfield(bitfield, BEHAVIOR_NEEDRIPE)))
def decryptAndCheckPubkeyPayload(data, address): def decryptAndCheckPubkeyPayload(data, address):
""" """