Skip to content

Commit

Permalink
Refactor X-chain tx execution (#2724)
Browse files Browse the repository at this point in the history
Co-authored-by: Chloe <99216251+coffeeavax@users.noreply.github.com>
  • Loading branch information
StephenButtolph and coffeeavax committed Mar 13, 2023
1 parent 161fe75 commit 036e34f
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 109 deletions.
91 changes: 0 additions & 91 deletions vms/avm/tx_execute.go

This file was deleted.

144 changes: 144 additions & 0 deletions vms/avm/txs/executor/executor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package executor

import (
"fmt"

"github.com/ava-labs/avalanchego/chains/atomic"
"github.com/ava-labs/avalanchego/codec"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/vms/avm/states"
"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/vms/components/avax"
)

var _ txs.Visitor = (*Executor)(nil)

type Executor struct {
Codec codec.Manager
State states.Chain // state will be modified
Tx *txs.Tx
Inputs set.Set[ids.ID] // imported inputs
AtomicRequests map[ids.ID]*atomic.Requests // may be nil
}

func (e *Executor) BaseTx(tx *txs.BaseTx) error {
txID := e.Tx.ID()
avax.Consume(e.State, tx.Ins)
avax.Produce(e.State, txID, tx.Outs)
return nil
}

func (e *Executor) CreateAssetTx(tx *txs.CreateAssetTx) error {
if err := e.BaseTx(&tx.BaseTx); err != nil {
return err
}

txID := e.Tx.ID()
index := len(tx.Outs)
for _, state := range tx.States {
for _, out := range state.Outs {
e.State.AddUTXO(&avax.UTXO{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(index),
},
Asset: avax.Asset{
ID: txID,
},
Out: out,
})
index++
}
}
return nil
}

func (e *Executor) OperationTx(tx *txs.OperationTx) error {
if err := e.BaseTx(&tx.BaseTx); err != nil {
return err
}

txID := e.Tx.ID()
index := len(tx.Outs)
for _, op := range tx.Ops {
asset := op.AssetID()
for _, out := range op.Op.Outs() {
e.State.AddUTXO(&avax.UTXO{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(index),
},
Asset: avax.Asset{ID: asset},
Out: out,
})
index++
}
}
return nil
}

func (e *Executor) ImportTx(tx *txs.ImportTx) error {
if err := e.BaseTx(&tx.BaseTx); err != nil {
return err
}

utxoIDs := make([][]byte, len(tx.ImportedIns))
for i, in := range tx.ImportedIns {
utxoID := in.UTXOID.InputID()

e.Inputs.Add(utxoID)
utxoIDs[i] = utxoID[:]
}
e.AtomicRequests = map[ids.ID]*atomic.Requests{
tx.SourceChain: {
RemoveRequests: utxoIDs,
},
}
return nil
}

func (e *Executor) ExportTx(tx *txs.ExportTx) error {
if err := e.BaseTx(&tx.BaseTx); err != nil {
return err
}

txID := e.Tx.ID()
index := len(tx.Outs)
elems := make([]*atomic.Element, len(tx.ExportedOuts))
for i, out := range tx.ExportedOuts {
utxo := &avax.UTXO{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(index),
},
Asset: avax.Asset{ID: out.AssetID()},
Out: out.Out,
}
index++

utxoBytes, err := e.Codec.Marshal(txs.CodecVersion, utxo)
if err != nil {
return fmt.Errorf("failed to marshal UTXO: %w", err)
}
utxoID := utxo.InputID()
elem := &atomic.Element{
Key: utxoID[:],
Value: utxoBytes,
}
if out, ok := utxo.Out.(avax.Addressable); ok {
elem.Traits = out.Addresses()
}

elems[i] = elem
}
e.AtomicRequests = map[ids.ID]*atomic.Requests{
tx.DestinationChain: {
PutRequests: elems,
},
}
return nil
}
31 changes: 13 additions & 18 deletions vms/avm/unique_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,19 +152,16 @@ func (tx *UniqueTx) Accept(context.Context) error {
return fmt.Errorf("error indexing tx: %w", err)
}

// Remove spent utxos
for _, utxo := range inputUTXOIDs {
if utxo.Symbolic() {
// If the UTXO is symbolic, it can't be spent
continue
}
utxoID := utxo.InputID()
tx.vm.state.DeleteUTXO(utxoID)
executor := &executor.Executor{
Codec: tx.vm.txBackend.Codec,
State: tx.vm.state,
Tx: tx.Tx,
}
// Add new utxos
for _, utxo := range outputUTXOs {
tx.vm.state.AddUTXO(utxo)
err := tx.Tx.Unsigned.Visit(executor)
if err != nil {
return fmt.Errorf("error staging accepted state changes: %w", err)
}

tx.setStatus(choices.Accepted)

commitBatch, err := tx.vm.state.CommitBatch()
Expand All @@ -173,14 +170,12 @@ func (tx *UniqueTx) Accept(context.Context) error {
}

defer tx.vm.state.Abort()
err = tx.Tx.Unsigned.Visit(&executeTx{
tx: tx.Tx,
batch: commitBatch,
sharedMemory: tx.vm.ctx.SharedMemory,
parser: tx.vm.parser,
})
err = tx.vm.ctx.SharedMemory.Apply(
executor.AtomicRequests,
commitBatch,
)
if err != nil {
return fmt.Errorf("ExecuteWithSideEffects erred while processing tx %s: %w", txID, err)
return fmt.Errorf("error committing accepted state changes while processing tx %s: %w", txID, err)
}

tx.vm.pubsub.Publish(NewPubSubFilterer(tx.Tx))
Expand Down

1 comment on commit 036e34f

@Mikhai56
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

что это за цифры постоянно приходят зачем они мне нужны????

Please sign in to comment.