structs_test.go 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. package vaa
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "crypto/elliptic"
  6. "crypto/rand"
  7. "encoding/binary"
  8. "encoding/hex"
  9. "encoding/json"
  10. "errors"
  11. "fmt"
  12. "math/big"
  13. "reflect"
  14. "testing"
  15. "time"
  16. "github.com/ethereum/go-ethereum/common"
  17. "github.com/ethereum/go-ethereum/crypto"
  18. "github.com/stretchr/testify/assert"
  19. "github.com/stretchr/testify/require"
  20. )
  21. func TestChainIDFromString(t *testing.T) {
  22. type test struct {
  23. input string
  24. output ChainID
  25. }
  26. // Positive Test Cases
  27. p_tests := []test{
  28. {input: "solana", output: ChainIDSolana},
  29. {input: "ethereum", output: ChainIDEthereum},
  30. {input: "terra", output: ChainIDTerra},
  31. {input: "bsc", output: ChainIDBSC},
  32. {input: "polygon", output: ChainIDPolygon},
  33. {input: "avalanche", output: ChainIDAvalanche},
  34. {input: "oasis", output: ChainIDOasis},
  35. {input: "algorand", output: ChainIDAlgorand},
  36. {input: "aptos", output: ChainIDAptos},
  37. {input: "sui", output: ChainIDSui},
  38. {input: "near", output: ChainIDNear},
  39. {input: "aurora", output: ChainIDAurora},
  40. {input: "fantom", output: ChainIDFantom},
  41. {input: "karura", output: ChainIDKarura},
  42. {input: "acala", output: ChainIDAcala},
  43. {input: "klaytn", output: ChainIDKlaytn},
  44. {input: "celo", output: ChainIDCelo},
  45. {input: "moonbeam", output: ChainIDMoonbeam},
  46. {input: "terra2", output: ChainIDTerra2},
  47. {input: "injective", output: ChainIDInjective},
  48. {input: "osmosis", output: ChainIDOsmosis},
  49. {input: "arbitrum", output: ChainIDArbitrum},
  50. {input: "pythnet", output: ChainIDPythNet},
  51. {input: "optimism", output: ChainIDOptimism},
  52. {input: "gnosis", output: ChainIDGnosis},
  53. {input: "xpla", output: ChainIDXpla},
  54. {input: "btc", output: ChainIDBtc},
  55. {input: "base", output: ChainIDBase},
  56. {input: "sei", output: ChainIDSei},
  57. {input: "rootstock", output: ChainIDRootstock},
  58. {input: "scroll", output: ChainIDScroll},
  59. {input: "mantle", output: ChainIDMantle},
  60. {input: "blast", output: ChainIDBlast},
  61. {input: "xlayer", output: ChainIDXLayer},
  62. {input: "linea", output: ChainIDLinea},
  63. {input: "berachain", output: ChainIDBerachain},
  64. {input: "snaxchain", output: ChainIDSnaxchain},
  65. {input: "unichain", output: ChainIDUnichain},
  66. {input: "worldchain", output: ChainIDWorldchain},
  67. {input: "ink", output: ChainIDInk},
  68. {input: "seievm", output: ChainIDSeiEVM},
  69. {input: "wormchain", output: ChainIDWormchain},
  70. {input: "cosmoshub", output: ChainIDCosmoshub},
  71. {input: "evmos", output: ChainIDEvmos},
  72. {input: "kujira", output: ChainIDKujira},
  73. {input: "neutron", output: ChainIDNeutron},
  74. {input: "celestia", output: ChainIDCelestia},
  75. {input: "stargaze", output: ChainIDStargaze},
  76. {input: "seda", output: ChainIDSeda},
  77. {input: "dymension", output: ChainIDDymension},
  78. {input: "provenance", output: ChainIDProvenance},
  79. {input: "sepolia", output: ChainIDSepolia},
  80. {input: "arbitrum_sepolia", output: ChainIDArbitrumSepolia},
  81. {input: "base_sepolia", output: ChainIDBaseSepolia},
  82. {input: "optimism_sepolia", output: ChainIDOptimismSepolia},
  83. {input: "holesky", output: ChainIDHolesky},
  84. {input: "polygon_sepolia", output: ChainIDPolygonSepolia},
  85. {input: "monad_devnet", output: ChainIDMonadDevnet},
  86. {input: "Solana", output: ChainIDSolana},
  87. {input: "Ethereum", output: ChainIDEthereum},
  88. {input: "Terra", output: ChainIDTerra},
  89. {input: "Bsc", output: ChainIDBSC},
  90. {input: "Polygon", output: ChainIDPolygon},
  91. {input: "Avalanche", output: ChainIDAvalanche},
  92. {input: "Oasis", output: ChainIDOasis},
  93. {input: "Algorand", output: ChainIDAlgorand},
  94. {input: "Aptos", output: ChainIDAptos},
  95. {input: "Sui", output: ChainIDSui},
  96. {input: "Near", output: ChainIDNear},
  97. {input: "Aurora", output: ChainIDAurora},
  98. {input: "Fantom", output: ChainIDFantom},
  99. {input: "Karura", output: ChainIDKarura},
  100. {input: "Acala", output: ChainIDAcala},
  101. {input: "Klaytn", output: ChainIDKlaytn},
  102. {input: "Celo", output: ChainIDCelo},
  103. {input: "Moonbeam", output: ChainIDMoonbeam},
  104. {input: "Terra2", output: ChainIDTerra2},
  105. {input: "Injective", output: ChainIDInjective},
  106. {input: "Osmosis", output: ChainIDOsmosis},
  107. {input: "Arbitrum", output: ChainIDArbitrum},
  108. {input: "Optimism", output: ChainIDOptimism},
  109. {input: "Gnosis", output: ChainIDGnosis},
  110. {input: "Pythnet", output: ChainIDPythNet},
  111. {input: "XPLA", output: ChainIDXpla},
  112. {input: "BTC", output: ChainIDBtc},
  113. {input: "Base", output: ChainIDBase},
  114. {input: "Sei", output: ChainIDSei},
  115. {input: "Rootstock", output: ChainIDRootstock},
  116. {input: "Scroll", output: ChainIDScroll},
  117. {input: "Mantle", output: ChainIDMantle},
  118. {input: "Blast", output: ChainIDBlast},
  119. {input: "XLayer", output: ChainIDXLayer},
  120. {input: "Linea", output: ChainIDLinea},
  121. {input: "Berachain", output: ChainIDBerachain},
  122. {input: "Snaxchain", output: ChainIDSnaxchain},
  123. {input: "Unichain", output: ChainIDUnichain},
  124. {input: "Worldchain", output: ChainIDWorldchain},
  125. {input: "Ink", output: ChainIDInk},
  126. {input: "SeiEVM", output: ChainIDSeiEVM},
  127. {input: "Wormchain", output: ChainIDWormchain},
  128. {input: "Cosmoshub", output: ChainIDCosmoshub},
  129. {input: "Evmos", output: ChainIDEvmos},
  130. {input: "Kujira", output: ChainIDKujira},
  131. {input: "Neutron", output: ChainIDNeutron},
  132. {input: "Celestia", output: ChainIDCelestia},
  133. {input: "Stargaze", output: ChainIDStargaze},
  134. {input: "Seda", output: ChainIDSeda},
  135. {input: "Dymension", output: ChainIDDymension},
  136. {input: "Provenance", output: ChainIDProvenance},
  137. {input: "Sepolia", output: ChainIDSepolia},
  138. {input: "Arbitrum_Sepolia", output: ChainIDArbitrumSepolia},
  139. {input: "Base_Sepolia", output: ChainIDBaseSepolia},
  140. {input: "Optimism_Sepolia", output: ChainIDOptimismSepolia},
  141. {input: "Holesky", output: ChainIDHolesky},
  142. {input: "Polygon_Sepolia", output: ChainIDPolygonSepolia},
  143. {input: "Monad_Devnet", output: ChainIDMonadDevnet},
  144. }
  145. // Negative Test Cases
  146. n_tests := []test{
  147. {input: "Unknown", output: ChainIDUnset},
  148. }
  149. for _, tc := range p_tests {
  150. t.Run(tc.input, func(t *testing.T) {
  151. chainId, err := ChainIDFromString(tc.input)
  152. assert.Equal(t, tc.output, chainId)
  153. assert.NoError(t, err)
  154. })
  155. }
  156. for _, tc := range n_tests {
  157. t.Run(tc.input, func(t *testing.T) {
  158. chainId, err := ChainIDFromString(tc.input)
  159. assert.Equal(t, tc.output, chainId)
  160. assert.NotNil(t, err)
  161. })
  162. }
  163. }
  164. func TestAddress_MarshalJSON(t *testing.T) {
  165. addr := Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
  166. expected := "223030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303422"
  167. marshalJsonAddress, err := addr.MarshalJSON()
  168. assert.Equal(t, hex.EncodeToString(marshalJsonAddress), expected)
  169. assert.NoError(t, err)
  170. }
  171. func TestAddress_UnmarshalJSON(t *testing.T) {
  172. tests := []struct {
  173. name string
  174. address Address
  175. addressJSON string
  176. err error
  177. }{
  178. {
  179. name: "working",
  180. addressJSON: "0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16",
  181. address: Address{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x90, 0xfb, 0x16, 0x72, 0x8, 0xaf, 0x45, 0x5b, 0xb1, 0x37, 0x78, 0x1, 0x63, 0xb7, 0xb7, 0xa9, 0xa1, 0xc, 0x16},
  182. err: nil,
  183. },
  184. {
  185. name: "failure",
  186. addressJSON: "derp",
  187. address: Address{},
  188. err: hex.InvalidByteError(0x72),
  189. },
  190. }
  191. for _, testCase := range tests {
  192. t.Run(testCase.name, func(t *testing.T) {
  193. var unmarshalAddr Address
  194. err := unmarshalAddr.UnmarshalJSON([]byte(testCase.addressJSON))
  195. require.Equal(t, testCase.err, err)
  196. assert.Equal(t, testCase.address, unmarshalAddr)
  197. })
  198. }
  199. }
  200. func TestAddress_Unmarshal(t *testing.T) {
  201. addr, _ := StringToAddress("0x0290fb167208af455bb137780163b7b7a9a10c16")
  202. b, err := json.Marshal(addr)
  203. require.NoError(t, err)
  204. var unmarshalAddr Address
  205. err = json.Unmarshal(b, &unmarshalAddr)
  206. require.NoError(t, err)
  207. assert.Equal(t, addr, unmarshalAddr)
  208. }
  209. func TestAddress_UnmarshalEmptyBuffer(t *testing.T) {
  210. b := []byte{}
  211. var unmarshalAddr Address
  212. err := json.Unmarshal(b, &unmarshalAddr)
  213. require.Error(t, err)
  214. }
  215. func TestAddress_UnmarshalBufferTooShort(t *testing.T) {
  216. addr, _ := StringToAddress("0x0290fb167208af455bb137780163b7b7a9a10c16")
  217. b, err := json.Marshal(addr)
  218. require.NoError(t, err)
  219. var unmarshalAddr Address
  220. // Lop off the first byte, and it should fail.
  221. b1 := b[1:]
  222. err = json.Unmarshal(b1, &unmarshalAddr)
  223. assert.Error(t, err)
  224. // Lop off the last byte, and it should fail.
  225. b2 := b[0 : len(b)-1]
  226. err = json.Unmarshal(b2, &unmarshalAddr)
  227. assert.Error(t, err)
  228. }
  229. func TestAddress_String(t *testing.T) {
  230. addr := Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
  231. expected := "0000000000000000000000000000000000000000000000000000000000000004"
  232. assert.Equal(t, addr.String(), expected)
  233. }
  234. func TestAddress_Bytes(t *testing.T) {
  235. addr := Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
  236. expected := []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4}
  237. assert.Equal(t, addr.Bytes(), expected)
  238. }
  239. func TestSignatureData_MarshalJSON(t *testing.T) {
  240. sigData := SignatureData{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}
  241. marshalJsonSigData, err := sigData.MarshalJSON()
  242. require.Nil(t, err)
  243. expected := "223030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303430303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303034303022"
  244. assert.Equal(t, hex.EncodeToString(marshalJsonSigData), expected)
  245. }
  246. func TestSignature_DataString(t *testing.T) {
  247. sigData := SignatureData{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}
  248. expected := "0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400"
  249. assert.Equal(t, sigData.String(), expected)
  250. }
  251. func TestMinVAALength(t *testing.T) {
  252. assert.Equal(t, minVAALength, 57)
  253. }
  254. func TestChainId_String(t *testing.T) {
  255. type test struct {
  256. input ChainID
  257. output string
  258. }
  259. tests := []test{
  260. {input: 0, output: "unset"},
  261. {input: 1, output: "solana"},
  262. {input: 2, output: "ethereum"},
  263. {input: 3, output: "terra"},
  264. {input: 4, output: "bsc"},
  265. {input: 5, output: "polygon"},
  266. {input: 6, output: "avalanche"},
  267. {input: 7, output: "oasis"},
  268. {input: 8, output: "algorand"},
  269. {input: 9, output: "aurora"},
  270. {input: 10, output: "fantom"},
  271. {input: 11, output: "karura"},
  272. {input: 12, output: "acala"},
  273. {input: 13, output: "klaytn"},
  274. {input: 14, output: "celo"},
  275. {input: 15, output: "near"},
  276. {input: 16, output: "moonbeam"},
  277. {input: 18, output: "terra2"},
  278. {input: 19, output: "injective"},
  279. {input: 20, output: "osmosis"},
  280. {input: 21, output: "sui"},
  281. {input: 22, output: "aptos"},
  282. {input: 23, output: "arbitrum"},
  283. {input: 24, output: "optimism"},
  284. {input: 25, output: "gnosis"},
  285. {input: 26, output: "pythnet"},
  286. {input: 28, output: "xpla"},
  287. {input: 29, output: "btc"},
  288. {input: 30, output: "base"},
  289. {input: 32, output: "sei"},
  290. {input: 33, output: "rootstock"},
  291. {input: 34, output: "scroll"},
  292. {input: 35, output: "mantle"},
  293. {input: 36, output: "blast"},
  294. {input: 37, output: "xlayer"},
  295. {input: 38, output: "linea"},
  296. {input: 39, output: "berachain"},
  297. {input: 40, output: "seievm"},
  298. {input: 43, output: "snaxchain"},
  299. {input: 44, output: "unichain"},
  300. {input: 45, output: "worldchain"},
  301. {input: 46, output: "ink"},
  302. {input: 3104, output: "wormchain"},
  303. {input: 4000, output: "cosmoshub"},
  304. {input: 4001, output: "evmos"},
  305. {input: 4002, output: "kujira"},
  306. {input: 4003, output: "neutron"},
  307. {input: 4004, output: "celestia"},
  308. {input: 4005, output: "stargaze"},
  309. {input: 4006, output: "seda"},
  310. {input: 10002, output: "sepolia"},
  311. {input: 10003, output: "arbitrum_sepolia"},
  312. {input: 10004, output: "base_sepolia"},
  313. {input: 10005, output: "optimism_sepolia"},
  314. {input: 10006, output: "holesky"},
  315. {input: 10007, output: "polygon_sepolia"},
  316. {input: 10008, output: "monad_devnet"},
  317. {input: 10000, output: "unknown chain ID: 10000"},
  318. }
  319. for _, tc := range tests {
  320. t.Run(tc.output, func(t *testing.T) {
  321. assert.Equal(t, ChainID(tc.input).String(), tc.output)
  322. })
  323. }
  324. }
  325. func getVaa() VAA {
  326. var payload = []byte{97, 97, 97, 97, 97, 97}
  327. var governanceEmitter = Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
  328. return VAA{
  329. Version: uint8(1),
  330. GuardianSetIndex: uint32(1),
  331. Signatures: []*Signature{},
  332. Timestamp: time.Unix(0, 0),
  333. Nonce: uint32(1),
  334. Sequence: uint64(1),
  335. ConsistencyLevel: uint8(32),
  336. EmitterChain: ChainIDSolana,
  337. EmitterAddress: governanceEmitter,
  338. Payload: payload,
  339. }
  340. }
  341. func getEmptyPayloadVaa() VAA {
  342. var payload = []byte{}
  343. var governanceEmitter = Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}
  344. return VAA{
  345. Version: uint8(1),
  346. GuardianSetIndex: uint32(1),
  347. Signatures: []*Signature{},
  348. Timestamp: time.Unix(0, 0),
  349. Nonce: uint32(1),
  350. Sequence: uint64(1),
  351. ConsistencyLevel: uint8(32),
  352. EmitterChain: ChainIDSolana,
  353. EmitterAddress: governanceEmitter,
  354. Payload: payload,
  355. }
  356. }
  357. func TestAddSignature(t *testing.T) {
  358. vaa := getVaa()
  359. // Generate a random private key to sign with
  360. key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  361. assert.Equal(t, []*Signature{}, vaa.Signatures)
  362. // Add a signature and make sure it's added
  363. vaa.AddSignature(key, 0)
  364. assert.Equal(t, len(vaa.Signatures), 1)
  365. }
  366. func TestSerializeBody(t *testing.T) {
  367. vaa := getVaa()
  368. expected := []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61}
  369. assert.Equal(t, vaa.serializeBody(), expected)
  370. }
  371. func TestSigningBody(t *testing.T) {
  372. vaa := getVaa()
  373. expected := []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61}
  374. assert.Equal(t, vaa.signingBody(), expected)
  375. }
  376. func TestSigningMsg(t *testing.T) {
  377. vaa := getVaa()
  378. expected := common.HexToHash("4fae136bb1fd782fe1b5180ba735cdc83bcece3f9b7fd0e5e35300a61c8acd8f")
  379. assert.Equal(t, vaa.SigningDigest(), expected)
  380. }
  381. func TestMessageID(t *testing.T) {
  382. vaa := getVaa()
  383. expected := "1/0000000000000000000000000000000000000000000000000000000000000004/1"
  384. assert.Equal(t, vaa.MessageID(), expected)
  385. }
  386. func TestHexDigest(t *testing.T) {
  387. vaa := getVaa()
  388. expected := "4fae136bb1fd782fe1b5180ba735cdc83bcece3f9b7fd0e5e35300a61c8acd8f"
  389. assert.Equal(t, vaa.HexDigest(), expected)
  390. }
  391. func TestMarshal(t *testing.T) {
  392. expectedBytes := []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61}
  393. vaa := getVaa()
  394. marshalBytes, err := vaa.Marshal()
  395. assert.Nil(t, err)
  396. assert.Equal(t, expectedBytes, marshalBytes)
  397. }
  398. func TestUnmarshal(t *testing.T) {
  399. vaaBytes := []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61}
  400. vaa1 := getVaa()
  401. vaa2, err := Unmarshal(vaaBytes)
  402. assert.Nil(t, err)
  403. assert.Equal(t, &vaa1, vaa2)
  404. }
  405. func TestUnmarshalNoPayload(t *testing.T) {
  406. vaaBytes := []byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20}
  407. vaa1 := getEmptyPayloadVaa()
  408. vaa2, err := Unmarshal(vaaBytes)
  409. assert.Nil(t, err)
  410. assert.Equal(t, &vaa1, vaa2)
  411. }
  412. func TestUnmarshalBigPayload(t *testing.T) {
  413. vaa := getVaa()
  414. // Create a payload of more than 1000 bytes.
  415. var payload []byte
  416. for i := 0; i < 2000; i++ {
  417. ch := i % 255
  418. payload = append(payload, byte(ch))
  419. }
  420. vaa.Payload = payload
  421. marshalBytes, err := vaa.Marshal()
  422. require.NoError(t, err)
  423. vaa2, err := Unmarshal(marshalBytes)
  424. require.NoError(t, err)
  425. assert.Equal(t, vaa, *vaa2)
  426. }
  427. func FuzzUnmarshalBigPayload(f *testing.F) {
  428. f.Add([]byte{})
  429. f.Add([]byte{0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x20})
  430. f.Fuzz(func(t *testing.T, payload []byte) {
  431. vaa := getVaa()
  432. vaa.Payload = payload
  433. // It should always marshal
  434. marshalBytes, err := vaa.Marshal()
  435. require.NoError(t, err)
  436. // It should aways unmarshal
  437. vaa2, err := Unmarshal(marshalBytes)
  438. require.NoError(t, err)
  439. // The payload should not be lossy
  440. assert.Equal(t, vaa.Payload, payload)
  441. assert.Equal(t, vaa2.Payload, payload)
  442. // The marshal and unmarshal should always be the same
  443. assert.Equal(t, vaa, *vaa2)
  444. })
  445. }
  446. func TestVerifySignatures(t *testing.T) {
  447. // Generate some random private keys to sign with
  448. privKey1, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  449. privKey2, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  450. privKey3, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  451. privKey4, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  452. // Give a fixed order of trusted addresses
  453. addrs := []common.Address{}
  454. addrs = append(addrs, crypto.PubkeyToAddress(privKey1.PublicKey))
  455. addrs = append(addrs, crypto.PubkeyToAddress(privKey2.PublicKey))
  456. addrs = append(addrs, crypto.PubkeyToAddress(privKey3.PublicKey))
  457. type test struct {
  458. label string
  459. keyOrder []*ecdsa.PrivateKey
  460. addrs []common.Address
  461. indexOrder []uint8
  462. result bool
  463. }
  464. tests := []test{
  465. {label: "NoSignerZero",
  466. keyOrder: []*ecdsa.PrivateKey{},
  467. addrs: addrs,
  468. indexOrder: []uint8{0},
  469. result: true},
  470. {label: "NoSignerOne",
  471. keyOrder: []*ecdsa.PrivateKey{},
  472. addrs: addrs,
  473. indexOrder: []uint8{1},
  474. result: true},
  475. {label: "SingleZero",
  476. keyOrder: []*ecdsa.PrivateKey{privKey1},
  477. addrs: addrs,
  478. indexOrder: []uint8{0},
  479. result: true},
  480. {label: "RogueSingleOne",
  481. keyOrder: []*ecdsa.PrivateKey{privKey4},
  482. addrs: addrs,
  483. indexOrder: []uint8{0},
  484. result: false},
  485. {label: "RogueSingleZero",
  486. keyOrder: []*ecdsa.PrivateKey{privKey4},
  487. addrs: addrs,
  488. indexOrder: []uint8{0},
  489. result: false},
  490. {label: "SingleOne",
  491. keyOrder: []*ecdsa.PrivateKey{privKey1},
  492. addrs: addrs,
  493. indexOrder: []uint8{0},
  494. result: true},
  495. {label: "MultiUniqSignerMonotonicIndex",
  496. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3},
  497. addrs: addrs,
  498. indexOrder: []uint8{0, 1, 2},
  499. result: true},
  500. {label: "MultiMisOrderedSignerMonotonicIndex",
  501. keyOrder: []*ecdsa.PrivateKey{privKey3, privKey2, privKey1},
  502. addrs: addrs,
  503. indexOrder: []uint8{0, 1, 2}, result: false},
  504. {label: "MultiUniqSignerNonMonotonic",
  505. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3},
  506. addrs: addrs,
  507. indexOrder: []uint8{0, 2, 1},
  508. result: false},
  509. {label: "MultiUniqSignerFullSameIndex0",
  510. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3},
  511. addrs: addrs,
  512. indexOrder: []uint8{0, 0, 0},
  513. result: false},
  514. {label: "MultiUniqSignerFullSameIndex1",
  515. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3},
  516. addrs: addrs,
  517. indexOrder: []uint8{0, 0, 0},
  518. result: false},
  519. {label: "MultiUniqSignerPartialSameIndex",
  520. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3},
  521. addrs: addrs,
  522. indexOrder: []uint8{0, 1, 1},
  523. result: false},
  524. {label: "MultiSameSignerPartialSameIndex",
  525. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey2},
  526. addrs: addrs,
  527. indexOrder: []uint8{0, 1, 1},
  528. result: false},
  529. {label: "MultiSameSignerNonMonotonic",
  530. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey2, privKey2},
  531. addrs: addrs,
  532. indexOrder: []uint8{0, 2, 1},
  533. result: false},
  534. {label: "MultiSameSignerFullSameIndex",
  535. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey1, privKey1},
  536. addrs: addrs,
  537. indexOrder: []uint8{0, 0, 0},
  538. result: false},
  539. {label: "MultiSameSignerMonotonic",
  540. keyOrder: []*ecdsa.PrivateKey{privKey1, privKey1, privKey1},
  541. addrs: addrs,
  542. indexOrder: []uint8{0, 1, 2},
  543. result: false},
  544. }
  545. for _, tc := range tests {
  546. t.Run(tc.label, func(t *testing.T) {
  547. vaa := getVaa()
  548. for i, key := range tc.keyOrder {
  549. vaa.AddSignature(key, tc.indexOrder[i])
  550. }
  551. assert.Equal(t, tc.result, vaa.VerifySignatures(tc.addrs))
  552. })
  553. }
  554. }
  555. func TestVerifySignaturesFuzz(t *testing.T) {
  556. // Generate some random trusted private keys to sign with
  557. privKey1, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  558. privKey2, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  559. privKey3, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  560. // Generate some random untrusted private keys to sign with
  561. privKey4, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  562. privKey5, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  563. privKey6, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
  564. // Give a fixed order of trusted addresses (we intentionally omit privKey4, privKey5, privKey6)
  565. addrs := []common.Address{}
  566. addrs = append(addrs, crypto.PubkeyToAddress(privKey1.PublicKey))
  567. addrs = append(addrs, crypto.PubkeyToAddress(privKey2.PublicKey))
  568. addrs = append(addrs, crypto.PubkeyToAddress(privKey3.PublicKey))
  569. // key space for fuzz tests
  570. keys := []*ecdsa.PrivateKey{}
  571. keys = append(keys, privKey1)
  572. keys = append(keys, privKey2)
  573. keys = append(keys, privKey3)
  574. keys = append(keys, privKey4)
  575. keys = append(keys, privKey5)
  576. keys = append(keys, privKey6)
  577. // index space for fuzz tests
  578. indexes := []uint8{0, 1, 2, 3, 4, 5}
  579. type test struct {
  580. label string
  581. keyOrder []*ecdsa.PrivateKey
  582. addrs []common.Address
  583. indexOrder []uint8
  584. result bool
  585. }
  586. type allow struct {
  587. keyPair []*ecdsa.PrivateKey
  588. indexPair []uint8
  589. }
  590. // Known good cases where we should have a verified result for
  591. allows := []allow{
  592. {keyPair: []*ecdsa.PrivateKey{}, indexPair: []uint8{}},
  593. {keyPair: []*ecdsa.PrivateKey{privKey1}, indexPair: []uint8{0}},
  594. {keyPair: []*ecdsa.PrivateKey{privKey2}, indexPair: []uint8{1}},
  595. {keyPair: []*ecdsa.PrivateKey{privKey3}, indexPair: []uint8{2}},
  596. {keyPair: []*ecdsa.PrivateKey{privKey1, privKey2}, indexPair: []uint8{0, 1}},
  597. {keyPair: []*ecdsa.PrivateKey{privKey1, privKey3}, indexPair: []uint8{0, 2}},
  598. {keyPair: []*ecdsa.PrivateKey{privKey2, privKey3}, indexPair: []uint8{1, 2}},
  599. {keyPair: []*ecdsa.PrivateKey{privKey1, privKey2, privKey3}, indexPair: []uint8{0, 1, 2}},
  600. }
  601. tests := []test{}
  602. keyPairs := [][]*ecdsa.PrivateKey{}
  603. indexPairs := [][]uint8{}
  604. // Build empty keyPair
  605. keyPairs = append(keyPairs, []*ecdsa.PrivateKey{})
  606. // Build single keyPairs
  607. for _, key := range keys {
  608. keyPairs = append(keyPairs, []*ecdsa.PrivateKey{key})
  609. }
  610. // Build double keyPairs
  611. for _, key_i := range keys {
  612. for _, key_j := range keys {
  613. keyPairs = append(keyPairs, []*ecdsa.PrivateKey{key_i, key_j})
  614. }
  615. }
  616. // Build triple keyPairs
  617. for _, key_i := range keys {
  618. for _, key_j := range keys {
  619. for _, key_k := range keys {
  620. keyPairs = append(keyPairs, []*ecdsa.PrivateKey{key_i, key_j, key_k})
  621. }
  622. }
  623. }
  624. // Build empty indexPairs
  625. indexPairs = append(indexPairs, []uint8{})
  626. // Build single indexPairs
  627. for _, ind := range indexes {
  628. indexPairs = append(indexPairs, []uint8{ind})
  629. }
  630. // Build double indexPairs
  631. for _, ind_i := range indexes {
  632. for _, ind_j := range indexes {
  633. indexPairs = append(indexPairs, []uint8{ind_i, ind_j})
  634. }
  635. }
  636. // Build triple keyPairs
  637. for _, ind_i := range indexes {
  638. for _, ind_j := range indexes {
  639. for _, ind_k := range indexes {
  640. indexPairs = append(indexPairs, []uint8{ind_i, ind_j, ind_k})
  641. }
  642. }
  643. }
  644. // Build out the fuzzTest cases
  645. for _, keyPair := range keyPairs {
  646. for _, indexPair := range indexPairs {
  647. if len(keyPair) == len(indexPair) {
  648. result := false
  649. for _, allow := range allows {
  650. if reflect.DeepEqual(allow.indexPair, indexPair) && reflect.DeepEqual(allow.keyPair, keyPair) {
  651. result = true
  652. break
  653. }
  654. }
  655. test := test{label: "A", keyOrder: keyPair, addrs: addrs, indexOrder: indexPair, result: result}
  656. tests = append(tests, test)
  657. }
  658. }
  659. }
  660. // Run the fuzzTest cases
  661. for _, tc := range tests {
  662. t.Run(tc.label, func(t *testing.T) {
  663. vaa := getVaa()
  664. for i, key := range tc.keyOrder {
  665. vaa.AddSignature(key, tc.indexOrder[i])
  666. }
  667. /* Fuzz Debugging
  668. * Tell us what keys and indexes were used (for debug when/if we have a failure case)
  669. */
  670. if vaa.VerifySignatures(tc.addrs) != tc.result {
  671. if len(tc.keyOrder) == 0 {
  672. t.Logf("Key Order %v\n", tc.keyOrder)
  673. } else {
  674. keyIndex := []uint8{}
  675. for i, key_i := range keys {
  676. for _, key_k := range tc.keyOrder {
  677. if key_i == key_k {
  678. keyIndex = append(keyIndex, uint8(i))
  679. }
  680. }
  681. }
  682. t.Logf("Key Order %v\n", keyIndex)
  683. }
  684. t.Logf("Index Order %v\n", tc.indexOrder)
  685. }
  686. assert.Equal(t, tc.result, vaa.VerifySignatures(tc.addrs))
  687. })
  688. }
  689. }
  690. func TestStringToAddress(t *testing.T) {
  691. type Test struct {
  692. label string
  693. rawAddr string
  694. addr Address
  695. errString string
  696. }
  697. tests := []Test{
  698. {label: "simple",
  699. rawAddr: "0000000000000000000000000000000000000000000000000000000000000004",
  700. addr: Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4},
  701. errString: ""},
  702. {label: "zero-padding",
  703. rawAddr: "04",
  704. addr: Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4},
  705. errString: ""},
  706. {label: "trim-0x", rawAddr: "0x04",
  707. addr: Address{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4},
  708. errString: ""},
  709. {label: "20byte eth-style address", rawAddr: "0x0290FB167208Af455bB137780163b7B7a9a10C16",
  710. addr: Address{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x90, 0xfb, 0x16, 0x72, 0x8, 0xaf, 0x45, 0x5b, 0xb1, 0x37, 0x78, 0x1, 0x63, 0xb7, 0xb7, 0xa9, 0xa1, 0xc, 0x16},
  711. errString: ""},
  712. {label: "too long",
  713. rawAddr: "0x0000000000000000000000000000000000000000000000000000000000000000000004",
  714. errString: "value must be no more than 32 bytes"},
  715. {label: "too short",
  716. rawAddr: "4",
  717. errString: "value must be at least 1 byte"},
  718. {label: "empty string",
  719. rawAddr: "",
  720. errString: "value must be at least 1 byte"},
  721. }
  722. for _, tc := range tests {
  723. t.Run(string(tc.label), func(t *testing.T) {
  724. addr, err := StringToAddress(tc.rawAddr)
  725. if len(tc.errString) == 0 {
  726. assert.NoError(t, err)
  727. assert.Equal(t, tc.addr, addr)
  728. } else {
  729. assert.Equal(t, tc.errString, err.Error())
  730. }
  731. })
  732. }
  733. }
  734. func TestBytesToAddress(t *testing.T) {
  735. addrStr := "0000000000000000000000003ee18b2214aff97000d974cf647e7c347e8fa585"
  736. expectedAddr, err := StringToAddress(addrStr)
  737. assert.NoError(t, err)
  738. addrBytes, err := hex.DecodeString(addrStr)
  739. assert.NoError(t, err)
  740. addr, err := BytesToAddress(addrBytes)
  741. assert.NoError(t, err)
  742. assert.Equal(t, expectedAddr, addr)
  743. // More than 32 bytes should generate an error.
  744. tooLongAddrBytes, err := hex.DecodeString("0000" + addrStr)
  745. assert.NoError(t, err)
  746. _, err = BytesToAddress(tooLongAddrBytes)
  747. assert.NotNil(t, err)
  748. assert.Equal(t, "value must be no more than 32 bytes", err.Error())
  749. // Less than 32 bytes should get left padded with zeros.
  750. shortAddr, err := BytesToAddress(addrBytes[4:])
  751. assert.NoError(t, err)
  752. assert.Equal(t, expectedAddr, shortAddr)
  753. }
  754. func TestDecodeTransferPayloadHdr(t *testing.T) {
  755. type Test struct {
  756. label string
  757. vaa string
  758. payloadType uint8
  759. emitterChainId ChainID
  760. emitterAddr string
  761. originChain ChainID
  762. originAddress string
  763. targetChain ChainID
  764. targetAddress string
  765. amount int64
  766. errString string
  767. }
  768. tests := []Test{
  769. {label: "valid vaa",
  770. vaa: "01000000000100e424aef95296cb0f2185f351086c7c0b9cd031d1288f0537d04ab20d5fc709416224b2bd9a8010a81988aa9cb38b378eb915f88b67e32a765928d948dc02077e00000102584a8d000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16000000000000000f0f01000000000000000000000000000000000000000000000000000000002b369f40000000000000000000000000ddb64fe46a91d46ee29420539fc25fd07c5fea3e000221c175fcd8e3a19fe2e0deae96534f0f4e6a896f4df0e3ec5345fe27ac3f63f000010000000000000000000000000000000000000000000000000000000000000000",
  771. payloadType: 1,
  772. emitterChainId: ChainIDEthereum,
  773. emitterAddr: "0000000000000000000000000290FB167208Af455bB137780163b7B7a9a10C16",
  774. originChain: ChainIDEthereum,
  775. originAddress: "000000000000000000000000DDb64fE46a91D46ee29420539FC25FD07c5FEa3E",
  776. targetChain: ChainIDSolana,
  777. targetAddress: "21c175fcd8e3a19fe2e0deae96534f0f4e6a896f4df0e3ec5345fe27ac3f63f0",
  778. amount: 725000000,
  779. errString: "",
  780. },
  781. {label: "unsupported payload type",
  782. vaa: "01000000000100e424aef95296cb0f2185f351086c7c0b9cd031d1288f0537d04ab20d5fc709416224b2bd9a8010a81988aa9cb38b378eb915f88b67e32a765928d948dc02077e00000102584a8d000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16000000000000000f0f02000000000000000000000000000000000000000000000000000000002b369f40000000000000000000000000ddb64fe46a91d46ee29420539fc25fd07c5fea3e000221c175fcd8e3a19fe2e0deae96534f0f4e6a896f4df0e3ec5345fe27ac3f63f000010000000000000000000000000000000000000000000000000000000000000000",
  783. errString: "unsupported payload type",
  784. },
  785. {label: "buffer too short",
  786. vaa: "01000000000100e424aef95296cb0f2185f351086c7c0b9cd031d1288f0537d04ab20d5fc709416224b2bd9a8010a81988aa9cb38b378eb915f88b67e32a765928d948dc02077e00000102584a8d000000020000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16000000000000000f0f01",
  787. errString: "buffer too short",
  788. },
  789. {label: "empty string",
  790. vaa: "",
  791. errString: "VAA is too short",
  792. },
  793. }
  794. for _, tc := range tests {
  795. t.Run(string(tc.label), func(t *testing.T) {
  796. data, err := hex.DecodeString(tc.vaa)
  797. assert.NoError(t, err)
  798. vaa, err := Unmarshal(data)
  799. if err != nil {
  800. assert.Equal(t, tc.errString, err.Error())
  801. } else {
  802. assert.NoError(t, err)
  803. assert.NotNil(t, vaa)
  804. if len(tc.errString) == 0 {
  805. expectedEmitterAddr, err := StringToAddress(tc.emitterAddr)
  806. assert.NoError(t, err)
  807. expectedOriginAddress, err := StringToAddress(tc.originAddress)
  808. assert.NoError(t, err)
  809. expectedTargetAddress, err := StringToAddress(tc.targetAddress)
  810. assert.NoError(t, err)
  811. expectedAmount := big.NewInt(tc.amount)
  812. assert.Equal(t, tc.emitterChainId, vaa.EmitterChain)
  813. assert.Equal(t, expectedEmitterAddr, vaa.EmitterAddress)
  814. assert.Equal(t, 133, len(vaa.Payload))
  815. payload, err := DecodeTransferPayloadHdr(vaa.Payload)
  816. assert.NoError(t, err)
  817. assert.Equal(t, tc.payloadType, payload.Type)
  818. assert.Equal(t, tc.originChain, payload.OriginChain)
  819. assert.Equal(t, expectedOriginAddress, payload.OriginAddress)
  820. assert.Equal(t, tc.targetChain, payload.TargetChain)
  821. assert.Equal(t, expectedTargetAddress, payload.TargetAddress)
  822. assert.Equal(t, expectedAmount.Cmp(payload.Amount), 0)
  823. } else {
  824. _, err = DecodeTransferPayloadHdr(vaa.Payload)
  825. assert.NotNil(t, err)
  826. assert.Equal(t, tc.errString, err.Error())
  827. }
  828. }
  829. })
  830. }
  831. }
  832. func TestIsTransfer(t *testing.T) {
  833. type Test struct {
  834. label string
  835. payload []byte
  836. result bool
  837. }
  838. tests := []Test{
  839. {label: "empty", payload: []byte{}, result: false},
  840. {label: "non-valid payload", payload: []byte{0x0}, result: false},
  841. {label: "payload 1", payload: []byte{0x1}, result: true},
  842. {label: "payload 2", payload: []byte{0x2}, result: false},
  843. {label: "payload 3", payload: []byte{0x3}, result: true},
  844. {label: "payload 4", payload: []byte{0x4}, result: false},
  845. }
  846. for _, tc := range tests {
  847. t.Run(string(tc.label), func(t *testing.T) {
  848. assert.Equal(t, tc.result, IsTransfer(tc.payload))
  849. })
  850. }
  851. }
  852. func TestUnmarshalBody(t *testing.T) {
  853. addr, _ := StringToAddress("0x0290fb167208af455bb137780163b7b7a9a10c16")
  854. testPayload := []byte("Hi")
  855. tests := []struct {
  856. name string
  857. data []byte
  858. vaa *VAA
  859. err error
  860. expectedVAA *VAA
  861. dataFunc func() []byte
  862. }{
  863. {
  864. name: "invalid_timestamp",
  865. dataFunc: func() []byte {
  866. return []byte("Hi")
  867. },
  868. err: fmt.Errorf("failed to read timestamp: %w", errors.New("unexpected EOF")),
  869. },
  870. {
  871. name: "invalid_nonce",
  872. err: fmt.Errorf("failed to read nonce: %w", errors.New("EOF")),
  873. vaa: &VAA{},
  874. dataFunc: func() []byte {
  875. buf := new(bytes.Buffer)
  876. MustWrite(buf, binary.BigEndian, uint32(time.Now().Unix()))
  877. return buf.Bytes()
  878. },
  879. },
  880. {
  881. name: "invalid_emmitter_chain",
  882. err: fmt.Errorf("failed to read emitter chain: %w", errors.New("EOF")),
  883. vaa: &VAA{},
  884. dataFunc: func() []byte {
  885. buf := new(bytes.Buffer)
  886. MustWrite(buf, binary.BigEndian, uint32(time.Now().Unix()))
  887. MustWrite(buf, binary.BigEndian, uint32(123))
  888. return buf.Bytes()
  889. },
  890. },
  891. {
  892. name: "invalid_emmitter_address",
  893. err: fmt.Errorf("failed to read emitter address [0]: %w", errors.New("EOF")),
  894. vaa: &VAA{},
  895. dataFunc: func() []byte {
  896. buf := new(bytes.Buffer)
  897. MustWrite(buf, binary.BigEndian, uint32(time.Now().Unix()))
  898. MustWrite(buf, binary.BigEndian, uint32(123))
  899. MustWrite(buf, binary.BigEndian, ChainIDPythNet)
  900. return buf.Bytes()
  901. },
  902. },
  903. {
  904. name: "invalid_sequence_number",
  905. err: fmt.Errorf("failed to read sequence: %w", errors.New("EOF")),
  906. vaa: &VAA{},
  907. dataFunc: func() []byte {
  908. buf := new(bytes.Buffer)
  909. MustWrite(buf, binary.BigEndian, uint32(time.Now().Unix()))
  910. MustWrite(buf, binary.BigEndian, uint32(123))
  911. MustWrite(buf, binary.BigEndian, ChainIDBSC)
  912. buf.Write(addr[:])
  913. return buf.Bytes()
  914. },
  915. },
  916. {
  917. name: "invalid_consistency_level",
  918. err: fmt.Errorf("failed to read commitment: %w", errors.New("EOF")),
  919. vaa: &VAA{},
  920. dataFunc: func() []byte {
  921. buf := new(bytes.Buffer)
  922. MustWrite(buf, binary.BigEndian, uint32(time.Now().Unix()))
  923. MustWrite(buf, binary.BigEndian, uint32(123))
  924. MustWrite(buf, binary.BigEndian, ChainIDBSC)
  925. buf.Write(addr[:])
  926. MustWrite(buf, binary.BigEndian, uint64(42))
  927. return buf.Bytes()
  928. },
  929. },
  930. {
  931. name: "has_payload",
  932. err: nil,
  933. vaa: &VAA{},
  934. expectedVAA: &VAA{
  935. Nonce: uint32(123),
  936. Sequence: uint64(42),
  937. ConsistencyLevel: uint8(1),
  938. EmitterChain: ChainIDBSC,
  939. Timestamp: time.Unix(0, 0),
  940. EmitterAddress: addr,
  941. Payload: testPayload,
  942. },
  943. dataFunc: func() []byte {
  944. buf := new(bytes.Buffer)
  945. MustWrite(buf, binary.BigEndian, uint32(0))
  946. MustWrite(buf, binary.BigEndian, uint32(123))
  947. MustWrite(buf, binary.BigEndian, ChainIDBSC)
  948. buf.Write(addr[:])
  949. MustWrite(buf, binary.BigEndian, uint64(42))
  950. MustWrite(buf, binary.BigEndian, uint8(1))
  951. buf.Write(testPayload)
  952. return buf.Bytes()
  953. },
  954. },
  955. {
  956. name: "has_empty_payload",
  957. err: nil,
  958. vaa: &VAA{},
  959. expectedVAA: &VAA{
  960. Nonce: uint32(123),
  961. Sequence: uint64(42),
  962. ConsistencyLevel: uint8(1),
  963. EmitterChain: ChainIDBSC,
  964. Timestamp: time.Unix(0, 0),
  965. EmitterAddress: addr,
  966. Payload: []byte{},
  967. },
  968. dataFunc: func() []byte {
  969. buf := new(bytes.Buffer)
  970. MustWrite(buf, binary.BigEndian, uint32(0))
  971. MustWrite(buf, binary.BigEndian, uint32(123))
  972. MustWrite(buf, binary.BigEndian, ChainIDBSC)
  973. buf.Write(addr[:])
  974. MustWrite(buf, binary.BigEndian, uint64(42))
  975. MustWrite(buf, binary.BigEndian, uint8(1))
  976. buf.Write([]byte{})
  977. return buf.Bytes()
  978. },
  979. },
  980. }
  981. for _, testCase := range tests {
  982. t.Run(testCase.name, func(t *testing.T) {
  983. testBytes := testCase.dataFunc()
  984. body, err := UnmarshalBody(testCase.data, bytes.NewReader(testBytes), testCase.vaa)
  985. require.Equal(t, testCase.err, err)
  986. if err == nil {
  987. assert.Equal(t, testCase.expectedVAA, body)
  988. }
  989. })
  990. }
  991. }