mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
v1.36.7: xvm native-nested composites — 2.8x X-tx build, import/export too
Consume utxo v0.5.6 + zap v1.2.3. X-chain BaseTx / ExportTx / ImportTx now build
their transferable out/in lists as native ZAP AddObjectPtr object-lists (no
per-container envelope prefix, no blob concat, no length lists) via
wire.AppendTransferable{Out,In} + TransferableXFromObject. baseTxWire composes
wire.XVMTransferOut/In directly. Removed the standalone transferableOut/InBytes
node helpers. Composite money-move build 2551ns/37allocs (byte-blob) ->
913ns/11allocs (native-nested), 2.8x. Full xvm suite green (round-trip/state/
block/executor/import/export); components-lux + wallet-x + platformvm-txs green.
Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
@@ -143,11 +143,11 @@ require (
|
||||
github.com/luxfi/timer v1.0.2
|
||||
github.com/luxfi/units v1.0.0
|
||||
github.com/luxfi/utils v1.2.0
|
||||
github.com/luxfi/utxo v0.5.3
|
||||
github.com/luxfi/utxo v0.5.6
|
||||
github.com/luxfi/validators v1.2.0
|
||||
github.com/luxfi/vm v1.2.7
|
||||
github.com/luxfi/warp v1.24.0
|
||||
github.com/luxfi/zap v1.2.2
|
||||
github.com/luxfi/zap v1.2.3
|
||||
github.com/luxfi/zwing v0.5.2
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354
|
||||
github.com/zap-proto/http v0.0.0-20260506200741-fd6047874433
|
||||
|
||||
@@ -419,6 +419,10 @@ github.com/luxfi/utils v1.2.0 h1:gtEiI7/NM6PQ/OasEpH0PvB+e5hIS/tpum9r64pYjMc=
|
||||
github.com/luxfi/utils v1.2.0/go.mod h1:T2OCKT1xG9jtKR/gyJQoSkticzrE9WFQ8eohJHGu9Fg=
|
||||
github.com/luxfi/utxo v0.5.3 h1:3RJ6Ow5zYs2atd6QkhRNsW/cgmrQKz/UOFI25ULebQ8=
|
||||
github.com/luxfi/utxo v0.5.3/go.mod h1:YF2r3EGm9pGviZuFBY5tX6rIIYmF+2KvFC/OkW/gqTg=
|
||||
github.com/luxfi/utxo v0.5.5 h1:57iLgiP2nY6d7ljvDpSoQefNbf9+S4Wknj0k99eQ20g=
|
||||
github.com/luxfi/utxo v0.5.5/go.mod h1:Qom/3mk7+9aEziXzdEGvHxTAl7lA2IsSDs+WUkFxjRY=
|
||||
github.com/luxfi/utxo v0.5.6 h1:xdmHmgzhq71rVLd752g4gzl7CFeUsKpxttDdzTQGXKc=
|
||||
github.com/luxfi/utxo v0.5.6/go.mod h1:Qom/3mk7+9aEziXzdEGvHxTAl7lA2IsSDs+WUkFxjRY=
|
||||
github.com/luxfi/validators v1.2.0 h1:VygpiBqBAdGrfkb7xzE2yrVmnXaqE+hm8FLWdGXO7G8=
|
||||
github.com/luxfi/validators v1.2.0/go.mod h1:GYLulrNXAan23ZlX7sgWVbVnLpUexeB/m2qr2ymsXok=
|
||||
github.com/luxfi/version v1.0.1 h1:T/1KYWEMmsrNQk7pN7PFPAwh/7XbeX7cFAKLBqI37Sk=
|
||||
@@ -429,6 +433,8 @@ github.com/luxfi/warp v1.24.0 h1:jrcJNlbOiZsAEopJMy9bSaCwI5NDZ8qgp/6sNoXqepg=
|
||||
github.com/luxfi/warp v1.24.0/go.mod h1:bKvTi24JHlANsl7qkWZAVr/DsMfvwy42f+Cc9x4+Sq8=
|
||||
github.com/luxfi/zap v1.2.2 h1:1WoijKzhx7P//fExdv9P9GNJS1rtpwlBzHLDh5TBc30=
|
||||
github.com/luxfi/zap v1.2.2/go.mod h1:JfqII8VtVQYLLTX6obU1DP9sjGqf9L24vfug5ifh0b8=
|
||||
github.com/luxfi/zap v1.2.3 h1:aLPUgXH5ITqbGRS6tFx1hMZqsB4kL6j39+4s7/JlGgs=
|
||||
github.com/luxfi/zap v1.2.3/go.mod h1:JfqII8VtVQYLLTX6obU1DP9sjGqf9L24vfug5ifh0b8=
|
||||
github.com/luxfi/zapcodec v1.0.1 h1:pRxLxCOi6uihQMg8A8riDjNjefU2cXZxfRVZ+obeuL8=
|
||||
github.com/luxfi/zapcodec v1.0.1/go.mod h1:txrRt2JK4O76ssTxlXIwoNVsgzyZVL0ES4mlXqGNogs=
|
||||
github.com/luxfi/zapdb v1.10.1 h1:XV3k4UTTKKxUMgbfC7woPXgUEIJd3P5nj2lGTQ88xeE=
|
||||
|
||||
@@ -68,7 +68,8 @@
|
||||
"v1.36.3",
|
||||
"v1.36.4",
|
||||
"v1.36.5",
|
||||
"v1.36.6"
|
||||
"v1.36.6",
|
||||
"v1.36.7"
|
||||
],
|
||||
"41": [
|
||||
"v1.13.2"
|
||||
|
||||
@@ -77,7 +77,7 @@ var (
|
||||
const (
|
||||
defaultMajor = 1
|
||||
defaultMinor = 36
|
||||
defaultPatch = 6
|
||||
defaultPatch = 7
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
+15
-8
@@ -105,24 +105,31 @@ func (t *BaseTx) serialize() ([]byte, error) {
|
||||
}
|
||||
|
||||
// baseTxWire builds the wire.XVMBaseTx envelope from the embedded spending
|
||||
// envelope: each Out/In becomes an fx-typed TransferableOut/In envelope built
|
||||
// from its inner fx primitive's .Bytes().
|
||||
// envelope. Each Out/In carries its AssetID (X-Chain is multi-asset) plus the
|
||||
// inner fx primitive's own wire envelope (.Bytes()); NewXVMBaseTx nests them
|
||||
// natively (AddObjectPtr object lists), so there is no per-container envelope
|
||||
// prefix and no blob concatenation.
|
||||
func (t *BaseTx) baseTxWire() ([]byte, error) {
|
||||
outs := make([][]byte, len(t.Outs))
|
||||
outs := make([]wire.XVMTransferOut, len(t.Outs))
|
||||
for i, o := range t.Outs {
|
||||
b, err := transferableOutBytes(o)
|
||||
inner, err := childBytes(o.Out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outs[i] = b
|
||||
outs[i] = wire.XVMTransferOut{AssetID: o.Asset.ID, Output: inner}
|
||||
}
|
||||
ins := make([][]byte, len(t.Ins))
|
||||
ins := make([]wire.XVMTransferIn, len(t.Ins))
|
||||
for i, in := range t.Ins {
|
||||
b, err := transferableInBytes(in)
|
||||
inner, err := childBytes(in.In)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ins[i] = b
|
||||
ins[i] = wire.XVMTransferIn{
|
||||
TxID: in.UTXOID.TxID,
|
||||
OutputIndex: in.UTXOID.OutputIndex,
|
||||
AssetID: in.Asset.ID,
|
||||
Input: inner,
|
||||
}
|
||||
}
|
||||
return wire.NewXVMBaseTx(wire.XVMBaseTxInput{
|
||||
NetworkID: t.NetworkID,
|
||||
|
||||
+20
-21
@@ -33,10 +33,9 @@ type ExportTx struct {
|
||||
}
|
||||
|
||||
const (
|
||||
offExportDest = 16 // 32B
|
||||
offExportOutsLen = 48 // list ptr
|
||||
offExportOutsBlob = 56 // bytes ptr
|
||||
sizeExport = 64
|
||||
offExportDest = 16 // 32B
|
||||
offExportOuts = 48 // objptr list (relOffset + count, 8 bytes)
|
||||
sizeExport = 56
|
||||
)
|
||||
|
||||
func (t *ExportTx) InitRuntime(rt *runtime.Runtime) {
|
||||
@@ -67,23 +66,28 @@ func (t *ExportTx) serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outs := make([][]byte, len(t.ExportedOuts))
|
||||
b := zap.NewBuilder(zap.HeaderSize + sizeExport + len(env) + 256)
|
||||
// Append each exported TransferableOut object inline, then an objptr list —
|
||||
// native nesting, no per-output envelope prefix, no blob concat.
|
||||
offs := make([]int, len(t.ExportedOuts))
|
||||
for i, o := range t.ExportedOuts {
|
||||
b, err := transferableOutBytes(o)
|
||||
inner, err := childBytes(o.Out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outs[i] = b
|
||||
offs[i] = wire.AppendTransferableOut(b, o.Asset.ID, inner)
|
||||
}
|
||||
b := zap.NewBuilder(zap.HeaderSize + sizeExport + len(env) + 256)
|
||||
outsLenOff, outsLenCount, outsBlob := writeBlobList(b, outs)
|
||||
lb := b.StartList(4)
|
||||
for _, off := range offs {
|
||||
lb.AddObjectPtr(off)
|
||||
}
|
||||
outsOff, outsLen := lb.Finish()
|
||||
|
||||
ob := b.StartObject(sizeExport)
|
||||
ob.SetUint8(offXKind, uint8(xkindExport))
|
||||
ob.SetBytes(offBaseTx, env)
|
||||
ob.SetBytesFixed(offExportDest, t.DestinationChain[:])
|
||||
ob.SetList(offExportOutsLen, outsLenOff, outsLenCount)
|
||||
ob.SetBytes(offExportOutsBlob, outsBlob)
|
||||
ob.SetList(offExportOuts, outsOff, outsLen)
|
||||
ob.FinishAsRoot()
|
||||
return b.Finish(), nil
|
||||
}
|
||||
@@ -95,16 +99,11 @@ func parseExportTx(unsignedBytes []byte, obj zap.Object) (*ExportTx, error) {
|
||||
}
|
||||
var destChain ids.ID
|
||||
copy(destChain[:], obj.BytesFixedSlice(offExportDest, 32))
|
||||
outBufs, err := readBlobList(obj, offExportOutsLen, offExportOutsBlob)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outs := make([]*lux.TransferableOutput, len(outBufs))
|
||||
for i, buf := range outBufs {
|
||||
w, err := wire.WrapTransferableOut(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := obj.Message()
|
||||
l := obj.ListStride(offExportOuts, 4)
|
||||
outs := make([]*lux.TransferableOutput, l.Len())
|
||||
for i := range outs {
|
||||
w := wire.TransferableOutFromObject(msg, l.ObjectPtr(i))
|
||||
out, err := outputFromWire(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+5
-21
@@ -81,27 +81,11 @@ func readBlobList(obj zap.Object, lenPtrOff, blobPtrOff int) ([][]byte, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ---- TransferableOutput / TransferableInput <-> wire envelopes ----
|
||||
|
||||
// transferableOutBytes builds a wire TransferableOut envelope (AssetID + inner
|
||||
// fx Output) from a lux.TransferableOutput.
|
||||
func transferableOutBytes(o *lux.TransferableOutput) ([]byte, error) {
|
||||
inner, err := childBytes(o.Out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wire.NewTransferableOut(o.Asset.ID, inner), nil
|
||||
}
|
||||
|
||||
// transferableInBytes builds a wire TransferableIn envelope (UTXOID + AssetID +
|
||||
// inner fx Input) from a lux.TransferableInput.
|
||||
func transferableInBytes(in *lux.TransferableInput) ([]byte, error) {
|
||||
inner, err := childBytes(in.In)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return wire.NewTransferableIn(in.UTXOID.TxID, in.UTXOID.OutputIndex, in.Asset.ID, inner), nil
|
||||
}
|
||||
// ---- TransferableOutput / TransferableInput <-> wire ----
|
||||
//
|
||||
// Build side lives in baseTxWire (BaseTx composes XVMTransferOut/In directly so
|
||||
// the whole tx nests in one buffer). These reconstruct the node types from the
|
||||
// nested wire accessors on the read side.
|
||||
|
||||
// outputFromWire reconstructs a lux.TransferableOutput from a parsed wire
|
||||
// TransferableOut, dispatching the inner fx Output on its own discriminator.
|
||||
|
||||
+18
-21
@@ -34,10 +34,9 @@ type ImportTx struct {
|
||||
}
|
||||
|
||||
const (
|
||||
offImportSource = 16 // 32B
|
||||
offImportInsLen = 48 // list ptr
|
||||
offImportInsBlob = 56 // bytes ptr
|
||||
sizeImport = 64
|
||||
offImportSource = 16 // 32B
|
||||
offImportIns = 48 // objptr list (relOffset + count, 8 bytes)
|
||||
sizeImport = 56
|
||||
)
|
||||
|
||||
// InputUTXOs track which UTXOs this transaction is consuming.
|
||||
@@ -88,23 +87,26 @@ func (t *ImportTx) serialize() ([]byte, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ins := make([][]byte, len(t.ImportedIns))
|
||||
b := zap.NewBuilder(zap.HeaderSize + sizeImport + len(env) + 256)
|
||||
offs := make([]int, len(t.ImportedIns))
|
||||
for i, in := range t.ImportedIns {
|
||||
b, err := transferableInBytes(in)
|
||||
inner, err := childBytes(in.In)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ins[i] = b
|
||||
offs[i] = wire.AppendTransferableIn(b, in.UTXOID.TxID, in.UTXOID.OutputIndex, in.Asset.ID, inner)
|
||||
}
|
||||
b := zap.NewBuilder(zap.HeaderSize + sizeImport + len(env) + 256)
|
||||
insLenOff, insLenCount, insBlob := writeBlobList(b, ins)
|
||||
lb := b.StartList(4)
|
||||
for _, off := range offs {
|
||||
lb.AddObjectPtr(off)
|
||||
}
|
||||
insOff, insLen := lb.Finish()
|
||||
|
||||
ob := b.StartObject(sizeImport)
|
||||
ob.SetUint8(offXKind, uint8(xkindImport))
|
||||
ob.SetBytes(offBaseTx, env)
|
||||
ob.SetBytesFixed(offImportSource, t.SourceChain[:])
|
||||
ob.SetList(offImportInsLen, insLenOff, insLenCount)
|
||||
ob.SetBytes(offImportInsBlob, insBlob)
|
||||
ob.SetList(offImportIns, insOff, insLen)
|
||||
ob.FinishAsRoot()
|
||||
return b.Finish(), nil
|
||||
}
|
||||
@@ -116,16 +118,11 @@ func parseImportTx(unsignedBytes []byte, obj zap.Object) (*ImportTx, error) {
|
||||
}
|
||||
var sourceChain ids.ID
|
||||
copy(sourceChain[:], obj.BytesFixedSlice(offImportSource, 32))
|
||||
inBufs, err := readBlobList(obj, offImportInsLen, offImportInsBlob)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ins := make([]*lux.TransferableInput, len(inBufs))
|
||||
for i, buf := range inBufs {
|
||||
w, err := wire.WrapTransferableIn(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg := obj.Message()
|
||||
l := obj.ListStride(offImportIns, 4)
|
||||
ins := make([]*lux.TransferableInput, l.Len())
|
||||
for i := range ins {
|
||||
w := wire.TransferableInFromObject(msg, l.ObjectPtr(i))
|
||||
in, err := inputFromWire(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user