structs.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package vaa
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "encoding/binary"
  6. "encoding/hex"
  7. "fmt"
  8. "io"
  9. "math/big"
  10. "time"
  11. "github.com/ethereum/go-ethereum/common"
  12. "github.com/ethereum/go-ethereum/crypto"
  13. )
  14. type (
  15. // VAA is a verifiable action approval of the Wormhole protocol
  16. VAA struct {
  17. // Version of the VAA schema
  18. Version uint8
  19. // GuardianSetIndex is the index of the guardian set that signed this VAA
  20. GuardianSetIndex uint32
  21. // SignatureData is the signature of the guardian set
  22. Signatures []*Signature
  23. // Timestamp when the VAA was created
  24. Timestamp time.Time
  25. // Payload of the VAA. This describes the action to be performed
  26. Payload vaaBody
  27. }
  28. // ChainID of a Wormhole chain
  29. ChainID uint8
  30. // Action of a VAA
  31. Action uint8
  32. // Address is a Wormhole protocol address, it contains the native chain's address. If the address data type of a
  33. // chain is < 32bytes the value is zero-padded on the left.
  34. Address [32]byte
  35. // Signature of a single guardian
  36. Signature struct {
  37. // Index of the validator
  38. Index uint8
  39. // Signature data
  40. Signature [65]byte // TODO: hex marshaller
  41. }
  42. // AssetMeta describes an asset within the Wormhole protocol
  43. AssetMeta struct {
  44. // Chain is the ID of the chain the original version of the asset exists on
  45. Chain ChainID
  46. // Address is the address of the token contract/mint/equivalent.
  47. Address Address
  48. // Decimals is the number of decimals the token has
  49. Decimals uint8
  50. }
  51. vaaBody interface {
  52. getActionID() Action
  53. serialize() ([]byte, error)
  54. }
  55. BodyTransfer struct {
  56. // Nonce is a user given unique nonce for this transfer
  57. Nonce uint32
  58. // SourceChain is the id of the chain the transfer was initiated from
  59. SourceChain ChainID
  60. // TargetChain is the id of the chain the transfer is directed to
  61. TargetChain ChainID
  62. // TargetAddress is the address of the sender on SourceChain
  63. SourceAddress Address
  64. // TargetAddress is the address of the recipient on TargetChain
  65. TargetAddress Address
  66. // Asset is the asset to be transferred
  67. Asset *AssetMeta
  68. // Amount is the amount of tokens to be transferred
  69. Amount *big.Int
  70. }
  71. BodyGuardianSetUpdate struct {
  72. // Key is the new guardian set key
  73. Keys []common.Address
  74. // NewIndex is the index of the new guardian set
  75. NewIndex uint32
  76. }
  77. BodyContractUpgrade struct {
  78. // ChainID is the chain on which the contract should be upgraded
  79. ChainID uint8
  80. // NewContract is the address of the account containing the new contract.
  81. NewContract Address
  82. }
  83. )
  84. func (a Address) String() string {
  85. return hex.EncodeToString(a[:])
  86. }
  87. func (c ChainID) String() string {
  88. switch c {
  89. case ChainIDSolana:
  90. return "solana"
  91. case ChainIDEthereum:
  92. return "ethereum"
  93. case ChainIDTerra:
  94. return "terra"
  95. default:
  96. return fmt.Sprintf("unknown chain ID: %d", c)
  97. }
  98. }
  99. const (
  100. ActionGuardianSetUpdate Action = 0x01
  101. ActionContractUpgrade Action = 0x02
  102. ActionTransfer Action = 0x10
  103. // ChainIDSolana is the ChainID of Solana
  104. ChainIDSolana = 1
  105. // ChainIDEthereum is the ChainID of Ethereum
  106. ChainIDEthereum = 2
  107. // ChainIDTerra is the ChainID of Terra
  108. ChainIDTerra = 3
  109. minVAALength = 1 + 4 + 52 + 4 + 1 + 1
  110. SupportedVAAVersion = 0x01
  111. )
  112. // Unmarshal deserializes the binary representation of a VAA
  113. func Unmarshal(data []byte) (*VAA, error) {
  114. if len(data) < minVAALength {
  115. return nil, fmt.Errorf("VAA is too short")
  116. }
  117. v := &VAA{}
  118. v.Version = data[0]
  119. if v.Version != SupportedVAAVersion {
  120. return nil, fmt.Errorf("unsupported VAA version: %d", v.Version)
  121. }
  122. reader := bytes.NewReader(data[1:])
  123. if err := binary.Read(reader, binary.BigEndian, &v.GuardianSetIndex); err != nil {
  124. return nil, fmt.Errorf("failed to read guardian set index: %w", err)
  125. }
  126. lenSignatures, er := reader.ReadByte()
  127. if er != nil {
  128. return nil, fmt.Errorf("failed to read signature length")
  129. }
  130. v.Signatures = make([]*Signature, lenSignatures)
  131. for i := 0; i < int(lenSignatures); i++ {
  132. index, err := reader.ReadByte()
  133. if err != nil {
  134. return nil, fmt.Errorf("failed to read validator index [%d]", i)
  135. }
  136. signature := [65]byte{}
  137. if n, err := reader.Read(signature[:]); err != nil || n != 65 {
  138. return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
  139. }
  140. v.Signatures[i] = &Signature{
  141. Index: index,
  142. Signature: signature,
  143. }
  144. }
  145. unixSeconds := uint32(0)
  146. if err := binary.Read(reader, binary.BigEndian, &unixSeconds); err != nil {
  147. return nil, fmt.Errorf("failed to read timestamp: %w", err)
  148. }
  149. v.Timestamp = time.Unix(int64(unixSeconds), 0)
  150. var (
  151. action uint8
  152. )
  153. if err := binary.Read(reader, binary.BigEndian, &action); err != nil {
  154. return nil, fmt.Errorf("failed to read action: %w", err)
  155. }
  156. currentPos := len(data) - reader.Len()
  157. payloadReader := bytes.NewReader(data[currentPos:])
  158. var err error
  159. switch Action(action) {
  160. case ActionGuardianSetUpdate:
  161. v.Payload, err = parseBodyGuardianSetUpdate(payloadReader)
  162. case ActionTransfer:
  163. v.Payload, err = parseBodyTransfer(payloadReader)
  164. case ActionContractUpgrade:
  165. v.Payload, err = parseBodyContractUpgrade(payloadReader)
  166. default:
  167. return nil, fmt.Errorf("unknown action: %d", action)
  168. }
  169. if err != nil {
  170. return nil, fmt.Errorf("failed to parse payload: %w", err)
  171. }
  172. return v, nil
  173. }
  174. // signingBody returns the binary representation of the data that is relevant for signing and verifying the VAA
  175. func (v *VAA) signingBody() ([]byte, error) {
  176. return v.serializeBody()
  177. }
  178. // SigningMsg returns the hash of the signing body. This is used for signature generation and verification
  179. func (v *VAA) SigningMsg() (common.Hash, error) {
  180. body, err := v.signingBody()
  181. if err != nil {
  182. // Should never happen on a successfully parsed VAA
  183. return common.Hash{}, fmt.Errorf("failed to serialize signing body: %w", err)
  184. }
  185. hash := crypto.Keccak256Hash(body)
  186. return hash, nil
  187. }
  188. // VerifySignature verifies the signature of the VAA given the signer addresses.
  189. func (v *VAA) VerifySignatures(addresses []common.Address) bool {
  190. if len(addresses) < len(v.Signatures) {
  191. return false
  192. }
  193. h, err := v.SigningMsg()
  194. if err != nil {
  195. return false
  196. }
  197. for _, sig := range v.Signatures {
  198. if int(sig.Index) >= len(addresses) {
  199. return false
  200. }
  201. pubKey, err := crypto.Ecrecover(h.Bytes(), sig.Signature[:])
  202. if err != nil {
  203. return false
  204. }
  205. addr := common.BytesToAddress(crypto.Keccak256(pubKey[1:])[12:])
  206. if addr != addresses[sig.Index] {
  207. return false
  208. }
  209. }
  210. return true
  211. }
  212. // Marshal returns the binary representation of the VAA
  213. func (v *VAA) Marshal() ([]byte, error) {
  214. buf := new(bytes.Buffer)
  215. MustWrite(buf, binary.BigEndian, v.Version)
  216. MustWrite(buf, binary.BigEndian, v.GuardianSetIndex)
  217. // Write signatures
  218. MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures)))
  219. for _, sig := range v.Signatures {
  220. MustWrite(buf, binary.BigEndian, sig.Index)
  221. buf.Write(sig.Signature[:])
  222. }
  223. // Write Body
  224. body, err := v.serializeBody()
  225. if err != nil {
  226. return nil, fmt.Errorf("failed to serialize body: %w", err)
  227. }
  228. buf.Write(body)
  229. return buf.Bytes(), nil
  230. }
  231. func (v *VAA) serializeBody() ([]byte, error) {
  232. buf := new(bytes.Buffer)
  233. MustWrite(buf, binary.BigEndian, uint32(v.Timestamp.Unix()))
  234. MustWrite(buf, binary.BigEndian, v.Payload.getActionID())
  235. payloadData, err := v.Payload.serialize()
  236. if err != nil {
  237. return nil, fmt.Errorf("failed to serialize payload: %w", err)
  238. }
  239. buf.Write(payloadData)
  240. return buf.Bytes(), nil
  241. }
  242. func (v *VAA) AddSignature(key *ecdsa.PrivateKey, index uint8) {
  243. data, err := v.SigningMsg()
  244. if err != nil {
  245. panic(err)
  246. }
  247. sig, err := crypto.Sign(data.Bytes(), key)
  248. if err != nil {
  249. panic(err)
  250. }
  251. sigData := [65]byte{}
  252. copy(sigData[:], sig)
  253. v.Signatures = append(v.Signatures, &Signature{
  254. Index: index,
  255. Signature: sigData,
  256. })
  257. }
  258. func parseBodyTransfer(r io.Reader) (*BodyTransfer, error) {
  259. b := &BodyTransfer{}
  260. if err := binary.Read(r, binary.BigEndian, &b.Nonce); err != nil {
  261. return nil, fmt.Errorf("failed to read nonce: %w", err)
  262. }
  263. if err := binary.Read(r, binary.BigEndian, &b.SourceChain); err != nil {
  264. return nil, fmt.Errorf("failed to read source chain: %w", err)
  265. }
  266. if err := binary.Read(r, binary.BigEndian, &b.TargetChain); err != nil {
  267. return nil, fmt.Errorf("failed to read target chain: %w", err)
  268. }
  269. if n, err := r.Read(b.SourceAddress[:]); err != nil || n != 32 {
  270. return nil, fmt.Errorf("failed to read source address: %w", err)
  271. }
  272. if n, err := r.Read(b.TargetAddress[:]); err != nil || n != 32 {
  273. return nil, fmt.Errorf("failed to read target address: %w", err)
  274. }
  275. b.Asset = &AssetMeta{}
  276. if err := binary.Read(r, binary.BigEndian, &b.Asset.Chain); err != nil {
  277. return nil, fmt.Errorf("failed to read asset chain: %w", err)
  278. }
  279. if n, err := r.Read(b.Asset.Address[:]); err != nil || n != 32 {
  280. return nil, fmt.Errorf("failed to read asset address: %w", err)
  281. }
  282. if err := binary.Read(r, binary.BigEndian, &b.Asset.Decimals); err != nil {
  283. return nil, fmt.Errorf("failed to read asset decimals: %w", err)
  284. }
  285. var amountBytes [32]byte
  286. if n, err := r.Read(amountBytes[:]); err != nil || n != 32 {
  287. return nil, fmt.Errorf("failed to read amount: %w", err)
  288. }
  289. b.Amount = new(big.Int).SetBytes(amountBytes[:])
  290. return b, nil
  291. }
  292. func (v *BodyTransfer) getActionID() Action {
  293. return ActionTransfer
  294. }
  295. func (v *BodyTransfer) serialize() ([]byte, error) {
  296. buf := new(bytes.Buffer)
  297. MustWrite(buf, binary.BigEndian, v.Nonce)
  298. MustWrite(buf, binary.BigEndian, v.SourceChain)
  299. MustWrite(buf, binary.BigEndian, v.TargetChain)
  300. buf.Write(v.SourceAddress[:])
  301. buf.Write(v.TargetAddress[:])
  302. if v.Asset == nil {
  303. return nil, fmt.Errorf("asset is empty")
  304. }
  305. MustWrite(buf, binary.BigEndian, v.Asset.Chain)
  306. buf.Write(v.Asset.Address[:])
  307. MustWrite(buf, binary.BigEndian, v.Asset.Decimals)
  308. if v.Amount == nil {
  309. return nil, fmt.Errorf("amount is empty")
  310. }
  311. buf.Write(common.LeftPadBytes(v.Amount.Bytes(), 32))
  312. return buf.Bytes(), nil
  313. }
  314. func parseBodyGuardianSetUpdate(r io.Reader) (*BodyGuardianSetUpdate, error) {
  315. b := &BodyGuardianSetUpdate{}
  316. if err := binary.Read(r, binary.BigEndian, &b.NewIndex); err != nil {
  317. return nil, fmt.Errorf("failed to read new index: %w", err)
  318. }
  319. keyLen := uint8(0)
  320. if err := binary.Read(r, binary.BigEndian, &keyLen); err != nil {
  321. return nil, fmt.Errorf("failed to read guardianset key len: %w", err)
  322. }
  323. for i := 0; i < int(keyLen); i++ {
  324. key := common.Address{}
  325. if n, err := r.Read(key[:]); err != nil || n != 20 {
  326. return nil, fmt.Errorf("failed to read guardianset key [%d]: %w", i, err)
  327. }
  328. b.Keys = append(b.Keys, key)
  329. }
  330. return b, nil
  331. }
  332. func (v *BodyGuardianSetUpdate) getActionID() Action {
  333. return ActionGuardianSetUpdate
  334. }
  335. func (v *BodyGuardianSetUpdate) serialize() ([]byte, error) {
  336. buf := new(bytes.Buffer)
  337. MustWrite(buf, binary.BigEndian, v.NewIndex)
  338. MustWrite(buf, binary.BigEndian, uint8(len(v.Keys)))
  339. for _, key := range v.Keys {
  340. buf.Write(key.Bytes())
  341. }
  342. return buf.Bytes(), nil
  343. }
  344. func parseBodyContractUpgrade(r io.Reader) (*BodyContractUpgrade, error) {
  345. b := &BodyContractUpgrade{}
  346. if err := binary.Read(r, binary.BigEndian, &b.ChainID); err != nil {
  347. return nil, fmt.Errorf("failed to read chain id: %w", err)
  348. }
  349. if n, err := r.Read(b.NewContract[:]); err != nil || n != 32 {
  350. return nil, fmt.Errorf("failed to read new contract address: %w", err)
  351. }
  352. return b, nil
  353. }
  354. func (v *BodyContractUpgrade) getActionID() Action {
  355. return ActionContractUpgrade
  356. }
  357. func (v *BodyContractUpgrade) serialize() ([]byte, error) {
  358. buf := new(bytes.Buffer)
  359. MustWrite(buf, binary.BigEndian, v.ChainID)
  360. buf.Write(v.NewContract[:])
  361. return buf.Bytes(), nil
  362. }
  363. // MustWrite calls binary.Write and panics on errors
  364. func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
  365. if err := binary.Write(w, order, data); err != nil {
  366. panic(fmt.Errorf("failed to write binary data: %v", data).Error())
  367. }
  368. }