mirror of
https://github.com/luxfi/proto.git
synced 2026-10-30 15:21:09 +00:00
- safemath.Add64/Mul64 → Add/Mul (Go generics; same wire/bounds
behaviour, fewer per-width copies). Sweep across p/{reward,utxo,txs}
and the x-side test helpers.
- lux.SortTransferableOutputs / SyntacticVerifier UTXO/Output helpers:
drop the threaded Codec arg; sort key is now Bytes()+assetID, no
codec roundtrip per compare. Callers in p/utxo/handler.go,
p/txs/{add_*,base_tx,builder,executor/*}, p/state, and
x/txs/executor/syntactic_verifier follow.
- stakeable.LockOut: implement Bytes() returning
0xFF || BE(Locktime) || inner.Bytes(). 0xFF marker keeps locked
outputs sorted strictly AFTER unlocked fxs primitives, preserving
the legacy ordering invariant the SyntacticVerify expects.
- Update test helpers in p/block/{builder,executor}, p/network, p/txs
to construct outputs without the codec arg and rely on the new sort.
89 lines
2.2 KiB
Go
89 lines
2.2 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package txs
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/luxfi/runtime"
|
|
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/proto/p/stakeable"
|
|
lux "github.com/luxfi/utxo"
|
|
"github.com/luxfi/utxo/secp256k1fx"
|
|
)
|
|
|
|
var (
|
|
_ UnsignedTx = (*ExportTx)(nil)
|
|
|
|
ErrWrongLocktime = errors.New("wrong locktime reported")
|
|
errNoExportOutputs = errors.New("no export outputs")
|
|
)
|
|
|
|
// ExportTx is an unsigned exportTx
|
|
type ExportTx struct {
|
|
BaseTx `serialize:"true"`
|
|
|
|
// Which chain to send the funds to
|
|
DestinationChain ids.ID `serialize:"true" json:"destinationChain"`
|
|
|
|
// Outputs that are exported to the chain
|
|
ExportedOutputs []*lux.TransferableOutput `serialize:"true" json:"exportedOutputs"`
|
|
}
|
|
|
|
// InitRuntime sets the FxID fields in the inputs and outputs of this
|
|
// [UnsignedExportTx]. Also sets the [ctx] to the given [vm.ctx] so that
|
|
// the addresses can be json marshalled into human readable format
|
|
func (tx *ExportTx) InitRuntime(rt *runtime.Runtime) {
|
|
tx.BaseTx.InitRuntime(rt)
|
|
for _, out := range tx.ExportedOutputs {
|
|
out.FxID = secp256k1fx.ID
|
|
out.InitRuntime(rt)
|
|
}
|
|
}
|
|
|
|
// SyntacticVerify this transaction is well-formed
|
|
func (tx *ExportTx) SyntacticVerify(rt *runtime.Runtime) error {
|
|
switch {
|
|
case tx == nil:
|
|
return ErrNilTx
|
|
case tx.SyntacticallyVerified: // already passed syntactic verification
|
|
return nil
|
|
case len(tx.ExportedOutputs) == 0:
|
|
return errNoExportOutputs
|
|
}
|
|
|
|
if err := tx.BaseTx.SyntacticVerify(rt); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, out := range tx.ExportedOutputs {
|
|
if err := out.Verify(); err != nil {
|
|
return fmt.Errorf("output failed verification: %w", err)
|
|
}
|
|
if _, ok := out.Output().(*stakeable.LockOut); ok {
|
|
return ErrWrongLocktime
|
|
}
|
|
}
|
|
if !lux.IsSortedTransferableOutputs(tx.ExportedOutputs) {
|
|
return errOutputsNotSorted
|
|
}
|
|
|
|
tx.SyntacticallyVerified = true
|
|
return nil
|
|
}
|
|
|
|
func (tx *ExportTx) Visit(visitor Visitor) error {
|
|
return visitor.ExportTx(tx)
|
|
}
|
|
|
|
// InitializeWithContext initializes the transaction with consensus context
|
|
func (tx *ExportTx) InitializeWithContext(ctx context.Context) error {
|
|
// Initialize any context-dependent fields here
|
|
return nil
|
|
}
|