Documentation
¶
Index ¶
- Constants
- Variables
- func ConvertChainIdToReadinessSyncing(chainID vaa.ChainID) (readiness.Component, error)
- func DecryptAESGCM(data, key []byte) ([]byte, error)
- func EncryptAESGCM(plaintext, key []byte) ([]byte, error)
- func GetOrCreateNodeKey(logger *zap.Logger, path string) (crypto.PrivKey, error)
- func LoadArmoredKey(filename string, blockType string, unsafeDevMode bool) (*ecdsa.PrivateKey, error)
- func LoadGuardianKey(filename string, unsafeDevMode bool) (*ecdsa.PrivateKey, error)
- func LockMemory()
- func MustConvertChainIdToReadinessSyncing(chainID vaa.ChainID) readiness.Component
- func MustRegisterReadinessSyncing(chainID vaa.ChainID)
- func NewInstrumentedGRPCServer(logger *zap.Logger, rpcLogDetail GrpcLogDetail) *grpc.Server
- func PostMsgWithTimestamp[T any](msg *T, c chan<- *MsgWithTimeStamp[T]) error
- func PostObservationRequest(obsvReqSendC chan<- *gossipv1.ObservationRequest, ...) error
- func ReadFromChannelWithTimeout[T any](ctx context.Context, ch <-chan T, maxCount int) ([]T, error)
- func RunWithScissors(ctx context.Context, errC chan error, name string, ...)
- func SafeRead(r io.Reader) ([]byte, error)
- func SetRestrictiveUmask()
- func StartRunnable(ctx context.Context, errC chan error, catchPanics bool, name string, ...)
- func ValidateURL(urlStr string, validSchemes []string) bool
- func WrapWithScissors(runnable supervisor.Runnable, name string) supervisor.Runnable
- func WriteArmoredKey(key *ecdsa.PrivateKey, description string, filename string, blockType string, ...) error
- func WriteToChannelWithoutBlocking[T any](channel chan<- T, evt T, label string)
- type Environment
- type ErrInputSize
- type ErrUnexpectedEndOfRead
- type GrpcLogDetail
- type GuardianSet
- type GuardianSetState
- func (st *GuardianSetState) Cleanup()
- func (st *GuardianSetState) Get() *GuardianSet
- func (st *GuardianSetState) GetAll() map[common.Address]map[peer.ID]*gossipv1.Heartbeat
- func (st *GuardianSetState) IsSubscribedToHeartbeats() bool
- func (st *GuardianSetState) LastHeartbeat(addr common.Address) map[peer.ID]*gossipv1.Heartbeat
- func (st *GuardianSetState) Set(set *GuardianSet)
- func (st *GuardianSetState) SetHeartbeat(addr common.Address, peerId peer.ID, hb *gossipv1.Heartbeat) error
- type MessagePublication
- func (msg *MessagePublication) CreateDigest() string
- func (msg *MessagePublication) CreateVAA(gsIndex uint32) *vaa.VAA
- func (msg *MessagePublication) IsWTT(env Environment) bool
- func (msg *MessagePublication) Marshal() ([]byte, error)deprecated
- func (msg *MessagePublication) MarshalBinary() ([]byte, error)
- func (msg *MessagePublication) MarshalJSON() ([]byte, error)
- func (msg *MessagePublication) MessageID() []byte
- func (msg *MessagePublication) MessageIDString() string
- func (msg *MessagePublication) SetVerificationState(s VerificationState) error
- func (msg *MessagePublication) TxIDString() string
- func (m *MessagePublication) UnmarshalBinary(data []byte) error
- func (msg *MessagePublication) UnmarshalJSON(data []byte) error
- func (msg *MessagePublication) VAAHash() string
- func (msg *MessagePublication) VerificationState() VerificationState
- func (msg *MessagePublication) ZapFields(fields ...zap.Field) []zap.Field
- type MsgWithTimeStamp
- type PendingMessage
- type PendingMessageQueue
- func (q *PendingMessageQueue) Contains(pMsg *PendingMessage) bool
- func (q *PendingMessageQueue) FetchMessagePublication(msgID []byte) (msgPub *MessagePublication)
- func (q *PendingMessageQueue) Len() int
- func (q *PendingMessageQueue) Peek() *PendingMessage
- func (q *PendingMessageQueue) Pop() *PendingMessage
- func (q *PendingMessageQueue) Push(pMsg *PendingMessage)
- func (q *PendingMessageQueue) RemoveItem(msgID []byte) (*PendingMessage, error)
- type VerificationState
Constants ¶
const ( // TxIDLenMin is the minimum length of a txID. TxIDLenMin = 32 // AddressLength is the length of a normalized Wormhole address in bytes. AddressLength = 32 // Wormhole supports arbitrary payloads due to the variance in transaction and block sizes between chains. // However, during serialization, payload lengths are limited by Go slice length constraints and violations // of these limits can cause panics. // (https://go.dev/src/runtime/slice.go) // This limit is chosen to be large enough to prevent such panics but it should comfortably handle all payloads. // If not, the limit can be increased. PayloadLenMax = 1024 * 1024 * 1024 * 10 // 10 GB // minMsgIdLen is the minimum length of a message ID. It is used to uniquely identify // messages in the case of a duplicate message ID and is stored in the database. MinMsgIdLen = len("1/0000000000000000000000000290fb167208af455bb137780163b7b7a9a10c16/0") )
const ( ReadinessEthSyncing readiness.Component = "ethSyncing" ReadinessIBCSyncing readiness.Component = "IBCSyncing" )
const (
GuardianKeyArmoredBlock = "WORMHOLE GUARDIAN PRIVATE KEY"
)
const MaxGuardianCount = 19
MaxGuardianCount specifies the maximum number of guardians supported by on-chain contracts.
Matching constants:
- MAX_LEN_GUARDIAN_KEYS in Solana contract (limited by transaction size - 19 is the maximum amount possible)
The Eth and Terra contracts do not specify a maximum number and support more than that, but presumably, chain-specific transaction size limits will apply at some point (untested).
const MaxNodesPerGuardian = 30
MaxNodesPerGuardian specifies the maximum amount of nodes per guardian key that we'll accept whenever we maintain any per-guardian, per-node state.
There currently isn't any state clean up, so the value is on the high side to prevent accidentally reaching the limit due to operational mistakes.
const MaxSafeInputSize = 128 * 1024 * 1024 // 128MB (arbitrary)
MaxSafeInputSize defines the maximum safe size for untrusted input from `io` Readers. It should be configured so that it can comfortably contain all valid reads while providing a strict upper bound to prevent unlimited reads.
const MaxStateAge = 1 * time.Minute
MaxStateAge specified the maximum age of state entries in seconds. Expired entries are purged from the state by Cleanup().
const NumVariantsVerificationState = 6
NumVariantsVerificationState is the number of variants in the VerificationState enum. Used to validate deserialization.
Variables ¶
var ( ErrInvalidBinaryBool = errors.New("invalid binary bool (neither 0x00 nor 0x01)") ErrInvalidVerificationState = errors.New("invalid verification state") )
var ( ErrBinaryWrite = errors.New("failed to write binary data") ErrTxIDTooLong = errors.New("field TxID too long") ErrTxIDTooShort = errors.New("field TxID too short") ErrInvalidPayload = errors.New("field payload too long") ErrDataTooShort = errors.New("data too short") ErrTimestampTooShort = errors.New("data too short for timestamp") ErrNonceTooShort = errors.New("data too short for nonce") ErrSequenceTooShort = errors.New("data too short for sequence") ErrConsistencyTooShort = errors.New("data too short for consistency level") ErrChainTooShort = errors.New("data too short for emitter chain") ErrAddressTooShort = errors.New("data too short for emitter address") ErrReobsTooShort = errors.New("data too short for IsReobservation") ErrUnreliableTooShort = errors.New("data too short for Unreliable") ErrVerStateTooShort = errors.New("data too short for verification state") ErrPayloadLenTooShort = errors.New("data too short for payload length") ErrPayloadTooShort = errors.New("data too short for payload") )
var ( ScissorsErrorsCaught = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "scissor_errors_caught", Help: "Total number of unhandled errors caught", }, []string{"name"}) ScissorsPanicsCaught = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "scissor_panics_caught", Help: "Total number of panics caught", }, []string{"name"}) )
var ErrChanFull = errors.New("channel is full")
var ErrInputTooLarge = errors.New("input data exceeds maximum allowed size")
Functions ¶
func ConvertChainIdToReadinessSyncing ¶
ConvertChainIdToReadinessSyncing maps a chain ID to a readiness syncing value. It returns an error if the chain ID is invalid.
func DecryptAESGCM ¶
func EncryptAESGCM ¶
func GetOrCreateNodeKey ¶
func LoadArmoredKey ¶
func LoadArmoredKey(filename string, blockType string, unsafeDevMode bool) (*ecdsa.PrivateKey, error)
LoadArmoredKey loads a serialized key from disk.
func LoadGuardianKey ¶
func LoadGuardianKey(filename string, unsafeDevMode bool) (*ecdsa.PrivateKey, error)
LoadGuardianKey loads a serialized guardian key from disk.
func LockMemory ¶
func LockMemory()
LockMemory locks current and future pages in memory to protect secret keys from being swapped out to disk. It's possible (and strongly recommended) to deploy Wormhole such that keys are only ever stored in memory and never touch the disk. This is a privileged operation and requires CAP_IPC_LOCK.
func MustConvertChainIdToReadinessSyncing ¶
MustConvertChainIdToReadinessSyncing maps a chain ID to a readiness syncing value. It panics if the chain ID is invalid so it should only be used during initialization.
func MustRegisterReadinessSyncing ¶
MustRegisterReadinessSyncing registers the specified chain for readiness syncing. It panics if the chain ID is invalid so it should only be used during initialization. TODO: Using vaa.ChainID is bad here because there can be multiple watchers for the same chainId, e.g. solana-finalized and solana-confirmed. This is currently handled as a special case for solana in node/node.go, but should really be fixed here.
func NewInstrumentedGRPCServer ¶
func NewInstrumentedGRPCServer(logger *zap.Logger, rpcLogDetail GrpcLogDetail) *grpc.Server
func PostMsgWithTimestamp ¶
func PostMsgWithTimestamp[T any](msg *T, c chan<- *MsgWithTimeStamp[T]) error
PostMsgWithTimestamp sends the message to the specified channel using the current timestamp. Returns ErrChanFull on error.
func PostObservationRequest ¶
func PostObservationRequest(obsvReqSendC chan<- *gossipv1.ObservationRequest, req *gossipv1.ObservationRequest) error
func ReadFromChannelWithTimeout ¶
ReadFromChannelWithTimeout reads events from the channel until a timeout occurs or the max maxCount is reached.
func RunWithScissors ¶
func RunWithScissors(ctx context.Context, errC chan error, name string, runnable supervisor.Runnable)
Start a go routine with recovering from any panic by sending an error to a error channel
func SafeRead ¶
SafeRead reads from r with a size limit to prevent memory exhaustion attacks. It returns an error if the input exceeds MaxSafeInputSize.
func SetRestrictiveUmask ¶
func SetRestrictiveUmask()
SetRestrictiveUmask masks the group and world bits. This ensures that key material and sockets we create aren't accidentally group- or world-readable.
func StartRunnable ¶
func StartRunnable(ctx context.Context, errC chan error, catchPanics bool, name string, runnable supervisor.Runnable)
StartRunnable starts a go routine with the ability to recover from errors by publishing them to an error channel. If catchPanics is true, it will also catch panics and publish the panic message to the error channel. If catchPanics is false, the panic will be propagated upward.
func ValidateURL ¶
func WrapWithScissors ¶
func WrapWithScissors(runnable supervisor.Runnable, name string) supervisor.Runnable
func WriteArmoredKey ¶
func WriteArmoredKey(key *ecdsa.PrivateKey, description string, filename string, blockType string, unsafe bool) error
WriteArmoredKey serializes a key and writes it to disk.
func WriteToChannelWithoutBlocking ¶
WriteToChannelWithoutBlocking attempts to write the specified event to the specified channel. If the write would block, it increments the `channelWriteDrops` metric with the specified channel ID.
Types ¶
type Environment ¶
type Environment string
const ( MainNet Environment = "prod" UnsafeDevNet Environment = "dev" // local devnet; Keys are deterministic and many security controls are disabled TestNet Environment = "test" // public testnet (needs to be reliable, but run with less Guardians and faster finality) GoTest Environment = "unit-test" AccountantMock Environment = "accountant-mock" // Used for mocking accountant with a Wormchain connection )
func ParseEnvironment ¶
func ParseEnvironment(str string) (Environment, error)
ParseEnvironment parses a string into the corresponding Environment value, allowing various reasonable variations.
func (Environment) ToSDK ¶
func (e Environment) ToSDK() sdk.Environment
ToSDK converts a common.Environment to sdk.Environment. This allows node code to use SDK functions that require sdk.Environment.
type ErrInputSize ¶
ErrInputSize is returned when the input size is not the expected size during marshaling.
func (ErrInputSize) Error ¶
func (e ErrInputSize) Error() string
type ErrUnexpectedEndOfRead ¶
type ErrUnexpectedEndOfRead struct {
// contains filtered or unexported fields
}
func (ErrUnexpectedEndOfRead) Error ¶
func (e ErrUnexpectedEndOfRead) Error() string
type GrpcLogDetail ¶
type GrpcLogDetail string
const ( GrpcLogDetailNone GrpcLogDetail = "none" GrpcLogDetailMinimal GrpcLogDetail = "minimal" GrpcLogDetailFull GrpcLogDetail = "full" )
type GuardianSet ¶
type GuardianSet struct {
// Guardian's public key hashes truncated by the ETH standard hashing mechanism (20 bytes).
Keys []common.Address
// On-chain set index
Index uint32
// contains filtered or unexported fields
}
func NewGuardianSet ¶
func NewGuardianSet(keys []common.Address, index uint32) *GuardianSet
func (*GuardianSet) KeyIndex ¶
func (g *GuardianSet) KeyIndex(addr common.Address) (int, bool)
KeyIndex returns a given address index from the guardian set. Returns (-1, false) if the address wasn't found and (addr, true) otherwise.
func (*GuardianSet) KeysAsHexStrings ¶
func (g *GuardianSet) KeysAsHexStrings() []string
func (*GuardianSet) Quorum ¶
func (gs *GuardianSet) Quorum() int
Quorum returns the current quorum value.
type GuardianSetState ¶
type GuardianSetState struct {
// contains filtered or unexported fields
}
func NewGuardianSetState ¶
func NewGuardianSetState(guardianSetStateUpdateC chan *gossipv1.Heartbeat) *GuardianSetState
NewGuardianSetState returns a new GuardianSetState.
The provided channel will be pushed heartbeat updates as they are set, but be aware that the channel will block guardian set updates if full.
func (*GuardianSetState) Cleanup ¶
func (st *GuardianSetState) Cleanup()
Cleanup removes expired entries from the state.
func (*GuardianSetState) Get ¶
func (st *GuardianSetState) Get() *GuardianSet
func (*GuardianSetState) IsSubscribedToHeartbeats ¶
func (st *GuardianSetState) IsSubscribedToHeartbeats() bool
IsSubscribedToHeartbeats returns true if the heartbeat update channel is set.
func (*GuardianSetState) LastHeartbeat ¶
LastHeartbeat returns the most recent heartbeat message received for a given guardian node, or nil if none have been received.
func (*GuardianSetState) Set ¶
func (st *GuardianSetState) Set(set *GuardianSet)
func (*GuardianSetState) SetHeartbeat ¶
func (st *GuardianSetState) SetHeartbeat(addr common.Address, peerId peer.ID, hb *gossipv1.Heartbeat) error
SetHeartbeat stores a verified heartbeat observed by a given guardian.
type MessagePublication ¶
type MessagePublication struct {
TxID []byte
Timestamp time.Time
Nonce uint32
Sequence uint64
ConsistencyLevel uint8
EmitterChain vaa.ChainID
EmitterAddress vaa.Address
// NOTE: there is no upper bound on the size of the payload. Wormhole supports arbitrary payloads
// due to the variance in transaction and block sizes between chains. However, during deserialization,
// payload lengths are bounds-checked against [PayloadLenMax] to prevent makeslice panics from malformed input.
Payload []byte
IsReobservation bool
// Unreliable indicates if this message can be reobserved. If a message is considered unreliable it cannot be
// reobserved.
Unreliable bool
// contains filtered or unexported fields
}
func UnmarshalMessagePublication
deprecated
func UnmarshalMessagePublication(data []byte) (*MessagePublication, error)
Deprecated: UnmarshalMessagePublication deserializes a MessagePublication. This function does not unmarshal the Unreliable or verificationState fields. Use MessagePublication.UnmarshalBinary instead.
func (*MessagePublication) CreateDigest ¶
func (msg *MessagePublication) CreateDigest() string
func (*MessagePublication) CreateVAA ¶
func (msg *MessagePublication) CreateVAA(gsIndex uint32) *vaa.VAA
func (*MessagePublication) IsWTT ¶
func (msg *MessagePublication) IsWTT(env Environment) bool
IsWTT checks if the MessagePublication represents a valid wrapped token transfer for a given environment. It verifies: 1. The payload is a transfer (payload type 1 or 3) via vaa.IsTransfer 2. The emitter is a known token bridge emitter for the specified environment
This method validates WTTs with respect to an environment's known token bridge emitters. For a context-free check that only verifies the payload type, use vaa.IsTransfer instead.
Returns false for test/mock environments (GoTest, AccountantMock) and if either check fails.
Note: This method uses the same validation logic as VAA.IsWTT.
func (*MessagePublication) Marshal
deprecated
func (msg *MessagePublication) Marshal() ([]byte, error)
Deprecated: This function does not unmarshal the Unreliable or verificationState fields. Use MessagePublication.MarshalBinary instead.
func (*MessagePublication) MarshalBinary ¶
func (msg *MessagePublication) MarshalBinary() ([]byte, error)
MarshalBinary implements the BinaryMarshaler interface for MessagePublication.
func (*MessagePublication) MarshalJSON ¶
func (msg *MessagePublication) MarshalJSON() ([]byte, error)
The standard json Marshal / Unmarshal of time.Time gets confused between local and UTC time.
func (*MessagePublication) MessageID ¶
func (msg *MessagePublication) MessageID() []byte
func (*MessagePublication) MessageIDString ¶
func (msg *MessagePublication) MessageIDString() string
func (*MessagePublication) SetVerificationState ¶
func (msg *MessagePublication) SetVerificationState(s VerificationState) error
SetVerificationState is the setter for verificationState. Returns an error if called in a way that likely indicates a programming mistake. This includes cases where: - an existing state would be overwritten by the NotVerified state - the argument is equal to the existing value
func (*MessagePublication) TxIDString ¶
func (msg *MessagePublication) TxIDString() string
TxIDString returns a hex-encoded representation of the TxID field, prefixed with '0x'.
func (*MessagePublication) UnmarshalBinary ¶
func (m *MessagePublication) UnmarshalBinary(data []byte) error
UnmarshalBinary implements the BinaryUnmarshaler interface for MessagePublication.
func (*MessagePublication) UnmarshalJSON ¶
func (msg *MessagePublication) UnmarshalJSON(data []byte) error
func (*MessagePublication) VAAHash ¶
func (msg *MessagePublication) VAAHash() string
VAAHash returns a hash corresponding to the fields of the Message Publication that are ultimately encoded in a VAA. This is a helper function used to uniquely identify a Message Publication.
func (*MessagePublication) VerificationState ¶
func (msg *MessagePublication) VerificationState() VerificationState
func (*MessagePublication) ZapFields ¶
func (msg *MessagePublication) ZapFields(fields ...zap.Field) []zap.Field
ZapFields takes some zap fields and appends zap fields related to the message. Example usage: `logger.Info("logging something with a message", msg.ZapFields(zap.Int("some_other_field", 100))...)“ TODO refactor the codebase to use this function instead of manually logging the message with inconsistent fields
type MsgWithTimeStamp ¶
MsgWithTimeStamp allows us to track the time of receipt of an event.
func CreateMsgWithTimestamp ¶
func CreateMsgWithTimestamp[T any](msg *T) *MsgWithTimeStamp[T]
CreateMsgWithTimestamp creates a new MsgWithTimeStamp with the current time.
type PendingMessage ¶
type PendingMessage struct {
ReleaseTime time.Time
Msg MessagePublication
}
PendingMessage is a wrapper type around a MessagePublication that includes the time for which it should be released.
func (PendingMessage) Compare ¶
func (p PendingMessage) Compare(other PendingMessage) int
func (*PendingMessage) MarshalBinary ¶
func (p *PendingMessage) MarshalBinary() ([]byte, error)
MarshalBinary implements BinaryMarshaler for PendingMessage.
func (*PendingMessage) UnmarshalBinary ¶
func (p *PendingMessage) UnmarshalBinary(data []byte) error
UnmarshalBinary implements BinaryUnmarshaler for PendingMessage.
type PendingMessageQueue ¶
type PendingMessageQueue struct {
// contains filtered or unexported fields
}
PendingMessageQueue is a thread-safe min-heap that sorts PendingMessage in descending order of Timestamp. It also prevents duplicate [MessagePublication]s from being added to the queue.
func NewPendingMessageQueue ¶
func NewPendingMessageQueue() *PendingMessageQueue
func (*PendingMessageQueue) Contains ¶
func (q *PendingMessageQueue) Contains(pMsg *PendingMessage) bool
Contains determines whether the queue contains a PendingMessage.
func (*PendingMessageQueue) FetchMessagePublication ¶
func (q *PendingMessageQueue) FetchMessagePublication(msgID []byte) (msgPub *MessagePublication)
FetchMessagePublication returns a MessagePublication with the given ID if it exists in the queue, and nil otherwise.
func (*PendingMessageQueue) Len ¶
func (q *PendingMessageQueue) Len() int
Len returns the number of elements in the queue. Returns 0 if the queue is nil.
func (*PendingMessageQueue) Peek ¶
func (q *PendingMessageQueue) Peek() *PendingMessage
Peek returns the element at the top of the heap without removing it.
func (*PendingMessageQueue) Pop ¶
func (q *PendingMessageQueue) Pop() *PendingMessage
Pop removes the last element from the heap and returns its value. Returns nil if the heap is empty or if the value is not a *PendingMessage.
func (*PendingMessageQueue) Push ¶
func (q *PendingMessageQueue) Push(pMsg *PendingMessage)
Push adds an element to the heap. If the pending message's message ID is invalid, or if it already exists in the queue, nothing is added.
func (*PendingMessageQueue) RemoveItem ¶
func (q *PendingMessageQueue) RemoveItem(msgID []byte) (*PendingMessage, error)
RemoveItem removes target MessagePublication with the message ID from the heap. Returns the element that was removed or nil if the item was not found. No error is returned if the item was not found.
type VerificationState ¶
type VerificationState uint8
The `VerificationState` is the result of applying transfer verification to the transaction associated with the `MessagePublication`. While this could likely be extended to additional security controls in the future, it is only used for `txverifier` at present. Consequently, its status should be set to `NotVerified` or `NotApplicable` for all messages that aren't token transfers.
const ( // The default state for a message. This can be used before verification occurs. If no verification is required, `NotApplicable` should be used instead. NotVerified VerificationState = iota // Represents a "known bad" status where a Message has been validated and the result indicates an erroneous or invalid message. The message should be discarded. Rejected // Represents a successful validation, neither confirmed to be good or bad, but unusual. Anomalous // Represents a "known good" status where a Message has been validated and the result is good. The message should be processed normally. Valid // Indicates that no verification is necessary. NotApplicable // The message could not complete the verification process. CouldNotVerify )
func (VerificationState) String ¶
func (v VerificationState) String() string