Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions plugin/evm/atomic/tx_semantic_verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/ava-labs/coreth/plugin/evm/upgrade/ap0"
)

var _ Visitor = (*SemanticVerifier)(nil)
var _ Visitor = (*semanticVerifier)(nil)

var (
ErrAssetIDMismatch = errors.New("asset IDs in the input don't match the utxo")
Expand All @@ -44,20 +44,30 @@ type VerifierBackend struct {
SecpCache *secp256k1.RecoverCache
}

// SemanticVerifier is a visitor that checks the semantic validity of atomic transactions.
type SemanticVerifier struct {
Backend *VerifierBackend
Tx *Tx
Parent AtomicBlockContext
BaseFee *big.Int
// SemanticVerify checks the semantic validity of atomic transactions.
func (b *VerifierBackend) SemanticVerify(tx *Tx, parent AtomicBlockContext, baseFee *big.Int) error {
return tx.UnsignedAtomicTx.Visit(&semanticVerifier{
backend: b,
tx: tx,
parent: parent,
baseFee: baseFee,
})
}

// ImportTx verifies this transaction is valid.
func (s *SemanticVerifier) ImportTx(utx *UnsignedImportTx) error {
backend := s.Backend
// semanticVerifier is a visitor that checks the semantic validity of atomic
// transactions.
type semanticVerifier struct {
backend *VerifierBackend
tx *Tx
parent AtomicBlockContext
baseFee *big.Int
}

func (s *semanticVerifier) ImportTx(utx *UnsignedImportTx) error {
backend := s.backend
ctx := backend.Ctx
rules := backend.Rules
stx := s.Tx
stx := s.tx
if err := utx.Verify(ctx, rules); err != nil {
return err
}
Expand All @@ -71,7 +81,7 @@ func (s *SemanticVerifier) ImportTx(utx *UnsignedImportTx) error {
if err != nil {
return err
}
txFee, err := CalculateDynamicFee(gasUsed, s.BaseFee)
txFee, err := CalculateDynamicFee(gasUsed, s.baseFee)
if err != nil {
return err
}
Expand Down Expand Up @@ -133,7 +143,7 @@ func (s *SemanticVerifier) ImportTx(utx *UnsignedImportTx) error {
}
}

return conflicts(backend, utx.InputUTXOs(), s.Parent)
return conflicts(backend, utx.InputUTXOs(), s.parent)
}

// conflicts returns an error if [inputs] conflicts with any of the atomic inputs contained in [ancestor]
Expand Down Expand Up @@ -176,12 +186,11 @@ func conflicts(backend *VerifierBackend, inputs set.Set[ids.ID], ancestor Atomic
return nil
}

// ExportTx verifies this transaction is valid.
func (s *SemanticVerifier) ExportTx(utx *UnsignedExportTx) error {
backend := s.Backend
func (s *semanticVerifier) ExportTx(utx *UnsignedExportTx) error {
backend := s.backend
ctx := backend.Ctx
rules := backend.Rules
stx := s.Tx
stx := s.tx
if err := utx.Verify(ctx, rules); err != nil {
return err
}
Expand All @@ -195,7 +204,7 @@ func (s *SemanticVerifier) ExportTx(utx *UnsignedExportTx) error {
if err != nil {
return err
}
txFee, err := CalculateDynamicFee(gasUsed, s.BaseFee)
txFee, err := CalculateDynamicFee(gasUsed, s.baseFee)
if err != nil {
return err
}
Expand Down Expand Up @@ -231,7 +240,7 @@ func (s *SemanticVerifier) ExportTx(utx *UnsignedExportTx) error {
if len(cred.Sigs) != 1 {
return fmt.Errorf("expected one signature for EVM Input Credential, but found: %d", len(cred.Sigs))
}
pubKey, err := s.Backend.SecpCache.RecoverPublicKey(utx.Bytes(), cred.Sigs[0][:])
pubKey, err := s.backend.SecpCache.RecoverPublicKey(utx.Bytes(), cred.Sigs[0][:])
if err != nil {
return err
}
Expand Down
34 changes: 7 additions & 27 deletions plugin/evm/export_tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -932,15 +932,7 @@ func TestExportTxSemanticVerify(t *testing.T) {
}

t.Run(test.name, func(t *testing.T) {
tx := test.tx
exportTx := tx.UnsignedAtomicTx

err := exportTx.Visit(&atomic.SemanticVerifier{
Backend: backend,
Tx: tx,
Parent: parent,
BaseFee: test.baseFee,
})
err := backend.SemanticVerify(test.tx, parent, test.baseFee)
if test.shouldErr && err == nil {
t.Fatalf("should have errored but returned valid")
}
Expand Down Expand Up @@ -1781,8 +1773,6 @@ func TestNewExportTx(t *testing.T) {
t.Fatal(err)
}

exportTx := tx.UnsignedAtomicTx

backend := &atomic.VerifierBackend{
Ctx: tvm.vm.ctx,
Fx: &tvm.vm.fx,
Expand All @@ -1791,16 +1781,11 @@ func TestNewExportTx(t *testing.T) {
BlockFetcher: tvm.vm,
SecpCache: tvm.vm.secpCache,
}

if err := exportTx.Visit(&atomic.SemanticVerifier{
Backend: backend,
Tx: tx,
Parent: parent,
BaseFee: parent.ethBlock.BaseFee(),
}); err != nil {
if err := backend.SemanticVerify(tx, parent, parent.ethBlock.BaseFee()); err != nil {
t.Fatal("newExportTx created an invalid transaction", err)
}

exportTx := tx.UnsignedAtomicTx
burnedAVAX, err := exportTx.Burned(tvm.vm.ctx.AVAXAssetID)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -1986,7 +1971,6 @@ func TestNewExportTxMulticoin(t *testing.T) {
t.Fatal(err)
}

exportTx := tx.UnsignedAtomicTx
backend := &atomic.VerifierBackend{
Ctx: tvm.vm.ctx,
Fx: &tvm.vm.fx,
Expand All @@ -1995,21 +1979,17 @@ func TestNewExportTxMulticoin(t *testing.T) {
BlockFetcher: tvm.vm,
SecpCache: tvm.vm.secpCache,
}

if err := exportTx.Visit(&atomic.SemanticVerifier{
Backend: backend,
Tx: tx,
Parent: parent,
BaseFee: parent.ethBlock.BaseFee(),
}); err != nil {
if err := backend.SemanticVerify(tx, parent, parent.ethBlock.BaseFee()); err != nil {
t.Fatal("newExportTx created an invalid transaction", err)
}

commitBatch, err := tvm.vm.versiondb.CommitBatch()
if err != nil {
t.Fatalf("Failed to create commit batch for VM due to %s", err)
}
chainID, atomicRequests, err := exportTx.AtomicOps()

exportTx := tx.UnsignedAtomicTx
chainID, atomicRequests, err := tx.UnsignedAtomicTx.AtomicOps()
if err != nil {
t.Fatalf("Failed to accept export transaction due to: %s", err)
}
Expand Down
7 changes: 1 addition & 6 deletions plugin/evm/tx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,7 @@ func executeTxTest(t *testing.T, test atomicTxTest) {
BlockFetcher: tvm.vm,
SecpCache: tvm.vm.secpCache,
}
if err := tx.UnsignedAtomicTx.Visit(&atomic.SemanticVerifier{
Backend: backend,
Tx: tx,
Parent: lastAcceptedBlock,
BaseFee: baseFee,
}); len(test.semanticVerifyErr) == 0 && err != nil {
if err := backend.SemanticVerify(tx, lastAcceptedBlock, baseFee); len(test.semanticVerifyErr) == 0 && err != nil {
t.Fatalf("SemanticVerify failed unexpectedly due to: %s", err)
} else if len(test.semanticVerifyErr) != 0 {
if err == nil {
Expand Down
21 changes: 5 additions & 16 deletions plugin/evm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1602,12 +1602,7 @@ func (vm *VM) verifyTx(tx *atomic.Tx, parentHash common.Hash, baseFee *big.Int,
BlockFetcher: vm,
SecpCache: vm.secpCache,
}
if err := tx.UnsignedAtomicTx.Visit(&atomic.SemanticVerifier{
Backend: atomicBackend,
Tx: tx,
Parent: parent,
BaseFee: baseFee,
}); err != nil {
if atomicBackend.SemanticVerify(tx, parent, baseFee); err != nil {
return err
}
return tx.UnsignedAtomicTx.EVMStateTransfer(vm.ctx, state)
Expand Down Expand Up @@ -1646,17 +1641,11 @@ func (vm *VM) verifyTxs(txs []*atomic.Tx, parentHash common.Hash, baseFee *big.I
BlockFetcher: vm,
SecpCache: vm.secpCache,
}
for _, atomicTx := range txs {
utx := atomicTx.UnsignedAtomicTx
if err := utx.Visit(&atomic.SemanticVerifier{
Backend: atomicBackend,
Tx: atomicTx,
Parent: ancestor,
BaseFee: baseFee,
}); err != nil {
return fmt.Errorf("invalid block due to failed semanatic verify: %w at height %d", err, height)
for _, tx := range txs {
if atomicBackend.SemanticVerify(tx, ancestor, baseFee); err != nil {
return fmt.Errorf("invalid block due to failed semantic verify: %w at height %d", err, height)
}
txInputs := utx.InputUTXOs()
txInputs := tx.UnsignedAtomicTx.InputUTXOs()
if inputs.Overlaps(txInputs) {
return atomic.ErrConflictingAtomicInputs
}
Expand Down
Loading