Skip to content

Latest commit

 

History

History
 
 

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Slow ABCI methods

ABCI methods (like EndBlocker) are not constrained by gas. Therefore, it is essential to ensure that they always will finish in a reasonable time. Otherwise, the chain will halt.

Example

Below you can find part of a tokens lending application. Before a block is executed, the BeginBlocker method charges an interest for each borrower.

func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
    updatePrices(ctx, k)
    accrueInterest(ctx, k)
}

func accrueInterest(ctx sdk.Context, k keeper.Keeper) {
    for _, pool := range k.GetLendingPools() {
        poolAssets := k.GetPoolAssets(ctx, pool.Id)
        for userId, _ := range k.GetAllUsers() {
            for _, asset := range poolAssets {
                for _, loan := range k.GetUserLoans(ctx, pool, asset, userId) {
                    if err := k.AccrueInterest(ctx, loan); err != nil {
                        k.PunishUser(ctx, userId)
                    }
                }
            }
        }
    }
}

The accrueInterest contains multiple nested for loops and is obviously too complex to be efficient. Mischievous users can take a lot of small loans to slow down computation to a point where the chain is not able to keep up with blocks production and halts.

Mitigations

External examples