From 52c6ccd2f063a6cccc35f5b4380b22fb9dd0f102 Mon Sep 17 00:00:00 2001 From: StephenButtolph Date: Thu, 20 Aug 2020 09:42:06 -0400 Subject: implemented exportTx accept --- plugin/evm/block.go | 78 ++++++++++++++++++++++++++----------------------- plugin/evm/export_tx.go | 35 ++++++++++++++++++++-- plugin/evm/vm.go | 13 +++++---- 3 files changed, 82 insertions(+), 44 deletions(-) diff --git a/plugin/evm/block.go b/plugin/evm/block.go index b3412a0..8e13c67 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -33,9 +33,12 @@ func (b *Block) Accept() error { vm.updateStatus(b.ID(), choices.Accepted) tx := vm.getAtomicTx(b.ethBlock) + if tx == nil { + return nil + } utx, ok := tx.UnsignedTx.(UnsignedAtomicTx) if !ok { - return errors.New("unknown atomic tx type") + return errors.New("unknown tx type") } return utx.Accept(vm.ctx, nil) @@ -73,47 +76,50 @@ func (b *Block) Parent() snowman.Block { func (b *Block) Verify() error { vm := b.vm tx := vm.getAtomicTx(b.ethBlock) - switch atx := tx.UnsignedTx.(type) { - case *UnsignedImportTx: - if b.ethBlock.Hash() == vm.genesisHash { - return nil - } - p := b.Parent() - path := []*Block{} - inputs := new(ids.Set) - for { - if p.Status() == choices.Accepted || p.(*Block).ethBlock.Hash() == vm.genesisHash { - break + if tx != nil { + switch atx := tx.UnsignedTx.(type) { + case *UnsignedImportTx: + if b.ethBlock.Hash() == vm.genesisHash { + return nil } - if ret, hit := vm.blockAtomicInputCache.Get(p.ID()); hit { - inputs = ret.(*ids.Set) - break + p := b.Parent() + path := []*Block{} + inputs := new(ids.Set) + for { + if p.Status() == choices.Accepted || p.(*Block).ethBlock.Hash() == vm.genesisHash { + break + } + if ret, hit := vm.blockAtomicInputCache.Get(p.ID()); hit { + inputs = ret.(*ids.Set) + break + } + path = append(path, p.(*Block)) + p = p.Parent().(*Block) } - path = append(path, p.(*Block)) - p = p.Parent().(*Block) - } - for i := len(path) - 1; i >= 0; i-- { - inputsCopy := new(ids.Set) - p := path[i] - atx := vm.getAtomicTx(p.ethBlock) - inputs.Union(atx.UnsignedTx.(UnsignedAtomicTx).InputUTXOs()) - inputsCopy.Union(*inputs) - vm.blockAtomicInputCache.Put(p.ID(), inputsCopy) - } - for _, in := range atx.InputUTXOs().List() { - if inputs.Contains(in) { - return errInvalidBlock + for i := len(path) - 1; i >= 0; i-- { + inputsCopy := new(ids.Set) + p := path[i] + atx := vm.getAtomicTx(p.ethBlock) + if atx != nil { + inputs.Union(atx.UnsignedTx.(UnsignedAtomicTx).InputUTXOs()) + inputsCopy.Union(*inputs) + } + vm.blockAtomicInputCache.Put(p.ID(), inputsCopy) } + for _, in := range atx.InputUTXOs().List() { + if inputs.Contains(in) { + return errInvalidBlock + } + } + case *UnsignedExportTx: + default: + return errors.New("unknown atomic tx type") } - case *UnsignedExportTx: - default: - return errors.New("unknown atomic tx type") - } - if tx.UnsignedTx.(UnsignedAtomicTx).SemanticVerify(vm, tx) != nil { - return errInvalidBlock + if tx.UnsignedTx.(UnsignedAtomicTx).SemanticVerify(vm, tx) != nil { + return errInvalidBlock + } } - _, err := b.vm.chain.InsertChain([]*types.Block{b.ethBlock}) return err } diff --git a/plugin/evm/export_tx.go b/plugin/evm/export_tx.go index 8b3c4f8..31b4681 100644 --- a/plugin/evm/export_tx.go +++ b/plugin/evm/export_tx.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/coreth/core/state" "github.com/ava-labs/go-ethereum/log" + "github.com/ava-labs/gecko/chains/atomic" "github.com/ava-labs/gecko/database" "github.com/ava-labs/gecko/ids" "github.com/ava-labs/gecko/snow" @@ -126,9 +127,37 @@ func (tx *UnsignedExportTx) SemanticVerify( } // Accept this transaction. -func (tx *UnsignedExportTx) Accept(ctx *snow.Context, batch database.Batch) error { - // TODO: finish this function via gRPC - return nil +func (tx *UnsignedExportTx) Accept(ctx *snow.Context, _ database.Batch) error { + txID := tx.ID() + + elems := make([]*atomic.Element, len(tx.ExportedOutputs)) + for i, out := range tx.ExportedOutputs { + utxo := &avax.UTXO{ + UTXOID: avax.UTXOID{ + TxID: txID, + OutputIndex: uint32(i), + }, + Asset: avax.Asset{ID: out.AssetID()}, + Out: out.Out, + } + + utxoBytes, err := Codec.Marshal(utxo) + if err != nil { + return err + } + + elem := &atomic.Element{ + Key: utxo.InputID().Bytes(), + Value: utxoBytes, + } + if out, ok := utxo.Out.(avax.Addressable); ok { + elem.Traits = out.Addresses() + } + + elems[i] = elem + } + + return ctx.SharedMemory.Put(tx.DestinationChain, elems) } // Create a new transaction diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 0910f6d..4ea3793 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -177,11 +177,10 @@ type VM struct { } func (vm *VM) getAtomicTx(block *types.Block) *Tx { + extdata := block.ExtraData() atx := new(Tx) - if extdata := block.ExtraData(); extdata != nil { - if err := vm.codec.Unmarshal(extdata, atx); err != nil { - panic(err) - } + if err := vm.codec.Unmarshal(extdata, atx); err != nil { + return nil } atx.Sign(vm.codec, nil) return atx @@ -284,7 +283,11 @@ func (vm *VM) Initialize( return vm.getLastAccepted().ethBlock }) chain.SetOnExtraStateChange(func(block *types.Block, state *state.StateDB) error { - return vm.getAtomicTx(block).UnsignedTx.(UnsignedAtomicTx).EVMStateTransfer(state) + tx := vm.getAtomicTx(block) + if tx == nil { + return nil + } + return tx.UnsignedTx.(UnsignedAtomicTx).EVMStateTransfer(state) }) vm.blockCache = cache.LRU{Size: 2048} vm.blockStatusCache = cache.LRU{Size: 1024} -- cgit v1.2.3-70-g09d2