Skip to content

Simplify tx verification #1654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
36988a4
Remove DAG based tx issuance logic
StephenButtolph Jun 19, 2023
f4ae592
Remove dagState and GetUTXOFromID
StephenButtolph Jun 19, 2023
d924932
Fix unit tests
StephenButtolph Jun 19, 2023
7d1dda4
Merge branch 'remove-get-utxo-from-id' into remove-avm-tx-batcher
StephenButtolph Jun 19, 2023
4855439
wip make tests compile
StephenButtolph Jun 19, 2023
c517ea9
nit lint
StephenButtolph Jun 20, 2023
30485cd
fix linting
StephenButtolph Jun 20, 2023
4bc87bd
Merge branch 'dev' into remove-get-utxo-from-id
StephenButtolph Jun 20, 2023
2ff0186
wip cleanup tests
StephenButtolph Jun 20, 2023
23c038d
Merge branch 'remove-get-utxo-from-id' into remove-avm-tx-batcher
StephenButtolph Jun 20, 2023
ad086ba
wip fixup service tests
StephenButtolph Jun 20, 2023
724d878
more cleanup
StephenButtolph Jun 20, 2023
26f86e0
fix tests
StephenButtolph Jun 21, 2023
97950f1
keep test
StephenButtolph Jun 21, 2023
4c2e286
nit
StephenButtolph Jun 21, 2023
168aed9
nit
StephenButtolph Jun 21, 2023
b03a622
nits
StephenButtolph Jun 21, 2023
e4aa1c9
Remove PendingTxs from the DAGVM interface
StephenButtolph Jun 21, 2023
fc2df6e
lint
StephenButtolph Jun 21, 2023
37ae15c
Remove GetTx from the DAGVM interface
StephenButtolph Jun 21, 2023
9ad9511
lint
StephenButtolph Jun 21, 2023
3db4590
clenaup
StephenButtolph Jun 21, 2023
ca82e41
remove code changes
StephenButtolph Jun 21, 2023
208c7d9
merged
StephenButtolph Jun 21, 2023
55d91dc
merged
StephenButtolph Jun 21, 2023
c4838d8
Merge branch 'remove-pending-txs' into remove-get-tx
StephenButtolph Jun 21, 2023
c512d15
oops
StephenButtolph Jun 21, 2023
ecd0848
Remove InputIDs() from the snowstorm.Tx interface
StephenButtolph Jun 21, 2023
851d0c9
remove more methods
StephenButtolph Jun 21, 2023
dad14d3
lint
StephenButtolph Jun 21, 2023
cc9f8fe
merged
StephenButtolph Jun 22, 2023
6b21940
Merge branch 'remove-get-tx' into simplify-unique-tx
StephenButtolph Jun 22, 2023
4e72c2b
Merge branch 'dev' into simplify-unique-tx
StephenButtolph Jun 22, 2023
c253785
Merge branch 'dev' into simplify-unique-tx
StephenButtolph Jun 26, 2023
1491192
Simplify tx verification
StephenButtolph Jun 26, 2023
a8e86ac
nit
StephenButtolph Jun 26, 2023
92bb0d9
merged
StephenButtolph Jun 26, 2023
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
87 changes: 8 additions & 79 deletions vms/avm/unique_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"errors"
"fmt"

"go.uber.org/zap"

"github.com/ava-labs/avalanchego/cache"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow/choices"
Expand All @@ -23,9 +21,8 @@ var (
_ snowstorm.Tx = (*UniqueTx)(nil)
_ cache.Evictable[ids.ID] = (*UniqueTx)(nil)

errMissingUTXO = errors.New("missing utxo")
errUnknownTx = errors.New("transaction is unknown")
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a non-issue now?

tx.Tx == nil no more?

Copy link
Contributor Author

@StephenButtolph StephenButtolph Jun 26, 2023

Choose a reason for hiding this comment

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

tx.Tx can only be nil now from the UniqueTx construction in Dependencies. We don't actually use these txs in consensus anywhere (see followup to remove them: #1656) so this should be impossible to happen now (i.e. consensus only handles txs returned from ParseTx).

errRejectedTx = errors.New("transaction is rejected")
errTxNotProcessing = errors.New("transaction is not processing")
errUnexpectedReject = errors.New("attempting to reject transaction")
)

