main.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import sys
  2. from collections import namedtuple
  3. from classnamespace import ClassNamespace
  4. from crypto import pallas_curve
  5. class TransactionBuilder:
  6. def __init__(self, ec):
  7. self.clear_inputs = []
  8. self.inputs = []
  9. self.outputs = []
  10. self.ec = ec
  11. def add_clear_input(self, value, token_id, signature_secret):
  12. clear_input = ClassNamespace()
  13. clear_input.value = value
  14. clear_input.token_id = token_id
  15. clear_input.signature_secret = signature_secret
  16. self.clear_inputs.append(clear_input)
  17. def add_input(self, input):
  18. self.inputs.append(input)
  19. def add_output(self, value, token_id, public):
  20. output = ClassNamespace()
  21. output.value = value
  22. output.token_id = token_id
  23. output.public = public
  24. self.outputs.append(output)
  25. def compute_remainder_blind(self, clear_inputs, input_blinds,
  26. output_blinds):
  27. total = 0
  28. total += sum(input.value_blind for input in clear_inputs)
  29. total += sum(input_blinds)
  30. total -= sum(output_blinds)
  31. return total % self.ec.order
  32. def build(self):
  33. tx = Transaction()
  34. token_blind = self.ec.random_scalar()
  35. for input in self.clear_inputs:
  36. tx_clear_input = ClassNamespace()
  37. tx_clear_input.value = input.value
  38. tx_clear_input.token_id = input.token_id
  39. tx_clear_input.value_blind = self.ec.random_scalar()
  40. tx_clear_input.token_blind = input.token_blind
  41. tx_clear_input.signature_public = self.ec.multiply(
  42. input.signature_secret, self.ec.G)
  43. tx.clear_inputs.append(tx_clear_input)
  44. input_blinds = []
  45. for input in self.inputs:
  46. tx_input = ClassNamespace()
  47. tx.inputs.append(tx_input)
  48. assert self.outputs
  49. output_blinds = []
  50. for i, output in enumerate(self.outputs):
  51. if i == len(self.outputs) - 1:
  52. value_blind = self.compute_remainder_blind(
  53. tx.clear_inputs, input_blinds, output_blinds)
  54. else:
  55. value_blind = self.ec.random_scalar()
  56. output_blinds.append(value_blind)
  57. note = ClassNamespace()
  58. note.serial = self.ec.random_base()
  59. note.value = output.value
  60. note.token_id = output.token_id
  61. note.coin_blind = self.ec.random_base()
  62. note.value_blind = value_blind
  63. tx_output = ClassNamespace()
  64. tx_output.mint_proof = MintProof(
  65. note.value, note.token_id, note.value_blind,
  66. token_blind, tx_output.serial, coin_blind, public)
  67. tx_output.revealed = tx_output.mint_proof.get_revealed()
  68. # Is normally encrypted
  69. tx_output.enc_note = note
  70. tx.outputs.append(tx_output)
  71. return tx
  72. class MintProof:
  73. def __init__(self, value, token_id, value_blind, token_blind, serial,
  74. coin_blind, public):
  75. self.value = value
  76. self.token_id = token_id
  77. self.value_blind = value_blind
  78. self.token_blind = token_blind
  79. self.serial = serial
  80. self.coin_blind = coin_blind
  81. self.public = public
  82. def get_revealed(self):
  83. revealed = ClassNamespace()
  84. return revealed
  85. def verify(self):
  86. pass
  87. class Transaction:
  88. def __init__(self):
  89. self.clear_inputs = []
  90. self.inputs = []
  91. self.outputs = []
  92. def main(argv):
  93. ec = pallas_curve()
  94. builder = TransactionBuilder(ec)
  95. builder.add_output(44, 110, "1234")
  96. tx = builder.build()
  97. if __name__ == "__main__":
  98. sys.exit(main(sys.argv))