utils.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import random
  2. import joblib
  3. import pickle
  4. def extended_euclidean_algorithm(a, b):
  5. """
  6. Returns a three-tuple (gcd, x, y) such that
  7. a * x + b * y == gcd, where gcd is the greatest
  8. common divisor of a and b.
  9. This function implements the extended Euclidean
  10. algorithm and runs in O(log b) in the worst case.
  11. """
  12. s, old_s = 0, 1
  13. t, old_t = 1, 0
  14. r, old_r = b, a
  15. while r != 0:
  16. quotient = old_r // r
  17. old_r, r = r, old_r - quotient * r
  18. old_s, s = s, old_s - quotient * s
  19. old_t, t = t, old_t - quotient * t
  20. return old_r, old_s, old_t
  21. def inverse_of(n, p):
  22. """
  23. Returns the multiplicative inverse of
  24. n modulo p.
  25. This function returns an integer m such that
  26. (n * m) % p == 1.
  27. """
  28. gcd, x, y = extended_euclidean_algorithm(n, p)
  29. assert (n * x + p * y) % p == gcd
  30. if gcd != 1:
  31. # Either n is 0, or p is not a prime number.
  32. raise ValueError(
  33. '{} has no multiplicative inverse '
  34. 'modulo {}'.format(n, p))
  35. else:
  36. return x % p
  37. '''
  38. @param nums: list of weight
  39. @param true_rnd_fn: truely random function
  40. @return zero-based index of the truely selected element
  41. '''
  42. def weighted_random(nums, true_rnd_fn=random.random):
  43. """
  44. nums is list of weight, it return the truely random
  45. weighted value.
  46. """
  47. L = len(nums)
  48. pair = [(i, nums[i]) for i in range(L)]
  49. pair.sort(key=lambda p: p[1])
  50. tot = sum([pair[i][1] for i in range(L)])
  51. frequency = [pair[i][1]/tot for i in range(L)]
  52. acc_prop = [sum(frequency[:i+1]) for i in range(L)]
  53. rnd = true_rnd_fn()
  54. for elected in range(L):
  55. if rnd<=acc_prop[elected]:
  56. break
  57. return pair[elected][0]
  58. '''
  59. @param data: data is dictionary of list of (pk_i, s_i) public key,
  60. and stake respectively of the corresponding stakeholder U_i,
  61. seed of the leader election function.
  62. '''
  63. def encode_genesis_data(data):
  64. return pickle.dumps(data)
  65. def decode_gensis_data(encoded_data):
  66. return pickle.loads(encoded_data)
  67. '''
  68. TODO this is a adhoc solution
  69. this has is used to compute the state of block from the previous block
  70. '''
  71. def state_hash(obj):
  72. return hash(obj)
  73. '''
  74. TODO this is a adhoc solution
  75. this is used to generate VRF's sk from some seed
  76. note there is a need for nounce to be concatenated with the seed,
  77. just in case two stakeholders started with the same seed
  78. (for the time being the seed is provided by the stakeholder, it's stakeholder passowrd)
  79. '''
  80. def vrf_hash(seed):
  81. return hash(seed)