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