structs.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. package vaa
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "encoding/binary"
  6. "encoding/hex"
  7. "fmt"
  8. "io"
  9. "time"
  10. "github.com/ethereum/go-ethereum/common"
  11. "github.com/ethereum/go-ethereum/crypto"
  12. )
  13. type (
  14. // VAA is a verifiable action approval of the Wormhole protocol
  15. VAA struct {
  16. // Version of the VAA schema
  17. Version uint8
  18. // GuardianSetIndex is the index of the guardian set that signed this VAA
  19. GuardianSetIndex uint32
  20. // SignatureData is the signature of the guardian set
  21. Signatures []*Signature
  22. // Timestamp when the VAA was created
  23. Timestamp time.Time
  24. // Nonce of the VAA
  25. Nonce uint32
  26. // Sequence of the VAA
  27. Sequence uint64
  28. /// ConsistencyLevel of the VAA
  29. ConsistencyLevel uint8
  30. // EmitterChain the VAA was emitted on
  31. EmitterChain ChainID
  32. // EmitterAddress of the contract that emitted the Message
  33. EmitterAddress Address
  34. // Payload of the message
  35. Payload []byte
  36. }
  37. // ChainID of a Wormhole chain
  38. ChainID uint16
  39. // Action of a VAA
  40. Action uint8
  41. // Address is a Wormhole protocol address, it contains the native chain's address. If the address data type of a
  42. // chain is < 32bytes the value is zero-padded on the left.
  43. Address [32]byte
  44. // Signature of a single guardian
  45. Signature struct {
  46. // Index of the validator
  47. Index uint8
  48. // Signature data
  49. Signature SignatureData
  50. }
  51. SignatureData [65]byte
  52. )
  53. func (a Address) MarshalJSON() ([]byte, error) {
  54. return []byte(fmt.Sprintf(`"%s"`, a)), nil
  55. }
  56. func (a Address) String() string {
  57. return hex.EncodeToString(a[:])
  58. }
  59. func (a SignatureData) MarshalJSON() ([]byte, error) {
  60. return []byte(fmt.Sprintf(`"%s"`, a)), nil
  61. }
  62. func (a SignatureData) String() string {
  63. return hex.EncodeToString(a[:])
  64. }
  65. func (c ChainID) String() string {
  66. switch c {
  67. case ChainIDSolana:
  68. return "solana"
  69. case ChainIDEthereum:
  70. return "ethereum"
  71. case ChainIDTerra:
  72. return "terra"
  73. case ChainIDBSC:
  74. return "bsc"
  75. default:
  76. return fmt.Sprintf("unknown chain ID: %d", c)
  77. }
  78. }
  79. const (
  80. // ChainIDSolana is the ChainID of Solana
  81. ChainIDSolana ChainID = 1
  82. // ChainIDEthereum is the ChainID of Ethereum
  83. ChainIDEthereum ChainID = 2
  84. // ChainIDTerra is the ChainID of Terra
  85. ChainIDTerra ChainID = 3
  86. // ChainIDBSC is the ChainID of Binance Smart Chain
  87. ChainIDBSC ChainID = 4
  88. minVAALength = 1 + 4 + 52 + 4 + 1 + 1
  89. SupportedVAAVersion = 0x01
  90. )
  91. // Unmarshal deserializes the binary representation of a VAA
  92. func Unmarshal(data []byte) (*VAA, error) {
  93. if len(data) < minVAALength {
  94. return nil, fmt.Errorf("VAA is too short")
  95. }
  96. v := &VAA{}
  97. v.Version = data[0]
  98. if v.Version != SupportedVAAVersion {
  99. return nil, fmt.Errorf("unsupported VAA version: %d", v.Version)
  100. }
  101. reader := bytes.NewReader(data[1:])
  102. if err := binary.Read(reader, binary.BigEndian, &v.GuardianSetIndex); err != nil {
  103. return nil, fmt.Errorf("failed to read guardian set index: %w", err)
  104. }
  105. lenSignatures, er := reader.ReadByte()
  106. if er != nil {
  107. return nil, fmt.Errorf("failed to read signature length")
  108. }
  109. v.Signatures = make([]*Signature, lenSignatures)
  110. for i := 0; i < int(lenSignatures); i++ {
  111. index, err := reader.ReadByte()
  112. if err != nil {
  113. return nil, fmt.Errorf("failed to read validator index [%d]", i)
  114. }
  115. signature := [65]byte{}
  116. if n, err := reader.Read(signature[:]); err != nil || n != 65 {
  117. return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
  118. }
  119. v.Signatures[i] = &Signature{
  120. Index: index,
  121. Signature: signature,
  122. }
  123. }
  124. unixSeconds := uint32(0)
  125. if err := binary.Read(reader, binary.BigEndian, &unixSeconds); err != nil {
  126. return nil, fmt.Errorf("failed to read timestamp: %w", err)
  127. }
  128. v.Timestamp = time.Unix(int64(unixSeconds), 0)
  129. if err := binary.Read(reader, binary.BigEndian, &v.Nonce); err != nil {
  130. return nil, fmt.Errorf("failed to read nonce: %w", err)
  131. }
  132. if err := binary.Read(reader, binary.BigEndian, &v.EmitterChain); err != nil {
  133. return nil, fmt.Errorf("failed to read emitter chain: %w", err)
  134. }
  135. emitterAddress := Address{}
  136. if n, err := reader.Read(emitterAddress[:]); err != nil || n != 32 {
  137. return nil, fmt.Errorf("failed to read emitter address [%d]: %w", n, err)
  138. }
  139. v.EmitterAddress = emitterAddress
  140. if err := binary.Read(reader, binary.BigEndian, &v.Sequence); err != nil {
  141. return nil, fmt.Errorf("failed to read sequence: %w", err)
  142. }
  143. if err := binary.Read(reader, binary.BigEndian, &v.ConsistencyLevel); err != nil {
  144. return nil, fmt.Errorf("failed to read commitment: %w", err)
  145. }
  146. payload := make([]byte, 1000)
  147. n, err := reader.Read(payload)
  148. if err != nil || n == 0 {
  149. return nil, fmt.Errorf("failed to read payload [%d]: %w", n, err)
  150. }
  151. v.Payload = payload[:n]
  152. return v, nil
  153. }
  154. // signingBody returns the binary representation of the data that is relevant for signing and verifying the VAA
  155. func (v *VAA) signingBody() ([]byte, error) {
  156. return v.serializeBody()
  157. }
  158. // SigningMsg returns the hash of the signing body. This is used for signature generation and verification
  159. func (v *VAA) SigningMsg() (common.Hash, error) {
  160. body, err := v.signingBody()
  161. if err != nil {
  162. // Should never happen on a successfully parsed VAA
  163. return common.Hash{}, fmt.Errorf("failed to serialize signing body: %w", err)
  164. }
  165. // In order to save space in the solana signature verification instruction, we hash twice so we only need to pass in
  166. // the first hash (32 bytes) vs the full body data.
  167. hash := crypto.Keccak256Hash(crypto.Keccak256Hash(body).Bytes())
  168. return hash, nil
  169. }
  170. // VerifySignature verifies the signature of the VAA given the signer addresses.
  171. func (v *VAA) VerifySignatures(addresses []common.Address) bool {
  172. if len(addresses) < len(v.Signatures) {
  173. return false
  174. }
  175. h, err := v.SigningMsg()
  176. if err != nil {
  177. return false
  178. }
  179. for _, sig := range v.Signatures {
  180. if int(sig.Index) >= len(addresses) {
  181. return false
  182. }
  183. pubKey, err := crypto.Ecrecover(h.Bytes(), sig.Signature[:])
  184. if err != nil {
  185. return false
  186. }
  187. addr := common.BytesToAddress(crypto.Keccak256(pubKey[1:])[12:])
  188. if addr != addresses[sig.Index] {
  189. return false
  190. }
  191. }
  192. return true
  193. }
  194. // Marshal returns the binary representation of the VAA
  195. func (v *VAA) Marshal() ([]byte, error) {
  196. buf := new(bytes.Buffer)
  197. MustWrite(buf, binary.BigEndian, v.Version)
  198. MustWrite(buf, binary.BigEndian, v.GuardianSetIndex)
  199. // Write signatures
  200. MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures)))
  201. for _, sig := range v.Signatures {
  202. MustWrite(buf, binary.BigEndian, sig.Index)
  203. buf.Write(sig.Signature[:])
  204. }
  205. // Write Body
  206. body, err := v.serializeBody()
  207. if err != nil {
  208. return nil, fmt.Errorf("failed to serialize body: %w", err)
  209. }
  210. buf.Write(body)
  211. return buf.Bytes(), nil
  212. }
  213. // MessageID returns a human-readable emitter_chain/emitter_address/sequence tuple.
  214. func (v *VAA) MessageID() string {
  215. return fmt.Sprintf("%d/%s/%d", v.EmitterChain, v.EmitterAddress, v.Sequence)
  216. }
  217. func (v *VAA) serializeBody() ([]byte, error) {
  218. buf := new(bytes.Buffer)
  219. MustWrite(buf, binary.BigEndian, uint32(v.Timestamp.Unix()))
  220. MustWrite(buf, binary.BigEndian, v.Nonce)
  221. MustWrite(buf, binary.BigEndian, v.EmitterChain)
  222. buf.Write(v.EmitterAddress[:])
  223. MustWrite(buf, binary.BigEndian, v.Sequence)
  224. MustWrite(buf, binary.BigEndian, v.ConsistencyLevel)
  225. buf.Write(v.Payload)
  226. return buf.Bytes(), nil
  227. }
  228. func (v *VAA) AddSignature(key *ecdsa.PrivateKey, index uint8) {
  229. data, err := v.SigningMsg()
  230. if err != nil {
  231. panic(err)
  232. }
  233. sig, err := crypto.Sign(data.Bytes(), key)
  234. if err != nil {
  235. panic(err)
  236. }
  237. sigData := [65]byte{}
  238. copy(sigData[:], sig)
  239. v.Signatures = append(v.Signatures, &Signature{
  240. Index: index,
  241. Signature: sigData,
  242. })
  243. }
  244. // MustWrite calls binary.Write and panics on errors
  245. func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
  246. if err := binary.Write(w, order, data); err != nil {
  247. panic(fmt.Errorf("failed to write binary data: %v", data).Error())
  248. }
  249. }