Files
proto/p/txs/sort_helpers.go
zeekay 20f4da93df proto/p: complete Wave 2A test migration — every _test.go off luxfi/codec
Closes the Wave 2A codec rip (#101). After this commit, proto/p
carries zero github.com/luxfi/codec imports — production AND tests.

  $ grep -rE '"github\.com/luxfi/codec' proto/p --include='*.go'
  (empty)

Test wiring is split across two helper packages to break the
test-time import cycle that proto/p/txs (the lowest layer in the
PVM dep graph) hit when reaching for the PVM codec helpers:

  * proto/internal/pcodectest — codec-agnostic. Re-exports
    codec.ErrCantUnpackVersion, codec.VersionSize, wrappers.Errs,
    wrappers.ErrInsufficientLength, wrappers.Packer, linearcodec.Codec.
    Provides NewLinearCodec / NewLinearCodecWithTags / NewCodecManager
    / NewDefaultCodecManager / MaxInt32Manager / MaxIntManager. NO
    proto/p imports — so any proto/p test file can reach for it
    without closing a cycle.

  * proto/internal/pvmcodectest — PVM-aware. Imports proto/p/{block,
    txs,warp,warp/message,warp/payload}. Provides NewPVMCodecs /
    NewPVMRuntimeCodec / NewPVMGenesisCodec / NewMetadataCodec /
    NewWarpCodec / NewMessageCodec / NewPayloadCodec / PVMCodecs.
    Tests in proto/p/{block,state,utxo,network,validators,txs/executor,
    txs/fee,txs/txheap,warp,warp/message,warp/payload} reach for this.
    Tests inside proto/p/txs can't (would close the cycle) — they
    build their own codec inline via pcodectest.NewLinearCodec +
    txs.RegisterTypes (see p/txs/codec_test.go).

Production-side changes (forward-only):

  * p/block/executor.Manager gains a BlockCodec() method and the
    NewManager constructor takes a blockCodec parameter. Block.Options()
    threads the manager's blockCodec into the options struct so the
    derived commit/abort block constructors get the right codec.

  * p/block/builder.builder.blockCodec() reads from the manager.
    blockBuilder's two pack paths (packDurangoBlockTxs,
    packQuasarBlockTxs) thread backend.WarpCodec into
    state.PickFeeCalculator / fee.TxComplexity, and executeTx threads
    backend.WarpCodec into txexecutor.VerifyWarpMessages.

  * p/block/builder.NewRewardValidatorTx now takes (ctx, txCodec, txID)
    instead of (ctx, txID). The codec comes from the manager via
    builder.blockCodec(). External callers pass it explicitly.

  * p/block/mock_block.go: MockBlock.initialize now takes (bytes, c)
    to match the post-Wave-2A block.Block interface.

  * p/txs/sort_helpers.go gains SortByCompare (exported wrapper around
    the package-internal sortByCompare). Used by tests that need to
    canonicalize input/output orderings under txs_test.

  * p/utxo/verifier_test.go: handler literal now sets codec from
    pcodectest.NewPVMRuntimeCodec — closed a long-standing latent nil
    pointer dereference in TestVerifySpendUTXOs (every locked-output
    case panicked because handler.codec was nil).

  * p/state/metadata_validator_test.go: TestWriteValidatorMetadata
    was rewritten in commit 767ff47 to assert require.True on
    netDB.Has after a bare LoadValidatorMetadata — but Load doesn't
    mark the entry as updated, so WriteValidatorMetadata was a no-op.
    Restored correct semantics by calling SetUptime between Load and
    Write.

Cascade fixes that landed alongside the test migration:

  * Backend struct literals in proto/p/{block,txs}/executor's *_test.go
    now populate TxCodec/WarpCodec/WarpMsgCodec/PayloadCodec. The
    standardTxExecutor's ExportTx, RegisterL1ValidatorTx,
    SetL1ValidatorWeightTx all reach for these codecs through the
    Backend — previously the tests left them nil and panicked at the
    first Marshal call.

  * fxVMInt stubs in p/block/{builder,executor}/helpers_test.go and
    p/txs/executor/helpers_test.go dropped the dead CodecRegistry()
    method (secp256k1fx.VM is ZAP-native now — only Clock() and
    Logger() remain).

  * p/txs/txstest/wallet.go switched from txs.Codec.Unmarshal (which
    is the type, not a value) to signer.Codec.Unmarshal — the SDK
    signer's singleton codec is the natural shared codec for test
    wallet UTXO and PChainOwner decode paths.

Results:
  $ cd proto && go test ./p/...
  ok      github.com/luxfi/proto/p/api
  ok      github.com/luxfi/proto/p/block
  ok      github.com/luxfi/proto/p/block/builder
  ok      github.com/luxfi/proto/p/block/executor
  ok      github.com/luxfi/proto/p/config
  ok      github.com/luxfi/proto/p/genesis
  ok      github.com/luxfi/proto/p/network
  ok      github.com/luxfi/proto/p/reward
  ok      github.com/luxfi/proto/p/stakeable
  ok      github.com/luxfi/proto/p/state
  ok      github.com/luxfi/proto/p/status
  ok      github.com/luxfi/proto/p/txs
  ok      github.com/luxfi/proto/p/txs/executor
  ok      github.com/luxfi/proto/p/txs/fee
  ok      github.com/luxfi/proto/p/txs/txheap
  ok      github.com/luxfi/proto/p/utxo
  ok      github.com/luxfi/proto/p/validators
  ok      github.com/luxfi/proto/p/validators/fee
  ok      github.com/luxfi/proto/p/validators/validatorstest
  ok      github.com/luxfi/proto/p/warp
  ok      github.com/luxfi/proto/p/warp/message
  ok      github.com/luxfi/proto/p/warp/payload
2026-06-06 02:34:50 -07:00

42 lines
964 B
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package txs
import (
"cmp"
"slices"
)
func sortByCompare[T interface{ Compare(T) int }](s []T) {
slices.SortFunc(s, func(a, b T) int {
return a.Compare(b)
})
}
// SortByCompare is the exported entry point for sortByCompare. Tests in
// external test packages (proto/p/txs_test, etc.) reach for this when
// they need to assemble the canonical input/output ordering that
// matches what the production txs.Tx serialiser produces.
func SortByCompare[T interface{ Compare(T) int }](s []T) {
sortByCompare(s)
}
func isSortedAndUniqueByCompare[T interface{ Compare(T) int }](s []T) bool {
for i := 1; i < len(s); i++ {
if s[i-1].Compare(s[i]) >= 0 {
return false
}
}
return true
}
func isSortedAndUniqueOrdered[T cmp.Ordered](s []T) bool {
for i := 1; i < len(s); i++ {
if s[i-1] >= s[i] {
return false
}
}
return true
}