blockbuster

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 26, 2024 License: Apache-2.0 Imports: 11 Imported by: 0

README

BlockBuster

📕 BlockBuster is an app-side mempool + set of proposal handlers that allows developers to configure modular lanes of transactions in their blocks with distinct validation/ordering logic. BlockBuster is the ultimate highway system for transactions.

High Level Overview

BlockBuster is a framework for creating modular, application specific mempools by separating transactions into “lanes” with custom transaction handling.

You can think of BlockBuster as a transaction highway system, where each lane on the highway serves a specific purpose and has its own set of rules and traffic flow.

Similarly, BlockBuster redefines block-space into lanes - where each lane has its own set of rules and transaction flow management systems.

  • A lane is what we might traditionally consider to be a standard mempool where transaction validation, ordering and prioritization for contained transactions are shared.
  • Lanes implement a standard interface that allows each individual lane to propose and validate a portion of a block.
  • Lanes are ordered with each other, configurable by developers. All lanes together define the desired block structure of a chain.

BlockBuster Use Cases

A mempool with separate lanes can be used for:

  1. MEV mitigation: a top of block lane could be designed to create an in-protocol top-of-block auction (as we are doing with POB) to recapture MEV in a transparent and governable way.
  2. Free/reduced fee txs: transactions with certain properties (e.g. from trusted accounts or performing encouraged actions) could leverage a free lane to reward behavior.
  3. Dedicated oracle space Oracles could be included before other kinds of transactions to ensure that price updates occur first, and are not able to be sandwiched or manipulated.
  4. Orderflow auctions: an OFA lane could be constructed such that order flow providers can have their submitted transactions bundled with specific backrunners, to guarantee MEV rewards are attributed back to users. Imagine MEV-share but in protocol.
  5. Enhanced and customizable privacy: privacy-enhancing features could be introduced, such as threshold encrypted lanes, to protect user data and maintain privacy for specific use cases.
  6. Fee market improvements: one or many fee markets - such as EIP-1559 - could be easily adopted for different lanes (potentially custom for certain dApps). Each smart contract/exchange could have its own fee market or auction for transaction ordering.
  7. Congestion management: segmentation of transactions to lanes can help mitigate network congestion by capping usage of certain applications and tailoring fee markets.

BlockBuster Design

BlockBuster is a mempool composed of sub-mempools called lanes. All lanes together define the transaction highway system and BlockBuster mempool. When instantiating the BlockBuster mempool, developers will define all of the desired lanes and their configurations (including lane ordering).

Utilizing BlockBuster is a simple three step process:

  • Determine the lanes desired. Currently, POB supports three different implementations of lanes: top of block lane, free lane, and a default lane.
    1. Top of block lane allows the top of every block to be auctioned off and constructed using logic defined by the x/builder module.
    2. Free lane allows base app to not charge certain types of transactions any fees. For example, delegations and/or re-delegations might be charged no fees. What qualifies as a free transaction is determined here.
    3. Default lane accepts all other transactions and is considered to be analogous to how mempools and proposals are constructed today.
  • Instantiate the mempool in base app.
mempool := blockbuster.NewMempool(lanes...)
app.App.SetMempool(mempool)
  • Instantiate the BlockBuster proposal handlers in base app.
proposalHandlers := abci.NewProposalHandler(
	app.Logger(),
	app.txConfig.TxDecoder(),
	mempool, // BlockBuster mempool
)
app.App.SetPrepareProposal(proposalHandlers.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandlers.ProcessProposalHandler())

Note: BlockBuster should configure a DefaultLane that accepts transactions that do not belong to any other lane.

Transactions are inserted into the first lane that the transaction matches to. This means that a given transaction should really only belong to one lane (but this isn’t enforced).

Proposals

The ordering of lanes when initializing BlockBuster in base app will determine the ordering of how proposals are built. For example, say that we instantiate three lanes:

  1. Top of block lane
  2. Free lane
  3. Default lane
Preparing Proposals

