readmes for all the lanes

This commit is contained in:
David Terpay 2023-08-15 18:34:36 -04:00
parent faa64a5415
commit 4cfb76e4e9
No known key found for this signature in database
GPG Key ID: 627EFB00DADF0CD1
6 changed files with 671 additions and 237 deletions

View File

@ -1,202 +0,0 @@
# Block SDK Proposals
> 🤓 Learn and read all about how proposals are constructed and verified using
> the Block SDK
## 📖 Overview
The Block SDK is a framework for building smarter blocks. The Block SDK is built
harnessing the power of ABCI++ which is a new ABCI implementation that allows
for more complex and expressive applications to be built on top of the Cosmos SDK.
The process of building and verifiying proposals can be broken down into two
distinct parts:
1. Preparing a proposal during `PrepareProposal`.
2. Processing a proposal during `ProcessProposal`.
The Block SDK provides a framework for building and verifying proposals by
segmenting a single block into multiple lanes. Each lane can be responsible for
proposing and verifying specific types of transaction. The Block SDK provides
a default implementation of a lane that can be used to build and verify proposals
similar to how they are built and verified in the Cosmos SDK today while also
providing a framework for building more complex lanes that can be used to build
and verify much more complex proposals.
## 🤔 How does it work
### 🔁 Transaction Lifecycle
The best way to understand how lanes work is to first understand the lifecycle
of a transaction. A transaction begins its lifecycle when it is first signed and
broadcasted to a chain. After it is broadcasted to a validator, it will be checked
in `CheckTx` by the base application. If the transaction is valid, it will be
inserted into the applications mempool.
The transaction then waits in the mempool until a new block needs to be proposed.
When a new block needs to be proposed, the application will call `PrepareProposal`
(which is a new ABCI++ addition) to request a new block from the current
proposer. The proposer will look at what transactions currently waiting to
be included in a block by looking at their mempool. The proposer will then
iteratively select transactions until the block is full. The proposer will then
send the block to other validators in the network.
When a validator receives a proposed block, the validator will first want to
verify the contents of the block before signing off on it. The validator will
call `ProcessProposal` to verify the contents of the block. If the block is
valid, the validator will sign off on the block and broadcast their vote to the
network. If the block is invalid, the validator will reject the block. Once a
block is accepted by the network, it is committed and the transactions that
were included in the block are removed from the validator's mempool (as they no
longer need to be considered).
### 🛣️ Lane Lifecycle
After a transaction is verified in `CheckTx`, it will attempt to be inserted
into the `LanedMempool`. A `LanedMempool` is composed of several distinct `Lanes`
that have the ability to store their own transactions. The `LanedMempool` will
insert the transaction into all lanes that will accept it. The criteria for
whether a lane will accept a transaction is defined by the lane's
`MatchHandler`. The default implementation of a `MatchHandler` will accept all transactions.
When a new block is proposed, the `PrepareProposalHandler` will iteratively call
`PrepareLane` on each lane (in the order in which they are defined in the
`LanedMempool`). The `PrepareLane` method is anaolgous to `PrepareProposal`. Calling
`PrepareLane` on a lane will trigger the lane to reap transactions from its mempool
and add them to the proposal (given they are valid respecting the verification rules
of the lane).
When proposals need to be verified in `ProcessProposal`, the `ProcessProposalHandler`
defined in `abci/abci.go` will call `ProcessLane` on each lane in the same order
as they were called in the `PrepareProposalHandler`. Each subsequent call to
`ProcessLane` will filter out transactions that belong to previous lanes. A given
lane's `ProcessLane` will only verify transactions that belong to that lane.
> **Scenario**
>
> Let's say we have a `LanedMempool` composed of two lanes: `LaneA` and `LaneB`.
> `LaneA` is defined first in the `LanedMempool` and `LaneB` is defined second.
> `LaneA` contains transactions `Tx1` and `Tx2` and `LaneB` contains transactions
> `Tx3` and `Tx4`.
When a new block needs to be proposed, the `PrepareProposalHandler` will call
`PrepareLane` on `LaneA` first and `LaneB` second. When `PrepareLane` is called
on `LaneA`, `LaneA` will reap transactions from its mempool and add them to the
proposal. Same applies for `LaneB`. Say `LaneA` reaps transactions `Tx1` and `Tx2`
and `LaneB` reaps transactions `Tx3` and `Tx4`. This gives us a proposal composed
of the following:
* `Tx1`, `Tx2`, `Tx3`, `Tx4`
When the `ProcessProposalHandler` is called, it will call `ProcessLane` on `LaneA`
with the proposal composed of `Tx1`, `Tx2`, `Tx3`, and `Tx4`. `LaneA` will then
verify `Tx1` and `Tx2` and return the remaining transactions - `Tx3` and `Tx4`.
The `ProcessProposalHandler` will then call `ProcessLane` on `LaneB` with the
remaining transactions - `Tx3` and `Tx4`. `LaneB` will then verify `Tx3` and `Tx4`
and return no remaining transactions.
## 🏗️ Setup
> **Note**
>
> For a more in depth example of how to use the Block SDK, check out our
> example application in `block-sdk/tests/app/app.go`.
### 📦 Dependencies
The Block SDK is built on top of the Cosmos SDK. The Block SDK is currently
compatible with Cosmos SDK versions greater than or equal to `v0.47.0`.
### 📥 Installation
To install the Block SDK, run the following command:
```bash
go get github.com/skip-mev/block-sdk/abci
```
### 📚 Usage
First determine the set of lanes that you want to use in your application. The available
lanes can be found in our **Lane App Store** in `block-sdk/lanes`. In your base
application, you will need to create a `LanedMempool` composed of the lanes that
you want to use. You will also need to create a `PrepareProposalHandler` and a
`ProcessProposalHandler` that will be responsible for preparing and processing
proposals respectively.
```golang
// 1. Create the lanes.
//
// NOTE: The lanes are ordered by priority. The first lane is the highest priority
// lane and the last lane is the lowest priority lane. Top of block lane allows
// transactions to bid for inclusion at the top of the next block.
//
// For more information on how to utilize the LaneConfig please
// visit the README in block-sdk/block/base.
//
// MEV lane hosts an action at the top of the block.
mevConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
mevLane := mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(app.txConfig.TxDecoder()),
)
// Free lane allows transactions to be included in the next block for free.
freeConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
freeLane := free.NewFreeLane(
freeConfig,
constructor.DefaultTxPriority(),
free.DefaultMatchHandler(),
)
// Default lane accepts all other transactions.
defaultConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
defaultLane := base.NewStandardLane(defaultConfig)
// Set the lanes into the mempool.
lanes := []block.Lane{
mevLane,
freeLane,
defaultLane,
}
mempool := block.NewLanedMempool(app.Logger(), true, lanes...)
app.App.SetMempool(mempool)
...
anteHandler := NewAnteHandler(options)
// Set the lane ante handlers on the lanes.
for _, lane := range lanes {
lane.SetAnteHandler(anteHandler)
}
app.App.SetAnteHandler(anteHandler)
// Set the abci handlers on base app
proposalHandler := abci.NewProposalHandler(
app.Logger(),
app.TxConfig().TxDecoder(),
lanes,
)
app.App.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandler.ProcessProposalHandler())
```

