Skip to content
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

Add VerifyTx to executor.Manager #2293

Merged
merged 7 commits into from
Nov 14, 2023
Merged
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
4 changes: 2 additions & 2 deletions vms/avm/block/executor/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ type Manager interface {
GetStatelessBlock(blkID ids.ID) (block.Block, error)
NewBlock(block.Block) snowman.Block

// VerifyTx verifies that the transaction can be issued based on the
// currently preferred state.
// VerifyTx verifies that the transaction can be issued based on the currently
// preferred state. This should *not* be used to verify transactions in a block.
VerifyTx(tx *txs.Tx) error

// VerifyUniqueInputs verifies that the inputs are not duplicated in the
Expand Down
13 changes: 1 addition & 12 deletions vms/platformvm/block/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ var (

ErrEndOfTime = errors.New("program time is suspiciously far in the future")
ErrNoPendingBlocks = errors.New("no pending blocks")
ErrChainNotSynced = errors.New("chain not synced")
)

type Builder interface {
Expand Down Expand Up @@ -103,24 +102,14 @@ func New(

// AddUnverifiedTx verifies a transaction and attempts to add it to the mempool
func (b *builder) AddUnverifiedTx(tx *txs.Tx) error {
if !b.txExecutorBackend.Bootstrapped.Get() {
return ErrChainNotSynced
}

txID := tx.ID()
if b.Mempool.Has(txID) {
abi87 marked this conversation as resolved.
Show resolved Hide resolved
// If the transaction is already in the mempool - then it looks the same
// as if it was successfully added
return nil
}

verifier := txexecutor.MempoolTxVerifier{
Backend: b.txExecutorBackend,
ParentID: b.blkManager.Preferred(), // We want to build off of the preferred block
StateVersions: b.blkManager,
Tx: tx,
}
if err := tx.Unsigned.Visit(&verifier); err != nil {
if err := b.blkManager.VerifyTx(tx); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename VerifyTx to something like VerifyMempoolCandidate both here and in X-chain.
This way we can avoid confusion and minimize awkwardness of having to state verify mempool candidate in blkManager. We can fully solve the awkwardness later on and jontly across P-chain and X-chain

b.MarkDropped(txID, err)
return err
}
Expand Down
32 changes: 29 additions & 3 deletions vms/platformvm/block/executor/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@
package executor

import (
"errors"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
"github.com/ava-labs/avalanchego/vms/platformvm/block"
"github.com/ava-labs/avalanchego/vms/platformvm/metrics"
"github.com/ava-labs/avalanchego/vms/platformvm/state"
"github.com/ava-labs/avalanchego/vms/platformvm/txs"
"github.com/ava-labs/avalanchego/vms/platformvm/txs/executor"
"github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool"
"github.com/ava-labs/avalanchego/vms/platformvm/validators"
)

var _ Manager = (*manager)(nil)
var (
_ Manager = (*manager)(nil)

ErrChainNotSynced = errors.New("chain not synced")
)

type Manager interface {
state.Versions
Expand All @@ -28,6 +35,10 @@ type Manager interface {
GetBlock(blkID ids.ID) (snowman.Block, error)
GetStatelessBlock(blkID ids.ID) (block.Block, error)
NewBlock(block.Block) snowman.Block

// VerifyTx verifies that the transaction can be issued based on the currently
// preferred state. This should *not* be used to verify transactions in a block.
VerifyTx(tx *txs.Tx) error
}

func NewManager(
Expand Down Expand Up @@ -62,7 +73,8 @@ func NewManager(
backend: backend,
addTxsToMempool: !txExecutorBackend.Config.PartialSyncPrimaryNetwork,
},
preferred: lastAccepted,
preferred: lastAccepted,
txExecutorBackend: txExecutorBackend,
}
}

Expand All @@ -72,7 +84,8 @@ type manager struct {
acceptor block.Visitor
rejector block.Visitor

preferred ids.ID
preferred ids.ID
txExecutorBackend *executor.Backend
}

func (m *manager) GetBlock(blkID ids.ID) (snowman.Block, error) {
Expand Down Expand Up @@ -103,3 +116,16 @@ func (m *manager) SetPreference(blockID ids.ID) (updated bool) {
func (m *manager) Preferred() ids.ID {
return m.preferred
}

func (m *manager) VerifyTx(tx *txs.Tx) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

what I think it's a bit confusing here is that VerifyTx is to verify mempool transactions but we already have a MempoolTxVerifier visitor that basically does all of it already.
So maybe the change to be done is to move the "isBootstrapped" check into the mempoolVerified and that's it.
This would avoid increasing the blkManager interface (as per @danlaine 's comment) and make blkManager more of a backend object for verification of both mempool txs and txs in block.

Copy link
Contributor Author

@dhrubabasu dhrubabasu Nov 13, 2023

Choose a reason for hiding this comment

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

This function uses the MempoolTxVerifier. I don't think it's a good design pattern to require consumers of this package to create a struct themselves. I think this pattern (from #2296 https://github.com/ava-labs/avalanchego/blob/remove-add-unverified-tx/vms/platformvm/network/network.go#L162-L181) is much more digestible:

	// Verify the tx at the currently preferred state
	if err := n.manager.VerifyTx(tx); err != nil {
		n.mempool.MarkDropped(txID, err)
		return err
	}

than the existing:

	verifier := txexecutor.MempoolTxVerifier{
		Backend:       b.txExecutorBackend,
		ParentID:      b.blkManager.Preferred(), // We want to build off of the preferred block
		StateVersions: b.blkManager,
		Tx:            tx,
	}
	if err := tx.Unsigned.Visit(&verifier); err != nil {
		b.MarkDropped(txID, err)
		return err
	}

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't really think it's more digestible but I'd suggest we find a proper name for manager.VerifyTx (my suggestion being manager.VerifyMempoolCandidate) and we defer discussions around mempool refactoring.

if !m.txExecutorBackend.Bootstrapped.Get() {
return ErrChainNotSynced
}

return tx.Unsigned.Visit(&executor.MempoolTxVerifier{
Backend: m.txExecutorBackend,
ParentID: m.preferred,
StateVersions: m,
Tx: tx,
})
}
15 changes: 15 additions & 0 deletions vms/platformvm/block/executor/mock_manager.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.