When the current proposer starts building a block, it will first populate the proposal with transactions from the top of block lane, followed by free and default lane. Each lane proposes its own set of transactions using the lane’s PrepareLane (analogous to PrepareProposal). Each lane has a limit on the relative percentage of total block space that the lane can consume. For example, the free lane might be configured to only make up 10% of any block. This is defined on each lane’s Config when it is instantiated.

In the case when any lane fails to propose its portion of the block, it will be skipped and the next lane in the set of lanes will propose its portion of the block. Failures of partial block proposals are independent of one another.

Processing Proposals

Block proposals are validated iteratively following the exact ordering of lanes defined on base app. Transactions included in block proposals must respect the ordering of lanes. Any proposal that includes transactions that are out of order relative to the ordering of lanes will be rejected. Following the example defined above, if a proposal contains the following transactions:

  1. Default transaction (belonging to the default lane)
  2. Top of block transaction (belonging to the top of block lane)
  3. Free transaction (belonging to the free lane)

It will be rejected because it does not respect the lane ordering.

The BlockBuster ProcessProposalHandler processes the proposal by verifying all transactions in the proposal according to each lane's verification logic in a greedy fashion. If a lane's portion of the proposal is invalid, we reject the proposal. After a lane's portion of the proposal is verified, we pass the remaining transactions to the next lane in the chain.

Coming Soon

BlockBuster will have its own dedicated gRPC service for searchers, wallets, and users that allows them to query what lane their transaction might belong in, what fees they might have to pay for a given transaction, and the general state of the BlockBuster mempool.

Lanes

Each lane will define its own:

  1. Unique prioritization/ordering mechanism i.e. how will transactions from a given lane be ordered in a block / mempool.
  2. Inclusion function to determine what types of transactions belong in the lane.
  3. Unique block building/verification mechanism.

The general interface that each lane must implement can be found here:

// Lane defines an interface used for block construction
Lane interface {
    sdkmempool.Mempool

    // Name returns the name of the lane.
    Name() string

    // Match determines if a transaction belongs to this lane.
    Match(tx sdk.Tx) bool

    // VerifyTx verifies the transaction belonging to this lane.
    VerifyTx(ctx sdk.Context, tx sdk.Tx) error

    // Contains returns true if the mempool contains the given transaction.
    Contains(tx sdk.Tx) (bool, error)

    // PrepareLane builds a portion of the block. It inputs the maxTxBytes that 
    // can be included in the proposal for the given lane, the partial 
    // proposal, and a function to call the next lane in the chain. The 
    // next lane in the chain will be called with the updated proposal and context.
    PrepareLane(
        ctx sdk.Context, 
        proposal BlockProposal, 
        maxTxBytes int64, 
        next PrepareLanesHandler,
    ) (BlockProposal, error)

    // ProcessLaneBasic validates that transactions belonging to this lane are 
    // not misplaced in the block proposal.
    ProcessLaneBasic(txs []sdk.Tx) error

    // ProcessLane verifies this lane's portion of a proposed block. It inputs 
    // the transactions that may belong to this lane and a function to call 
    // the next lane in the chain. The next lane in the chain will be
    // called with the updated context and filtered down transactions.
    ProcessLane(
        ctx sdk.Context, 
        proposalTxs []sdk.Tx, 
        next ProcessLanesHandler,
    ) (sdk.Context, error)

    // SetAnteHandler sets the lane's antehandler.
    SetAnteHandler(antehander sdk.AnteHandler)

    // Logger returns the lane's logger.
    Logger() log.Logger

    // GetMaxBlockSpace returns the max block space for the lane as a relative percentage.
    GetMaxBlockSpace() sdk.Dec
}
1. Intra-lane Transaction Ordering

Note: Lanes must implement the sdk.Mempool interface.

Transactions within a lane are ordered in a proposal respecting the ordering defined on the lane’s mempool. Developers can define their own custom ordering by implementing a custom TxPriority struct that allows the lane’s mempool to determine the priority of a transaction GetTxPriority and relatively order two transactions given the priority Compare. The top of block lane includes an custom TxPriority that orders transactions in the mempool based on their bid.

