Skip to content

Commit

Permalink
Trim low fee transactions before sim
Browse files Browse the repository at this point in the history
Optimizes the sim performance by discarding low fee transactions which
likely do not influence the result.
  • Loading branch information
bitcoinfees committed Oct 27, 2016
1 parent 7db2347 commit dbde8cd
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 6 deletions.
51 changes: 47 additions & 4 deletions feesim.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"log"
"math"
"sort"
"sync"
"time"

Expand Down Expand Up @@ -405,6 +406,8 @@ func (s *FeeSim) loopSim(period int) {
}

func (s *FeeSim) setupSim() (*sim.TransientSim, error) {
logger := s.cfg.logger

state := s.collect.State()
if state == nil {
return nil, errors.New("mempool state not available")
Expand All @@ -417,15 +420,55 @@ func (s *FeeSim) setupSim() (*sim.TransientSim, error) {
if err != nil {
return nil, err
}

// Trim the mempool to optimize sim time. The idea is that since we're only
// simulating up to a certain MaxBlockConfirms, we can safely ignore many
// low fee transactions.
maxBlockConfirms := s.cfg.Transient.MaxBlockConfirms
txratefn, capratefn, sizefn := txsource.RateFn(), blocksource.RateFn(), state.SizeFn()

maxcap := capratefn.Eval(math.MaxFloat64) // Maximum capacity byte rate

highfee := sizefn.Inverse(0)
var n int
if highfee > float64(math.MaxInt32) {
n = math.MaxInt32
} else {
n = int(highfee)
}

cutoff := sim.FeeRate(sort.Search(n, func(i int) bool {
d := sizefn.Eval(float64(i)) / (maxcap - txratefn.Eval(float64(i))) * blocksource.BlockRate()
const buffer = 3
return d < buffer*float64(maxBlockConfirms) && d >= 0
}))

initmempool, err := col.SimifyMempool(state.Entries)
if err != nil {
logger.Println("[ERROR] SimifyMempool:", err)
return nil, err
}

// TODO: choose a better low fee rate
ns := sim.NewSim(txsource, blocksource, initmempool)
s.cfg.logger.Println("[DEBUG] Transient sim stablefeerate:", ns.StableFee())
return sim.NewTransientSim(ns, s.cfg.Transient), nil
// Remove all transactions with fee rate less than cutoff. We remove all the
// parents as well, although it's not strictly necessary since it's done in
// sim.NewSim as well (the model does not consider mempool deps anymore
// CPFP, see sim.NewSim). However, we do it for neatness' sake, to avoid
// dangling deps.
var initmempoolTrimmed []*sim.Tx
for _, tx := range initmempool {
if tx.FeeRate >= cutoff {
tx.Parents = tx.Parents[:0]
initmempoolTrimmed = append(initmempoolTrimmed, tx)
}
}

ns := sim.NewSim(txsource, blocksource, initmempoolTrimmed)
transientCfg := s.cfg.Transient
transientCfg.LowestFeeRate = cutoff
logger.Println("[DEBUG] Transient sim stablefeerate:", ns.StableFee())
logger.Println("[DEBUG] Transient sim lowfee:", transientCfg.LowestFeeRate)

return sim.NewTransientSim(ns, transientCfg), nil
}

func (s *FeeSim) IsPaused() bool {
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Commands:

const (
coin = 100000000
version = "0.2.0"
version = "0.2.1"
)

func main() {
Expand Down
2 changes: 2 additions & 0 deletions sim/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ type TxSource interface {
type BlockSource interface {
Next() (t time.Duration, b BlockPolicy)

BlockRate() float64 // Blocks per second

// Return n copies of this source, which must have isolated random states.
// This is so that:
// 1. The source will be concurrent-safe.
Expand Down
4 changes: 4 additions & 0 deletions sim/indblock.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ func (b *IndBlockSource) Next() (t time.Duration, p BlockPolicy) {
return
}

func (b *IndBlockSource) BlockRate() float64 {
return b.blockrate
}

func (b *IndBlockSource) Copy(n int) []BlockSource {
bb := make([]BlockSource, n)
r := getrand(n + 1)
Expand Down
2 changes: 1 addition & 1 deletion sim/transient.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type TransientSim struct {
cfg TransientConfig

// Lowest fee rate for which conf times will be estimated.
// It's max(s.StableFee(), c.LowestFeeRate)
// It's max(sim.StableFee(), cfg.LowestFeeRate)
lowestfee FeeRate

// Used to stop the sim, ans also to signify that Run has been called, since
Expand Down

0 comments on commit dbde8cd

Please sign in to comment.