Make PoW optional in disseminatePreEncryptedMsg API command #2211
82
src/api.py
82
src/api.py
|
@ -66,12 +66,11 @@ import socket
|
||||||
import subprocess # nosec B404
|
import subprocess # nosec B404
|
||||||
import time
|
import time
|
||||||
from binascii import hexlify, unhexlify
|
from binascii import hexlify, unhexlify
|
||||||
from struct import pack
|
from struct import pack, unpack
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from six.moves import configparser, http_client, xmlrpc_server
|
from six.moves import configparser, http_client, xmlrpc_server
|
||||||
|
|
||||||
import defaults
|
|
||||||
import helper_inbox
|
import helper_inbox
|
||||||
import helper_sent
|
import helper_sent
|
||||||
import protocol
|
import protocol
|
||||||
|
@ -89,6 +88,9 @@ from addresses import (
|
||||||
)
|
)
|
||||||
from bmconfigparser import config
|
from bmconfigparser import config
|
||||||
from debug import logger
|
from debug import logger
|
||||||
|
from defaults import (
|
||||||
|
networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
|
networkDefaultPayloadLengthExtraBytes)
|
||||||
from helper_sql import (
|
from helper_sql import (
|
||||||
SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure, sql_ready)
|
SqlBulkExecute, sqlExecute, sqlQuery, sqlStoredProcedure, sql_ready)
|
||||||
from highlevelcrypto import calculateInventoryHash
|
from highlevelcrypto import calculateInventoryHash
|
||||||
|
@ -657,13 +659,11 @@ class BMRPCDispatcher(object):
|
||||||
nonceTrialsPerByte = self.config.get(
|
nonceTrialsPerByte = self.config.get(
|
||||||
'bitmessagesettings', 'defaultnoncetrialsperbyte'
|
'bitmessagesettings', 'defaultnoncetrialsperbyte'
|
||||||
) if not totalDifficulty else int(
|
) if not totalDifficulty else int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
||||||
* totalDifficulty)
|
|
||||||
payloadLengthExtraBytes = self.config.get(
|
payloadLengthExtraBytes = self.config.get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes'
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes'
|
||||||
) if not smallMessageDifficulty else int(
|
) if not smallMessageDifficulty else int(
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes
|
networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
|
||||||
* smallMessageDifficulty)
|
|
||||||
|
|
||||||
if not isinstance(eighteenByteRipe, bool):
|
if not isinstance(eighteenByteRipe, bool):
|
||||||
raise APIError(
|
raise APIError(
|
||||||
|
@ -705,13 +705,11 @@ class BMRPCDispatcher(object):
|
||||||
nonceTrialsPerByte = self.config.get(
|
nonceTrialsPerByte = self.config.get(
|
||||||
'bitmessagesettings', 'defaultnoncetrialsperbyte'
|
'bitmessagesettings', 'defaultnoncetrialsperbyte'
|
||||||
) if not totalDifficulty else int(
|
) if not totalDifficulty else int(
|
||||||
defaults.networkDefaultProofOfWorkNonceTrialsPerByte
|
networkDefaultProofOfWorkNonceTrialsPerByte * totalDifficulty)
|
||||||
* totalDifficulty)
|
|
||||||
payloadLengthExtraBytes = self.config.get(
|
payloadLengthExtraBytes = self.config.get(
|
||||||
'bitmessagesettings', 'defaultpayloadlengthextrabytes'
|
'bitmessagesettings', 'defaultpayloadlengthextrabytes'
|
||||||
) if not smallMessageDifficulty else int(
|
) if not smallMessageDifficulty else int(
|
||||||
defaults.networkDefaultPayloadLengthExtraBytes
|
networkDefaultPayloadLengthExtraBytes * smallMessageDifficulty)
|
||||||
* smallMessageDifficulty)
|
|
||||||
|
|
||||||
if not passphrase:
|
if not passphrase:
|
||||||
raise APIError(1, 'The specified passphrase is blank.')
|
raise APIError(1, 'The specified passphrase is blank.')
|
||||||
|
@ -1284,46 +1282,53 @@ class BMRPCDispatcher(object):
|
||||||
})
|
})
|
||||||
return {'subscriptions': data}
|
return {'subscriptions': data}
|
||||||
|
|
||||||
@command('disseminatePreEncryptedMsg')
|
@command('disseminatePreEncryptedMsg', 'disseminatePreparedObject')
|
||||||
def HandleDisseminatePreEncryptedMsg(
|
def HandleDisseminatePreparedObject(
|
||||||
self, encryptedPayload, requiredAverageProofOfWorkNonceTrialsPerByte,
|
self, encryptedPayload,
|
||||||
requiredPayloadLengthExtraBytes):
|
nonceTrialsPerByte=networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
"""Handle a request to disseminate an encrypted message"""
|
payloadLengthExtraBytes=networkDefaultPayloadLengthExtraBytes
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Handle a request to disseminate an encrypted message.
|
||||||
|
|
||||||
# The device issuing this command to PyBitmessage supplies a msg
|
The device issuing this command to PyBitmessage supplies an object
|
||||||
# object that has already been encrypted but which still needs the POW
|
that has already been encrypted but which may still need the PoW
|
||||||
# to be done. PyBitmessage accepts this msg object and sends it out
|
to be done. PyBitmessage accepts this object and sends it out
|
||||||
# to the rest of the Bitmessage network as if it had generated
|
to the rest of the Bitmessage network as if it had generated
|
||||||
# the message itself. Please do not yet add this to the api doc.
|
the message itself.
|
||||||
encryptedPayload = b'\x00' * 8 + self._decode(encryptedPayload, "hex")
|
|
||||||
# compatibility stub ^, since disseminatePreEncryptedMsg
|
*encryptedPayload* is a hex encoded string starting with the nonce,
|
||||||
# still expects the encryptedPayload without a nonce
|
8 zero bytes in case of no PoW done.
|
||||||
|
"""
|
||||||
|
encryptedPayload = self._decode(encryptedPayload, "hex")
|
||||||
|
|
||||||
|
nonce, = unpack('>Q', encryptedPayload[:8])
|
||||||
objectType, toStreamNumber, expiresTime = \
|
objectType, toStreamNumber, expiresTime = \
|
||||||
protocol.decodeObjectParameters(encryptedPayload)
|
protocol.decodeObjectParameters(encryptedPayload)
|
||||||
|
|
||||||
|
if nonce == 0: # Let us do the POW and attach it to the front
|
||||||
encryptedPayload = encryptedPayload[8:]
|
encryptedPayload = encryptedPayload[8:]
|
||||||
TTL = expiresTime - time.time() + 300 # a bit of extra padding
|
TTL = expiresTime - time.time() + 300 # a bit of extra padding
|
||||||
# Let us do the POW and attach it to the front
|
# Let us do the POW and attach it to the front
|
||||||
target = 2**64 / (
|
|
||||||
requiredAverageProofOfWorkNonceTrialsPerByte * (
|
|
||||||
len(encryptedPayload) + 8
|
|
||||||
+ requiredPayloadLengthExtraBytes + ((
|
|
||||||
TTL * (
|
|
||||||
len(encryptedPayload) + 8
|
|
||||||
+ requiredPayloadLengthExtraBytes
|
|
||||||
)) / (2 ** 16))
|
|
||||||
))
|
|
||||||
logger.debug("expiresTime: %s", expiresTime)
|
logger.debug("expiresTime: %s", expiresTime)
|
||||||
logger.debug("TTL: %s", TTL)
|
logger.debug("TTL: %s", TTL)
|
||||||
logger.debug("objectType: %s", objectType)
|
logger.debug("objectType: %s", objectType)
|
||||||
logger.info(
|
logger.info(
|
||||||
'(For msg message via API) Doing proof of work. Total required'
|
'(For msg message via API) Doing proof of work. Total required'
|
||||||
' difficulty: %s\nRequired small message difficulty: %s',
|
' difficulty: %s\nRequired small message difficulty: %s',
|
||||||
float(requiredAverageProofOfWorkNonceTrialsPerByte)
|
float(nonceTrialsPerByte)
|
||||||
/ defaults.networkDefaultProofOfWorkNonceTrialsPerByte,
|
/ networkDefaultProofOfWorkNonceTrialsPerByte,
|
||||||
float(requiredPayloadLengthExtraBytes)
|
float(payloadLengthExtraBytes)
|
||||||
/ defaults.networkDefaultPayloadLengthExtraBytes,
|
/ networkDefaultPayloadLengthExtraBytes,
|
||||||
)
|
)
|
||||||
powStartTime = time.time()
|
powStartTime = time.time()
|
||||||
|
target = 2**64 / (
|
||||||
|
nonceTrialsPerByte * (
|
||||||
|
len(encryptedPayload) + 8 + payloadLengthExtraBytes + ((
|
||||||
|
TTL * (
|
||||||
|
len(encryptedPayload) + 8 + payloadLengthExtraBytes
|
||||||
|
)) / (2 ** 16))
|
||||||
|
))
|
||||||
initialHash = hashlib.sha512(encryptedPayload).digest()
|
initialHash = hashlib.sha512(encryptedPayload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -1333,6 +1338,7 @@ class BMRPCDispatcher(object):
|
||||||
nonce / (time.time() - powStartTime)
|
nonce / (time.time() - powStartTime)
|
||||||
)
|
)
|
||||||
encryptedPayload = pack('>Q', nonce) + encryptedPayload
|
encryptedPayload = pack('>Q', nonce) + encryptedPayload
|
||||||
|
|
||||||
inventoryHash = calculateInventoryHash(encryptedPayload)
|
inventoryHash = calculateInventoryHash(encryptedPayload)
|
||||||
Inventory()[inventoryHash] = (
|
Inventory()[inventoryHash] = (
|
||||||
objectType, toStreamNumber, encryptedPayload,
|
objectType, toStreamNumber, encryptedPayload,
|
||||||
|
@ -1365,8 +1371,8 @@ class BMRPCDispatcher(object):
|
||||||
|
|
||||||
# Let us do the POW
|
# Let us do the POW
|
||||||
target = 2 ** 64 / ((
|
target = 2 ** 64 / ((
|
||||||
len(payload) + defaults.networkDefaultPayloadLengthExtraBytes + 8
|
len(payload) + networkDefaultPayloadLengthExtraBytes + 8
|
||||||
) * defaults.networkDefaultProofOfWorkNonceTrialsPerByte)
|
) * networkDefaultProofOfWorkNonceTrialsPerByte)
|
||||||
logger.info('(For pubkey message via API) Doing proof of work...')
|
logger.info('(For pubkey message via API) Doing proof of work...')
|
||||||
initialHash = hashlib.sha512(payload).digest()
|
initialHash = hashlib.sha512(payload).digest()
|
||||||
trialValue, nonce = proofofwork.run(target, initialHash)
|
trialValue, nonce = proofofwork.run(target, initialHash)
|
||||||
|
|
|
@ -20,11 +20,11 @@ sample_addr_data = unhexlify(
|
||||||
|
|
||||||
# These keys are from addresses test script
|
# These keys are from addresses test script
|
||||||
sample_pubsigningkey = unhexlify(
|
sample_pubsigningkey = unhexlify(
|
||||||
'044a367f049ec16cb6b6118eb734a9962d10b8db59c890cd08f210c43ff08bdf09d'
|
'044a367f049ec16cb6b6118eb734a9962d10b8db59c890cd08f210c43ff08bdf09'
|
||||||
'16f502ca26cd0713f38988a1237f1fc8fa07b15653c996dc4013af6d15505ce')
|
'd16f502ca26cd0713f38988a1237f1fc8fa07b15653c996dc4013af6d15505ce')
|
||||||
sample_pubencryptionkey = unhexlify(
|
sample_pubencryptionkey = unhexlify(
|
||||||
'044597d59177fc1d89555d38915f581b5ff2286b39d022ca0283d2bdd5c36be5d3c'
|
'044597d59177fc1d89555d38915f581b5ff2286b39d022ca0283d2bdd5c36be5d3'
|
||||||
'e7b9b97792327851a562752e4b79475d1f51f5a71352482b241227f45ed36a9')
|
'ce7b9b97792327851a562752e4b79475d1f51f5a71352482b241227f45ed36a9')
|
||||||
sample_privsigningkey = \
|
sample_privsigningkey = \
|
||||||
b'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665'
|
b'93d0b61371a54b53df143b954035d612f8efa8a3ed1cf842c2186bfd8f876665'
|
||||||
sample_privencryptionkey = \
|
sample_privencryptionkey = \
|
||||||
|
|
|
@ -8,9 +8,7 @@ from struct import pack
|
||||||
from six.moves import queue, xmlrpc_client
|
from six.moves import queue, xmlrpc_client
|
||||||
|
|
||||||
from pybitmessage import protocol
|
from pybitmessage import protocol
|
||||||
from pybitmessage.defaults import (
|
from pybitmessage.highlevelcrypto import calculateInventoryHash
|
||||||
networkDefaultProofOfWorkNonceTrialsPerByte,
|
|
||||||
networkDefaultPayloadLengthExtraBytes)
|
|
||||||
|
|
||||||
from .partial import TestPartialRun
|
from .partial import TestPartialRun
|
||||||
from .samples import sample_statusbar_msg, sample_object_data
|
from .samples import sample_statusbar_msg, sample_object_data
|
||||||
|
@ -80,12 +78,14 @@ class TestAPIThread(TestPartialRun):
|
||||||
from inventory import Inventory
|
from inventory import Inventory
|
||||||
|
|
||||||
proofofwork.init()
|
proofofwork.init()
|
||||||
update_object = pack(
|
self.assertEqual(
|
||||||
|
unhexlify(self.api.disseminatePreparedObject(
|
||||||
|
hexlify(sample_object_data).decode())),
|
||||||
|
calculateInventoryHash(sample_object_data))
|
||||||
|
update_object = b'\x00' * 8 + pack(
|
||||||
'>Q', int(time.time() + 7200)) + sample_object_data[16:]
|
'>Q', int(time.time() + 7200)) + sample_object_data[16:]
|
||||||
invhash = unhexlify(self.api.disseminatePreEncryptedMsg(
|
invhash = unhexlify(self.api.disseminatePreEncryptedMsg(
|
||||||
hexlify(update_object).decode(),
|
hexlify(update_object).decode()
|
||||||
networkDefaultProofOfWorkNonceTrialsPerByte,
|
|
||||||
networkDefaultPayloadLengthExtraBytes
|
|
||||||
))
|
))
|
||||||
obj_type, obj_stream, obj_data = Inventory()[invhash][:3]
|
obj_type, obj_stream, obj_data = Inventory()[invhash][:3]
|
||||||
self.assertEqual(obj_type, 42)
|
self.assertEqual(obj_type, 42)
|
||||||
|
|
Reference in New Issue
Block a user