vm_export_supervisor.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import struct
  2. from vm import VariableType, VariableRefType
  3. class Operation:
  4. def __init__(self, ident, args):
  5. self.ident = ident
  6. self.args = args
  7. class ArgVarRef:
  8. def __init__(self, type, index):
  9. self.type = type
  10. self.index = index
  11. def bytes(self):
  12. return struct.pack("<BI", self.type, self.index)
  13. class ArgVarIndex:
  14. def __init__(self, _, index):
  15. self.index = index
  16. def bytes(self):
  17. return struct.pack("<I", self.index)
  18. class ArgString:
  19. def __init__(self, description, index):
  20. self.description = description
  21. self.index = index
  22. ops_table = {
  23. "set": Operation(0, [ArgVarRef, ArgVarRef]),
  24. "mul": Operation(1, [ArgVarRef, ArgVarRef]),
  25. "add": Operation(2, [ArgVarRef, ArgVarRef]),
  26. "sub": Operation(3, [ArgVarRef, ArgVarRef]),
  27. "divide": Operation(4, [ArgVarRef, ArgVarRef]),
  28. "double": Operation(5, [ArgVarRef]),
  29. "square": Operation(6, [ArgVarRef]),
  30. "invert": Operation(7, [ArgVarRef]),
  31. "unpack_bits": Operation(8, [ArgVarRef, ArgVarRef, ArgVarRef]),
  32. "local": Operation(9, []),
  33. "load": Operation(10, [ArgVarRef, ArgVarIndex]),
  34. "debug": Operation(11, [ArgString, ArgVarRef]),
  35. "dump_alloc": Operation(12, []),
  36. "dump_local": Operation(13, []),
  37. }
  38. constraint_ident_map = {
  39. "lc0_add": 0,
  40. "lc1_add": 1,
  41. "lc2_add": 2,
  42. "lc0_sub": 3,
  43. "lc1_sub": 4,
  44. "lc2_sub": 5,
  45. "lc0_add_one": 6,
  46. "lc1_add_one": 7,
  47. "lc2_add_one": 8,
  48. "lc0_sub_one": 9,
  49. "lc1_sub_one": 10,
  50. "lc2_sub_one": 11,
  51. "lc0_add_coeff": 12,
  52. "lc1_add_coeff": 13,
  53. "lc2_add_coeff": 14,
  54. "lc0_add_one_coeff": 15,
  55. "lc1_add_one_coeff": 16,
  56. "lc2_add_one_coeff": 17,
  57. "enforce": 18,
  58. "lc_coeff_reset": 19,
  59. "lc_coeff_double": 20,
  60. }
  61. def varuint(value):
  62. if value <= 0xfc:
  63. return struct.pack("<B", value)
  64. elif value <= 0xffff:
  65. return struct.pack("<BH", 0xfd, value)
  66. elif value <= 0xffffffff:
  67. return struct.pack("<BI", 0xfe, value)
  68. else:
  69. return struct.pack("<BQ", 0xff, value)
  70. def export(output, contract_name, contract):
  71. output.write(varuint(len(contract_name)))
  72. output.write(contract_name.encode())
  73. constants = list(contract.constants.items())
  74. constants.sort(key=lambda obj: obj[1][0])
  75. constants = [(obj[0], obj[1][1]) for obj in constants]
  76. output.write(varuint(len(constants)))
  77. for symbol, value in constants:
  78. print("Constant '%s' = %s" % (symbol, value))
  79. # Bellman uses little endian for Scalars from_bytes function
  80. const_bytes = bytearray.fromhex(value)[::-1]
  81. assert len(const_bytes) == 32
  82. output.write(const_bytes)
  83. output.write(varuint(len(contract.alloc)))
  84. for symbol, variable in contract.alloc.items():
  85. print("Alloc '%s' = (%s, %s)" % (symbol,
  86. variable.type.name, variable.index))
  87. if variable.type.name == VariableType.PRIVATE.name:
  88. typeval = 0
  89. elif variable.type.name == VariableType.PUBLIC.name:
  90. typeval = 1
  91. else:
  92. assert False
  93. alloc_bytes = struct.pack("<BI", typeval, variable.index)
  94. assert len(alloc_bytes) == 5
  95. output.write(alloc_bytes)
  96. output.write(varuint(len(contract.ops)))
  97. for op in contract.ops:
  98. op_form = ops_table[op.command]
  99. output.write(struct.pack("B", op_form.ident))
  100. if op.command == "debug":
  101. # Special case
  102. assert len(op.args) == 1
  103. line_str = str(op.line).encode()
  104. output.write(varuint(len(line_str)))
  105. output.write(line_str)
  106. op_arg = op.args[0]
  107. if op_arg.type.name == VariableRefType.AUX.name:
  108. arg_type = 0
  109. elif op_arg.type.name == VariableRefType.LOCAL.name:
  110. arg_type = 1
  111. arg = ArgVarRef(arg_type, op_arg.index)
  112. output.write(arg.bytes())
  113. continue
  114. assert len(op_form.args) == len(op.args)
  115. for arg_form, op_arg in zip(op_form.args, op.args):
  116. if op_arg.type.name == VariableRefType.AUX.name:
  117. arg_type = 0
  118. elif op_arg.type.name == VariableRefType.LOCAL.name:
  119. arg_type = 1
  120. arg = arg_form(arg_type, op_arg.index)
  121. output.write(arg.bytes())
  122. print("Operation", op.command,
  123. [(arg.type.name, arg.index) for arg in op.args])
  124. output.write(varuint(len(contract.constraints)))
  125. for constraint in contract.constraints:
  126. args = constraint.args[:]
  127. if (constraint.command == "lc0_add_coeff" or
  128. constraint.command == "lc1_add_coeff" or
  129. constraint.command == "lc2_add_coeff" or
  130. constraint.command == "lc0_add_one_coeff" or
  131. constraint.command == "lc1_add_one_coeff" or
  132. constraint.command == "lc2_add_one_coeff"):
  133. args[0] = args[0][0]
  134. print("Constraint", constraint.command, args)
  135. enum_ident = constraint_ident_map[constraint.command]
  136. output.write(struct.pack("B", enum_ident))
  137. for arg in args:
  138. output.write(struct.pack("<I", arg))