mirror of
https://github.com/luxfi/node.git
synced 2026-10-30 15:24:05 +00:00
The module already called itself github.com/luxfi/node while containing no node in Go: cmd/luxd was twenty-one lines that printed the size of a few types, and the Go column of the matrix measured a VM plugin. A repo that fetches the thing it claims to be has not replaced it, so the Go sources move in — 1515 files, the daemon and everything under it — and the build reaches outside this module for nothing. Rust and C++ sit beside it unchanged and are still measured against it by the differential. That is the point of one repo: the reference implementation and the two ports are the same checkout, so parity is a thing you can run rather than a thing you assert. Verified: builds, and the closure carries no lux-private — checked at build time rather than believed. The daemon starts twelve chains on a local network (P X C Q Z A B G K M F, plus D through its plugin) and reports healthy.
116 lines
2.7 KiB
Go
116 lines
2.7 KiB
Go
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package txs
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/node/vms/components/verify"
|
|
lux "github.com/luxfi/utxo"
|
|
)
|
|
|
|
// testOperable is a minimal fxs.FxOperation: it verifies (via the embedded
|
|
// TestState), costs zero (via TestTransferable), yields no outputs, and is
|
|
// wire-serializable via a constant fx-operation envelope so the byte-keyed
|
|
// operation sort has a stable key.
|
|
type testOperable struct {
|
|
lux.TestTransferable
|
|
|
|
Outputs []verify.State
|
|
}
|
|
|
|
func (o *testOperable) Outs() []verify.State {
|
|
return o.Outputs
|
|
}
|
|
|
|
func (*testOperable) Bytes() []byte {
|
|
// A deterministic, non-empty fx-operation envelope stand-in. The operation
|
|
// sort key is Asset + UTXOIDs + this blob; distinct UTXOIDs make distinct
|
|
// keys.
|
|
return []byte{0x01, 0x05}
|
|
}
|
|
|
|
func TestOperationVerifyNil(t *testing.T) {
|
|
op := (*Operation)(nil)
|
|
err := op.Verify()
|
|
require.ErrorIs(t, err, ErrNilOperation)
|
|
}
|
|
|
|
func TestOperationVerifyEmpty(t *testing.T) {
|
|
op := &Operation{
|
|
Asset: lux.Asset{ID: ids.Empty},
|
|
}
|
|
err := op.Verify()
|
|
require.ErrorIs(t, err, ErrNilFxOperation)
|
|
}
|
|
|
|
func TestOperationVerifyUTXOIDsNotSorted(t *testing.T) {
|
|
op := &Operation{
|
|
Asset: lux.Asset{ID: ids.Empty},
|
|
UTXOIDs: []*lux.UTXOID{
|
|
{
|
|
TxID: ids.Empty,
|
|
OutputIndex: 1,
|
|
},
|
|
{
|
|
TxID: ids.Empty,
|
|
OutputIndex: 0,
|
|
},
|
|
},
|
|
Op: &testOperable{},
|
|
}
|
|
err := op.Verify()
|
|
require.ErrorIs(t, err, ErrNotSortedAndUniqueUTXOIDs)
|
|
}
|
|
|
|
func TestOperationVerify(t *testing.T) {
|
|
assetID := ids.GenerateTestID()
|
|
op := &Operation{
|
|
Asset: lux.Asset{ID: assetID},
|
|
UTXOIDs: []*lux.UTXOID{
|
|
{
|
|
TxID: assetID,
|
|
OutputIndex: 1,
|
|
},
|
|
},
|
|
Op: &testOperable{},
|
|
}
|
|
require.NoError(t, op.Verify())
|
|
}
|
|
|
|
func TestOperationSorting(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
ops := []*Operation{
|
|
{
|
|
Asset: lux.Asset{ID: ids.Empty},
|
|
UTXOIDs: []*lux.UTXOID{{TxID: ids.Empty, OutputIndex: 1}},
|
|
Op: &testOperable{},
|
|
},
|
|
{
|
|
Asset: lux.Asset{ID: ids.Empty},
|
|
UTXOIDs: []*lux.UTXOID{{TxID: ids.Empty, OutputIndex: 0}},
|
|
Op: &testOperable{},
|
|
},
|
|
}
|
|
require.False(IsSortedAndUniqueOperations(ops))
|
|
SortOperations(ops)
|
|
require.True(IsSortedAndUniqueOperations(ops))
|
|
ops = append(ops, &Operation{
|
|
Asset: lux.Asset{ID: ids.Empty},
|
|
UTXOIDs: []*lux.UTXOID{{TxID: ids.Empty, OutputIndex: 1}},
|
|
Op: &testOperable{},
|
|
})
|
|
require.False(IsSortedAndUniqueOperations(ops))
|
|
}
|
|
|
|
func TestOperationTxNotState(t *testing.T) {
|
|
intf := interface{}(&OperationTx{})
|
|
_, ok := intf.(verify.State)
|
|
require.False(t, ok)
|
|
}
|