wormhole/node/pkg/vaa/structs.go

565 lines
14 KiB
Go
Raw Normal View History

2020-08-04 14:40:00 -07:00
package vaa
import (
"bytes"
"crypto/ecdsa"
2020-08-04 14:40:00 -07:00
"encoding/binary"
2020-08-21 04:00:40 -07:00
"encoding/hex"
2020-08-04 14:40:00 -07:00
"fmt"
"io"
"math/big"
"strings"
2020-08-04 14:40:00 -07:00
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
2020-08-04 14:40:00 -07:00
)
type (
// VAA is a verifiable action approval of the Wormhole protocol
VAA struct {
// Version of the VAA schema
Version uint8
// GuardianSetIndex is the index of the guardian set that signed this VAA
GuardianSetIndex uint32
2020-08-14 13:45:45 -07:00
// SignatureData is the signature of the guardian set
Signatures []*Signature
2020-08-04 14:40:00 -07:00
// Timestamp when the VAA was created
Timestamp time.Time
// Nonce of the VAA
Nonce uint32
// Sequence of the VAA
Sequence uint64
/// ConsistencyLevel of the VAA
ConsistencyLevel uint8
// EmitterChain the VAA was emitted on
EmitterChain ChainID
// EmitterAddress of the contract that emitted the Message
EmitterAddress Address
// Payload of the message
Payload []byte
2020-08-04 14:40:00 -07:00
}
// ChainID of a Wormhole chain
ChainID uint16
2020-08-04 14:40:00 -07:00
// Action of a VAA
Action uint8
// Address is a Wormhole protocol address, it contains the native chain's address. If the address data type of a
// chain is < 32bytes the value is zero-padded on the left.
Address [32]byte
2020-08-14 13:45:45 -07:00
// Signature of a single guardian
2020-08-04 14:40:00 -07:00
Signature struct {
2020-08-14 13:45:45 -07:00
// Index of the validator
Index uint8
// Signature data
Signature SignatureData
2020-08-04 14:40:00 -07:00
}
SignatureData [65]byte
TransferPayloadHdr struct {
Type uint8
Amount *big.Int
OriginAddress Address
OriginChain ChainID
TargetAddress Address
TargetChain ChainID
}
2020-08-04 14:40:00 -07:00
)
func (a Address) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, a)), nil
}
2020-08-21 04:00:40 -07:00
func (a Address) String() string {
return hex.EncodeToString(a[:])
}
func (a Address) Bytes() []byte {
return a[:]
}
func (a SignatureData) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"%s"`, a)), nil
}
func (a SignatureData) String() string {
return hex.EncodeToString(a[:])
}
2020-08-21 04:00:40 -07:00
func (c ChainID) String() string {
switch c {
case ChainIDUnset:
return "unset"
2020-08-21 04:00:40 -07:00
case ChainIDSolana:
return "solana"
case ChainIDEthereum:
return "ethereum"
2020-11-16 04:23:29 -08:00
case ChainIDTerra:
return "terra"
case ChainIDBSC:
return "bsc"
case ChainIDPolygon:
return "polygon"
case ChainIDAvalanche:
return "avalanche"
case ChainIDOasis:
return "oasis"
case ChainIDAurora:
return "aurora"
case ChainIDFantom:
return "fantom"
case ChainIDAlgorand:
return "algorand"
case ChainIDNear:
return "near"
case ChainIDEthereumRopsten:
return "ethereum-ropsten"
case ChainIDKarura:
return "karura"
case ChainIDAcala:
return "acala"
case ChainIDKlaytn:
return "klaytn"
case ChainIDCelo:
return "celo"
case ChainIDMoonbeam:
return "moonbeam"
case ChainIDNeon:
return "neon"
2022-06-16 12:17:43 -07:00
case ChainIDTerra2:
return "terra2"
2022-07-06 07:19:57 -07:00
case ChainIDInjective:
return "injective"
2022-07-28 10:30:00 -07:00
case ChainIDPythNet:
return "pythnet"
2020-08-21 04:00:40 -07:00
default:
return fmt.Sprintf("unknown chain ID: %d", c)
}
}
func ChainIDFromString(s string) (ChainID, error) {
s = strings.ToLower(s)
switch s {
case "solana":
return ChainIDSolana, nil
case "ethereum":
return ChainIDEthereum, nil
case "terra":
return ChainIDTerra, nil
case "bsc":
return ChainIDBSC, nil
case "polygon":
return ChainIDPolygon, nil
case "avalanche":
return ChainIDAvalanche, nil
case "oasis":
return ChainIDOasis, nil
case "aurora":
return ChainIDAurora, nil
case "fantom":
return ChainIDFantom, nil
case "algorand":
return ChainIDAlgorand, nil
case "near":
return ChainIDNear, nil
case "ethereum-ropsten":
return ChainIDEthereumRopsten, nil
case "karura":
return ChainIDKarura, nil
case "acala":
return ChainIDAcala, nil
case "klaytn":
return ChainIDKlaytn, nil
case "celo":
return ChainIDCelo, nil
case "moonbeam":
return ChainIDMoonbeam, nil
case "neon":
return ChainIDNeon, nil
2022-06-16 12:17:43 -07:00
case "terra2":
return ChainIDTerra2, nil
2022-07-06 07:19:57 -07:00
case "injective":
return ChainIDInjective, nil
2022-07-28 10:30:00 -07:00
case "pythnet":
return ChainIDPythNet, nil
default:
return ChainIDUnset, fmt.Errorf("unknown chain ID: %s", s)
}
}
2020-08-04 14:40:00 -07:00
const (
ChainIDUnset ChainID = 0
2020-08-04 14:40:00 -07:00
// ChainIDSolana is the ChainID of Solana
ChainIDSolana ChainID = 1
2020-08-04 14:40:00 -07:00
// ChainIDEthereum is the ChainID of Ethereum
ChainIDEthereum ChainID = 2
// ChainIDTerra is the ChainID of Terra
ChainIDTerra ChainID = 3
// ChainIDBSC is the ChainID of Binance Smart Chain
ChainIDBSC ChainID = 4
// ChainIDPolygon is the ChainID of Polygon
ChainIDPolygon ChainID = 5
// ChainIDAvalanche is the ChainID of Avalanche
ChainIDAvalanche ChainID = 6
// ChainIDOasis is the ChainID of Oasis
ChainIDOasis ChainID = 7
// ChainIDAlgorand is the ChainID of Algorand
ChainIDAlgorand ChainID = 8
// ChainIDAurora is the ChainID of Aurora
ChainIDAurora ChainID = 9
// ChainIDFantom is the ChainID of Fantom
ChainIDFantom ChainID = 10
// ChainIDKarura is the ChainID of Karura
ChainIDKarura ChainID = 11
// ChainIDAcala is the ChainID of Acala
ChainIDAcala ChainID = 12
// ChainIDKlaytn is the ChainID of Klaytn
ChainIDKlaytn ChainID = 13
// ChainIDCelo is the ChainID of Celo
ChainIDCelo ChainID = 14
// ChainIDNear is the ChainID of Near
ChainIDNear ChainID = 15
// ChainIDMoonbeam is the ChainID of Moonbeam
ChainIDMoonbeam ChainID = 16
// ChainIDNeon is the ChainID of Neon
ChainIDNeon ChainID = 17
2022-06-16 12:17:43 -07:00
// ChainIDTerra2 is the ChainID of Terra 2
ChainIDTerra2 ChainID = 18
2022-07-06 07:19:57 -07:00
// ChainIDInjective is the ChainID of Injective
ChainIDInjective ChainID = 19
2022-07-28 10:30:00 -07:00
// ChainIDPythNet is the ChainID of PythNet
ChainIDPythNet ChainID = 26
// ChainIDEthereumRopsten is the ChainID of Ethereum Ropsten
ChainIDEthereumRopsten ChainID = 10001
2020-08-04 14:40:00 -07:00
// Minimum VAA size is derrived from the following assumptions:
// HEADER
// - Supported VAA Version (1 byte)
// - Guardian Set Index (4 bytes)
// - Length of Signatures (1 byte) <== assume no signatures
// - Actual Signatures (0 bytes)
// BODY
// - timestamp (4 bytes)
// - nonce (4 bytes)
// - emitter chain (2 bytes)
// - emitter address (32 bytes)
// - sequence (8 bytes)
// - consistency level (1 byte)
// - payload (0 bytes)
//
// From Above: 1 + 4 + 1 + 0 + 4 + 4 + 2 + 32 + 8 + 1 + 0 // Equals 57
//
// More details here: https://docs.wormholenetwork.com/wormhole/vaas
minVAALength = 57
2020-08-20 12:48:58 -07:00
SupportedVAAVersion = 0x01
Chain governor (#1277) * Rebase * Reload from db on start up Change-Id: I1deac9db28ad1157ea7e0c84af41c35b38497f4e * Console commands Change-Id: Ic242038312b7c837443a2df8823f100b3cdffd77 * Query prices from CoinGecko Change-Id: I9a8c282ba374d32ef7045d11979a27ede3c52827 * Move chain config to separate file Change-Id: I6a790eca765bce1f2caf48134e225df5c4daff15 * More code cleanup Change-Id: Id12affa78cdc2d394d6dab0c53bb7ad06df8007e * Few minor tweaks Change-Id: I6cb511599d669e0b3d716d9f314ac0f26935ee92 * Create separate tests for different packages Change-Id: Idb4da6817c9daad2a7420abc11bdaa702ae056dc * Fix lint errors Change-Id: I137c9e7e4574aee9c9fec22e91e19eee0e86a349 * Simplify chainlock message tests * Add more governor db test coverage * Next batch of review rework Change-Id: Ife54852fca6c6990d1ffb3d60a8dd7f49d526f0a * Still more rework Change-Id: I43a8aa7fa4e1a7cea4d7fde68c963123c1ca8d53 * More rework Change-Id: I9382412af4ffeda74967a834a6b0195a9d28b720 * Fix lint errors Change-Id: Idaafce9b0314192557b7207911375d000bac5ae2 * Add rest and prometheus support Change-Id: Ib870ed7eb305ef1ebbf6a7cedabc665c37c19171 * Add separate configs for testnet and devnet Change-Id: I76b11d8940a8dc9935b3f276a008ed20ef60b850 * Update mainnet tokens to fix decimals Change-Id: Iab018827766bc7748038b7be2f51342afb79b87c * Let small enqueued VAAs go out when big ones can't Change-Id: I7d3ef88d4579702d0c6ff4eaf5a8524799610ff6 * Tweak testnet config parameters Change-Id: Id2c54151a7183ab3fb4af8060929198f6021ba4e * Rework / enhancements from testnet testing Change-Id: I1387b1d22667fa6ffe0bb1832dbc0b31196505d3 * Use known emitter maps Change-Id: If330ee9d30ac3c2d1c6dca674f7777dc759de230 * Fix typo and out of date comments Change-Id: I54a19792104ccc6ca023020303a710ef3ba18f74 Co-authored-by: claudijd <jclaudius@jumptrading.com>
2022-07-19 11:08:06 -07:00
InternalTruncatedPayloadSafetyLimit = 1000
2020-08-04 14:40:00 -07:00
)
// Unmarshal deserializes the binary representation of a VAA
//
// WARNING: Unmarshall will truncate payloads at 1000 bytes, this is done mainly to avoid denial of service
// - If you need to access the full payload, consider parsing VAA from Bytes instead of Unmarshal
//
func Unmarshal(data []byte) (*VAA, error) {
2020-08-04 14:40:00 -07:00
if len(data) < minVAALength {
return nil, fmt.Errorf("VAA is too short")
}
2020-08-14 13:45:45 -07:00
v := &VAA{}
2020-08-04 14:40:00 -07:00
v.Version = data[0]
2020-08-20 12:48:58 -07:00
if v.Version != SupportedVAAVersion {
2020-08-04 14:40:00 -07:00
return nil, fmt.Errorf("unsupported VAA version: %d", v.Version)
}
reader := bytes.NewReader(data[1:])
if err := binary.Read(reader, binary.BigEndian, &v.GuardianSetIndex); err != nil {
return nil, fmt.Errorf("failed to read guardian set index: %w", err)
}
2020-08-14 13:45:45 -07:00
lenSignatures, er := reader.ReadByte()
if er != nil {
return nil, fmt.Errorf("failed to read signature length")
2020-08-04 14:40:00 -07:00
}
2020-08-14 13:45:45 -07:00
v.Signatures = make([]*Signature, lenSignatures)
for i := 0; i < int(lenSignatures); i++ {
index, err := reader.ReadByte()
if err != nil {
return nil, fmt.Errorf("failed to read validator index [%d]", i)
}
signature := [65]byte{}
if n, err := reader.Read(signature[:]); err != nil || n != 65 {
return nil, fmt.Errorf("failed to read signature [%d]: %w", i, err)
}
v.Signatures[i] = &Signature{
Index: index,
Signature: signature,
}
2020-08-04 14:40:00 -07:00
}
unixSeconds := uint32(0)
if err := binary.Read(reader, binary.BigEndian, &unixSeconds); err != nil {
return nil, fmt.Errorf("failed to read timestamp: %w", err)
}
v.Timestamp = time.Unix(int64(unixSeconds), 0)
if err := binary.Read(reader, binary.BigEndian, &v.Nonce); err != nil {
return nil, fmt.Errorf("failed to read nonce: %w", err)
2020-08-04 14:40:00 -07:00
}
if err := binary.Read(reader, binary.BigEndian, &v.EmitterChain); err != nil {
return nil, fmt.Errorf("failed to read emitter chain: %w", err)
2020-08-04 14:40:00 -07:00
}
emitterAddress := Address{}
if n, err := reader.Read(emitterAddress[:]); err != nil || n != 32 {
return nil, fmt.Errorf("failed to read emitter address [%d]: %w", n, err)
2020-08-04 14:40:00 -07:00
}
v.EmitterAddress = emitterAddress
if err := binary.Read(reader, binary.BigEndian, &v.Sequence); err != nil {
return nil, fmt.Errorf("failed to read sequence: %w", err)
}
if err := binary.Read(reader, binary.BigEndian, &v.ConsistencyLevel); err != nil {
return nil, fmt.Errorf("failed to read commitment: %w", err)
}
2020-08-04 14:40:00 -07:00
Chain governor (#1277) * Rebase * Reload from db on start up Change-Id: I1deac9db28ad1157ea7e0c84af41c35b38497f4e * Console commands Change-Id: Ic242038312b7c837443a2df8823f100b3cdffd77 * Query prices from CoinGecko Change-Id: I9a8c282ba374d32ef7045d11979a27ede3c52827 * Move chain config to separate file Change-Id: I6a790eca765bce1f2caf48134e225df5c4daff15 * More code cleanup Change-Id: Id12affa78cdc2d394d6dab0c53bb7ad06df8007e * Few minor tweaks Change-Id: I6cb511599d669e0b3d716d9f314ac0f26935ee92 * Create separate tests for different packages Change-Id: Idb4da6817c9daad2a7420abc11bdaa702ae056dc * Fix lint errors Change-Id: I137c9e7e4574aee9c9fec22e91e19eee0e86a349 * Simplify chainlock message tests * Add more governor db test coverage * Next batch of review rework Change-Id: Ife54852fca6c6990d1ffb3d60a8dd7f49d526f0a * Still more rework Change-Id: I43a8aa7fa4e1a7cea4d7fde68c963123c1ca8d53 * More rework Change-Id: I9382412af4ffeda74967a834a6b0195a9d28b720 * Fix lint errors Change-Id: Idaafce9b0314192557b7207911375d000bac5ae2 * Add rest and prometheus support Change-Id: Ib870ed7eb305ef1ebbf6a7cedabc665c37c19171 * Add separate configs for testnet and devnet Change-Id: I76b11d8940a8dc9935b3f276a008ed20ef60b850 * Update mainnet tokens to fix decimals Change-Id: Iab018827766bc7748038b7be2f51342afb79b87c * Let small enqueued VAAs go out when big ones can't Change-Id: I7d3ef88d4579702d0c6ff4eaf5a8524799610ff6 * Tweak testnet config parameters Change-Id: Id2c54151a7183ab3fb4af8060929198f6021ba4e * Rework / enhancements from testnet testing Change-Id: I1387b1d22667fa6ffe0bb1832dbc0b31196505d3 * Use known emitter maps Change-Id: If330ee9d30ac3c2d1c6dca674f7777dc759de230 * Fix typo and out of date comments Change-Id: I54a19792104ccc6ca023020303a710ef3ba18f74 Co-authored-by: claudijd <jclaudius@jumptrading.com>
2022-07-19 11:08:06 -07:00
payload := make([]byte, InternalTruncatedPayloadSafetyLimit)
n, err := reader.Read(payload)
if err != nil || n == 0 {
return nil, fmt.Errorf("failed to read payload [%d]: %w", n, err)
}
v.Payload = payload[:n]
2020-08-04 14:40:00 -07:00
return v, nil
}
// signingBody returns the binary representation of the data that is relevant for signing and verifying the VAA
func (v *VAA) signingBody() []byte {
2020-08-04 14:40:00 -07:00
return v.serializeBody()
}
// SigningMsg returns the hash of the signing body. This is used for signature generation and verification
func (v *VAA) SigningMsg() common.Hash {
// In order to save space in the solana signature verification instruction, we hash twice so we only need to pass in
// the first hash (32 bytes) vs the full body data.
hash := crypto.Keccak256Hash(crypto.Keccak256Hash(v.signingBody()).Bytes())
return hash
}
// VerifySignatures verifies the signature of the VAA given the signer addresses.
// Returns true if the signatures were verified successfully.
2020-08-14 13:45:45 -07:00
func (v *VAA) VerifySignatures(addresses []common.Address) bool {
if len(addresses) < len(v.Signatures) {
return false
}
h := v.SigningMsg()
last_index := -1
signing_addresses := []common.Address{}
2020-08-14 13:45:45 -07:00
for _, sig := range v.Signatures {
if int(sig.Index) >= len(addresses) {
return false
}
// Ensure increasing indexes
if int(sig.Index) <= last_index {
return false
}
last_index = int(sig.Index)
// Get pubKey to determine who signers address
2020-08-14 13:45:45 -07:00
pubKey, err := crypto.Ecrecover(h.Bytes(), sig.Signature[:])
if err != nil {
return false
}
addr := common.BytesToAddress(crypto.Keccak256(pubKey[1:])[12:])
// Ensure this signer is at the correct positional index
2020-08-14 13:45:45 -07:00
if addr != addresses[sig.Index] {
return false
}
// Ensure we never see the same signer twice
for _, signing_address := range signing_addresses {
if signing_address == addr {
return false
}
}
signing_addresses = append(signing_addresses, addr)
}
2020-08-14 13:45:45 -07:00
return true
}
// Marshal returns the binary representation of the VAA
func (v *VAA) Marshal() ([]byte, error) {
2020-08-04 14:40:00 -07:00
buf := new(bytes.Buffer)
MustWrite(buf, binary.BigEndian, v.Version)
MustWrite(buf, binary.BigEndian, v.GuardianSetIndex)
2020-08-14 13:45:45 -07:00
// Write signatures
MustWrite(buf, binary.BigEndian, uint8(len(v.Signatures)))
for _, sig := range v.Signatures {
MustWrite(buf, binary.BigEndian, sig.Index)
buf.Write(sig.Signature[:])
2020-08-04 14:40:00 -07:00
}
// Write Body
buf.Write(v.serializeBody())
2020-08-04 14:40:00 -07:00
return buf.Bytes(), nil
}
// MessageID returns a human-readable emitter_chain/emitter_address/sequence tuple.
func (v *VAA) MessageID() string {
return fmt.Sprintf("%d/%s/%d", v.EmitterChain, v.EmitterAddress, v.Sequence)
}
// HexDigest returns the hex-encoded digest.
func (v *VAA) HexDigest() string {
return hex.EncodeToString(v.SigningMsg().Bytes())
}
func (v *VAA) serializeBody() []byte {
2020-08-04 14:40:00 -07:00
buf := new(bytes.Buffer)
MustWrite(buf, binary.BigEndian, uint32(v.Timestamp.Unix()))
MustWrite(buf, binary.BigEndian, v.Nonce)
MustWrite(buf, binary.BigEndian, v.EmitterChain)
buf.Write(v.EmitterAddress[:])
MustWrite(buf, binary.BigEndian, v.Sequence)
MustWrite(buf, binary.BigEndian, v.ConsistencyLevel)
buf.Write(v.Payload)
2020-08-04 14:40:00 -07:00
return buf.Bytes()
2020-08-04 14:40:00 -07:00
}
func (v *VAA) AddSignature(key *ecdsa.PrivateKey, index uint8) {
sig, err := crypto.Sign(v.SigningMsg().Bytes(), key)
if err != nil {
panic(err)
}
sigData := [65]byte{}
copy(sigData[:], sig)
v.Signatures = append(v.Signatures, &Signature{
Index: index,
Signature: sigData,
})
}
// NOTE: This function assumes that the caller has verified that the VAA is from the token bridge.
func IsTransfer(payload []byte) bool {
return (len(payload) > 0) && ((payload[0] == 1) || (payload[0] == 3))
}
func DecodeTransferPayloadHdr(payload []byte) (*TransferPayloadHdr, error) {
if !IsTransfer(payload) {
return nil, fmt.Errorf("unsupported payload type")
}
if len(payload) < 101 {
return nil, fmt.Errorf("buffer too short")
}
p := &TransferPayloadHdr{}
// Payload type: payload[0]
p.Type = uint8(payload[0])
// Amount: payload[1] for 32
p.Amount = new(big.Int)
p.Amount.SetBytes(payload[1:33])
reader := bytes.NewReader(payload[33:])
// Origin address: payload[33] for 32
err := binary.Read(reader, binary.BigEndian, &p.OriginAddress)
if err != nil {
return nil, err
}
// Origin chain ID: payload[65] for 2
err = binary.Read(reader, binary.BigEndian, &p.OriginChain)
if err != nil {
return nil, err
}
// Target address: payload[67] for 32
err = binary.Read(reader, binary.BigEndian, &p.TargetAddress)
if err != nil {
return nil, err
}
// Target chain ID: payload[99] for 2
err = binary.Read(reader, binary.BigEndian, &p.TargetChain)
if err != nil {
return nil, err
}
return p, nil
}
// GetEmitterChain implements the processor.Observation interface for *VAA.
func (v *VAA) GetEmitterChain() ChainID {
return v.EmitterChain
}
2020-08-04 14:40:00 -07:00
// MustWrite calls binary.Write and panics on errors
func MustWrite(w io.Writer, order binary.ByteOrder, data interface{}) {
if err := binary.Write(w, order, data); err != nil {
panic(fmt.Errorf("failed to write binary data: %v", data).Error())
}
}
// StringToAddress converts a hex-encoded address into a vaa.Address
func StringToAddress(value string) (Address, error) {
var address Address
// Make sure we have enough to decode
if len(value) < 2 {
return address, fmt.Errorf("value must be at least 1 byte")
}
// Trim any preceding "0x" to the address
Chain governor (#1277) * Rebase * Reload from db on start up Change-Id: I1deac9db28ad1157ea7e0c84af41c35b38497f4e * Console commands Change-Id: Ic242038312b7c837443a2df8823f100b3cdffd77 * Query prices from CoinGecko Change-Id: I9a8c282ba374d32ef7045d11979a27ede3c52827 * Move chain config to separate file Change-Id: I6a790eca765bce1f2caf48134e225df5c4daff15 * More code cleanup Change-Id: Id12affa78cdc2d394d6dab0c53bb7ad06df8007e * Few minor tweaks Change-Id: I6cb511599d669e0b3d716d9f314ac0f26935ee92 * Create separate tests for different packages Change-Id: Idb4da6817c9daad2a7420abc11bdaa702ae056dc * Fix lint errors Change-Id: I137c9e7e4574aee9c9fec22e91e19eee0e86a349 * Simplify chainlock message tests * Add more governor db test coverage * Next batch of review rework Change-Id: Ife54852fca6c6990d1ffb3d60a8dd7f49d526f0a * Still more rework Change-Id: I43a8aa7fa4e1a7cea4d7fde68c963123c1ca8d53 * More rework Change-Id: I9382412af4ffeda74967a834a6b0195a9d28b720 * Fix lint errors Change-Id: Idaafce9b0314192557b7207911375d000bac5ae2 * Add rest and prometheus support Change-Id: Ib870ed7eb305ef1ebbf6a7cedabc665c37c19171 * Add separate configs for testnet and devnet Change-Id: I76b11d8940a8dc9935b3f276a008ed20ef60b850 * Update mainnet tokens to fix decimals Change-Id: Iab018827766bc7748038b7be2f51342afb79b87c * Let small enqueued VAAs go out when big ones can't Change-Id: I7d3ef88d4579702d0c6ff4eaf5a8524799610ff6 * Tweak testnet config parameters Change-Id: Id2c54151a7183ab3fb4af8060929198f6021ba4e * Rework / enhancements from testnet testing Change-Id: I1387b1d22667fa6ffe0bb1832dbc0b31196505d3 * Use known emitter maps Change-Id: If330ee9d30ac3c2d1c6dca674f7777dc759de230 * Fix typo and out of date comments Change-Id: I54a19792104ccc6ca023020303a710ef3ba18f74 Co-authored-by: claudijd <jclaudius@jumptrading.com>
2022-07-19 11:08:06 -07:00
value = strings.TrimPrefix(value, "0x")
// Decode the string from hex to binary
res, err := hex.DecodeString(value)
if err != nil {
return address, err
}
// Make sure we don't have too many bytes
if len(res) > 32 {
return address, fmt.Errorf("value must be no more than 32 bytes")
}
copy(address[32-len(res):], res)
return address, nil
}
Chain governor (#1277) * Rebase * Reload from db on start up Change-Id: I1deac9db28ad1157ea7e0c84af41c35b38497f4e * Console commands Change-Id: Ic242038312b7c837443a2df8823f100b3cdffd77 * Query prices from CoinGecko Change-Id: I9a8c282ba374d32ef7045d11979a27ede3c52827 * Move chain config to separate file Change-Id: I6a790eca765bce1f2caf48134e225df5c4daff15 * More code cleanup Change-Id: Id12affa78cdc2d394d6dab0c53bb7ad06df8007e * Few minor tweaks Change-Id: I6cb511599d669e0b3d716d9f314ac0f26935ee92 * Create separate tests for different packages Change-Id: Idb4da6817c9daad2a7420abc11bdaa702ae056dc * Fix lint errors Change-Id: I137c9e7e4574aee9c9fec22e91e19eee0e86a349 * Simplify chainlock message tests * Add more governor db test coverage * Next batch of review rework Change-Id: Ife54852fca6c6990d1ffb3d60a8dd7f49d526f0a * Still more rework Change-Id: I43a8aa7fa4e1a7cea4d7fde68c963123c1ca8d53 * More rework Change-Id: I9382412af4ffeda74967a834a6b0195a9d28b720 * Fix lint errors Change-Id: Idaafce9b0314192557b7207911375d000bac5ae2 * Add rest and prometheus support Change-Id: Ib870ed7eb305ef1ebbf6a7cedabc665c37c19171 * Add separate configs for testnet and devnet Change-Id: I76b11d8940a8dc9935b3f276a008ed20ef60b850 * Update mainnet tokens to fix decimals Change-Id: Iab018827766bc7748038b7be2f51342afb79b87c * Let small enqueued VAAs go out when big ones can't Change-Id: I7d3ef88d4579702d0c6ff4eaf5a8524799610ff6 * Tweak testnet config parameters Change-Id: Id2c54151a7183ab3fb4af8060929198f6021ba4e * Rework / enhancements from testnet testing Change-Id: I1387b1d22667fa6ffe0bb1832dbc0b31196505d3 * Use known emitter maps Change-Id: If330ee9d30ac3c2d1c6dca674f7777dc759de230 * Fix typo and out of date comments Change-Id: I54a19792104ccc6ca023020303a710ef3ba18f74 Co-authored-by: claudijd <jclaudius@jumptrading.com>
2022-07-19 11:08:06 -07:00
func BytesToAddress(b []byte) (Address, error) {
var address Address
if len(b) > 32 {
return address, fmt.Errorf("value must be no more than 32 bytes")
}
copy(address[32-len(b):], b)
return address, nil
}