diff --git a/abci/README.md b/abci/README.md deleted file mode 100644 index 48f006e..0000000 --- a/abci/README.md +++ /dev/null @@ -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()) -``` \ No newline at end of file diff --git a/block/README.md b/block/README.md index f80eb41..9c6082d 100644 --- a/block/README.md +++ b/block/README.md @@ -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. \ No newline at end of file +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()) +``` diff --git a/lanes/README.md b/lanes/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/lanes/free/README.md b/lanes/free/README.md index e69de29..165a579 100644 --- a/lanes/free/README.md +++ b/lanes/free/README.md @@ -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()) + + ... +} +``` diff --git a/lanes/mev/README.md b/lanes/mev/README.md index e69de29..4c7c701 100644 --- a/lanes/mev/README.md +++ b/lanes/mev/README.md @@ -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()) + + ... +} +``` diff --git a/lanes/standard/README.md b/lanes/standard/README.md index e69de29..f466958 100644 --- a/lanes/standard/README.md +++ b/lanes/standard/README.md @@ -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()) + + ... +} +```