gentest.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. from eth_abi import encode_single, encode_abi
  2. import sys
  3. import string
  4. import pprint
  5. import time
  6. from Cryptodome.Hash import keccak
  7. import coincurve
  8. import base64
  9. import random
  10. from algosdk.encoding import decode_address
  11. class GenTest:
  12. def __init__(self, bigSet) -> None:
  13. if bigSet:
  14. self.guardianKeys = [
  15. "52A26Ce40F8CAa8D36155d37ef0D5D783fc614d2",
  16. "389A74E8FFa224aeAD0778c786163a7A2150768C",
  17. "B4459EA6482D4aE574305B239B4f2264239e7599",
  18. "072491bd66F63356090C11Aae8114F5372aBf12B",
  19. "51280eA1fd2B0A1c76Ae29a7d54dda68860A2bfF",
  20. "fa9Aa60CfF05e20E2CcAA784eE89A0A16C2057CB",
  21. "e42d59F8FCd86a1c5c4bA351bD251A5c5B05DF6A",
  22. "4B07fF9D5cE1A6ed58b6e9e7d6974d1baBEc087e",
  23. "c8306B84235D7b0478c61783C50F990bfC44cFc0",
  24. "C8C1035110a13fe788259A4148F871b52bAbcb1B",
  25. "58A2508A20A7198E131503ce26bBE119aA8c62b2",
  26. "8390820f04ddA22AFe03be1c3bb10f4ba6CF94A0",
  27. "1FD6e97387C34a1F36DE0f8341E9D409E06ec45b",
  28. "255a41fC2792209CB998A8287204D40996df9E54",
  29. "bA663B12DD23fbF4FbAC618Be140727986B3BBd0",
  30. "79040E577aC50486d0F6930e160A5C75FD1203C6",
  31. "3580D2F00309A9A85efFAf02564Fc183C0183A96",
  32. "3869795913D3B6dBF3B24a1C7654672c69A23c35",
  33. "1c0Cc52D7673c52DE99785741344662F5b2308a0",
  34. ]
  35. self.guardianPrivKeys = [
  36. "563d8d2fd4e701901d3846dee7ae7a92c18f1975195264d676f8407ac5976757",
  37. "8d97f25916a755df1d9ef74eb4dbebc5f868cb07830527731e94478cdc2b9d5f",
  38. "9bd728ad7617c05c31382053b57658d4a8125684c0098f740a054d87ddc0e93b",
  39. "5a02c4cd110d20a83a7ce8d1a2b2ae5df252b4e5f6781c7855db5cc28ed2d1b4",
  40. "93d4e3b443bf11f99a00901222c032bd5f63cf73fc1bcfa40829824d121be9b2",
  41. "ea40e40c63c6ff155230da64a2c44fcd1f1c9e50cacb752c230f77771ce1d856",
  42. "87eaabe9c27a82198e618bca20f48f9679c0f239948dbd094005e262da33fe6a",
  43. "61ffed2bff38648a6d36d6ed560b741b1ca53d45391441124f27e1e48ca04770",
  44. "bd12a242c6da318fef8f98002efb98efbf434218a78730a197d981bebaee826e",
  45. "20d3597bb16525b6d09e5fb56feb91b053d961ab156f4807e37d980f50e71aff",
  46. "344b313ffbc0199ff6ca08cacdaf5dc1d85221e2f2dc156a84245bd49b981673",
  47. "848b93264edd3f1a521274ca4da4632989eb5303fd15b14e5ec6bcaa91172b05",
  48. "c6f2046c1e6c172497fc23bd362104e2f4460d0f61984938fa16ef43f27d93f6",
  49. "693b256b1ee6b6fb353ba23274280e7166ab3be8c23c203cc76d716ba4bc32bf",
  50. "13c41508c0da03018d61427910b9922345ced25e2bbce50652e939ee6e5ea56d",
  51. "460ee0ee403be7a4f1eb1c63dd1edaa815fbaa6cf0cf2344dcba4a8acf9aca74",
  52. "b25148579b99b18c8994b0b86e4dd586975a78fa6e7ad6ec89478d7fbafd2683",
  53. "90d7ac6a82166c908b8cf1b352f3c9340a8d1f2907d7146fb7cd6354a5436cca",
  54. "b71d23908e4cf5d6cd973394f3a4b6b164eb1065785feee612efdfd8d30005ed",
  55. ]
  56. else:
  57. self.guardianKeys = [
  58. "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe"
  59. ]
  60. self.guardianPrivKeys = [
  61. "cfb12303a19cde580bb4dd771639b0d26bc68353645571a8cff516ab2ee113a0"
  62. ]
  63. self.zeroPadBytes = "00"*64
  64. def encoder(self, type, val):
  65. if type == 'uint8':
  66. return encode_single(type, val).hex()[62:64]
  67. if type == 'uint16':
  68. return encode_single(type, val).hex()[60:64]
  69. if type == 'uint32':
  70. return encode_single(type, val).hex()[56:64]
  71. if type == 'uint64':
  72. return encode_single(type, val).hex()[64-(16):64]
  73. if type == 'uint128':
  74. return encode_single(type, val).hex()[64-(32):64]
  75. if type == 'uint256' or type == 'bytes32':
  76. return encode_single(type, val).hex()[64-(64):64]
  77. raise Exception("invalid type")
  78. def createTrashVAA(self, guardianSetIndex, ts, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, target, payload, version=1):
  79. return self.createSignedVAA(
  80. guardianSetIndex,
  81. # set the minimum amount of trash as signature for this to pass validations
  82. [random.randbytes(32).hex() for _ in range(int(len(self.guardianKeys)*2/3)+1)],
  83. ts,
  84. nonce,
  85. emitterChainId,
  86. emitterAddress,
  87. sequence,
  88. consistencyLevel,
  89. target,
  90. payload,
  91. version
  92. )
  93. def createSignedVAA(self, guardianSetIndex, signers, ts, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, target, payload, version=1):
  94. b = ""
  95. b += self.encoder("uint32", ts)
  96. b += self.encoder("uint32", nonce)
  97. b += self.encoder("uint16", emitterChainId)
  98. b += self.encoder("bytes32", emitterAddress)
  99. b += self.encoder("uint64", sequence)
  100. b += self.encoder("uint8", consistencyLevel)
  101. b += payload
  102. hash = keccak.new(digest_bits=256).update(keccak.new(digest_bits=256).update(bytes.fromhex(b)).digest()).digest()
  103. signatures = ""
  104. for i in range(len(signers)):
  105. signatures += self.encoder("uint8", i)
  106. key = coincurve.PrivateKey(bytes.fromhex(signers[i]))
  107. signature = key.sign_recoverable(hash, hasher=None)
  108. signatures += signature.hex()
  109. ret = self.encoder("uint8", version)
  110. ret += self.encoder("uint32", guardianSetIndex)
  111. ret += self.encoder("uint8", len(signers))
  112. ret += signatures
  113. ret += b
  114. print(ret)
  115. return ret
  116. def createValidRandomSignedVAA(self, guardianSetIndex, signers, sequence):
  117. ts = random.randint(0, 2**32-1)
  118. nonce = random.randint(0, 2**32-1)
  119. emitterChainId = random.randint(0, 2**16-1)
  120. emitterAddress = random.randbytes(32)
  121. consitencyLevel = random.randint(0, 2**8-1)
  122. payload = self.createRandomValidPayload().hex()
  123. return self.createSignedVAA(
  124. guardianSetIndex, # guardian set index needs to be fixed so contract knows where to look into
  125. signers,
  126. ts,
  127. nonce,
  128. emitterChainId,
  129. emitterAddress,
  130. sequence,
  131. consitencyLevel,
  132. 0, #target = not used?
  133. payload,
  134. 1, # only version 1 VAA
  135. )
  136. def createRandomValidPayload(self):
  137. action = (0x03).to_bytes(1, byteorder="big")
  138. # action = random.choice([0x01, 0x03]).to_bytes(1, byteorder="big")
  139. amount = random.randint(0, 2**128-1).to_bytes(32, byteorder="big")
  140. # TODO: we should support more addresses than this one, but this
  141. # is hardcoded in the tests and probably used in the deploy, so we
  142. # will make do. same goes for the token_address
  143. some_token_address = b"4523c3F29447d1f32AEa95BEBD00383c4640F1b4"
  144. tokenAddress = some_token_address
  145. # TODO: same goes for the token chain, just use what's available for now
  146. try:
  147. tokenChain = bytes.fromhex(self.getEmitter(1))
  148. except:
  149. raise
  150. to = random.randbytes(32)
  151. toChain = random.randint(0, 2**16-1).to_bytes(2, byteorder="big")
  152. payload = action + amount + tokenAddress + tokenChain + to + toChain
  153. if action == 0x01:
  154. fee = random.randint(0, 2**256-1).to_bytes(32, byteorder="big")
  155. payload += fee
  156. if action == 0x03:
  157. fromAddress = random.randbytes(2)
  158. arbitraryPayload = random.randbytes(random.randint(0,4))
  159. payload += fromAddress + arbitraryPayload
  160. return payload
  161. def createRandomSignedVAA(self, guardianSetIndex, signers):
  162. ts = random.randint(0, 2**32-1)
  163. nonce = random.randint(0, 2**32-1)
  164. emitterChainId = random.randint(0, 2**16-1)
  165. emitterAddress = random.randbytes(32)
  166. sequence = random.randint(0, 2**64-1)
  167. consitencyLevel = random.randint(0, 2**8-1)
  168. # payload = ''.join(random.choices(string.ascii_uppercase + string.digits, k=random.randint(0,500)))
  169. payload = random.randbytes(random.randint(0,496)).hex()
  170. version = random.randint(0,10)
  171. return self.createSignedVAA(
  172. guardianSetIndex, # guardian set index needs to be fixed so contract knows where to look into
  173. signers,
  174. ts,
  175. nonce,
  176. emitterChainId,
  177. emitterAddress,
  178. sequence,
  179. consitencyLevel,
  180. 0, #target = not used?
  181. payload,
  182. version,
  183. )
  184. def genGuardianSetUpgrade(self, signers, guardianSet, targetSet, nonce, seq):
  185. b = self.zeroPadBytes[0:(28*2)]
  186. b += self.encoder("uint8", ord("C"))
  187. b += self.encoder("uint8", ord("o"))
  188. b += self.encoder("uint8", ord("r"))
  189. b += self.encoder("uint8", ord("e"))
  190. b += self.encoder("uint8", 2)
  191. b += self.encoder("uint16", 0)
  192. b += self.encoder("uint32", targetSet)
  193. b += self.encoder("uint8", len(self.guardianKeys))
  194. for i in self.guardianKeys:
  195. b += i
  196. emitter = bytes.fromhex(self.zeroPadBytes[0:(31*2)] + "04")
  197. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  198. def genGSetFee(self, signers, guardianSet, nonce, seq, amt):
  199. b = self.zeroPadBytes[0:(28*2)]
  200. b += self.encoder("uint8", ord("C"))
  201. b += self.encoder("uint8", ord("o"))
  202. b += self.encoder("uint8", ord("r"))
  203. b += self.encoder("uint8", ord("e"))
  204. b += self.encoder("uint8", 3)
  205. b += self.encoder("uint16", 8)
  206. b += self.encoder("uint256", int(amt)) # a whole algo!
  207. emitter = bytes.fromhex(self.zeroPadBytes[0:(31*2)] + "04")
  208. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  209. def genGFeePayout(self, signers, guardianSet, targetSet, nonce, seq, amt, dest):
  210. b = self.zeroPadBytes[0:(28*2)]
  211. b += self.encoder("uint8", ord("C"))
  212. b += self.encoder("uint8", ord("o"))
  213. b += self.encoder("uint8", ord("r"))
  214. b += self.encoder("uint8", ord("e"))
  215. b += self.encoder("uint8", 4)
  216. b += self.encoder("uint16", 8)
  217. b += self.encoder("uint256", int(amt * 1000000))
  218. b += decode_address(dest).hex()
  219. emitter = bytes.fromhex(self.zeroPadBytes[0:(31*2)] + "04")
  220. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  221. def getEmitter(self, chain):
  222. if chain == 1:
  223. return "ec7372995d5cc8732397fb0ad35c0121e0eaa90d26f828a534cab54391b3a4f5"
  224. if chain == 2:
  225. return "0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585"
  226. if chain == 3:
  227. return "0000000000000000000000007cf7b764e38a0a5e967972c1df77d432510564e2"
  228. if chain == 4:
  229. return "000000000000000000000000b6f6d86a8f9879a9c87f643768d9efc38c1da6e7"
  230. if chain == 5:
  231. return "0000000000000000000000005a58505a96d1dbf8df91cb21b54419fc36e93fde"
  232. raise Exception("invalid chain")
  233. def genRegisterChain(self, signers, guardianSet, nonce, seq, chain, addr = None):
  234. b = self.zeroPadBytes[0:((32 -11)*2)]
  235. b += self.encoder("uint8", ord("T"))
  236. b += self.encoder("uint8", ord("o"))
  237. b += self.encoder("uint8", ord("k"))
  238. b += self.encoder("uint8", ord("e"))
  239. b += self.encoder("uint8", ord("n"))
  240. b += self.encoder("uint8", ord("B"))
  241. b += self.encoder("uint8", ord("r"))
  242. b += self.encoder("uint8", ord("i"))
  243. b += self.encoder("uint8", ord("d"))
  244. b += self.encoder("uint8", ord("g"))
  245. b += self.encoder("uint8", ord("e"))
  246. b += self.encoder("uint8", 1) # action
  247. b += self.encoder("uint16", 0) # target chain
  248. b += self.encoder("uint16", chain)
  249. if addr == None:
  250. b += self.getEmitter(chain)
  251. else:
  252. b += addr
  253. emitter = bytes.fromhex(self.zeroPadBytes[0:(31*2)] + "04")
  254. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  255. def genAssetMeta(self, signers, guardianSet, nonce, seq, tokenAddress, chain, decimals, symbol, name):
  256. b = self.encoder("uint8", 2)
  257. b += self.zeroPadBytes[0:((32-len(tokenAddress))*2)]
  258. b += tokenAddress.hex()
  259. b += self.encoder("uint16", chain)
  260. b += self.encoder("uint8", decimals)
  261. b += symbol.hex()
  262. b += self.zeroPadBytes[0:((32-len(symbol))*2)]
  263. b += name.hex()
  264. b += self.zeroPadBytes[0:((32-len(name))*2)]
  265. emitter = bytes.fromhex(self.getEmitter(chain))
  266. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  267. def genRandomValidTransfer(self,
  268. signers,
  269. guardianSet,
  270. seq,
  271. tokenAddress,
  272. toAddress,
  273. amount_max):
  274. amount = random.randint(0, int(amount_max / 100000000))
  275. fee = random.randint(0, amount) # fee must be lower than amount for VAA to be valid
  276. return self.genTransfer(
  277. signers=signers,
  278. guardianSet=guardianSet,
  279. nonce=random.randint(0, 2**32-1),
  280. seq=seq,
  281. # amount gets encoded as an uint256, but it's actually clearly
  282. # to only eight bytes. all other bytes _must_ be zero.
  283. amount=amount,
  284. # token address must be registed on the bridge
  285. tokenAddress=tokenAddress,
  286. # tokenAddress=random.randbytes(32),
  287. tokenChain=1,
  288. toAddress=toAddress,
  289. # must be directed at algorand chain
  290. toChain=8,
  291. # fee is in the same situation as amount
  292. fee=fee,
  293. )
  294. def genTransfer(self, signers, guardianSet, nonce, seq, amount, tokenAddress, tokenChain, toAddress, toChain, fee):
  295. b = self.encoder("uint8", 1)
  296. b += self.encoder("uint256", int(amount * 100000000))
  297. b += self.zeroPadBytes[0:((32-len(tokenAddress))*2)]
  298. b += tokenAddress.hex()
  299. b += self.encoder("uint16", tokenChain)
  300. b += self.zeroPadBytes[0:((32-len(toAddress))*2)]
  301. b += toAddress.hex()
  302. b += self.encoder("uint16", toChain)
  303. b += self.encoder("uint256", int(fee * 100000000))
  304. emitter = bytes.fromhex(self.getEmitter(tokenChain))
  305. return self.createSignedVAA(guardianSet, signers, int(time.time()), nonce, 1, emitter, seq, 32, 0, b)
  306. def genVaa(self, emitter, seq, payload):
  307. nonce = int(random.random() * 4000000.0)
  308. return self.createSignedVAA(1, self.guardianPrivKeys, int(time.time()), nonce, 8, emitter, seq, 32, 0, payload.hex())
  309. def test(self):
  310. print(self.genTransfer(self.guardianPrivKeys, 1, 1, 1, 1, bytes.fromhex("4523c3F29447d1f32AEa95BEBD00383c4640F1b4"), 1, decode_address("ROOKEPZMHHBAEH75Y44OCNXQAGTXZWG3PY7IYQQCMXO7IG7DJMVHU32YVI"), 8, 0))
  311. if __name__ == '__main__':
  312. core = GenTest(True)
  313. core.test()