func TxPriority(config Factory) blockbuster.TxPriority[string] {
    return blockbuster.TxPriority[string]{
        GetTxPriority: func(goCtx context.Context, tx sdk.Tx) string {
            bidInfo, err := config.GetAuctionBidInfo(tx)
            if err != nil {
                panic(err)
            }

            return bidInfo.Bid.String()
        },
        Compare: func(a, b string) int {
            aCoins, _ := sdk.ParseCoinsNormalized(a)
            bCoins, _ := sdk.ParseCoinsNormalized(b)

            switch {
            case aCoins == nil && bCoins == nil:
                return 0

            case aCoins == nil:
                return -1

            case bCoins == nil:
                return 1

            default:
                switch {
                case aCoins.IsAllGT(bCoins):
                        return 1

                case aCoins.IsAllLT(bCoins):
                        return -1

                default:
                        return 0
                }
            }
        },
        MinValue: "",
    }
}

// NewMempool returns a new auction mempool.
func NewMempool(txEncoder sdk.TxEncoder, maxTx int, config Factory) *TOBMempool {
	return &TOBMempool{
		index: blockbuster.NewPriorityMempool(
			blockbuster.PriorityNonceMempoolConfig[string]{
				TxPriority: TxPriority(config),
				MaxTx:      maxTx,
			},
		),
		txEncoder: txEncoder,
		txIndex:   make(map[string]struct{}),
		Factory:   config,
	}
}
2. [Optional] Transaction Information Retrieval

Each lane can define a factory that configures the necessary set of interfaces required for transaction processing, ordering, and validation. Lanes are designed such that any given chain can adopt upstream POB lanes as long as developers implement the specified interface(s) associated with transaction information retrieval for that lane.

A standard cosmos chain or EVM chain can then implement their own versions of these interfaces and automatically utilize the lane with no changes upstream!

For example, the free lane defines an Factory that includes a single IsFreeTx function that allows developers to configure what is a free transaction. The default implementation categorizes free transactions as any transaction that includes a delegate type message.

// IsFreeTx defines a default function that checks if a transaction is free. In 
// this case, any transaction that is a delegation/redelegation transaction is free.
func (config *DefaultFreeFactory) IsFreeTx(tx sdk.Tx) bool {
	for _, msg := range tx.GetMsgs() {
		switch msg.(type) {
		case *types.MsgDelegate:
			return true
		case *types.MsgBeginRedelegate:
			return true
		case *types.MsgCancelUnbondingDelegation:
			return true
		}
	}

	return false
}
3. Lane Inclusion Functionality

Lanes must implement a Match interface which determines whether a transaction should be considered for a given lane. Developer’s are encouraged to utilize the same interfaces defined in the Factory to match transactions to lanes. For example, developers might configure a top of block auction lane to accept transactions if they contain a single MsgAuctionBid message in the transaction.

4.1. [Optional] Transaction Validation

Transactions will be verified the lane’s VerifyTx function. This logic can be completely arbitrary. For example, the default lane verifies transactions using base app’s AnteHandler while the top of block lane verifies transactions by extracting all bundled transactions included in the bid transaction and then verifying the transaction iteratively given the bundle.

4.2. Block Building/Verification Logic

Each lane will implement block building and verification logic - analogous to Prepare and Process proposal - that is unique to itself.

  • PrepareLane will be in charge of building a partial block given the transactions in the lane.
  • ProcessLaneBasic ensures that transactions that should be included in the current lane are not interleaved with other lanes i.e. transactions in proposals are ordered respecting the ordering of lanes.
  • ProcessLane will be in charge of verifying the lane’s partial block.
Inheritance

Lanes can inherit the underlying implementation of other lanes and overwrite any part of the implementation with their own custom functionality. We recommend that user’s extend the functionality of the Base lane when first exploring the code base.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsEmpty

func IsEmpty[C comparable](mempool sdkmempool.Mempool) error

Types

type BBMempool

