structs.go 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. package vaa
  2. import (
  3. "bytes"
  4. "crypto/ecdsa"
  5. "encoding"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "io"
  12. "math"
  13. "math/big"
  14. "strconv"
  15. "strings"
  16. "time"
  17. "github.com/ethereum/go-ethereum/common"
  18. "github.com/ethereum/go-ethereum/crypto"
  19. )
  20. type (
  21. // VAA is a verifiable action approval of the Wormhole protocol
  22. VAA struct {
  23. // Version of the VAA schema
  24. Version uint8
  25. // GuardianSetIndex is the index of the guardian set that signed this VAA
  26. GuardianSetIndex uint32
  27. // SignatureData is the signature of the guardian set
  28. Signatures []*Signature
  29. // Timestamp when the VAA was created
  30. Timestamp time.Time
  31. // Nonce of the VAA
  32. Nonce uint32
  33. // Sequence of the VAA
  34. Sequence uint64
  35. /// ConsistencyLevel of the VAA
  36. ConsistencyLevel uint8
  37. // EmitterChain the VAA was emitted on
  38. EmitterChain ChainID
  39. // EmitterAddress of the contract that emitted the Message
  40. EmitterAddress Address
  41. // Payload of the message
  42. Payload []byte
  43. }
  44. // ChainID of a Wormhole chain
  45. ChainID uint16
  46. // Action of a VAA
  47. Action uint8
  48. // Address is a Wormhole protocol address, it contains the native chain's address. If the address data type of a
  49. // chain is < 32bytes the value is zero-padded on the left.
  50. Address [32]byte
  51. // Signature of a single guardian
  52. Signature struct {
  53. // Index of the validator
  54. Index uint8
  55. // Signature data
  56. Signature SignatureData
  57. }
  58. SignatureData [65]byte
  59. Observation struct {
  60. // Index of the observation in a Batch array
  61. Index uint8
  62. // Signed Observation data
  63. Observation *VAA
  64. }
  65. TransferPayloadHdr struct {
  66. Type uint8
  67. Amount *big.Int
  68. OriginAddress Address
  69. OriginChain ChainID
  70. TargetAddress Address
  71. TargetChain ChainID
  72. }
  73. // Attestation interface contains the methods common to all VAA types
  74. Attestation interface {
  75. encoding.BinaryMarshaler
  76. encoding.BinaryUnmarshaler
  77. serializeBody()
  78. signingBody() []byte
  79. SigningMsg() common.Hash
  80. VerifySignatures(addrs []common.Address) bool
  81. UniqueID() string
  82. HexDigest() string
  83. AddSignature(key *ecdsa.PrivateKey, index uint8)
  84. GetEmitterChain() ChainID
  85. }
  86. // number is a constraint for generic functions that can safely convert integer types to a ChainID (uint16).
  87. number interface {
  88. ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
  89. }
  90. )
  91. const (
  92. ConsistencyLevelPublishImmediately = uint8(200)
  93. ConsistencyLevelSafe = uint8(201)
  94. ConsistencyLevelFinalized = uint8(202)
  95. ConsistencyLevelCustom = uint8(203)
  96. )
  97. //nolint:unparam // error is always nil here but the return type is required to satisfy the interface.
  98. func (a Address) MarshalJSON() ([]byte, error) {
  99. return []byte(fmt.Sprintf(`"%s"`, a)), nil
  100. }
  101. // Standard marshal stores the Address like this: "[0,0,0,0,0,0,0,0,0,0,0,0,2,144,251,22,114,8,175,69,91,177,55,120,1,99,183,183,169,161,12,22]"
  102. // The above MarshalJSON stores it like this (66 bytes): ""0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16""
  103. func (a *Address) UnmarshalJSON(data []byte) error {
  104. addr, err := StringToAddress(strings.Trim(string(data), `"`))
  105. if err != nil {
  106. return err
  107. }
  108. *a = addr
  109. return nil
  110. }
  111. func (a Address) String() string {
  112. return hex.EncodeToString(a[:])
  113. }
  114. func (a Address) Bytes() []byte {
  115. return a[:]
  116. }
  117. //nolint:unparam // error is always nil here but the return type is required to satisfy the interface.
  118. func (a SignatureData) MarshalJSON() ([]byte, error) {
  119. return []byte(fmt.Sprintf(`"%s"`, a)), nil
  120. }
  121. func (a SignatureData) String() string {
  122. return hex.EncodeToString(a[:])
  123. }
  124. // ChainIDFromNumber converts an unsigned integer into a ChainID. This function only determines whether the input is valid
  125. // with respect to its type; it does not check whether the ChainID is actually registered or used anywhere.
  126. // This function can be used to validate ChainID values that are deserialized from protobuf messages. (As protobuf
  127. // does not support the uint16 type, ChainIDs are usually encoded as uint32.)
  128. // https://protobuf.dev/reference/protobuf/proto3-spec/#fields
  129. // Returns an error if the argument would overflow uint16.
  130. func ChainIDFromNumber[N number](n N) (ChainID, error) {
  131. if n < 0 {
  132. return ChainIDUnset, fmt.Errorf("chainID cannot be negative but got %d", n)
  133. }
  134. switch any(n).(type) {
  135. case int8, uint8, int16, uint16:
  136. // Because these values have been checked to be non-negative, we can return early with a simple conversion.
  137. return ChainID(n), nil
  138. }
  139. // Use intermediate uint64 to safely handle conversion and allow comparison with MaxUint16.
  140. // This is safe to do because the negative case is already handled.
  141. val := uint64(n)
  142. if val > uint64(math.MaxUint16) {
  143. return ChainIDUnset, fmt.Errorf("chainID must be less than or equal to %d but got %d", math.MaxUint16, n)
  144. }
  145. return ChainID(n), nil
  146. }
  147. // KnownChainIDFromNumber converts an unsigned integer into a known ChainID. It is a wrapper function for ChainIDFromNumber
  148. // that also checks whether the ChainID corresponds to a real, configured chain.
  149. func KnownChainIDFromNumber[N number](n N) (ChainID, error) {
  150. id, err := ChainIDFromNumber(n)
  151. if err != nil {
  152. return ChainIDUnset, err
  153. }
  154. // NOTE: slice.Contains is not used here because some SDK integrators (e.g. wormchain, maybe others) use old versions of Go.
  155. for _, known := range GetAllNetworkIDs() {
  156. if id == known {
  157. return id, nil
  158. }
  159. }
  160. return ChainIDUnset, fmt.Errorf("no known ChainID for input %d", n)
  161. }
  162. // StringToKnownChainID converts from a string representation of a chain into a ChainID that is registered in the SDK.
  163. // The argument can be either a numeric string representation of a number or a known chain name such as "solana".
  164. // Inputs of unknown ChainIDs, including 0, will result in an error.
  165. func StringToKnownChainID(s string) (ChainID, error) {
  166. // Try to convert from chain name first, and return early if it's found.
  167. id, err := ChainIDFromString(s)
  168. if err == nil {
  169. return id, nil
  170. }
  171. // Ensure that the string can be parsed into a uint16 in order to avoid overflow issues when converting
  172. // to ChainID (which is a uint16).
  173. u16, err := strconv.ParseUint(s, 10, 16)
  174. if err != nil {
  175. return ChainIDUnset, err
  176. }
  177. return KnownChainIDFromNumber(u16)
  178. }
  179. // NOTE: Please keep these in numerical order.
  180. const (
  181. ChainIDUnset ChainID = 0
  182. // ChainIDSolana is the ChainID of Solana
  183. ChainIDSolana ChainID = 1
  184. // ChainIDEthereum is the ChainID of Ethereum
  185. ChainIDEthereum ChainID = 2
  186. // WARNING: ChainIDTerra is only supported in devnet / Tilt.
  187. ChainIDTerra ChainID = 3
  188. // ChainIDBSC is the ChainID of Binance Smart Chain
  189. ChainIDBSC ChainID = 4
  190. // ChainIDPolygon is the ChainID of Polygon
  191. ChainIDPolygon ChainID = 5
  192. // ChainIDAvalanche is the ChainID of Avalanche
  193. ChainIDAvalanche ChainID = 6
  194. // OBSOLETE: ChainIDOasis ChainID = 7
  195. // ChainIDAlgorand is the ChainID of Algorand
  196. ChainIDAlgorand ChainID = 8
  197. // OBSOLETE: ChainIDAurora ChainID = 9
  198. // ChainIDFantom is the ChainID of Fantom
  199. ChainIDFantom ChainID = 10
  200. // OBSOLETE: ChainIDKarura ChainID = 11
  201. // OBSOLETE: ChainIDAcala ChainID = 12
  202. // ChainIDKlaytn is the ChainID of Klaytn
  203. ChainIDKlaytn ChainID = 13
  204. // ChainIDCelo is the ChainID of Celo
  205. ChainIDCelo ChainID = 14
  206. // ChainIDNear is the ChainID of Near
  207. ChainIDNear ChainID = 15
  208. // ChainIDMoonbeam is the ChainID of Moonbeam
  209. ChainIDMoonbeam ChainID = 16
  210. // OBSOLETE: ChainIDNeon ChainID = 17
  211. // WARNING: ChainIDTerra2 is only supported in devnet / Tilt.
  212. ChainIDTerra2 ChainID = 18
  213. // ChainIDInjective is the ChainID of Injective
  214. ChainIDInjective ChainID = 19
  215. // ChainIDOsmosis is the ChainID of Osmosis
  216. ChainIDOsmosis ChainID = 20
  217. // ChainIDSui is the ChainID of Sui
  218. ChainIDSui ChainID = 21
  219. // ChainIDAptos is the ChainID of Aptos
  220. ChainIDAptos ChainID = 22
  221. // ChainIDArbitrum is the ChainID of Arbitrum
  222. ChainIDArbitrum ChainID = 23
  223. // ChainIDOptimism is the ChainID of Optimism
  224. ChainIDOptimism ChainID = 24
  225. // ChainIDGnosis is the ChainID of Gnosis
  226. ChainIDGnosis ChainID = 25
  227. // ChainIDPythNet is the ChainID of PythNet
  228. ChainIDPythNet ChainID = 26
  229. // NOTE: 27 belongs to a chain that was never deployed.
  230. // OBSOLETE: ChainIDXpla ChainID = 28
  231. // ChainIDBtc is the ChainID of Bitcoin
  232. ChainIDBtc ChainID = 29
  233. // ChainIDBase is the ChainID of Base
  234. ChainIDBase ChainID = 30
  235. // ChainIDFileCoin is the ChainID of FileCoin
  236. ChainIDFileCoin ChainID = 31
  237. // ChainIDSei is the ChainID of Sei
  238. ChainIDSei ChainID = 32
  239. // ChainIDRootstock is the ChainID of Rootstock
  240. ChainIDRootstock ChainID = 33
  241. // ChainIDScroll is the ChainID of Scroll
  242. ChainIDScroll ChainID = 34
  243. // ChainIDMantle is the ChainID of Mantle
  244. ChainIDMantle ChainID = 35
  245. // OBSOLETE: ChainIDBlast ChainID = 36
  246. // ChainIDXLayer is the ChainID of XLayer
  247. ChainIDXLayer ChainID = 37
  248. // ChainIDLinea is the ChainID of Linea
  249. ChainIDLinea ChainID = 38
  250. // ChainIDBerachain is the ChainID of Berachain
  251. ChainIDBerachain ChainID = 39
  252. // ChainIDSeiEVM is the ChainID of SeiEVM
  253. ChainIDSeiEVM ChainID = 40
  254. // ChainIDEclipse is the ChainID of Eclipse
  255. ChainIDEclipse ChainID = 41
  256. // ChainIDBOB is the ChainID of BOB
  257. ChainIDBOB ChainID = 42
  258. // OBSOLETE: ChainIDSnaxchain ChainID = 43
  259. // ChainIDUnichain is the ChainID of Unichain
  260. ChainIDUnichain ChainID = 44
  261. // ChainIDWorldchain is the ChainID of Worldchain
  262. ChainIDWorldchain ChainID = 45
  263. // ChainIDInk is the ChainID of Ink
  264. ChainIDInk ChainID = 46
  265. // ChainIDHyperEVM is the ChainID of HyperEVM
  266. ChainIDHyperEVM ChainID = 47
  267. // ChainIDMonad is the ChainID of Monad
  268. ChainIDMonad ChainID = 48
  269. // ChainIDMovement is the ChainID of Movement
  270. ChainIDMovement ChainID = 49
  271. // ChainIDMezo is the ChainID of Mezo
  272. ChainIDMezo ChainID = 50
  273. // ChainIDFogo is the ChainID of Fogo
  274. ChainIDFogo ChainID = 51
  275. // ChainIDSonic is the ChainID of Sonic
  276. ChainIDSonic ChainID = 52
  277. // ChainIDConverge is the ChainID of Converge
  278. ChainIDConverge ChainID = 53
  279. // ChainIDCodex is the ChainID of Codex
  280. ChainIDCodex ChainID = 54
  281. // ChainIdPlume is the ChainID of Plume
  282. ChainIDPlume ChainID = 55
  283. // ChainIdAztec is the ChainID of Aztec
  284. ChainIDAztec ChainID = 56
  285. // ChainIdXRPLEVM is the ChainID of XRPL-EVM
  286. ChainIDXRPLEVM ChainID = 57
  287. // ChainIDPlasma is the ChainID of Plasma
  288. ChainIDPlasma ChainID = 58
  289. // ChainIDCreditCoin is the ChainID of CreditCoin
  290. ChainIDCreditCoin ChainID = 59
  291. // ChainIDStacks is the ChainID of Stacks
  292. ChainIDStacks ChainID = 60
  293. // ChainIDStellar is the ChainID of Stellar
  294. ChainIDStellar ChainID = 61
  295. // ChainIDTON is the ChainID of TON
  296. ChainIDTON ChainID = 62
  297. // ChainIDMoca is the ChainID of Moca
  298. ChainIDMoca ChainID = 63
  299. // ChainIDWormchain is the ChainID of Wormchain and is in its own range.
  300. ChainIDWormchain ChainID = 3104
  301. // The IBC chains start at 4000.
  302. // ChainIDCosmoshub is the ChainID of Cosmoshub
  303. ChainIDCosmoshub ChainID = 4000
  304. // ChainIDEvmos is the ChainID of Evmos
  305. ChainIDEvmos ChainID = 4001
  306. // ChainIDKujira is the ChainID of Kujira
  307. ChainIDKujira ChainID = 4002
  308. // ChainIDNeutron is the ChainID of Neutron
  309. ChainIDNeutron ChainID = 4003
  310. // ChainIDCelestia is the ChainID of Celestia
  311. ChainIDCelestia ChainID = 4004
  312. // ChainIDStargaze is the ChainID of Stargaze
  313. ChainIDStargaze ChainID = 4005
  314. // ChainIDSeda is the ChainID of Seda
  315. ChainIDSeda ChainID = 4006
  316. // ChainIDDymension is the ChainID of Dymension
  317. ChainIDDymension ChainID = 4007
  318. // ChainIDProvenance is the ChainID of Provenance
  319. ChainIDProvenance ChainID = 4008
  320. // ChainIDNoble is the ChainID of Noble
  321. ChainIDNoble ChainID = 4009
  322. // The Testnet only chains start at 10000.
  323. // ChainIDSepolia is the ChainID of Sepolia
  324. ChainIDSepolia ChainID = 10002
  325. // ChainIDArbitrumSepolia is the ChainID of Arbitrum on Sepolia
  326. ChainIDArbitrumSepolia ChainID = 10003
  327. // ChainIDBaseSepolia is the ChainID of Base on Sepolia
  328. ChainIDBaseSepolia ChainID = 10004
  329. // ChainIDOptimismSepolia is the ChainID of Optimism on Sepolia
  330. ChainIDOptimismSepolia ChainID = 10005
  331. // ChainIDHolesky is the ChainID of Holesky
  332. ChainIDHolesky ChainID = 10006
  333. // ChainIDPolygonSepolia is the ChainID of Polygon on Sepolia
  334. ChainIDPolygonSepolia ChainID = 10007
  335. // OBSOLETE: ChainIDMonadDevnet ChainID = 10008
  336. // Minimum VAA size is derrived from the following assumptions:
  337. // HEADER
  338. // - Supported VAA Version (1 byte)
  339. // - Guardian Set Index (4 bytes)
  340. // - Length of Signatures (1 byte) <== assume no signatures
  341. // - Actual Signatures (0 bytes)
  342. // BODY
  343. // - timestamp (4 bytes)
  344. // - nonce (4 bytes)
  345. // - emitter chain (2 bytes)
  346. // - emitter address (32 bytes)
  347. // - sequence (8 bytes)
  348. // - consistency level (1 byte)
  349. // - payload (0 bytes)
  350. // BATCH
  351. // - Length of Observation Hashes (1 byte) <== minimum one
  352. // - Observation Hash (32 bytes)
  353. // - Length of Observations (1 byte) <== minimum one
  354. // - Observation Index (1 byte)
  355. // - Observation Length (1 byte)
  356. // - Observation, aka BODY, aka Headless (51 bytes)
  357. // From Above:
  358. // HEADER: 1 + 4 + 1 + 0 = 6
  359. // BODY: 4 + 4 + 2 + 32 + 8 + 1 + 0 = 51
  360. // BATCH: 1 + 32 + 1 + 1 + 1 + 51 = 88
  361. //
  362. // More details here: https://docs.wormholenetwork.com/wormhole/vaas
  363. minHeadlessVAALength = 51 // HEADER
  364. minVAALength = 57 // HEADER + BODY
  365. SupportedVAAVersion = 0x01
  366. )
  367. // UnmarshalBody deserializes the binary representation of a VAA's "BODY" properties
  368. // The BODY fields are common among multiple types of VAA - v1, v2, etc
  369. // parameter. This function should probably be reworked as a method of the VAA type.
  370. //
  371. //nolint:unparam // TODO: The argument data is not used here. Instead data is read from the VAA
  372. func UnmarshalBody(data []byte, reader *bytes.Reader, v *VAA) (*VAA, error) {
  373. unixSeconds := uint32(0)
  374. if err := binary.Read(reader, binary.BigEndian, &unixSeconds); err != nil {
  375. return nil, fmt.Errorf("failed to read timestamp: %w", err)
  376. }
  377. v.Timestamp = time.Unix(int64(unixSeconds), 0)
  378. if err := binary.Read(reader, binary.BigEndian, &v.Nonce); err != nil {
  379. return nil, fmt.Errorf("failed to read nonce: %w", err)
  380. }
  381. if err := binary.Read(reader, binary.BigEndian, &v.EmitterChain); err != nil {
  382. return nil, fmt.Errorf("failed to read emitter chain: %w", err)
  383. }
  384. emitterAddress := Address{}
  385. if n, err := reader.Read(emitterAddress[:]); err != nil || n != 32 {
  386. return nil, fmt.Errorf("failed to read emitter address [%d]: %w", n, err)
  387. }
  388. v.EmitterAddress = emitterAddress
  389. if err := binary.Read(reader, binary.BigEndian, &v.Sequence); err != nil {
  390. return nil, fmt.Errorf("failed to read sequence: %w", err)
  391. }
  392. if err := binary.Read(reader, binary.BigEndian, &v.ConsistencyLevel); err != nil {
  393. return nil, fmt.Errorf("failed to read commitment: %w", err)
  394. }
  395. // Make sure to only read the payload if the VAA has one; VAAs may have a 0 length payload
  396. if reader.Len() != 0 {
  397. payload := make([]byte, reader.Len())
  398. n, err := reader.Read(payload)
  399. if err != nil {
  400. return nil, fmt.Errorf("failed to read payload [%d]: %w", n, err)
  401. }
  402. v.Payload = payload[:n]
  403. } else {
  404. v.Payload = []byte{}
  405. }
  406. return v, nil
  407. }
  408. // Unmarshal deserializes the binary representation of a VAA
  409. func Unmarshal(data []byte) (*VAA, error) {
  410. if len(data) < minVAALength {
  411. return nil, fmt.Errorf("VAA is too short")
  412. }
  413. v := &VAA{}
  414. v.Version = data[0]
  415. if v.Version != SupportedVAAVersion {
  416. return nil, fmt.Errorf("unsupported VAA version: %d", v.Version)
  417. }
  418. reader := bytes.NewReader(data[1:])
  419. if err := binary.Read(reader, binary.BigEndian, &v.GuardianSetIndex); err != nil {
  420. return nil, fmt.Errorf("failed to read guardian set index: %w", err)
  421. }
  422. lenSignatures, er := reader.ReadByte()
  423. if er != nil {
  424. return nil, fmt.Errorf("failed to read signature length")
  425. }
  426. v.Signatures = make([]*Signature, lenSignatures)
  427. for i := 0; i < int(lenSignatures); i++ {
  428. index, err := reader.ReadByte()
  429. if err != nil {
  430. return nil, fmt.Errorf("failed to read validator index [%d]", i)
  431. }
  432. signature := [65]byte{}
  433. if n, err := reader.Read(signature[:]); err != nil || n != 65 {
  434. return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
  435. }
  436. v.Signatures[i] = &Signature{
  437. Index: index,
  438. Signature: signature,
  439. }
  440. }
  441. return UnmarshalBody(data, reader, v)
  442. }
  443. // signingBody returns the binary representation of the data that is relevant for signing and verifying the VAA
  444. func (v *VAA) signingBody() []byte {
  445. return v.serializeBody()
  446. }
  447. func doubleKeccak(bz []byte) common.Hash {
  448. // In order to save space in the solana signature verification instruction, we hash twice so we only need to pass in
  449. // the first hash (32 bytes) vs the full body data.
  450. return crypto.Keccak256Hash(crypto.Keccak256Hash(bz).Bytes())
  451. }
  452. // This is a temporary method to produce a vaa signing digest on raw bytes.
  453. // It is error prone and we should use `v.SigningDigest()` instead.
  454. // whenever possible.
  455. // This will be removed in a subsequent release.
  456. func DeprecatedSigningDigest(bz []byte) common.Hash {
  457. return doubleKeccak(bz)
  458. }
  459. // MessageSigningDigest returns the hash of the data prepended with it's signing prefix.
  460. // This is intending to be used for signing messages of different types from VAA's.
  461. // The message prefix helps protect from message collisions.
  462. func MessageSigningDigest(prefix []byte, data []byte) (common.Hash, error) {
  463. if len(prefix) < 32 {
  464. // Prefixes must be at least 32 bytes
  465. // https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0009_guardian_signer.md
  466. return common.Hash([32]byte{}), errors.New("prefix must be at least 32 bytes")
  467. }
  468. return crypto.Keccak256Hash(prefix[:], data), nil
  469. }
  470. // SigningDigest returns the hash of the vaa hash to be signed directly.
  471. // This is used for signature generation and verification
  472. func (v *VAA) SigningDigest() common.Hash {
  473. return doubleKeccak(v.signingBody())
  474. }
  475. // Verify Signature checks that the provided address matches the address that created the signature for the provided digest
  476. // Digest should be the output of SigningMsg(data).Bytes()
  477. // Should not be public as other message types should be verified using a message prefix.
  478. func verifySignature(vaa_digest []byte, signature *Signature, address common.Address) bool {
  479. // retrieve the address that signed the data
  480. pubKey, err := crypto.Ecrecover(vaa_digest, signature.Signature[:])
  481. if err != nil {
  482. return false
  483. }
  484. addr := common.BytesToAddress(crypto.Keccak256(pubKey[1:])[12:])
  485. // check that the recovered address equals the provided address
  486. return addr == address
  487. }
  488. // Digest should be the output of SigningMsg(data).Bytes()
  489. // Should not be public as other message types should be verified using a message prefix.
  490. // Returns false when the signatures or addresses are empty.
  491. func verifySignatures(vaa_digest []byte, signatures []*Signature, addresses []common.Address) bool {
  492. // An empty set is neither valid nor invalid, it's just specified incorrectly.
  493. // To help with backward-compatibility, return false instead of changing the function
  494. // signature to return an error.
  495. if len(signatures) == 0 || len(addresses) == 0 {
  496. return false
  497. }
  498. if len(addresses) < len(signatures) {
  499. return false
  500. }
  501. last_index := -1
  502. signing_addresses := []common.Address{}
  503. for _, sig := range signatures {
  504. if int(sig.Index) >= len(addresses) {
  505. return false
  506. }
  507. // Ensure increasing indexes
  508. if int(sig.Index) <= last_index {
  509. return false
  510. }
  511. last_index = int(sig.Index)
  512. // verify this signature
  513. addr := addresses[sig.Index]
  514. ok := verifySignature(vaa_digest, sig, addr)
  515. if !ok {
  516. return false
  517. }
  518. // Ensure we never see the same signer twice
  519. for _, signing_address := range signing_addresses {
  520. if signing_address == addr {
  521. return false
  522. }
  523. }
  524. signing_addresses = append(signing_addresses, addr)
  525. }
  526. return true
  527. }
  528. // Operating on bytes directly is error prone. We should use `vaa.VerifyingSignatures()` whenever possible.
  529. // This function will be removed in a subsequent release.
  530. func DeprecatedVerifySignatures(vaaBody []byte, signatures []*Signature, addresses []common.Address) bool {
  531. vaaDigest := doubleKeccak(vaaBody)
  532. return verifySignatures(vaaDigest[:], signatures, addresses)
  533. }
  534. func VerifyMessageSignature(prefix []byte, messageBody []byte, signatures *Signature, addresses common.Address) bool {
  535. if len(prefix) < 32 {
  536. return false
  537. }
  538. msgDigest, err := MessageSigningDigest(prefix, messageBody)
  539. if err != nil {
  540. return false
  541. }
  542. return verifySignature(msgDigest[:], signatures, addresses)
  543. }
  544. // VerifySignatures verifies the signature of the VAA given the signer addresses.
  545. // Returns true if the signatures were verified successfully.
  546. // Returns false when the signatures or addresses are empty.
  547. //
  548. // WARNING: This function is not sufficient for validating a VAA as it does not consider
  549. // signature quorum. [VAA.Verify] should be used instead.
  550. func (v *VAA) VerifySignatures(addresses []common.Address) bool {
  551. return verifySignatures(v.SigningDigest().Bytes(), v.Signatures, addresses)
  552. }
  553. // Verify is a function on the VAA that takes a complete set of guardian keys as input and attempts certain checks with respect to this guardian.
  554. // Verify will return nil if the VAA passes checks. Otherwise, Verify will return an error containing the text of the first check to fail.
  555. // NOTE: Verify will not work correctly if a subset of the guardian set keys is passed in. The complete guardian set must be passed in.
  556. // Verify does the following checks:
  557. // - If the guardian does not have or know its own guardian set keys, then the VAA cannot be verified.
  558. // - Quorum is calculated on the guardian set passed in and checks if the VAA has enough signatures.
  559. // - The signatures in the VAA is verified against the guardian set keys.
  560. func (v *VAA) Verify(addresses []common.Address) error {
  561. if addresses == nil {
  562. return errors.New("no addresses were provided")
  563. }
  564. // Check if VAA doesn't have any signatures
  565. if len(v.Signatures) == 0 {
  566. return errors.New("VAA was not signed")
  567. }
  568. // Verify VAA has enough signatures for quorum
  569. quorum := CalculateQuorum(len(addresses))
  570. if len(v.Signatures) < quorum {
  571. return errors.New("VAA did not have a quorum")
  572. }
  573. // Verify VAA signatures to prevent a DoS attack on our local store.
  574. if !v.VerifySignatures(addresses) {
  575. return errors.New("VAA had bad signatures")
  576. }
  577. return nil
  578. }
  579. // Marshal returns the binary representation of the VAA
  580. func (v *VAA) Marshal() ([]byte, error) {
  581. buf := new(bytes.Buffer)
  582. MustWrite(buf, binary.BigEndian, v.Version)
  583. MustWrite(buf, binary.BigEndian, v.GuardianSetIndex)
  584. // Write signatures
  585. MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures))) // #nosec G115 -- There will never be 256 guardians
  586. for _, sig := range v.Signatures {
  587. MustWrite(buf, binary.BigEndian, sig.Index)
  588. buf.Write(sig.Signature[:])
  589. }
  590. // Write Body
  591. buf.Write(v.serializeBody())
  592. return buf.Bytes(), nil
  593. }
  594. // implement encoding.BinaryMarshaler interface for the VAA struct
  595. func (v VAA) MarshalBinary() ([]byte, error) {
  596. return v.Marshal()
  597. }
  598. // implement encoding.BinaryUnmarshaler interface for the VAA struct
  599. func (v *VAA) UnmarshalBinary(data []byte) error {
  600. vaa, err := Unmarshal(data)
  601. if err != nil {
  602. return err
  603. }
  604. // derefernce the stuct created by Unmarshal, and assign it to the method's context
  605. *v = *vaa
  606. return nil
  607. }
  608. // MessageID returns a human-readable emitter_chain/emitter_address/sequence tuple.
  609. func (v *VAA) MessageID() string {
  610. return fmt.Sprintf("%d/%s/%d", v.EmitterChain, v.EmitterAddress, v.Sequence)
  611. }
  612. // UniqueID normalizes the ID of the VAA (any type) for the Attestation interface
  613. // UniqueID returns the MessageID that uniquely identifies the Attestation
  614. func (v *VAA) UniqueID() string {
  615. return v.MessageID()
  616. }
  617. // HexDigest returns the hex-encoded digest.
  618. func (v *VAA) HexDigest() string {
  619. return hex.EncodeToString(v.SigningDigest().Bytes())
  620. }
  621. /*
  622. SECURITY: Do not change this code! Changing it could result in two different hashes for
  623. the same observation. But xDapps rely on the hash of an observation for replay protection.
  624. */
  625. func (v *VAA) serializeBody() []byte {
  626. buf := new(bytes.Buffer)
  627. MustWrite(buf, binary.BigEndian, uint32(v.Timestamp.Unix())) // #nosec G115 -- This conversion is safe until year 2106
  628. MustWrite(buf, binary.BigEndian, v.Nonce)
  629. MustWrite(buf, binary.BigEndian, v.EmitterChain)
  630. buf.Write(v.EmitterAddress[:])
  631. MustWrite(buf, binary.BigEndian, v.Sequence)
  632. MustWrite(buf, binary.BigEndian, v.ConsistencyLevel)
  633. buf.Write(v.Payload)
  634. return buf.Bytes()
  635. }
  636. func (v *VAA) AddSignature(key *ecdsa.PrivateKey, index uint8) {
  637. sig, err := crypto.Sign(v.SigningDigest().Bytes(), key)
  638. if err != nil {
  639. panic(err)
  640. }
  641. sigData := [65]byte{}
  642. copy(sigData[:], sig)
  643. v.Signatures = append(v.Signatures, &Signature{
  644. Index: index,
  645. Signature: sigData,
  646. })
  647. }
  648. // NOTE: This function assumes that the caller has verified that the VAA is from the token bridge.
  649. func IsTransfer(payload []byte) bool {
  650. return (len(payload) > 0) && ((payload[0] == 1) || (payload[0] == 3))
  651. }
  652. func DecodeTransferPayloadHdr(payload []byte) (*TransferPayloadHdr, error) {
  653. if !IsTransfer(payload) {
  654. return nil, fmt.Errorf("unsupported payload type")
  655. }
  656. if len(payload) < 101 {
  657. return nil, fmt.Errorf("buffer too short")
  658. }
  659. p := &TransferPayloadHdr{}
  660. // Payload type: payload[0]
  661. p.Type = uint8(payload[0])
  662. // Amount: payload[1] for 32
  663. p.Amount = new(big.Int)
  664. p.Amount.SetBytes(payload[1:33])
  665. reader := bytes.NewReader(payload[33:])
  666. // Origin address: payload[33] for 32
  667. err := binary.Read(reader, binary.BigEndian, &p.OriginAddress)
  668. if err != nil {
  669. return nil, err
  670. }
  671. // Origin chain ID: payload[65] for 2
  672. err = binary.Read(reader, binary.BigEndian, &p.OriginChain)
  673. if err != nil {
  674. return nil, err
  675. }
  676. // Target address: payload[67] for 32
  677. err = binary.Read(reader, binary.BigEndian, &p.TargetAddress)
  678. if err != nil {
  679. return nil, err
  680. }
  681. // Target chain ID: payload[99] for 2
  682. err = binary.Read(reader, binary.BigEndian, &p.TargetChain)
  683. if err != nil {
  684. return nil, err
  685. }
  686. return p, nil
  687. }
  688. // GetEmitterChain implements the processor.Observation interface for *VAA.
  689. func (v *VAA) GetEmitterChain() ChainID {
  690. return v.EmitterChain
  691. }
  692. // MustWrite calls binary.Write and panics on errors
  693. func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
  694. if err := binary.Write(w, order, data); err != nil {
  695. panic(fmt.Errorf("failed to write binary data: %v", data).Error())
  696. }
  697. }
  698. // StringToAddress converts a hex-encoded address into a vaa.Address
  699. func StringToAddress(value string) (Address, error) {
  700. var address Address
  701. // Make sure we have enough to decode
  702. if len(value) < 2 {
  703. return address, fmt.Errorf("value must be at least 1 byte")
  704. }
  705. // Trim any preceding "0x" to the address
  706. value = strings.TrimPrefix(value, "0x")
  707. // Decode the string from hex to binary
  708. res, err := hex.DecodeString(value)
  709. if err != nil {
  710. return address, err
  711. }
  712. // Make sure we don't have too many bytes
  713. if len(res) > 32 {
  714. return address, fmt.Errorf("value must be no more than 32 bytes")
  715. }
  716. copy(address[32-len(res):], res)
  717. return address, nil
  718. }
  719. func BytesToAddress(b []byte) (Address, error) {
  720. var address Address
  721. if len(b) > 32 {
  722. return address, fmt.Errorf("value must be no more than 32 bytes")
  723. }
  724. copy(address[32-len(b):], b)
  725. return address, nil
  726. }
  727. // StringToHash converts a hex-encoded string into a common.Hash
  728. func StringToHash(value string) (common.Hash, error) {
  729. var tx common.Hash
  730. // Make sure we have enough to decode
  731. if len(value) < 2 {
  732. return tx, fmt.Errorf("value must be at least 1 byte")
  733. }
  734. // Trim any preceding "0x" to the address
  735. value = strings.TrimPrefix(value, "0x")
  736. res, err := hex.DecodeString(value)
  737. if err != nil {
  738. return tx, err
  739. }
  740. tx = common.BytesToHash(res)
  741. return tx, nil
  742. }
  743. func BytesToHash(b []byte) (common.Hash, error) {
  744. var hash common.Hash
  745. if len(b) > 32 {
  746. return hash, fmt.Errorf("value must be no more than 32 bytes")
  747. }
  748. hash = common.BytesToHash(b)
  749. return hash, nil
  750. }
  751. // DebugString returns a pretty-formatted JSON string representation of the VAA.
  752. func (v *VAA) DebugString() (string, error) {
  753. jsonBytes, err := json.MarshalIndent(v, "", " ")
  754. if err != nil {
  755. return "", fmt.Errorf("failed to marshal VAA to JSON for debugging: %w", err)
  756. }
  757. return string(jsonBytes), nil
  758. }