View File

@ -1,44 +1,202 @@
# Block SDK 🧱
> 🤓 Learn and read all about how proposals are constructed and verified using
> the Block SDK
## 📖 Overview
The Block SDK is a framework for building smarter blocks. The Block SDK is built
harnessing the power of ABCI++ which is a new ABCI implementation that allows
for more complex and expressive applications to be built on top of the Cosmos SDK.
The process of building and verifiying proposals can be broken down into two
distinct parts:
1. Preparing a proposal during `PrepareProposal`.
2. Processing a proposal during `ProcessProposal`.
The Block SDK provides a framework for building and verifying proposals by
segmenting a single block into multiple lanes. Each lane can be responsible for
proposing and verifying specific types of transaction. The Block SDK provides
a default implementation of a lane that can be used to build and verify proposals
similar to how they are built and verified in the Cosmos SDK today while also
providing a framework for building more complex lanes that can be used to build
and verify much more complex proposals.
## 🤔 How does it work
### Transaction Lifecycle
### 🔁 Transaction Lifecycle
The best way to understand how lanes work is to first understand the lifecycle
of a transaction. When a transaction is submitted to the chain, it will be checked
of a transaction. A transaction begins its lifecycle when it is first signed and
broadcasted to a chain. After it is broadcasted to a validator, it will be checked
in `CheckTx` by the base application. If the transaction is valid, it will be
inserted into the applications mempool. The transaction then waits in the mempool
until a new block needs to be proposed. When a new block needs to be proposed,
the application will call `PrepareProposal` (which is a new ABCI++ addition) to
request a new block from the current proposer. The proposer will look at what the
transactions currently waiting to be included in a block in their mempool and
will iterative select transactions until the block is full. The proposer will then
send the block to other validators in the network. When a validator receives a
proposed block, the validator will first want to verify the contents of the block
before signing off on it. The validator will call `ProcessProposal` to verify the
contents of the block. If the block is valid, the validator will sign off on the
block and broadcast their vote to the network. If the block is invalid, the validator
will reject the block. Once a block is accepted by the network, it is committed
and the transactions that were included in the block are removed from the mempool.
inserted into the applications mempool.
### Lane Lifecycle
The transaction then waits in the mempool until a new block needs to be proposed.
When a new block needs to be proposed, the application will call `PrepareProposal`
(which is a new ABCI++ addition) to request a new block from the current
proposer. The proposer will look at what transactions currently waiting to
be included in a block by looking at their mempool. The proposer will then
iteratively select transactions until the block is full. The proposer will then
send the block to other validators in the network.
The Lane Constructor implements the `Lane` interface. After transactions are
check in `CheckTx`, they will be added to this lane's mempool (data structure
responsible for storing transactions). When a new block is proposed, `PrepareLane`
will be called by the `PrepareProposalHandler` defined in `abci/abci.go`. This
will trigger the lane to reap transactions from its mempool and add them to the
proposal. By default, transactions are added to proposals in the order that they
are reaped from the mempool. Transactions will only be added to a proposal
if they are valid according to the lane's verification logic. The default implementation
determines whether a transaction is valid by running the transaction through the
lane's `AnteHandler`. If any transactions are invalid, they will be removed from
lane's mempool from further consideration.
When a validator receives a proposed block, the validator will first want to
verify the contents of the block before signing off on it. The validator will
call `ProcessProposal` to verify the contents of the block. If the block is
valid, the validator will sign off on the block and broadcast their vote to the
network. If the block is invalid, the validator will reject the block. Once a
block is accepted by the network, it is committed and the transactions that
were included in the block are removed from the validator's mempool (as they no
longer need to be considered).
### 🛣️ Lane Lifecycle
After a transaction is verified in `CheckTx`, it will attempt to be inserted
into the `LanedMempool`. A `LanedMempool` is composed of several distinct `Lanes`
that have the ability to store their own transactions. The `LanedMempool` will
insert the transaction into all lanes that will accept it. The criteria for
whether a lane will accept a transaction is defined by the lane's
`MatchHandler`. The default implementation of a `MatchHandler` will accept all transactions.
When a new block is proposed, the `PrepareProposalHandler` will iteratively call
`PrepareLane` on each lane (in the order in which they are defined in the
`LanedMempool`). The `PrepareLane` method is anaolgous to `PrepareProposal`. Calling
`PrepareLane` on a lane will trigger the lane to reap transactions from its mempool
and add them to the proposal (given they are valid respecting the verification rules
of the lane).
When proposals need to be verified in `ProcessProposal`, the `ProcessProposalHandler`
defined in `abci/abci.go` will call `ProcessLane` on each lane. This will trigger
the lane to process all transactions that are included in the proposal. Lane's
should only verify transactions that belong to their lane. The default implementation
of `ProcessLane` will first check that transactions that should belong to the
current lane are ordered correctly in the proposal. If they are not, the proposal
will be rejected. If they are, the lane will run the transactions through its `ProcessLaneHandler`
which is responsible for verifying the transactions against the lane's verification
logic. If any transactions are invalid, the proposal will be rejected.
defined in `abci/abci.go` will call `ProcessLane` on each lane in the same order
as they were called in the `PrepareProposalHandler`. Each subsequent call to
`ProcessLane` will filter out transactions that belong to previous lanes. A given
lane's `ProcessLane` will only verify transactions that belong to that lane.
> **Scenario**
>
> Let's say we have a `LanedMempool` composed of two lanes: `LaneA` and `LaneB`.
> `LaneA` is defined first in the `LanedMempool` and `LaneB` is defined second.
> `LaneA` contains transactions `Tx1` and `Tx2` and `LaneB` contains transactions
> `Tx3` and `Tx4`.
When a new block needs to be proposed, the `PrepareProposalHandler` will call
`PrepareLane` on `LaneA` first and `LaneB` second. When `PrepareLane` is called
on `LaneA`, `LaneA` will reap transactions from its mempool and add them to the
proposal. Same applies for `LaneB`. Say `LaneA` reaps transactions `Tx1` and `Tx2`
and `LaneB` reaps transactions `Tx3` and `Tx4`. This gives us a proposal composed
of the following:
* `Tx1`, `Tx2`, `Tx3`, `Tx4`
When the `ProcessProposalHandler` is called, it will call `ProcessLane` on `LaneA`
with the proposal composed of `Tx1`, `Tx2`, `Tx3`, and `Tx4`. `LaneA` will then
verify `Tx1` and `Tx2` and return the remaining transactions - `Tx3` and `Tx4`.
The `ProcessProposalHandler` will then call `ProcessLane` on `LaneB` with the
remaining transactions - `Tx3` and `Tx4`. `LaneB` will then verify `Tx3` and `Tx4`
and return no remaining transactions.
## 🏗️ Setup
> **Note**
>
> For a more in depth example of how to use the Block SDK, check out our
> example application in `block-sdk/tests/app/app.go`.
### 📦 Dependencies
The Block SDK is built on top of the Cosmos SDK. The Block SDK is currently
compatible with Cosmos SDK versions greater than or equal to `v0.47.0`.
### 📥 Installation
To install the Block SDK, run the following command:
```bash
go get github.com/skip-mev/block-sdk/abci
```
### 📚 Usage
First determine the set of lanes that you want to use in your application. The available
lanes can be found in our **Lane App Store** in `block-sdk/lanes`. In your base
application, you will need to create a `LanedMempool` composed of the lanes that
you want to use. You will also need to create a `PrepareProposalHandler` and a
`ProcessProposalHandler` that will be responsible for preparing and processing
proposals respectively.
```golang
// 1. Create the lanes.
//
// NOTE: The lanes are ordered by priority. The first lane is the highest priority
// lane and the last lane is the lowest priority lane. Top of block lane allows
// transactions to bid for inclusion at the top of the next block.
//
// For more information on how to utilize the LaneConfig please
// visit the README in block-sdk/block/base.
//
// MEV lane hosts an action at the top of the block.
mevConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
mevLane := mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(app.txConfig.TxDecoder()),
)
// Free lane allows transactions to be included in the next block for free.
freeConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
freeLane := free.NewFreeLane(
freeConfig,
constructor.DefaultTxPriority(),
free.DefaultMatchHandler(),
)
// Default lane accepts all other transactions.
defaultConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
defaultLane := base.NewStandardLane(defaultConfig)
// Set the lanes into the mempool.
lanes := []block.Lane{
mevLane,
freeLane,
defaultLane,
}
mempool := block.NewLanedMempool(app.Logger(), true, lanes...)
app.App.SetMempool(mempool)
...
anteHandler := NewAnteHandler(options)
// Set the lane ante handlers on the lanes.
for _, lane := range lanes {
lane.SetAnteHandler(anteHandler)
}
app.App.SetAnteHandler(anteHandler)
// Set the abci handlers on base app
proposalHandler := abci.NewProposalHandler(
app.Logger(),
app.TxConfig().TxDecoder(),
lanes,
)
app.App.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandler.ProcessProposalHandler())
```