type BBMempool struct {
	// contains filtered or unexported fields
}

Mempool defines the Blockbuster mempool implement. It contains a registry of lanes, which allows for customizable block proposal construction.

func NewMempool

func NewMempool(lanes ...Lane) *BBMempool

NewMempool returns a new Blockbuster mempool. The blockbuster mempool is comprised of a registry of lanes. Each lane is responsible for selecting transactions according to its own selection logic. The lanes are ordered according to their priority. The first lane in the registry has the highest priority. Proposals are verified according to the order of the lanes in the registry. Basic mempool API, such as insertion, removal, and contains, are delegated to the first lane that matches the transaction. Each transaction should only belong in one lane.

func (*BBMempool) Contains

func (m *BBMempool) Contains(tx sdk.Tx) (bool, error)

Contains returns true if the transaction is contained in the mempool. It checks the first lane that it matches to.

func (*BBMempool) CountTx

func (m *BBMempool) CountTx() int

CountTx returns the total number of transactions in the mempool. This will be the sum of the number of transactions in each lane.

func (*BBMempool) GetLane

func (m *BBMempool) GetLane(name string) (Lane, error)

GetLane returns the lane with the given name.

func (*BBMempool) GetTxDistribution

func (m *BBMempool) GetTxDistribution() map[string]int

GetTxDistribution returns the number of transactions in each lane.

func (*BBMempool) Insert

func (m *BBMempool) Insert(ctx context.Context, tx sdk.Tx) error

Insert will insert a transaction into the mempool. It inserts the transaction into the first lane that it matches.

func (*BBMempool) Match

func (m *BBMempool) Match(tx sdk.Tx) (Lane, error)

Match will return the lane that the transaction belongs to. It matches to the first lane where lane.Match(tx) is true.

func (*BBMempool) Registry

func (m *BBMempool) Registry() []Lane

Registry returns the mempool's lane registry.

func (*BBMempool) Remove

func (m *BBMempool) Remove(tx sdk.Tx) error

Remove removes a transaction from the mempool based on the first lane that it matches.

func (*BBMempool) Select

func (m *BBMempool) Select(_ context.Context, _ [][]byte) sdkmempool.Iterator

Insert returns a nil iterator.

TODO: - Determine if it even makes sense to return an iterator. What does that even mean in the context where you have multiple lanes? - Perhaps consider implementing and returning a no-op iterator?

func (*BBMempool) ValidateBasic

func (m *BBMempool) ValidateBasic() error

ValidateBasic validates the mempools configuration.

type BaseLaneConfig

type BaseLaneConfig struct {
	Logger      log.Logger
	TxEncoder   sdk.TxEncoder
	TxDecoder   sdk.TxDecoder
	AnteHandler sdk.AnteHandler

	// MaxBlockSpace defines the relative percentage of block space that can be
	// used by this lane. NOTE: If this is set to zero, then there is no limit
	// on the number of transactions that can be included in the block for this
	// lane (up to maxTxBytes as provided by the request). This is useful for the default lane.
	MaxBlockSpace sdk.Dec

	// IgnoreList defines the list of lanes to ignore when processing transactions. This
	// is useful for when you want lanes to exist after the default lane. For example,
	// say there are two lanes: default and free. The free lane should be processed after
	// the default lane. In this case, the free lane should be added to the ignore list
	// of the default lane. Otherwise, the transactions that belong to the free lane
	// will be processed by the default lane.
	IgnoreList []Lane
}

BaseLaneConfig defines the basic functionality needed for a lane.

func NewBaseLaneConfig

func NewBaseLaneConfig(logger log.Logger, txEncoder sdk.TxEncoder, txDecoder sdk.TxDecoder, anteHandler sdk.AnteHandler, maxBlockSpace sdk.Dec) BaseLaneConfig

NewLaneConfig returns a new LaneConfig. This will be embedded in a lane.

func (*BaseLaneConfig) ValidateBasic

func (c *BaseLaneConfig) ValidateBasic() error

ValidateBasic validates the lane configuration.

