Files
evmgpu/warp/backend_test.go
zeekayandHanzo Dev 0c11cf1960 warp: name the message for what it now is
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]>
2026-09-06 03:52:57 -07:00

196 lines
6.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package warp
import (
"context"
"crypto/rand"
"testing"
"github.com/luxfi/cache/lru"
"github.com/luxfi/crypto"
"github.com/luxfi/crypto/bls"
"github.com/luxfi/database"
"github.com/luxfi/database/memdb"
"github.com/luxfi/ids"
"github.com/luxfi/warp"
"github.com/luxfi/warp/payload"
"github.com/luxfi/evmgpu/warp/warptest"
"github.com/stretchr/testify/require"
)
var (
networkID uint32 = 54321
sourceChainID = ids.GenerateTestID()
testSourceAddress []byte
testPayload = []byte("test")
testMessage *warp.Message
)
// evmMessageID is the key the backend stores a message under. AddMessage,
// GetMessageSignature and the off-chain message load all hash the message ID
// before touching the database, so a lookup by the bare ID misses.
func evmMessageID(msg *warp.Message) ids.ID {
id := msg.ID()
return ids.ID(crypto.Keccak256Hash(id[:]))
}
func init() {
testSourceAddress = make([]byte, 20)
_, _ = rand.Read(testSourceAddress)
testAddressedCallPayload, err := payload.NewAddressedCall(testSourceAddress, testPayload)
if err != nil {
panic(err)
}
testMessage, err = warp.NewMessage(networkID, sourceChainID, testAddressedCallPayload.Bytes())
if err != nil {
panic(err)
}
}
func TestAddAndGetValidMessage(t *testing.T) {
db := memdb.New()
sk, err := bls.NewSecretKey()
require.NoError(t, err)
warpSigner := warp.NewSigner(sk, networkID, sourceChainID)
messageSignatureCache := lru.NewCache[ids.ID, []byte](500)
backend, err := NewBackend(networkID, sourceChainID, warpSigner, nil, &warptest.NoOpValidatorReader{}, db, messageSignatureCache, nil)
require.NoError(t, err)
// Add testMessage to the warp backend
require.NoError(t, backend.AddMessage(testMessage))
// Verify that a signature is returned successfully, and compare to expected signature.
signature, err := backend.GetMessageSignature(context.TODO(), testMessage)
require.NoError(t, err)
expectedSig, err := warpSigner.Sign(testMessage)
require.NoError(t, err)
require.Equal(t, expectedSig, signature[:])
}
func TestAddAndGetUnknownMessage(t *testing.T) {
db := memdb.New()
sk, err := bls.NewSecretKey()
require.NoError(t, err)
warpSigner := warp.NewSigner(sk, networkID, sourceChainID)
messageSignatureCache := lru.NewCache[ids.ID, []byte](500)
backend, err := NewBackend(networkID, sourceChainID, warpSigner, nil, &warptest.NoOpValidatorReader{}, db, messageSignatureCache, nil)
require.NoError(t, err)
// Try getting a signature for a message that was not added.
_, err = backend.GetMessageSignature(context.TODO(), testMessage)
require.Error(t, err)
}
func TestGetBlockSignature(t *testing.T) {
require := require.New(t)
blkID := ids.GenerateTestID()
blockClient := warptest.MakeBlockClient(blkID)
db := memdb.New()
sk, err := bls.NewSecretKey()
require.NoError(err)
warpSigner := warp.NewSigner(sk, networkID, sourceChainID)
messageSignatureCache := lru.NewCache[ids.ID, []byte](500)
backend, err := NewBackend(networkID, sourceChainID, warpSigner, blockClient, &warptest.NoOpValidatorReader{}, db, messageSignatureCache, nil)
require.NoError(err)
blockHashPayload, err := payload.NewHash(blkID[:])
require.NoError(err)
msg, err := warp.NewMessage(networkID, sourceChainID, blockHashPayload.Bytes())
require.NoError(err)
expectedSig, err := warpSigner.Sign(msg)
require.NoError(err)
signature, err := backend.GetBlockSignature(context.TODO(), blkID)
require.NoError(err)
require.Equal(expectedSig, signature[:])
_, err = backend.GetBlockSignature(context.TODO(), ids.GenerateTestID())
require.Error(err)
}
func TestZeroSizedCache(t *testing.T) {
db := memdb.New()
sk, err := bls.NewSecretKey()
require.NoError(t, err)
warpSigner := warp.NewSigner(sk, networkID, sourceChainID)
// Verify zero sized cache works normally, because the lru cache will be initialized to size 1 for any size parameter <= 0.
messageSignatureCache := lru.NewCache[ids.ID, []byte](0)
backend, err := NewBackend(networkID, sourceChainID, warpSigner, nil, &warptest.NoOpValidatorReader{}, db, messageSignatureCache, nil)
require.NoError(t, err)
// Add testMessage to the warp backend
require.NoError(t, backend.AddMessage(testMessage))
// Verify that a signature is returned successfully, and compare to expected signature.
signature, err := backend.GetMessageSignature(context.TODO(), testMessage)
require.NoError(t, err)
expectedSig, err := warpSigner.Sign(testMessage)
require.NoError(t, err)
require.Equal(t, expectedSig, signature[:])
}
func TestOffChainMessages(t *testing.T) {
type test struct {
offchainMessages [][]byte
check func(require *require.Assertions, b Backend)
err error
}
sk, err := bls.NewSecretKey()
require.NoError(t, err)
warpSigner := warp.NewSigner(sk, networkID, sourceChainID)
for name, test := range map[string]test{
"no offchain messages": {},
"single off-chain message": {
offchainMessages: [][]byte{
testMessage.Bytes(),
},
check: func(require *require.Assertions, b Backend) {
msg, err := b.GetMessage(evmMessageID(testMessage))
require.NoError(err)
require.Equal(testMessage.Bytes(), msg.Bytes())
signature, err := b.GetMessageSignature(context.TODO(), testMessage)
require.NoError(err)
expectedSignatureBytes, err := warpSigner.Sign(msg)
require.NoError(err)
require.Equal(expectedSignatureBytes, signature[:])
},
},
"unknown message": {
check: func(require *require.Assertions, b Backend) {
_, err := b.GetMessage(evmMessageID(testMessage))
require.ErrorIs(err, database.ErrNotFound)
},
},
"invalid message": {
offchainMessages: [][]byte{{1, 2, 3}},
err: errParsingOffChainMessage,
},
} {
t.Run(name, func(t *testing.T) {
require := require.New(t)
db := memdb.New()
messageSignatureCache := lru.NewCache[ids.ID, []byte](0)
backend, err := NewBackend(networkID, sourceChainID, warpSigner, nil, &warptest.NoOpValidatorReader{}, db, messageSignatureCache, test.offchainMessages)
require.ErrorIs(err, test.err)
if test.check != nil {
test.check(require, backend)
}
})
}
}