View File

View File

@ -0,0 +1,157 @@
# Free Lane
> Leverage the free lane to encourage certain activity (such as staking) on
> your chain.
## 📖 Overview
The Free Lane is a lane that allows transactions to be included in the next block
for free. By default, transactions that are staking related (e.g. delegation,
undelegation, redelegate, etc.) are included in the Free Lane, however, this
can be easily replaced! For more information on that, please see the
`MatchHandler` section in the README found in `block-sdk/block/base`.
## 🏗️ Setup
> **Note**
>
> For a more in depth example of how to use the Block SDK, check out our
> example application in `block-sdk/tests/app/app.go`.
### 📦 Dependencies
The Block SDK is built on top of the Cosmos SDK. The Block SDK is currently
compatible with Cosmos SDK versions greater than or equal to `v0.47.0`.
### 📥 Installation
To install the Block SDK, run the following command:
```bash
$ go get github.com/skip-mev/block-sdk/abci
$ go get github.com/skip-mev/block-sdk/lanes/free
```
### 📚 Usage
1. First determine the set of lanes that you want to use in your application. The
available lanes can be found in our **Lane App Store** in `block-sdk/lanes`. In
your base application, you will need to create a `LanedMempool` composed of the
lanes that you want to use.
2. Next, order the lanes by priority. The first lane is the highest priority lane
and the last lane is the lowest priority lane. Determine exactly where you want
the free lane to be in the priority order.
3. Set up your `FeeDeductorDecorator` to ignore the free lane where ever you
initialize your `AnteHandler`. This will ensure that the free lane is not
subject to deducting transaction fees.
4. You will also need to create a `PrepareProposalHandler` and a
`ProcessProposalHandler` that will be responsible for preparing and processing
proposals respectively. Configure the order of the lanes in the
`PrepareProposalHandler` and `ProcessProposalHandler` to match the order of the
lanes in the `LanedMempool`.
```golang
import (
"github.com/skip-mev/block-sdk/abci"
"github.com/skip-mev/block-sdk/lanes/free"
)
...
```
```golang
func NewApp() {
...
// 1. Create the lanes.
//
// NOTE: The lanes are ordered by priority. The first lane is the highest priority
// lane and the last lane is the lowest priority lane. Top of block lane allows
// transactions to bid for inclusion at the top of the next block.
//
// For more information on how to utilize the LaneConfig please
// visit the README in block-sdk/block/base.
//
// MEV lane hosts an action at the top of the block.
mevConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
mevLane := mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(app.txConfig.TxDecoder()),
)
// Free lane allows transactions to be included in the next block for free.
freeConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
freeLane := free.NewFreeLane(
freeConfig,
constructor.DefaultTxPriority(),
free.DefaultMatchHandler(),
)
// Default lane accepts all other transactions.
defaultConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
defaultLane := base.NewStandardLane(defaultConfig)
// 2. Set up the relateive priority of lanes
lanes := []block.Lane{
mevLane,
freeLane,
defaultLane,
}
mempool := block.NewLanedMempool(app.Logger(), true, lanes...)
app.App.SetMempool(mempool)
...
// 3. Set up the ante handler.
anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(),
...
utils.NewIgnoreDecorator(
ante.NewDeductFeeDecorator(
options.BaseOptions.AccountKeeper,
options.BaseOptions.BankKeeper,
options.BaseOptions.FeegrantKeeper,
options.BaseOptions.TxFeeChecker,
),
options.FreeLane,
),
...
}
anteHandler := sdk.ChainAnteDecorators(anteDecorators...)
// Set the lane ante handlers on the lanes.
for _, lane := range lanes {
lane.SetAnteHandler(anteHandler)
}
app.App.SetAnteHandler(anteHandler)
// 4. Set the abci handlers on base app
proposalHandler := abci.NewProposalHandler(
app.Logger(),
app.TxConfig().TxDecoder(),
lanes,
)
app.App.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandler.ProcessProposalHandler())
...
}
```

