diff options
Diffstat (limited to 'plugin/evm/block.go')
-rw-r--r-- | plugin/evm/block.go | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/plugin/evm/block.go b/plugin/evm/block.go index 80c03a2..375dc6d 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -4,9 +4,10 @@ package evm import ( + "errors" "fmt" - "github.com/ava-labs/go-ethereum/core/types" + "github.com/ava-labs/coreth/core/types" "github.com/ava-labs/go-ethereum/rlp" "github.com/ava-labs/gecko/ids" @@ -27,9 +28,21 @@ func (b *Block) ID() ids.ID { return b.id } // Accept implements the snowman.Block interface func (b *Block) Accept() error { - b.vm.ctx.Log.Verbo("Block %s is accepted", b.ID()) - b.vm.updateStatus(b.ID(), choices.Accepted) - return nil + vm := b.vm + + vm.ctx.Log.Verbo("Block %s is accepted", b.ID()) + 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 tx type") + } + + return utx.Accept(vm.ctx, nil) } // Reject implements the snowman.Block interface @@ -61,6 +74,59 @@ func (b *Block) Parent() snowman.Block { // Verify implements the snowman.Block interface func (b *Block) Verify() error { + // Ensure the minimum gas price is paid for every transaction + for _, tx := range b.ethBlock.Transactions() { + if tx.GasPrice().Cmp(minGasPrice) < 0 { + return errInvalidBlock + } + } + + vm := b.vm + tx := vm.getAtomicTx(b.ethBlock) + if tx != nil { + 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 ret, hit := vm.blockAtomicInputCache.Get(p.ID()); hit { + inputs = ret.(*ids.Set) + break + } + 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) + 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") + } + + if tx.UnsignedTx.(UnsignedAtomicTx).SemanticVerify(vm, tx) != nil { + return errInvalidBlock + } + } _, err := b.vm.chain.InsertChain([]*types.Block{b.ethBlock}) return err } |