Files
zeekay 7cf87b230b node-unified is the node
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.
2026-09-07 16:15:25 -07:00

91 lines
2.0 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package tx
import (
"github.com/luxfi/crypto/hash"
"github.com/luxfi/crypto/secp256k1"
"github.com/luxfi/ids"
"github.com/luxfi/zap"
)
// Tx object layout: unsigned bytes ptr @0, signature 65B @8. size 73.
const (
offTxUnsigned = 0
offTxSignature = 8
sizeTx = 73
)
type Tx struct {
Unsigned `json:"unsigned"`
Signature [secp256k1.SignatureLen]byte `json:"signature"`
}
// Marshal encodes the signed tx: the unsigned tx bytes (self-describing via its
// own kind byte) plus the fixed signature.
func (tx *Tx) Marshal() ([]byte, error) {
unsignedBytes, err := tx.Unsigned.Marshal()
if err != nil {
return nil, err
}
b := zap.NewBuilder(zap.HeaderSize + sizeTx + len(unsignedBytes))
ob := b.StartObject(sizeTx)
ob.SetBytes(offTxUnsigned, unsignedBytes)
ob.SetBytesFixed(offTxSignature, tx.Signature[:])
ob.FinishAsRoot()
return b.Finish(), nil
}
func Parse(bytes []byte) (*Tx, error) {
msg, err := zap.Parse(bytes)
if err != nil {
return nil, err
}
obj := msg.Root()
unsigned, err := parseUnsigned(obj.Bytes(offTxUnsigned))
if err != nil {
return nil, err
}
tx := &Tx{Unsigned: unsigned}
copy(tx.Signature[:], obj.BytesFixedSlice(offTxSignature, sigLen))
return tx, nil
}
func Sign(utx Unsigned, key *secp256k1.PrivateKey) (*Tx, error) {
unsignedBytes, err := utx.Marshal()
if err != nil {
return nil, err
}
sig, err := key.Sign(unsignedBytes)
if err != nil {
return nil, err
}
tx := &Tx{
Unsigned: utx,
}
copy(tx.Signature[:], sig[:])
return tx, nil
}
func (tx *Tx) ID() (ids.ID, error) {
bytes, err := tx.Marshal()
return hash.ComputeHash256Array(bytes), err
}
func (tx *Tx) SenderID() (ids.ShortID, error) {
unsignedBytes, err := tx.Unsigned.Marshal()
if err != nil {
return ids.ShortEmpty, err
}
pk, err := secp256k1.RecoverPublicKey(unsignedBytes, tx.Signature[:])
if err != nil {
return ids.ShortEmpty, err
}
addr := pk.Address()
return ids.ShortID(addr), nil
}