View File

@ -0,0 +1,160 @@
# MEV Lane
> The MEV Lane hosts top of block auctions in protocol and verifiably builds
> blocks with top-of-block block space reserved for auction winners, with
> auction revenue being redistributed to chains.
## 📖 Overview
Blockspace is valuable, and MEV bots find arbitrage opportunities to capture
value. The Block SDK provides a fair auction for these opportunities via the
x/auction module inside the Block SDK so that protocols are rewarded while
ensuring that users are not front-run or sandwiched in the process.
The Block SDK uses the app-side mempool, PrepareLane / ProcessLane, and CheckTx
to create an MEV marketplace inside the protocol. It introduces a new message
type, called a MsgAuctionBid, that allows the submitter to execute multiple
transactions at the top of the block atomically
(atomically = directly next to each other).
## 🏗️ Setup
> **Note**
>
> For a more in depth example of how to use the Block SDK, check out our
> example application in `block-sdk/tests/app/app.go`.
### 📦 Dependencies
The Block SDK is built on top of the Cosmos SDK. The Block SDK is currently
compatible with Cosmos SDK versions greater than or equal to `v0.47.0`.
### 📥 Installation
To install the Block SDK, run the following command:
```bash
$ go get github.com/skip-mev/block-sdk/abci
$ go get github.com/skip-mev/block-sdk/lanes/mev
```
### 📚 Usage
1. First determine the set of lanes that you want to use in your application. The
available lanes can be found in our **Lane App Store** in `block-sdk/lanes`. In
your base application, you will need to create a `LanedMempool` composed of the
lanes that you want to use.
2. Next, order the lanes by priority. The first lane is the highest priority lane
and the last lane is the lowest priority lane. **It is recommended that the first
lane is the MEV lane as the top of block is the most valuable block space.**
3. You will also need to create a `PrepareProposalHandler` and a
`ProcessProposalHandler` that will be responsible for preparing and processing
proposals respectively. Configure the order of the lanes in the
`PrepareProposalHandler` and `ProcessProposalHandler` to match the order of the
lanes in the `LanedMempool`.
```golang
import (
"github.com/skip-mev/block-sdk/abci"
"github.com/skip-mev/block-sdk/lanes/mev"
)
...
```
```golang
func NewApp() {
...
// 1. Create the lanes.
//
// NOTE: The lanes are ordered by priority. The first lane is the highest priority
// lane and the last lane is the lowest priority lane. Top of block lane allows
// transactions to bid for inclusion at the top of the next block.
//
// For more information on how to utilize the LaneConfig please
// visit the README in block-sdk/block/base.
//
// MEV lane hosts an action at the top of the block.
mevConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
mevLane := mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(app.txConfig.TxDecoder()),
)
// Free lane allows transactions to be included in the next block for free.
freeConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
freeLane := free.NewFreeLane(
freeConfig,
constructor.DefaultTxPriority(),
free.DefaultMatchHandler(),
)
// Default lane accepts all other transactions.
defaultConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
defaultLane := base.NewStandardLane(defaultConfig)
// 2. Set up the relateive priority of lanes
lanes := []block.Lane{
mevLane,
freeLane,
defaultLane,
}
mempool := block.NewLanedMempool(app.Logger(), true, lanes...)
app.App.SetMempool(mempool)
...
// 3. Set up the ante handler.
anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(),
...
utils.NewIgnoreDecorator(
ante.NewDeductFeeDecorator(
options.BaseOptions.AccountKeeper,
options.BaseOptions.BankKeeper,
options.BaseOptions.FeegrantKeeper,
options.BaseOptions.TxFeeChecker,
),
options.FreeLane,
),
...
}
anteHandler := sdk.ChainAnteDecorators(anteDecorators...)
// Set the lane ante handlers on the lanes.
for _, lane := range lanes {
lane.SetAnteHandler(anteHandler)
}
app.App.SetAnteHandler(anteHandler)
// 4. Set the abci handlers on base app
proposalHandler := abci.NewProposalHandler(
app.Logger(),
app.TxConfig().TxDecoder(),
lanes,
)
app.App.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandler.ProcessProposalHandler())
...
}
```