type BlockProposal

type BlockProposal interface {
	// UpdateProposal updates the proposal with the given transactions. There are a
	// few invarients that are checked:
	//  1. The total size of the proposal must be less than the maximum number of bytes allowed.
	//  2. The total size of the partial proposal must be less than the maximum number of bytes allowed for
	//     the lane.
	UpdateProposal(lane LaneProposal, partialProposalTxs [][]byte) error

	// GetMaxTxBytes returns the maximum number of bytes that can be included in the proposal.
	GetMaxTxBytes() int64

	// GetTotalTxBytes returns the total number of bytes currently included in the proposal.
	GetTotalTxBytes() int64

	// GetTxs returns the transactions in the proposal.
	GetTxs() [][]byte

	// GetNumTxs returns the number of transactions in the proposal.
	GetNumTxs() int

	// Contains returns true if the proposal contains the given transaction.
	Contains(tx []byte) bool

	// AddVoteExtension adds a vote extension to the proposal.
	AddVoteExtension(voteExtension []byte)

	// GetVoteExtensions returns the vote extensions in the proposal.
	GetVoteExtensions() [][]byte

	// GetProposal returns all of the transactions in the proposal along with the vote extensions
	// at the top of the proposal.
	GetProposal() [][]byte
}

BlockProposal is the interface/APIs that are required for proposal creation + interacting with and updating proposals. BlockProposals are iteratively updated as each lane prepares its partial proposal. Each lane must call UpdateProposal with its partial proposal in PrepareLane. BlockProposals can also include vote extensions, which are included at the top of the proposal.

type Lane

type Lane interface {
	sdkmempool.Mempool

	// Name returns the name of the lane.
	Name() string

	// Match determines if a transaction belongs to this lane.
	Match(tx sdk.Tx) bool

	// VerifyTx verifies the transaction belonging to this lane.
	VerifyTx(ctx sdk.Context, tx sdk.Tx) error

	// Contains returns true if the mempool contains the given transaction.
	Contains(tx sdk.Tx) (bool, error)

	// PrepareLane builds a portion of the block. It inputs the maxTxBytes that can be
	// included in the proposal for the given lane, the partial proposal, and a function
	// to call the next lane in the chain. The next lane in the chain will be called with
	// the updated proposal and context.
	PrepareLane(ctx sdk.Context, proposal BlockProposal, maxTxBytes int64, next PrepareLanesHandler) (BlockProposal, error)

	// ProcessLaneBasic validates that transactions belonging to this lane are not misplaced
	// in the block proposal.
	ProcessLaneBasic(txs []sdk.Tx) error

	// ProcessLane verifies this lane's portion of a proposed block. It inputs the transactions
	// that may belong to this lane and a function to call the next lane in the chain. The next
	// lane in the chain will be called with the updated context and filtered down transactions.
	ProcessLane(ctx sdk.Context, proposalTxs []sdk.Tx, next ProcessLanesHandler) (sdk.Context, error)

	// SetAnteHandler sets the lane's antehandler.
	SetAnteHandler(antehander sdk.AnteHandler)

	// Logger returns the lane's logger.
	Logger() log.Logger

	// GetMaxBlockSpace returns the max block space for the lane as a relative percentage.
	GetMaxBlockSpace() sdk.Dec
}

Lane defines an interface used for block construction

type LaneProposal

type LaneProposal interface {
	// Logger returns the lane's logger.
	Logger() log.Logger

	// GetMaxBlockSpace returns the maximum block space for the lane as a relative percentage.
	GetMaxBlockSpace() sdk.Dec

	// Name returns the name of the lane.
	Name() string
}

LaneProposal defines the interface/APIs that are required for the proposal to interact with a lane.

type Mempool

type Mempool interface {
	sdkmempool.Mempool

	// Registry returns the mempool's lane registry.
	Registry() []Lane

	// Contains returns true if the transaction is contained in the mempool.
	Contains(tx sdk.Tx) (bool, error)

	// GetTxDistribution returns the number of transactions in each lane.
	GetTxDistribution() map[string]int

	// Match will return the lane that the transaction belongs to.
	Match(tx sdk.Tx) (Lane, error)

	// GetLane returns the lane with the given name.
	GetLane(name string) (Lane, error)
}

