estimatefee.go raw

   1  package mempool
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/binary"
   6  	"errors"
   7  	"fmt"
   8  	"github.com/p9c/p9/pkg/amt"
   9  	"github.com/p9c/p9/pkg/block"
  10  	"io"
  11  	"math"
  12  	"math/rand"
  13  	"sort"
  14  	"strings"
  15  	"sync"
  16  	
  17  	"github.com/p9c/p9/pkg/chainhash"
  18  	"github.com/p9c/p9/pkg/mining"
  19  	"github.com/p9c/p9/pkg/util"
  20  )
  21  
  22  // DUOPerKilobyte is number with units of parallelcoins per kilobyte.
  23  type DUOPerKilobyte float64
  24  
  25  // FeeEstimator manages the data necessary to create fee estimations. It is safe for concurrent access.
  26  type FeeEstimator struct {
  27  	maxRollback uint32
  28  	binSize     int32
  29  	// The maximum number of replacements that can be made in a single bin per block. Default is
  30  	// estimateFeeMaxReplacements
  31  	maxReplacements int32
  32  	// The minimum number of blocks that can be registered with the fee estimator before it will provide answers.
  33  	minRegisteredBlocks uint32
  34  	// The last known height.
  35  	lastKnownHeight int32
  36  	// The number of blocks that have been registered.
  37  	numBlocksRegistered uint32
  38  	mtx                 sync.RWMutex
  39  	observed            map[chainhash.Hash]*observedTransaction
  40  	bin                 [estimateFeeDepth][]*observedTransaction
  41  	// The cached estimates.
  42  	cached []SatoshiPerByte
  43  	// Transactions that have been removed from the bins. This allows us to revert in case of an orphaned block.
  44  	dropped []*registeredBlock
  45  }
  46  
  47  // FeeEstimatorState represents a saved FeeEstimator that can be restored with data from an earlier session of the
  48  // program.
  49  type FeeEstimatorState []byte
  50  
  51  // SatoshiPerByte is number with units of satoshis per byte.
  52  type SatoshiPerByte float64
  53  
  54  // estimateFeeSet is a set of txs that can that is sorted by the fee per kb rate.
  55  type estimateFeeSet struct {
  56  	feeRate []SatoshiPerByte
  57  	bin     [estimateFeeDepth]uint32
  58  }
  59  
  60  // observedTransaction represents an observed transaction and some additional data required for the fee estimation
  61  // algorithm.
  62  type observedTransaction struct {
  63  	// A transaction hash.
  64  	hash chainhash.Hash
  65  	// The fee per byte of the transaction in satoshis.
  66  	feeRate SatoshiPerByte
  67  	// The block height when it was observed.
  68  	observed int32
  69  	// The height of the block in which it was mined. If the transaction has not yet been mined, it is zero.
  70  	mined int32
  71  }
  72  
  73  // observedTxSet is a set of txs that can that is sorted by hash. It exists for serialization purposes so that a
  74  // serialized state always comes out the same.
  75  type observedTxSet []*observedTransaction
  76  
  77  // registeredBlock has the hash of a block and the list of transactions it mined which had been previously observed by
  78  // the FeeEstimator. It is used if Rollback is called to reverse the effect of registering a block.
  79  type registeredBlock struct {
  80  	hash         chainhash.Hash
  81  	transactions []*observedTransaction
  82  }
  83  
  84  // TODO incorporate Alex Morcos' modifications to Gavin's initial model
  85  //  https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2014-October/006824.html
  86  const (
  87  	// estimateFeeDepth is the maximum number of blocks before a transaction is confirmed that we want to track.
  88  	estimateFeeDepth = 25
  89  	// estimateFeeBinSize is the number of txs stored in each bin.
  90  	estimateFeeBinSize = 100
  91  	// estimateFeeMaxReplacements is the max number of replacements that can be made by the txs found in a given block.
  92  	estimateFeeMaxReplacements = 10
  93  	// DefaultEstimateFeeMaxRollback is the default number of rollbacks allowed by the fee estimator for orphaned
  94  	// blocks.
  95  	DefaultEstimateFeeMaxRollback = 2
  96  	// DefaultEstimateFeeMinRegisteredBlocks is the default minimum number of blocks which must be observed by the fee
  97  	// estimator before will provide fee estimations.
  98  	DefaultEstimateFeeMinRegisteredBlocks = 3
  99  	bytePerKb                             = 1000
 100  	duoPerSatoshi                         = 1e-8
 101  )
 102  
 103  // In case the format for the serialized version of the FeeEstimator changes, we use a version number. If the version
 104  // number changes, it does not make sense to try to upgrade a previous version to a new version. Instead, just start fee
 105  // estimation over.
 106  const estimateFeeSaveVersion = 1
 107  
 108  var (
 109  	// EstimateFeeDatabaseKey is the key that we use to store the fee estimator in the database.
 110  	EstimateFeeDatabaseKey = []byte("estimatefee")
 111  )
 112  
 113  // EstimateFee estimates the fee per byte to have a tx confirmed a given number of blocks from now.
 114  func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (DUOPerKilobyte, error) {
 115  	ef.mtx.Lock()
 116  	defer ef.mtx.Unlock()
 117  	// If the number of registered blocks is below the minimum, return an error.
 118  	if ef.numBlocksRegistered < ef.minRegisteredBlocks {
 119  		return -1, errors.New("not enough blocks have been observed")
 120  	}
 121  	if numBlocks == 0 {
 122  		return -1, errors.New("cannot confirm transaction in zero blocks")
 123  	}
 124  	if numBlocks > estimateFeeDepth {
 125  		return -1, fmt.Errorf(
 126  			"can only estimate fees for up to %d blocks from now",
 127  			estimateFeeBinSize,
 128  		)
 129  	}
 130  	// If there are no cached results, generate them.
 131  	if ef.cached == nil {
 132  		ef.cached = ef.estimates()
 133  	}
 134  	return ef.cached[int(numBlocks)-1].ToBtcPerKb(), nil
 135  }
 136  
 137  func // LastKnownHeight returns the height of the last block which was
 138  // registered.
 139  (ef *FeeEstimator) LastKnownHeight() int32 {
 140  	ef.mtx.Lock()
 141  	defer ef.mtx.Unlock()
 142  	return ef.lastKnownHeight
 143  }
 144  
 145  // ObserveTransaction is called when a new transaction is observed in the mempool.
 146  func (ef *FeeEstimator) ObserveTransaction(
 147  	t *TxDesc,
 148  ) {
 149  	ef.mtx.Lock()
 150  	defer ef.mtx.Unlock()
 151  	// If we haven't seen a block yet we don't know when this one arrived, so we ignore it.
 152  	if ef.lastKnownHeight == mining.UnminedHeight {
 153  		return
 154  	}
 155  	hash := *t.Tx.Hash()
 156  	if _, ok := ef.observed[hash]; !ok {
 157  		size := uint32(GetTxVirtualSize(t.Tx))
 158  		ef.observed[hash] = &observedTransaction{
 159  			hash:     hash,
 160  			feeRate:  NewSatoshiPerByte(amt.Amount(t.Fee), size),
 161  			observed: t.Height,
 162  			mined:    mining.UnminedHeight,
 163  		}
 164  	}
 165  }
 166  
 167  // RegisterBlock informs the fee estimator of a new block to take into account.
 168  func (ef *FeeEstimator) RegisterBlock(
 169  	block *block.Block,
 170  ) (e error) {
 171  	ef.mtx.Lock()
 172  	defer ef.mtx.Unlock()
 173  	// The previous sorted list is invalid, so delete it.
 174  	ef.cached = nil
 175  	height := block.Height()
 176  	if height != ef.lastKnownHeight+1 && ef.lastKnownHeight != mining.UnminedHeight {
 177  		return fmt.Errorf(
 178  			"intermediate block not recorded; current height is %d; new height is %d",
 179  			ef.lastKnownHeight, height,
 180  		)
 181  	}
 182  	// Update the last known height.
 183  	ef.lastKnownHeight = height
 184  	ef.numBlocksRegistered++
 185  	// Randomly order txs in block.
 186  	transactions := make(map[*util.Tx]struct{})
 187  	for _, t := range block.Transactions() {
 188  		transactions[t] = struct{}{}
 189  	}
 190  	// Count the number of replacements we make per bin so that we don't replace too many.
 191  	var replacementCounts [estimateFeeDepth]int
 192  	// Keep track of which txs were dropped in case of an orphan block.
 193  	dropped := &registeredBlock{
 194  		hash:         *block.Hash(),
 195  		transactions: make([]*observedTransaction, 0, 100),
 196  	}
 197  	// Go through the txs in the block.
 198  	for t := range transactions {
 199  		hash := *t.Hash()
 200  		// Have we observed this tx in the mempool?
 201  		o, ok := ef.observed[hash]
 202  		if !ok {
 203  			continue
 204  		}
 205  		// Put the observed tx in the appropriate bin.
 206  		blocksToConfirm := height - o.observed - 1
 207  		// This shouldn't happen if the fee estimator works correctly, but return an error if it does.
 208  		if o.mined != mining.UnminedHeight {
 209  			E.Ln("Estimate fee: transaction ", hash, " has already been mined")
 210  			return errors.New("transaction has already been mined")
 211  		}
 212  		// This shouldn't happen but check just in case to avoid an out-of -bounds array index later.
 213  		if blocksToConfirm >= estimateFeeDepth {
 214  			continue
 215  		}
 216  		// Make sure we do not replace too many transactions per min.
 217  		if replacementCounts[blocksToConfirm] == int(ef.maxReplacements) {
 218  			continue
 219  		}
 220  		o.mined = height
 221  		replacementCounts[blocksToConfirm]++
 222  		bin := ef.bin[blocksToConfirm]
 223  		// Remove a random element and replace it with this new tx.
 224  		if len(bin) == int(ef.binSize) {
 225  			// Don't drop transactions we have just added from this same block.
 226  			l := int(ef.binSize) - replacementCounts[blocksToConfirm]
 227  			drop := rand.Intn(l)
 228  			dropped.transactions = append(dropped.transactions, bin[drop])
 229  			bin[drop] = bin[l-1]
 230  			bin[l-1] = o
 231  		} else {
 232  			bin = append(bin, o)
 233  		}
 234  		ef.bin[blocksToConfirm] = bin
 235  	}
 236  	// Go through the mempool for txs that have been in too long.
 237  	for hash, o := range ef.observed {
 238  		if o.mined == mining.UnminedHeight && height-o.observed >= estimateFeeDepth {
 239  			delete(ef.observed, hash)
 240  		}
 241  	}
 242  	// Add dropped list to history.
 243  	if ef.maxRollback == 0 {
 244  		return nil
 245  	}
 246  	if uint32(len(ef.dropped)) == ef.maxRollback {
 247  		ef.dropped = append(ef.dropped[1:], dropped)
 248  	} else {
 249  		ef.dropped = append(ef.dropped, dropped)
 250  	}
 251  	return nil
 252  }
 253  
 254  // Rollback unregisters a recently registered block from the FeeEstimator. This can be used to reverse the effect of an
 255  // orphaned block on the fee estimator. The maximum number of rollbacks allowed is given by maxRollbacks. Note: not
 256  // everything can be rolled back because some transactions are deleted if they have been observed too long ago. That
 257  // means the result of Rollback won't always be exactly the same as if the last block had not happened, but it should be
 258  // close enough.
 259  func (ef *FeeEstimator) Rollback(hash *chainhash.Hash) (e error) {
 260  	ef.mtx.Lock()
 261  	defer ef.mtx.Unlock()
 262  	// Find this block in the stack of recent registered blocks.
 263  	var n int
 264  	for n = 1; n <= len(ef.dropped); n++ {
 265  		if ef.dropped[len(ef.dropped)-n].hash.IsEqual(hash) {
 266  			break
 267  		}
 268  	}
 269  	if n > len(ef.dropped) {
 270  		return errors.New("no such block was recently registered")
 271  	}
 272  	for i := 0; i < n; i++ {
 273  		ef.rollback()
 274  	}
 275  	return nil
 276  }
 277  
 278  // Save records the current state of the FeeEstimator to a []byte that can be restored later.
 279  func (ef *FeeEstimator) Save() FeeEstimatorState {
 280  	ef.mtx.Lock()
 281  	defer ef.mtx.Unlock()
 282  	// TODO figure out what the capacity should be.
 283  	w := bytes.NewBuffer(make([]byte, 0))
 284  	e := binary.Write(
 285  		w, binary.BigEndian, uint32(estimateFeeSaveVersion),
 286  	)
 287  	if e != nil {
 288  		F.Ln("failed to write fee estimates", e)
 289  	}
 290  	// Insert basic parameters.
 291  	e = binary.Write(w, binary.BigEndian, &ef.maxRollback)
 292  	if e != nil {
 293  		F.Ln("failed to write fee estimates", e)
 294  	}
 295  	e = binary.Write(w, binary.BigEndian, &ef.binSize)
 296  	if e != nil {
 297  		F.Ln("failed to write fee estimates", e)
 298  	}
 299  	e = binary.Write(w, binary.BigEndian, &ef.maxReplacements)
 300  	if e != nil {
 301  		F.Ln("failed to write fee estimates", e)
 302  	}
 303  	e = binary.Write(w, binary.BigEndian, &ef.minRegisteredBlocks)
 304  	if e != nil {
 305  		F.Ln("failed to write fee estimates", e)
 306  	}
 307  	e = binary.Write(w, binary.BigEndian, &ef.lastKnownHeight)
 308  	if e != nil {
 309  		F.Ln("failed to write fee estimates", e)
 310  	}
 311  	e = binary.Write(w, binary.BigEndian, &ef.numBlocksRegistered)
 312  	if e != nil {
 313  		F.Ln("failed to write fee estimates", e)
 314  	}
 315  	// Put all the observed transactions in a sorted list.
 316  	var txCount uint32
 317  	ots := make([]*observedTransaction, len(ef.observed))
 318  	for hash := range ef.observed {
 319  		ots[txCount] = ef.observed[hash]
 320  		txCount++
 321  	}
 322  	sort.Sort(observedTxSet(ots))
 323  	txCount = 0
 324  	observed := make(map[*observedTransaction]uint32)
 325  	e = binary.Write(w, binary.BigEndian, uint32(len(ef.observed)))
 326  	if e != nil {
 327  		F.Ln("failed to write:", e)
 328  	}
 329  	for _, ot := range ots {
 330  		ot.Serialize(w)
 331  		observed[ot] = txCount
 332  		txCount++
 333  	}
 334  	// Save all the right bins.
 335  	for _, list := range ef.bin {
 336  		e = binary.Write(w, binary.BigEndian, uint32(len(list)))
 337  		if e != nil {
 338  			F.Ln("failed to write:", e)
 339  		}
 340  		for _, o := range list {
 341  			e = binary.Write(w, binary.BigEndian, observed[o])
 342  			if e != nil {
 343  				F.Ln("failed to write:", e)
 344  			}
 345  		}
 346  	}
 347  	// Dropped transactions.
 348  	e = binary.Write(w, binary.BigEndian, uint32(len(ef.dropped)))
 349  	if e != nil {
 350  		F.Ln("failed to write:", e)
 351  	}
 352  	for _, registered := range ef.dropped {
 353  		registered.serialize(w, observed)
 354  	}
 355  	// Commit the tx and return.
 356  	return w.Bytes()
 357  }
 358  
 359  // estimates returns the set of all fee estimates from 1 to estimateFeeDepth confirmations from now.
 360  func (ef *FeeEstimator) estimates() []SatoshiPerByte {
 361  	set := ef.newEstimateFeeSet()
 362  	estimates := make([]SatoshiPerByte, estimateFeeDepth)
 363  	for i := 0; i < estimateFeeDepth; i++ {
 364  		estimates[i] = set.estimateFee(i + 1)
 365  	}
 366  	return estimates
 367  }
 368  
 369  // newEstimateFeeSet creates a temporary data structure that can be used to find all fee estimates.
 370  func (ef *FeeEstimator) newEstimateFeeSet() *estimateFeeSet {
 371  	set := &estimateFeeSet{}
 372  	capacity := 0
 373  	for i, b := range ef.bin {
 374  		l := len(b)
 375  		set.bin[i] = uint32(l)
 376  		capacity += l
 377  	}
 378  	set.feeRate = make([]SatoshiPerByte, capacity)
 379  	i := 0
 380  	for _, b := range ef.bin {
 381  		for _, o := range b {
 382  			set.feeRate[i] = o.feeRate
 383  			i++
 384  		}
 385  	}
 386  	sort.Sort(set)
 387  	return set
 388  }
 389  
 390  // rollback rolls back the effect of the last block in the stack of registered blocks.
 391  func (ef *FeeEstimator) rollback() {
 392  	// The previous sorted list is invalid, so delete it.
 393  	ef.cached = nil
 394  	// pop the last list of dropped txs from the stack.
 395  	last := len(ef.dropped) - 1
 396  	if last == -1 {
 397  		// Cannot really happen because the exported calling function only rolls back a block already known to be in the
 398  		// list of dropped transactions.
 399  		return
 400  	}
 401  	dropped := ef.dropped[last]
 402  	// where we are in each bin as we replace txs?
 403  	var replacementCounters [estimateFeeDepth]int
 404  	// Go through the txs in the dropped block.
 405  	for _, o := range dropped.transactions {
 406  		// Which bin was this tx in?
 407  		blocksToConfirm := o.mined - o.observed - 1
 408  		bin := ef.bin[blocksToConfirm]
 409  		var counter = replacementCounters[blocksToConfirm]
 410  		// Continue to go through that bin where we left off.
 411  		for {
 412  			if counter >= len(bin) {
 413  				// Panic, as we have entered an unrecoverable invalid state.
 414  				panic(
 415  					errors.New(
 416  						"illegal state: cannot rollback dropped transaction",
 417  					),
 418  				)
 419  			}
 420  			prev := bin[counter]
 421  			if prev.mined == ef.lastKnownHeight {
 422  				prev.mined = mining.UnminedHeight
 423  				bin[counter] = o
 424  				counter++
 425  				break
 426  			}
 427  			counter++
 428  		}
 429  		replacementCounters[blocksToConfirm] = counter
 430  	}
 431  	// Continue going through bins to find other txs to remove which did not replace any other when they were entered.
 432  	for i, j := range replacementCounters {
 433  		for {
 434  			l := len(ef.bin[i])
 435  			if j >= l {
 436  				break
 437  			}
 438  			prev := ef.bin[i][j]
 439  			if prev.mined == ef.lastKnownHeight {
 440  				prev.mined = mining.UnminedHeight
 441  				newBin := append(ef.bin[i][0:j], ef.bin[i][j+1:l]...)
 442  				// TODO This line should prevent an unintentional memory leak
 443  				//  but it causes a panic when it is uncommented.
 444  				// ef.bin[i][j] = nil
 445  				ef.bin[i] = newBin
 446  				continue
 447  			}
 448  			j++
 449  		}
 450  	}
 451  	ef.dropped = ef.dropped[0:last]
 452  	// The number of blocks the fee estimator has seen is decremented.
 453  	ef.numBlocksRegistered--
 454  	ef.lastKnownHeight--
 455  }
 456  func (b *estimateFeeSet) Len() int           { return len(b.feeRate) }
 457  func (b *estimateFeeSet) Less(i, j int) bool { return b.feeRate[i] > b.feeRate[j] }
 458  func (b *estimateFeeSet) Swap(i, j int) {
 459  	b.feeRate[i], b.feeRate[j] = b.feeRate[j], b.feeRate[i]
 460  }
 461  
 462  // estimateFee returns the estimated fee for a transaction to confirm in confirmations blocks from now, given the data
 463  // set we have collected.
 464  func (b *estimateFeeSet) estimateFee(confirmations int) SatoshiPerByte {
 465  	if confirmations <= 0 {
 466  		return SatoshiPerByte(math.Inf(1))
 467  	}
 468  	if confirmations > estimateFeeDepth {
 469  		return 0
 470  	}
 471  	// We don't have any transactions!
 472  	if len(b.feeRate) == 0 {
 473  		return 0
 474  	}
 475  	var min, max int
 476  	for i := 0; i < confirmations-1; i++ {
 477  		min += int(b.bin[i])
 478  	}
 479  	max = min + int(b.bin[confirmations-1]) - 1
 480  	if max < min {
 481  		max = min
 482  	}
 483  	feeIndex := (min + max) / 2
 484  	if feeIndex >= len(b.feeRate) {
 485  		feeIndex = len(b.feeRate) - 1
 486  	}
 487  	return b.feeRate[feeIndex]
 488  }
 489  func (o *observedTransaction) Serialize(w io.Writer) {
 490  	e := binary.Write(w, binary.BigEndian, o.hash)
 491  	if e != nil {
 492  		F.Ln("failed to serialize observed transaction:", e)
 493  	}
 494  	e = binary.Write(w, binary.BigEndian, o.feeRate)
 495  	if e != nil {
 496  		F.Ln("failed to serialize observed transaction:", e)
 497  	}
 498  	e = binary.Write(w, binary.BigEndian, o.observed)
 499  	if e != nil {
 500  		F.Ln("failed to serialize observed transaction:", e)
 501  	}
 502  	e = binary.Write(w, binary.BigEndian, o.mined)
 503  	if e != nil {
 504  		F.Ln("failed to serialize observed transaction:", e)
 505  	}
 506  }
 507  
 508  func (rb *registeredBlock) serialize(
 509  	w io.Writer,
 510  	txs map[*observedTransaction]uint32,
 511  ) {
 512  	e := binary.Write(w, binary.BigEndian, rb.hash)
 513  	if e != nil {
 514  		F.Ln("failed to write:", e)
 515  	}
 516  	e = binary.Write(w, binary.BigEndian, uint32(len(rb.transactions)))
 517  	if e != nil {
 518  		F.Ln("failed to write:", e)
 519  	}
 520  	for _, o := range rb.transactions {
 521  		e = binary.Write(w, binary.BigEndian, txs[o])
 522  		if e != nil {
 523  			F.Ln("failed to write:", e)
 524  		}
 525  	}
 526  }
 527  
 528  // Fee returns the fee for a transaction of a given size for the given fee rate.
 529  func (rate SatoshiPerByte) Fee(size uint32) amt.Amount {
 530  	// If our rate is the error value, return that.
 531  	if rate == SatoshiPerByte(-1) {
 532  		return amt.Amount(-1)
 533  	}
 534  	return amt.Amount(float64(rate) * float64(size))
 535  }
 536  
 537  // ToBtcPerKb returns a float value that represents the given SatoshiPerByte converted to satoshis per kb.
 538  func (rate SatoshiPerByte) ToBtcPerKb() DUOPerKilobyte {
 539  	// If our rate is the error value, return that.
 540  	if rate == SatoshiPerByte(-1.0) {
 541  		return -1.0
 542  	}
 543  	return DUOPerKilobyte(float64(rate) * bytePerKb * duoPerSatoshi)
 544  }
 545  
 546  func (q observedTxSet) Len() int { return len(q) }
 547  func (q observedTxSet) Less(i, j int) bool {
 548  	return strings.Compare(q[i].hash.String(), q[j].hash.String()) < 0
 549  }
 550  func (q observedTxSet) Swap(i, j int) { q[i], q[j] = q[j], q[i] }
 551  
 552  // NewFeeEstimator creates a FeeEstimator for which at most maxRollback blocks can be unregistered and which returns an
 553  // error unless minRegisteredBlocks have been registered with it.
 554  func NewFeeEstimator(maxRollback, minRegisteredBlocks uint32) *FeeEstimator {
 555  	return &FeeEstimator{
 556  		maxRollback:         maxRollback,
 557  		minRegisteredBlocks: minRegisteredBlocks,
 558  		lastKnownHeight:     mining.UnminedHeight,
 559  		binSize:             estimateFeeBinSize,
 560  		maxReplacements:     estimateFeeMaxReplacements,
 561  		observed:            make(map[chainhash.Hash]*observedTransaction),
 562  		dropped:             make([]*registeredBlock, 0, maxRollback),
 563  	}
 564  }
 565  
 566  // NewSatoshiPerByte creates a SatoshiPerByte from an Amount and a size in bytes.
 567  func NewSatoshiPerByte(fee amt.Amount, size uint32) SatoshiPerByte {
 568  	return SatoshiPerByte(float64(fee) / float64(size))
 569  }
 570  
 571  // RestoreFeeEstimator takes a FeeEstimatorState that was previously returned by Save and restores it to a FeeEstimator
 572  func RestoreFeeEstimator(data FeeEstimatorState) (*FeeEstimator, error) {
 573  	r := bytes.NewReader(data)
 574  	// Chk version
 575  	var version uint32
 576  	e := binary.Read(r, binary.BigEndian, &version)
 577  	if e != nil {
 578  		return nil, e
 579  	}
 580  	if version != estimateFeeSaveVersion {
 581  		return nil, fmt.Errorf(
 582  			"incorrect version: expected %d found %d",
 583  			estimateFeeSaveVersion, version,
 584  		)
 585  	}
 586  	ef := &FeeEstimator{
 587  		observed: make(map[chainhash.Hash]*observedTransaction),
 588  	}
 589  	// Read basic parameters.
 590  	e = binary.Read(r, binary.BigEndian, &ef.maxRollback)
 591  	if e != nil {
 592  		F.Ln("failed to read", e)
 593  	}
 594  	e = binary.Read(r, binary.BigEndian, &ef.binSize)
 595  	if e != nil {
 596  		F.Ln("failed to read", e)
 597  	}
 598  	e = binary.Read(r, binary.BigEndian, &ef.maxReplacements)
 599  	if e != nil {
 600  		F.Ln("failed to read", e)
 601  	}
 602  	e = binary.Read(r, binary.BigEndian, &ef.minRegisteredBlocks)
 603  	if e != nil {
 604  		F.Ln("failed to read", e)
 605  	}
 606  	e = binary.Read(r, binary.BigEndian, &ef.lastKnownHeight)
 607  	if e != nil {
 608  		F.Ln("failed to read", e)
 609  	}
 610  	e = binary.Read(r, binary.BigEndian, &ef.numBlocksRegistered)
 611  	if e != nil {
 612  		F.Ln("failed to read", e)
 613  	}
 614  	// Read transactions.
 615  	var numObserved uint32
 616  	observed := make(map[uint32]*observedTransaction)
 617  	e = binary.Read(r, binary.BigEndian, &numObserved)
 618  	if e != nil {
 619  		F.Ln("failed to read", e)
 620  	}
 621  	for i := uint32(0); i < numObserved; i++ {
 622  		var ot *observedTransaction
 623  		ot, e = deserializeObservedTransaction(r)
 624  		if e != nil {
 625  			return nil, e
 626  		}
 627  		observed[i] = ot
 628  		ef.observed[ot.hash] = ot
 629  	}
 630  	// Read bins.
 631  	for i := 0; i < estimateFeeDepth; i++ {
 632  		var numTransactions uint32
 633  		e = binary.Read(r, binary.BigEndian, &numTransactions)
 634  		if e != nil {
 635  			F.Ln("failed to read", e)
 636  		}
 637  		bin := make([]*observedTransaction, numTransactions)
 638  		for j := uint32(0); j < numTransactions; j++ {
 639  			var index uint32
 640  			e = binary.Read(r, binary.BigEndian, &index)
 641  			if e != nil {
 642  				F.Ln("failed to read", e)
 643  			}
 644  			var exists bool
 645  			bin[j], exists = observed[index]
 646  			if !exists {
 647  				return nil, fmt.Errorf(
 648  					"invalid transaction reference %d",
 649  					index,
 650  				)
 651  			}
 652  		}
 653  		ef.bin[i] = bin
 654  	}
 655  	// Read dropped transactions.
 656  	var numDropped uint32
 657  	e = binary.Read(r, binary.BigEndian, &numDropped)
 658  	if e != nil {
 659  		F.Ln("failed to read", e)
 660  	}
 661  	ef.dropped = make([]*registeredBlock, numDropped)
 662  	for i := uint32(0); i < numDropped; i++ {
 663  		var e error
 664  		ef.dropped[int(i)], e = deserializeRegisteredBlock(r, observed)
 665  		if e != nil {
 666  			return nil, e
 667  		}
 668  	}
 669  	return ef, nil
 670  }
 671  func deserializeObservedTransaction(r io.Reader) (*observedTransaction, error) {
 672  	ot := observedTransaction{}
 673  	// The first 32 bytes should be a hash.
 674  	e := binary.Read(r, binary.BigEndian, &ot.hash)
 675  	if e != nil {
 676  		F.Ln("failed to read", e)
 677  	}
 678  	// The next 8 are SatoshiPerByte
 679  	e = binary.Read(r, binary.BigEndian, &ot.feeRate)
 680  	if e != nil {
 681  		F.Ln("failed to read", e)
 682  	}
 683  	// And next there are two uint32's.
 684  	e = binary.Read(r, binary.BigEndian, &ot.observed)
 685  	if e != nil {
 686  		F.Ln("failed to read", e)
 687  	}
 688  	e = binary.Read(r, binary.BigEndian, &ot.mined)
 689  	if e != nil {
 690  		F.Ln("failed to read", e)
 691  	}
 692  	return &ot, nil
 693  }
 694  func deserializeRegisteredBlock(
 695  	r io.Reader,
 696  	txs map[uint32]*observedTransaction,
 697  ) (*registeredBlock, error) {
 698  	var lenTransactions uint32
 699  	rb := &registeredBlock{}
 700  	e := binary.Read(r, binary.BigEndian, &rb.hash)
 701  	if e != nil {
 702  		F.Ln("failed to read", e)
 703  	}
 704  	e = binary.Read(r, binary.BigEndian, &lenTransactions)
 705  	if e != nil {
 706  		F.Ln("failed to read", e)
 707  	}
 708  	rb.transactions = make([]*observedTransaction, lenTransactions)
 709  	for i := uint32(0); i < lenTransactions; i++ {
 710  		var index uint32
 711  		e = binary.Read(r, binary.BigEndian, &index)
 712  		if e != nil {
 713  			F.Ln("failed to read", e)
 714  		}
 715  		rb.transactions[i] = txs[index]
 716  	}
 717  	return rb, nil
 718  }
 719