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.
91 lines
2.0 KiB
Go
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
|
|
}
|