// UniqueTx provides a de-duplication service for txs. This only provides a
Expand All @@ -40,8 +37,7 @@ type UniqueTx struct {
type TxCachedState struct {
*txs.Tx

unique, verifiedTx, verifiedState bool
validity error
unique bool

deps []snowstorm.Tx

Expand Down Expand Up @@ -118,7 +114,7 @@ func (tx *UniqueTx) Key() ids.ID {
// Accept is called when the transaction was finalized as accepted by consensus
func (tx *UniqueTx) Accept(context.Context) error {
if s := tx.Status(); s != choices.Processing {
return fmt.Errorf("transaction has invalid status: %s", s)
return fmt.Errorf("%w: %s", errTxNotProcessing, s)
}

if err := tx.vm.onAccept(tx.Tx); err != nil {
Expand Down Expand Up @@ -157,27 +153,8 @@ func (tx *UniqueTx) Accept(context.Context) error {
return tx.vm.metrics.MarkTxAccepted(tx.Tx)
}

// Reject is called when the transaction was finalized as rejected by consensus
func (tx *UniqueTx) Reject(context.Context) error {
tx.setStatus(choices.Rejected)

txID := tx.ID()
tx.vm.ctx.Log.Debug("rejecting tx",
zap.Stringer("txID", txID),
)

if err := tx.vm.state.Commit(); err != nil {
tx.vm.ctx.Log.Error("failed to commit reject",
zap.Stringer("txID", tx.txID),
zap.Error(err),
)
return err
}

tx.vm.walletService.decided(txID)

tx.deps = nil // Needed to prevent a memory leak
return nil
func (*UniqueTx) Reject(context.Context) error {
return errUnexpectedReject
}

// Status returns the current status of this transaction
Expand Down Expand Up @@ -228,59 +205,11 @@ func (tx *UniqueTx) Bytes() []byte {
return tx.Tx.Bytes()
}

func (tx *UniqueTx) verifyWithoutCacheWrites() error {
switch status := tx.Status(); status {
case choices.Unknown:
return errUnknownTx
case choices.Accepted:
return nil
case choices.Rejected:
return errRejectedTx
default:
return tx.SemanticVerify()
}
}

// Verify the validity of this transaction
func (tx *UniqueTx) Verify(context.Context) error {
if err := tx.verifyWithoutCacheWrites(); err != nil {
return err
}

tx.verifiedState = true
return nil
}

// SyntacticVerify verifies that this transaction is well formed
func (tx *UniqueTx) SyntacticVerify() error {
tx.refresh()

if tx.Tx == nil {
return errUnknownTx
}

if tx.verifiedTx {
return tx.validity
}

tx.verifiedTx = true
tx.validity = tx.Tx.Unsigned.Visit(&executor.SyntacticVerifier{
Backend: tx.vm.txBackend,
Tx: tx.Tx,
})
return tx.validity
}

// SemanticVerify the validity of this transaction
func (tx *UniqueTx) SemanticVerify() error {
if err := tx.SyntacticVerify(); err != nil {
return err
}

if tx.validity != nil || tx.verifiedState {
return tx.validity
if s := tx.Status(); s != choices.Processing {
return fmt.Errorf("%w: %s", errTxNotProcessing, s)
}

return tx.Unsigned.Visit(&executor.SemanticVerifier{
Backend: tx.vm.txBackend,
State: tx.vm.state,
Expand Down
11 changes: 8 additions & 3 deletions vms/avm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,16 +460,21 @@ func (vm *VM) ParseTx(_ context.Context, bytes []byte) (snowstorm.Tx, error) {
return nil, err
}

err = rawTx.Unsigned.Visit(&txexecutor.SyntacticVerifier{
Backend: vm.txBackend,
Tx: rawTx,
})
if err != nil {
return nil, err
}

tx := &UniqueTx{
TxCachedState: &TxCachedState{
Tx: rawTx,
},
vm: vm,
txID: rawTx.ID(),
}
if err := tx.SyntacticVerify(); err != nil {
return nil, err
}

if tx.Status() == choices.Unknown {
vm.state.AddTx(tx.Tx)
Expand Down
3 changes: 3 additions & 0 deletions vms/avm/wallet_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package avm

import (
"errors"
"fmt"
"net/http"

Expand All @@ -22,6 +23,8 @@ import (
"github.com/ava-labs/avalanchego/vms/secp256k1fx"
)

var errMissingUTXO = errors.New("missing utxo")

type WalletService struct {
vm *VM
pendingTxs linkedhashmap.LinkedHashmap[ids.ID, *txs.Tx]
Expand Down