Files
utxo/wire/composite_bench_test.go
zeekayandHanzo Dev 233df7108f wire: native-nested XVMBaseTx (AddObjectPtr object lists) — 2.8x faster X-tx build
Replace the byte-blob composite (per-container TypeKind/ShapeKind prefix +
OutsBytes/InsBytes concat + parallel u32 length lists) with native ZAP nesting:
XVMBaseTx carries Outs/Ins as AddObjectPtr object-lists, each element a
TransferableOut/In OBJECT living inline in the same buffer. The fx-agnostic
container needs no prefix (fx polymorphism stays on the inner Output/Input
envelope's discriminator, stored zero-copy in the leaf bytes field). Needs zap
v1.2.3 (List.ObjectPtr).

Composite 2in/2out money-move build (vs prior wire):
  v0.5.2 byte-blob:      2551ns / 5328B / 37 allocs
  v0.5.4 pooled+fixed:   1345ns / 2401B / 19 allocs
  v0.5.5 native-nested:  ~913ns / 1328B / 11 allocs   (2.8x / 4x mem / 3.4x allocs vs v0.5.2)

Fully general — all 11 fx round-trip suites green (secp/ed25519/mldsa/slhdsa/
secp256r1/schnorr/bls/nft/property + wire). NewXVMBaseTx now takes
XVMTransferOut/In (AssetID + inner envelope) directly; standalone
NewTransferableOut/In + WrapTransferableOut/In envelopes are gone (they only
ever nested). The remaining 11 allocs are the 4 leaf .Bytes() envelopes + slices;
leaf-inline (per-fx AppendObject) is the zero-alloc follow-up.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-14 06:33:40 -07:00

57 lines
1.5 KiB
Go

// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package wire_test
import (
"testing"
"github.com/luxfi/ids"
"github.com/luxfi/utxo/secp256k1fx"
"github.com/luxfi/utxo/wire"
)
// BenchmarkComposite_XVMBaseTx measures the full X-chain money-move wire
// composition (2 outs + 2 ins, secp256k1fx inner envelopes + Transferable
// envelopes + XVMBaseTx envelope) — the exact per-tx build work xvm's
// serializeUnsigned performs. This is the pooled-builder + SetBytesFixed +
// zero-copy-SetBytes hot path.
func BenchmarkComposite_XVMBaseTx(b *testing.B) {
assetID := ids.ID{0x51, 0xc2, 0x4f, 0xe7}
txID := ids.ID{0xaa, 0xbb}
addr := ids.ShortID{0x01, 0x02, 0x03}
out := &secp256k1fx.TransferOutput{
Amt: 1_000_000,
OutputOwners: secp256k1fx.OutputOwners{
Threshold: 1,
Addrs: []ids.ShortID{addr},
},
}
in := &secp256k1fx.TransferInput{
Amt: 2_000_000,
Input: secp256k1fx.Input{SigIndices: []uint32{0}},
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
outs := make([]wire.XVMTransferOut, 2)
for j := range outs {
outs[j] = wire.XVMTransferOut{AssetID: assetID, Output: out.Bytes()}
}
ins := make([]wire.XVMTransferIn, 2)
for j := range ins {
ins[j] = wire.XVMTransferIn{TxID: txID, OutputIndex: uint32(j), AssetID: assetID, Input: in.Bytes()}
}
env := wire.NewXVMBaseTx(wire.XVMBaseTxInput{
NetworkID: 1,
BlockchainID: [32]byte{0x01},
Outs: outs,
Ins: ins,
})
if len(env) == 0 {
b.Fatal("empty")
}
}
}