View File

@ -0,0 +1,161 @@
# Standard Lane
> The Standard Lane is the most general and least restrictive lane. The Standard
> Lane accepts all transactions that are not accepted by the other lanes, is
> generally the lowest priority lane, and consumes all blockspace that is not
> consumed by the other lanes.
## 📖 Overview
Blockspace is valuable, and MEV bots find arbitrage opportunities to capture
value. The Block SDK provides a fair auction for these opportunities via the
x/auction module inside the Block SDK so that protocols are rewarded while
ensuring that users are not front-run or sandwiched in the process.
The Block SDK uses the app-side mempool, PrepareLane / ProcessLane, and CheckTx
to create an MEV marketplace inside the protocol. It introduces a new message
type, called a MsgAuctionBid, that allows the submitter to execute multiple
transactions at the top of the block atomically
(atomically = directly next to each other).
## 🏗️ Setup
> **Note**
>
> For a more in depth example of how to use the Block SDK, check out our
> example application in `block-sdk/tests/app/app.go`.
### 📦 Dependencies
The Block SDK is built on top of the Cosmos SDK. The Block SDK is currently
compatible with Cosmos SDK versions greater than or equal to `v0.47.0`.
### 📥 Installation
To install the Block SDK, run the following command:
```bash
$ go get github.com/skip-mev/block-sdk/abci
$ go get github.com/skip-mev/block-sdk/lanes/standard
```
### 📚 Usage
1. First determine the set of lanes that you want to use in your application. The
available lanes can be found in our **Lane App Store** in `block-sdk/lanes`. In
your base application, you will need to create a `LanedMempool` composed of the
lanes that you want to use.
2. Next, order the lanes by priority. The first lane is the highest priority lane
and the last lane is the lowest priority lane. **It is recommended that the last
lane is the standard lane.**
3. You will also need to create a `PrepareProposalHandler` and a
`ProcessProposalHandler` that will be responsible for preparing and processing
proposals respectively. Configure the order of the lanes in the
`PrepareProposalHandler` and `ProcessProposalHandler` to match the order of the
lanes in the `LanedMempool`.
```golang
import (
"github.com/skip-mev/block-sdk/abci"
"github.com/skip-mev/block-sdk/lanes/standard"
)
...
```
```golang
func NewApp() {
...
// 1. Create the lanes.
//
// NOTE: The lanes are ordered by priority. The first lane is the highest priority
// lane and the last lane is the lowest priority lane. Top of block lane allows
// transactions to bid for inclusion at the top of the next block.
//
// For more information on how to utilize the LaneConfig please
// visit the README in block-sdk/block/base.
//
// MEV lane hosts an action at the top of the block.
mevConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
mevLane := mev.NewMEVLane(
mevConfig,
mev.NewDefaultAuctionFactory(app.txConfig.TxDecoder()),
)
// Free lane allows transactions to be included in the next block for free.
freeConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
freeLane := free.NewFreeLane(
freeConfig,
constructor.DefaultTxPriority(),
free.DefaultMatchHandler(),
)
// Standard lane accepts all other transactions.
defaultConfig := constructor.LaneConfig{
Logger: app.Logger(),
TxEncoder: app.txConfig.TxEncoder(),
TxDecoder: app.txConfig.TxDecoder(),
MaxBlockSpace: math.LegacyZeroDec(),
MaxTxs: 0,
}
defaultLane := base.NewStandardLane(defaultConfig)
// 2. Set up the relateive priority of lanes
lanes := []block.Lane{
mevLane,
freeLane,
defaultLane,
}
mempool := block.NewLanedMempool(app.Logger(), true, lanes...)
app.App.SetMempool(mempool)
...
// 3. Set up the ante handler.
anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(),
...
utils.NewIgnoreDecorator(
ante.NewDeductFeeDecorator(
options.BaseOptions.AccountKeeper,
options.BaseOptions.BankKeeper,
options.BaseOptions.FeegrantKeeper,
options.BaseOptions.TxFeeChecker,
),
options.FreeLane,
),
...
}
anteHandler := sdk.ChainAnteDecorators(anteDecorators...)
// Set the lane ante handlers on the lanes.
for _, lane := range lanes {
lane.SetAnteHandler(anteHandler)
}
app.App.SetAnteHandler(anteHandler)
// 4. Set the abci handlers on base app
proposalHandler := abci.NewProposalHandler(
app.Logger(),
app.TxConfig().TxDecoder(),
lanes,
)
app.App.SetPrepareProposal(proposalHandler.PrepareProposalHandler())
app.App.SetProcessProposal(proposalHandler.ProcessProposalHandler())
...
}
```