github.com/MetalBlockchain/metalgo@v1.11.9/vms/platformvm/txs/export_tx.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package txs 5 6 import ( 7 "errors" 8 "fmt" 9 10 "github.com/MetalBlockchain/metalgo/ids" 11 "github.com/MetalBlockchain/metalgo/snow" 12 "github.com/MetalBlockchain/metalgo/vms/components/avax" 13 "github.com/MetalBlockchain/metalgo/vms/platformvm/stakeable" 14 "github.com/MetalBlockchain/metalgo/vms/secp256k1fx" 15 ) 16 17 var ( 18 _ UnsignedTx = (*ExportTx)(nil) 19 20 ErrWrongLocktime = errors.New("wrong locktime reported") 21 errNoExportOutputs = errors.New("no export outputs") 22 ) 23 24 // ExportTx is an unsigned exportTx 25 type ExportTx struct { 26 BaseTx `serialize:"true"` 27 28 // Which chain to send the funds to 29 DestinationChain ids.ID `serialize:"true" json:"destinationChain"` 30 31 // Outputs that are exported to the chain 32 ExportedOutputs []*avax.TransferableOutput `serialize:"true" json:"exportedOutputs"` 33 } 34 35 // InitCtx sets the FxID fields in the inputs and outputs of this 36 // [UnsignedExportTx]. Also sets the [ctx] to the given [vm.ctx] so that 37 // the addresses can be json marshalled into human readable format 38 func (tx *ExportTx) InitCtx(ctx *snow.Context) { 39 tx.BaseTx.InitCtx(ctx) 40 for _, out := range tx.ExportedOutputs { 41 out.FxID = secp256k1fx.ID 42 out.InitCtx(ctx) 43 } 44 } 45 46 // SyntacticVerify this transaction is well-formed 47 func (tx *ExportTx) SyntacticVerify(ctx *snow.Context) error { 48 switch { 49 case tx == nil: 50 return ErrNilTx 51 case tx.SyntacticallyVerified: // already passed syntactic verification 52 return nil 53 case len(tx.ExportedOutputs) == 0: 54 return errNoExportOutputs 55 } 56 57 if err := tx.BaseTx.SyntacticVerify(ctx); err != nil { 58 return err 59 } 60 61 for _, out := range tx.ExportedOutputs { 62 if err := out.Verify(); err != nil { 63 return fmt.Errorf("output failed verification: %w", err) 64 } 65 if _, ok := out.Output().(*stakeable.LockOut); ok { 66 return ErrWrongLocktime 67 } 68 } 69 if !avax.IsSortedTransferableOutputs(tx.ExportedOutputs, Codec) { 70 return errOutputsNotSorted 71 } 72 73 tx.SyntacticallyVerified = true 74 return nil 75 } 76 77 func (tx *ExportTx) Visit(visitor Visitor) error { 78 return visitor.ExportTx(tx) 79 }