Mempool defines the Blockbuster mempool interface.

type PrepareLanesHandler

type PrepareLanesHandler func(ctx sdk.Context, proposal BlockProposal) (BlockProposal, error)

PrepareLanesHandler wraps all of the lanes Prepare function into a single chained function. You can think of it like an AnteHandler, but for preparing proposals in the context of lanes instead of modules.

type PriorityNonceIterator

type PriorityNonceIterator[C comparable] struct {
	// contains filtered or unexported fields
}

PriorityNonceIterator defines an iterator that is used for mempool iteration on Select().

func (*PriorityNonceIterator[C]) Next

func (i *PriorityNonceIterator[C]) Next() sdkmempool.Iterator

func (*PriorityNonceIterator[C]) Tx

func (i *PriorityNonceIterator[C]) Tx() sdk.Tx

type PriorityNonceMempool

type PriorityNonceMempool[C comparable] struct {
	// contains filtered or unexported fields
}

PriorityNonceMempool is a mempool implementation that stores txs in a partially ordered set by 2 dimensions: priority, and sender-nonce (sequence number). Internally it uses one priority ordered skip list and one skip list per sender ordered by sender-nonce (sequence number). When there are multiple txs from the same sender, they are not always comparable by priority to other sender txs and must be partially ordered by both sender-nonce and priority.

func DefaultPriorityMempool

func DefaultPriorityMempool() *PriorityNonceMempool[int64]

DefaultPriorityMempool returns a priorityNonceMempool with no options.

func NewPriorityMempool

func NewPriorityMempool[C comparable](cfg PriorityNonceMempoolConfig[C]) *PriorityNonceMempool[C]

NewPriorityMempool returns the SDK's default mempool implementation which returns txs in a partial order by 2 dimensions; priority, and sender-nonce.

func (*PriorityNonceMempool[C]) CountTx

func (mp *PriorityNonceMempool[C]) CountTx() int

CountTx returns the number of transactions in the mempool.

func (*PriorityNonceMempool[C]) Insert

func (mp *PriorityNonceMempool[C]) Insert(ctx context.Context, tx sdk.Tx) error

Insert attempts to insert a Tx into the app-side mempool in O(log n) time, returning an error if unsuccessful. Sender and nonce are derived from the transaction's first signature.

Transactions are unique by sender and nonce. Inserting a duplicate tx is an O(log n) no-op.

Inserting a duplicate tx with a different priority overwrites the existing tx, changing the total order of the mempool.

func (*PriorityNonceMempool[C]) NextSenderTx

func (mp *PriorityNonceMempool[C]) NextSenderTx(sender string) sdk.Tx

NextSenderTx returns the next transaction for a given sender by nonce order, i.e. the next valid transaction for the sender. If no such transaction exists, nil will be returned.

func (*PriorityNonceMempool[C]) Remove

func (mp *PriorityNonceMempool[C]) Remove(tx sdk.Tx) error

Remove removes a transaction from the mempool in O(log n) time, returning an error if unsuccessful.

func (*PriorityNonceMempool[C]) Select

func (mp *PriorityNonceMempool[C]) Select(_ context.Context, _ [][]byte) sdkmempool.Iterator

Select returns a set of transactions from the mempool, ordered by priority and sender-nonce in O(n) time. The passed in list of transactions are ignored. This is a readonly operation, the mempool is not modified.

The maxBytes parameter defines the maximum number of bytes of transactions to return.

type PriorityNonceMempoolConfig

