github.com/MetalBlockchain/metalgo@v1.11.9/vms/avm/txs/executor/executor.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package executor 5 6 import ( 7 "fmt" 8 9 "github.com/MetalBlockchain/metalgo/chains/atomic" 10 "github.com/MetalBlockchain/metalgo/codec" 11 "github.com/MetalBlockchain/metalgo/ids" 12 "github.com/MetalBlockchain/metalgo/utils/set" 13 "github.com/MetalBlockchain/metalgo/vms/avm/state" 14 "github.com/MetalBlockchain/metalgo/vms/avm/txs" 15 "github.com/MetalBlockchain/metalgo/vms/components/avax" 16 ) 17 18 var _ txs.Visitor = (*Executor)(nil) 19 20 type Executor struct { 21 Codec codec.Manager 22 State state.Chain // state will be modified 23 Tx *txs.Tx 24 Inputs set.Set[ids.ID] // imported inputs 25 AtomicRequests map[ids.ID]*atomic.Requests // may be nil 26 } 27 28 func (e *Executor) BaseTx(tx *txs.BaseTx) error { 29 txID := e.Tx.ID() 30 avax.Consume(e.State, tx.Ins) 31 avax.Produce(e.State, txID, tx.Outs) 32 return nil 33 } 34 35 func (e *Executor) CreateAssetTx(tx *txs.CreateAssetTx) error { 36 if err := e.BaseTx(&tx.BaseTx); err != nil { 37 return err 38 } 39 40 txID := e.Tx.ID() 41 index := len(tx.Outs) 42 for _, state := range tx.States { 43 for _, out := range state.Outs { 44 e.State.AddUTXO(&avax.UTXO{ 45 UTXOID: avax.UTXOID{ 46 TxID: txID, 47 OutputIndex: uint32(index), 48 }, 49 Asset: avax.Asset{ 50 ID: txID, 51 }, 52 Out: out, 53 }) 54 index++ 55 } 56 } 57 return nil 58 } 59 60 func (e *Executor) OperationTx(tx *txs.OperationTx) error { 61 if err := e.BaseTx(&tx.BaseTx); err != nil { 62 return err 63 } 64 65 txID := e.Tx.ID() 66 index := len(tx.Outs) 67 for _, op := range tx.Ops { 68 for _, utxoID := range op.UTXOIDs { 69 e.State.DeleteUTXO(utxoID.InputID()) 70 } 71 asset := op.AssetID() 72 for _, out := range op.Op.Outs() { 73 e.State.AddUTXO(&avax.UTXO{ 74 UTXOID: avax.UTXOID{ 75 TxID: txID, 76 OutputIndex: uint32(index), 77 }, 78 Asset: avax.Asset{ID: asset}, 79 Out: out, 80 }) 81 index++ 82 } 83 } 84 return nil 85 } 86 87 func (e *Executor) ImportTx(tx *txs.ImportTx) error { 88 if err := e.BaseTx(&tx.BaseTx); err != nil { 89 return err 90 } 91 92 utxoIDs := make([][]byte, len(tx.ImportedIns)) 93 for i, in := range tx.ImportedIns { 94 utxoID := in.UTXOID.InputID() 95 96 e.Inputs.Add(utxoID) 97 utxoIDs[i] = utxoID[:] 98 } 99 e.AtomicRequests = map[ids.ID]*atomic.Requests{ 100 tx.SourceChain: { 101 RemoveRequests: utxoIDs, 102 }, 103 } 104 return nil 105 } 106 107 func (e *Executor) ExportTx(tx *txs.ExportTx) error { 108 if err := e.BaseTx(&tx.BaseTx); err != nil { 109 return err 110 } 111 112 txID := e.Tx.ID() 113 index := len(tx.Outs) 114 elems := make([]*atomic.Element, len(tx.ExportedOuts)) 115 for i, out := range tx.ExportedOuts { 116 utxo := &avax.UTXO{ 117 UTXOID: avax.UTXOID{ 118 TxID: txID, 119 OutputIndex: uint32(index), 120 }, 121 Asset: avax.Asset{ID: out.AssetID()}, 122 Out: out.Out, 123 } 124 index++ 125 126 utxoBytes, err := e.Codec.Marshal(txs.CodecVersion, utxo) 127 if err != nil { 128 return fmt.Errorf("failed to marshal UTXO: %w", err) 129 } 130 utxoID := utxo.InputID() 131 elem := &atomic.Element{ 132 Key: utxoID[:], 133 Value: utxoBytes, 134 } 135 if out, ok := utxo.Out.(avax.Addressable); ok { 136 elem.Traits = out.Addresses() 137 } 138 139 elems[i] = elem 140 } 141 e.AtomicRequests = map[ids.ID]*atomic.Requests{ 142 tx.DestinationChain: { 143 PutRequests: elems, 144 }, 145 } 146 return nil 147 }