mirror of
https://github.com/luxfi/evmgpu.git
synced 2026-10-30 16:57:11 +00:00
The identifiers still said unsigned, but warp no longer has an unsigned message: the Message that the previous commit migrated to is the signed subject, and the thing that carries a signature beside it is the Envelope. Locals and parameters that held one drop the prefix, the LocalSigner method that signs one becomes SignMessage, and the two places where a test builds a deliberately malformed message or reads one back out of an event name it invalidMsg and unpacked rather than shadowing the valid message in the enclosing test. PackSendWarpMessageEvent keeps unsignedMessageID, which mirrors the field name in the SendWarpMessage ABI event rather than a Go type. Co-authored-by: Hanzo Dev <[email protected]>
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package warp
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/evmgpu/warp/messages"
|
|
|
|
"github.com/luxfi/crypto"
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/warp"
|
|
"github.com/luxfi/warp/payload"
|
|
)
|
|
|
|
const (
|
|
ParseErrCode = iota + 1
|
|
VerifyErrCode
|
|
)
|
|
|
|
// Verify verifies the signature of the message
|
|
// It implements the warp.Verifier interface
|
|
func (b *backend) Verify(ctx context.Context, msg *warp.Message, _ []byte) error {
|
|
messageIDBytes := msg.ID()
|
|
messageID := ids.ID(crypto.Keccak256Hash(messageIDBytes[:]))
|
|
// Known on-chain messages should be signed
|
|
if _, err := b.GetMessage(messageID); err == nil {
|
|
return nil
|
|
} else if err != database.ErrNotFound {
|
|
return fmt.Errorf("failed to get message %s: %w", messageID, err)
|
|
}
|
|
|
|
parsed, err := payload.ParsePayload(msg.Payload)
|
|
if err != nil {
|
|
b.stats.IncMessageParseFail()
|
|
return fmt.Errorf("failed to parse payload: %w", err)
|
|
}
|
|
|
|
switch p := parsed.(type) {
|
|
case *payload.AddressedCall:
|
|
return b.verifyOffchainAddressedCall(p)
|
|
case *payload.Hash:
|
|
return b.verifyBlockMessage(ctx, p)
|
|
default:
|
|
b.stats.IncMessageParseFail()
|
|
return fmt.Errorf("unknown payload type: %T", p)
|
|
}
|
|
}
|
|
|
|
// verifyBlockMessage returns nil if blockHashPayload contains the ID
|
|
// of an accepted block indicating it should be signed by the VM.
|
|
func (b *backend) verifyBlockMessage(ctx context.Context, blockHashPayload *payload.Hash) error {
|
|
// Convert []byte to ids.ID
|
|
var blockID ids.ID
|
|
copy(blockID[:], blockHashPayload.Hash)
|
|
_, err := b.blockClient.GetAcceptedBlock(ctx, blockID)
|
|
if err != nil {
|
|
b.stats.IncBlockValidationFail()
|
|
return fmt.Errorf("failed to get block %s: %w", blockID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// verifyOffchainAddressedCall verifies the addressed call message
|
|
func (b *backend) verifyOffchainAddressedCall(addressedCall *payload.AddressedCall) error {
|
|
// Further, parse the payload to see if it is a known type.
|
|
parsed, err := messages.Parse(addressedCall.Payload)
|
|
if err != nil {
|
|
b.stats.IncMessageParseFail()
|
|
return fmt.Errorf("failed to parse addressed call message: %w", err)
|
|
}
|
|
|
|
if len(addressedCall.SourceAddress) != 0 {
|
|
return errors.New("source address should be empty for offchain addressed messages")
|
|
}
|
|
|
|
switch p := parsed.(type) {
|
|
case *messages.ValidatorUptime:
|
|
if err := b.verifyUptimeMessage(p); err != nil {
|
|
b.stats.IncUptimeValidationFail()
|
|
return err
|
|
}
|
|
default:
|
|
b.stats.IncMessageParseFail()
|
|
return fmt.Errorf("unknown message type: %T", p)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (b *backend) verifyUptimeMessage(uptimeMsg *messages.ValidatorUptime) error {
|
|
vdr, currentUptime, _, err := b.validatorReader.GetValidatorAndUptime(uptimeMsg.ValidationID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get uptime for validationID %s: %w", uptimeMsg.ValidationID, err)
|
|
}
|
|
|
|
currentUptimeSeconds := uint64(currentUptime.Seconds())
|
|
// verify the current uptime against the total uptime in the message
|
|
if currentUptimeSeconds < uptimeMsg.TotalUptime {
|
|
return fmt.Errorf("current uptime %d is less than queried uptime %d for nodeID %s", currentUptimeSeconds, uptimeMsg.TotalUptime, vdr.NodeID)
|
|
}
|
|
|
|
return nil
|
|
}
|