mirror of
https://github.com/luxfi/warp.git
synced 2026-10-30 15:13:04 +00:00
366 lines
9.0 KiB
Go
366 lines
9.0 KiB
Go
// Copyright (C) 2019-2025, Lux Partners Limited. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package payload
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/geth/rlp"
|
|
)
|
|
|
|
// Payload types
|
|
const (
|
|
// AddressedCall payload type ID
|
|
AddressedCallID uint32 = 0
|
|
|
|
// Hash payload type ID
|
|
HashID uint32 = 1
|
|
|
|
// L1ValidatorRegistration payload type ID
|
|
L1ValidatorRegistrationID uint32 = 2
|
|
|
|
// RegisterL1Validator payload type ID
|
|
RegisterL1ValidatorID uint32 = 3
|
|
|
|
// ChainToL1Conversion payload type ID
|
|
ChainToL1ConversionID uint32 = 4
|
|
|
|
// L1ValidatorWeight payload type ID
|
|
L1ValidatorWeightID uint32 = 5
|
|
)
|
|
|
|
var (
|
|
// ErrInvalidPayload is returned when a payload is invalid
|
|
ErrInvalidPayload = errors.New("invalid payload")
|
|
)
|
|
|
|
// Payload is an interface for warp message payloads
|
|
type Payload interface {
|
|
// Bytes returns the byte representation of the payload
|
|
Bytes() []byte
|
|
|
|
// Verify verifies the payload
|
|
Verify() error
|
|
}
|
|
|
|
// ParsePayload parses a payload from bytes
|
|
func ParsePayload(bytes []byte) (Payload, error) {
|
|
// Try to decode as each payload type
|
|
// This is a simplified approach - in production you'd use a type registry
|
|
var err error
|
|
|
|
// Try AddressedCall
|
|
ac := &AddressedCall{}
|
|
if err = rlp.DecodeBytes(bytes, ac); err == nil {
|
|
if err = ac.Verify(); err == nil {
|
|
return ac, nil
|
|
}
|
|
}
|
|
|
|
// Try Hash
|
|
h := &Hash{}
|
|
if err = rlp.DecodeBytes(bytes, h); err == nil {
|
|
if err = h.Verify(); err == nil {
|
|
return h, nil
|
|
}
|
|
}
|
|
|
|
// Try L1ValidatorRegistration
|
|
lvr := &L1ValidatorRegistration{}
|
|
if err = rlp.DecodeBytes(bytes, lvr); err == nil {
|
|
if err = lvr.Verify(); err == nil {
|
|
return lvr, nil
|
|
}
|
|
}
|
|
|
|
// Try RegisterL1Validator
|
|
rlv := &RegisterL1Validator{}
|
|
if err = rlp.DecodeBytes(bytes, rlv); err == nil {
|
|
if err = rlv.Verify(); err == nil {
|
|
return rlv, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("%w: unable to decode payload", ErrInvalidPayload)
|
|
}
|
|
|
|
// ParseAddressedCall parses a payload from bytes as an AddressedCall
|
|
func ParseAddressedCall(bytes []byte) (*AddressedCall, error) {
|
|
// First try to parse as generic payload
|
|
p, err := ParsePayload(bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Type assert to AddressedCall
|
|
ac, ok := p.(*AddressedCall)
|
|
if !ok {
|
|
return nil, fmt.Errorf("payload is not an AddressedCall")
|
|
}
|
|
return ac, nil
|
|
}
|
|
|
|
// ParseHash parses a payload from bytes as a Hash
|
|
func ParseHash(bytes []byte) (*Hash, error) {
|
|
// First try to parse as generic payload
|
|
p, err := ParsePayload(bytes)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Type assert to Hash
|
|
h, ok := p.(*Hash)
|
|
if !ok {
|
|
return nil, fmt.Errorf("payload is not a Hash")
|
|
}
|
|
return h, nil
|
|
}
|
|
|
|
// AddressedCall is a payload for cross-VM calls
|
|
type AddressedCall struct {
|
|
SourceAddress []byte `serialize:"true"`
|
|
Payload []byte `serialize:"true"`
|
|
}
|
|
|
|
// NewAddressedCall creates a new addressed call payload
|
|
func NewAddressedCall(sourceAddress []byte, payload []byte) (*AddressedCall, error) {
|
|
ac := &AddressedCall{
|
|
SourceAddress: sourceAddress,
|
|
Payload: payload,
|
|
}
|
|
if err := ac.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return ac, nil
|
|
}
|
|
|
|
// Verify verifies the addressed call payload
|
|
func (a *AddressedCall) Verify() error {
|
|
if len(a.SourceAddress) == 0 {
|
|
return fmt.Errorf("%w: empty source address", ErrInvalidPayload)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (a *AddressedCall) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(a)
|
|
return bytes
|
|
}
|
|
|
|
// Hash is a simple hash payload
|
|
type Hash struct {
|
|
Hash []byte `serialize:"true"`
|
|
}
|
|
|
|
// NewHash creates a new hash payload
|
|
func NewHash(hash []byte) (*Hash, error) {
|
|
h := &Hash{Hash: hash}
|
|
if err := h.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return h, nil
|
|
}
|
|
|
|
// Verify verifies the hash payload
|
|
func (h *Hash) Verify() error {
|
|
if len(h.Hash) != 32 {
|
|
return fmt.Errorf("%w: hash must be 32 bytes", ErrInvalidPayload)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (h *Hash) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(h)
|
|
return bytes
|
|
}
|
|
|
|
// L1ValidatorRegistration represents a validator registration status
|
|
type L1ValidatorRegistration struct {
|
|
Valid bool `serialize:"true"`
|
|
Validation []byte `serialize:"true"`
|
|
}
|
|
|
|
// NewL1ValidatorRegistration creates a new L1 validator registration payload
|
|
func NewL1ValidatorRegistration(valid bool, validation []byte) (*L1ValidatorRegistration, error) {
|
|
r := &L1ValidatorRegistration{
|
|
Valid: valid,
|
|
Validation: validation,
|
|
}
|
|
if err := r.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
// Verify verifies the registration payload
|
|
func (r *L1ValidatorRegistration) Verify() error {
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (r *L1ValidatorRegistration) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(r)
|
|
return bytes
|
|
}
|
|
|
|
// RegisterL1Validator adds a validator to a chain
|
|
type RegisterL1Validator struct {
|
|
ChainID []byte `serialize:"true"`
|
|
NodeID []byte `serialize:"true"`
|
|
Weight uint64 `serialize:"true"`
|
|
BLSPublicKey []byte `serialize:"true"`
|
|
RegistrationTime uint64 `serialize:"true"`
|
|
}
|
|
|
|
// NewRegisterL1Validator creates a new register L1 validator payload
|
|
func NewRegisterL1Validator(
|
|
chainID []byte,
|
|
nodeID []byte,
|
|
weight uint64,
|
|
blsPublicKey []byte,
|
|
registrationTime uint64,
|
|
) (*RegisterL1Validator, error) {
|
|
r := &RegisterL1Validator{
|
|
ChainID: chainID,
|
|
NodeID: nodeID,
|
|
Weight: weight,
|
|
BLSPublicKey: blsPublicKey,
|
|
RegistrationTime: registrationTime,
|
|
}
|
|
if err := r.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
// Verify verifies the register validator payload
|
|
func (r *RegisterL1Validator) Verify() error {
|
|
if len(r.ChainID) != 32 {
|
|
return fmt.Errorf("%w: chain ID must be 32 bytes", ErrInvalidPayload)
|
|
}
|
|
if len(r.NodeID) == 0 {
|
|
return fmt.Errorf("%w: empty node ID", ErrInvalidPayload)
|
|
}
|
|
if r.Weight == 0 {
|
|
return fmt.Errorf("%w: zero weight", ErrInvalidPayload)
|
|
}
|
|
if len(r.BLSPublicKey) == 0 {
|
|
return fmt.Errorf("%w: empty BLS public key", ErrInvalidPayload)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (r *RegisterL1Validator) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(r)
|
|
return bytes
|
|
}
|
|
|
|
// ChainToL1Conversion represents a chain conversion message
|
|
type ChainToL1Conversion struct {
|
|
ChainID []byte `serialize:"true"`
|
|
ManagerChainID []byte `serialize:"true"`
|
|
Address []byte `serialize:"true"`
|
|
Managers [][]byte `serialize:"true"`
|
|
}
|
|
|
|
// NewChainToL1Conversion creates a new chain to L1 conversion payload
|
|
func NewChainToL1Conversion(
|
|
chainID []byte,
|
|
managerChainID []byte,
|
|
address []byte,
|
|
managers [][]byte,
|
|
) (*ChainToL1Conversion, error) {
|
|
c := &ChainToL1Conversion{
|
|
ChainID: chainID,
|
|
ManagerChainID: managerChainID,
|
|
Address: address,
|
|
Managers: managers,
|
|
}
|
|
if err := c.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// Verify verifies the conversion payload
|
|
func (c *ChainToL1Conversion) Verify() error {
|
|
if len(c.ChainID) != 32 {
|
|
return fmt.Errorf("%w: chain ID must be 32 bytes", ErrInvalidPayload)
|
|
}
|
|
if len(c.ChainID) != 32 {
|
|
return fmt.Errorf("%w: chain ID must be 32 bytes", ErrInvalidPayload)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (c *ChainToL1Conversion) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(c)
|
|
return bytes
|
|
}
|
|
|
|
// L1ValidatorWeight represents a validator weight update
|
|
type L1ValidatorWeight struct {
|
|
ValidationID []byte `serialize:"true"`
|
|
Nonce uint64 `serialize:"true"`
|
|
Weight uint64 `serialize:"true"`
|
|
}
|
|
|
|
// NewL1ValidatorWeight creates a new validator weight payload
|
|
func NewL1ValidatorWeight(
|
|
validationID []byte,
|
|
nonce uint64,
|
|
weight uint64,
|
|
) (*L1ValidatorWeight, error) {
|
|
w := &L1ValidatorWeight{
|
|
ValidationID: validationID,
|
|
Nonce: nonce,
|
|
Weight: weight,
|
|
}
|
|
if err := w.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return w, nil
|
|
}
|
|
|
|
// Verify verifies the weight payload
|
|
func (w *L1ValidatorWeight) Verify() error {
|
|
if len(w.ValidationID) != 32 {
|
|
return fmt.Errorf("%w: validation ID must be 32 bytes", ErrInvalidPayload)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Bytes returns the byte representation of the payload
|
|
func (w *L1ValidatorWeight) Bytes() []byte {
|
|
bytes, _ := rlp.EncodeToBytes(w)
|
|
return bytes
|
|
}
|
|
|
|
// ParseRegisterL1Validator parses a payload from bytes as a RegisterL1Validator
|
|
func ParseRegisterL1Validator(bytes []byte) (*RegisterL1Validator, error) {
|
|
rlv := &RegisterL1Validator{}
|
|
if err := rlp.DecodeBytes(bytes, rlv); err != nil {
|
|
return nil, fmt.Errorf("failed to decode register L1 validator: %w", err)
|
|
}
|
|
if err := rlv.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return rlv, nil
|
|
}
|
|
|
|
// ParseL1ValidatorRegistration parses a payload from bytes as an L1ValidatorRegistration
|
|
func ParseL1ValidatorRegistration(bytes []byte) (*L1ValidatorRegistration, error) {
|
|
lvr := &L1ValidatorRegistration{}
|
|
if err := rlp.DecodeBytes(bytes, lvr); err != nil {
|
|
return nil, fmt.Errorf("failed to decode L1 validator registration: %w", err)
|
|
}
|
|
if err := lvr.Verify(); err != nil {
|
|
return nil, err
|
|
}
|
|
return lvr, nil
|
|
}
|