type PriorityNonceMempoolConfig[C comparable] struct {
	// TxPriority defines the transaction priority and comparator.
	TxPriority TxPriority[C]

	// OnRead is a callback to be called when a tx is read from the mempool.
	OnRead func(tx sdk.Tx)

	// TxReplacement is a callback to be called when duplicated transaction nonce
	// detected during mempool insert. An application can define a transaction
	// replacement rule based on tx priority or certain transaction fields.
	TxReplacement func(op, np C, oTx, nTx sdk.Tx) bool

	// MaxTx sets the maximum number of transactions allowed in the mempool with
	// the semantics:
	// - if MaxTx == 0, there is no cap on the number of transactions in the mempool
	// - if MaxTx > 0, the mempool will cap the number of transactions it stores,
	//   and will prioritize transactions by their priority and sender-nonce
	//   (sequence number) when evicting transactions.
	// - if MaxTx < 0, `Insert` is a no-op.
	MaxTx int
}

PriorityNonceMempoolConfig defines the configuration used to configure the PriorityNonceMempool.

func DefaultPriorityNonceMempoolConfig

func DefaultPriorityNonceMempoolConfig() PriorityNonceMempoolConfig[int64]

type ProcessLanesHandler

type ProcessLanesHandler func(ctx sdk.Context, txs []sdk.Tx) (sdk.Context, error)

ProcessLanesHandler wraps all of the lanes Process functions into a single chained function. You can think of it like an AnteHandler, but for processing proposals in the context of lanes instead of modules.

type Proposal

type Proposal struct {
	// contains filtered or unexported fields
}

Proposal defines a block proposal type.

func NewProposal

func NewProposal(maxTxBytes int64) *Proposal

NewProposal returns a new empty proposal.

func (*Proposal) AddVoteExtension

func (p *Proposal) AddVoteExtension(voteExtension []byte)

AddVoteExtension adds a vote extension to the proposal.

func (*Proposal) Contains

func (p *Proposal) Contains(tx []byte) bool

Contains returns true if the proposal contains the given transaction.

func (*Proposal) GetMaxTxBytes

func (p *Proposal) GetMaxTxBytes() int64

GetMaxTxBytes returns the maximum number of bytes that can be included in the proposal.

func (*Proposal) GetNumTxs

func (p *Proposal) GetNumTxs() int

GetNumTxs returns the number of transactions in the proposal.

func (*Proposal) GetProposal

func (p *Proposal) GetProposal() [][]byte

GetProposal returns all of the transactions in the proposal along with the vote extensions at the top of the proposal.

func (*Proposal) GetTotalTxBytes

func (p *Proposal) GetTotalTxBytes() int64

GetTotalTxBytes returns the total number of bytes currently included in the proposal.

func (*Proposal) GetTxs

func (p *Proposal) GetTxs() [][]byte

GetTxs returns the transactions in the proposal.

func (*Proposal) GetVoteExtensions

func (p *Proposal) GetVoteExtensions() [][]byte

GetVoteExtensions returns the vote extensions in the proposal.

func (*Proposal) UpdateProposal

func (p *Proposal) UpdateProposal(lane LaneProposal, partialProposalTxs [][]byte) error

UpdateProposal updates the proposal with the given transactions and total size. There are a few invarients that are checked:

  1. The total size of the proposal must be less than the maximum number of bytes allowed.
  2. The total size of the partial proposal must be less than the maximum number of bytes allowed for the lane.

type TxPriority

type TxPriority[C comparable] struct {
	// GetTxPriority returns the priority of the transaction. A priority must be
	// comparable via Compare.
	GetTxPriority func(ctx context.Context, tx sdk.Tx) C

	// CompareTxPriority compares two transaction priorities. The result should be
	// 0 if a == b, -1 if a < b, and +1 if a > b.
	Compare func(a, b C) int

	// MinValue defines the minimum priority value, e.g. MinInt64. This value is
	// used when instantiating a new iterator and comparing weights.
	MinValue C
}

TxPriority defines a type that is used to retrieve and compare transaction priorities. Priorities must be comparable.

func NewDefaultTxPriority

func NewDefaultTxPriority() TxPriority[int64]

NewDefaultTxPriority returns a TxPriority comparator using ctx.Priority as the defining transaction priority.

Directories

Path Synopsis
lanes

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL