qp_node.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. from dht_common import SIZE_OF_HASH, SIZE_OF_IP_ADDRESS, SIZE_OF_OT_VALUE, SIZE_OF_KEY, SIZE_OF_SIGNATURE, SIZE_OF_TIMESTAMP
  2. from rcp_node import RCP_Quorum
  3. from collections import defaultdict
  4. class QP_Quorum(RCP_Quorum):
  5. def __init__(self, quorumID, documentSize, numNodes, numItems=0, table=[]):
  6. RCP_Quorum.__init__(self, quorumID, documentSize, numNodes, numItems, table)
  7. self.fingerTableRangeAccesses = [defaultdict(lambda: 0) for i in range(self.numNodes)]
  8. self.fingerTableAccesses = [defaultdict(lambda: 0) for i in range(self.numNodes)]
  9. def get_finger_table_range_accesses(self, whichNode):
  10. return self.fingerTableRangeAccesses[whichNode]
  11. def get_finger_table_accesses(self, whichNode):
  12. return self.fingerTableAccesses[whichNode]
  13. # This shouldn't be used, just here to make sure you don't try the RCP_Quorum function it overrides
  14. def get_finger_table_val(self):
  15. return None
  16. def get_finger_table_ranges(self, whichNode, numKeys, numSignatures):
  17. numEntries = len(self.table.items())
  18. retval = (list(self.table.keys()), numEntries)
  19. # Asker's ID
  20. sizeOfRequest = SIZE_OF_HASH
  21. # timestamp
  22. sizeOfRequest += SIZE_OF_TIMESTAMP
  23. # keys in request
  24. sizeOfRequest += SIZE_OF_KEY * numKeys
  25. # signatures in request
  26. sizeOfRequest += SIZE_OF_SIGNATURE * numSignatures
  27. # The set of hashes in the finger table
  28. sizeOfResponse = SIZE_OF_HASH * numEntries
  29. # Then the entrywise encrypted finger table routing information
  30. sizeOfResponse += (SIZE_OF_IP_ADDRESS * self.numNodes + SIZE_OF_KEY) * numEntries
  31. # Then the OT prime values
  32. sizeOfResponse += 2 * SIZE_OF_OT_VALUE * numEntries
  33. # Then, finally, a signature to tie it together
  34. sizeOfResponse += SIZE_OF_SIGNATURE
  35. self.nodeNumRounds[whichNode] += 1
  36. self.nodeNumMessagesSent[whichNode] += 1
  37. self.nodeNumMessagesRecv[whichNode] += 1
  38. self.nodeNumBytesSent[whichNode] += sizeOfResponse
  39. self.nodeNumBytesRecv[whichNode] += sizeOfRequest
  40. self.fingerTableRangeAccesses[whichNode][numEntries] += 1
  41. return retval
  42. def OT_get_finger_table_val(self, whichNode, index):
  43. numEntries = len(self.table.items())
  44. retval = self.table[index]
  45. # OT prime value to be able to open one of the entries in the finger table
  46. sizeOfRequest = SIZE_OF_OT_VALUE
  47. # And a signature to confirm it's valid
  48. sizeOfRequest += SIZE_OF_SIGNATURE
  49. # The final OT prime value
  50. sizeOfResponse = SIZE_OF_OT_VALUE
  51. # And a signature to boot
  52. sizeOfResponse += SIZE_OF_SIGNATURE
  53. self.nodeNumRounds[whichNode] += 1
  54. self.nodeNumMessagesSent[whichNode] += 1
  55. self.nodeNumMessagesRecv[whichNode] += 1
  56. self.nodeNumBytesSent[whichNode] += sizeOfResponse
  57. self.nodeNumBytesRecv[whichNode] += sizeOfRequest
  58. self.fingerTableAccesses[whichNode][numEntries] += 1
  59. return retval
  60. # TODO: Add unit tests for size calculations
  61. # TODO: Add unit test to make sure finger_table_ranges/OT_val is still firing correctly?
  62. if __name__ == "__main__":
  63. SIZE_OF_DOCUMENTS_IN_TEST = 1024
  64. NUM_NODES_PER_QUORUM_IN_TEST = 10
  65. test = QP_Quorum(0, SIZE_OF_DOCUMENTS_IN_TEST, NUM_NODES_PER_QUORUM_IN_TEST)
  66. randomNode = 0
  67. [test.insert() for x in range(NUM_NODES_PER_QUORUM_IN_TEST)]
  68. [test.retrieve(randomNode) for x in range(NUM_NODES_PER_QUORUM_IN_TEST)]
  69. print("Insert and retrieval on node 0 fires correctly.")
  70. [test.retrieve(x) for x in range(NUM_NODES_PER_QUORUM_IN_TEST)]
  71. print("Retrieval fires on all nodes correctly.")