common.go raw

   1  // Package indexers implements optional block chain indexes.
   2  package index
   3  
   4  import (
   5  	"encoding/binary"
   6  	"errors"
   7  	"github.com/p9c/p9/pkg/block"
   8  	
   9  	"github.com/p9c/p9/pkg/blockchain"
  10  	"github.com/p9c/p9/pkg/database"
  11  )
  12  
  13  var (
  14  	// byteOrder is the preferred byte order used for serializing numeric fields for storage in the database.
  15  	byteOrder = binary.LittleEndian
  16  	// errInterruptRequested indicates that an operation was cancelled due to a user-requested interrupt.
  17  	errInterruptRequested = errors.New("interrupt requested")
  18  )
  19  
  20  // NeedsInputser provides a generic interface for an indexer to specify the it requires the ability to look up inputs
  21  // for a transaction.
  22  type NeedsInputser interface {
  23  	NeedsInputs() bool
  24  }
  25  
  26  // Indexer provides a generic interface for an indexer that is managed by an index manager such as the Manager type
  27  // provided by this package.
  28  type Indexer interface {
  29  	// Key returns the key of the index as a byte slice.
  30  	Key() []byte
  31  	// Name returns the human-readable name of the index.
  32  	Name() string
  33  	// Create is invoked when the indexer manager determines the index needs to be created for the first time.
  34  	Create(dbTx database.Tx) error
  35  	// Init is invoked when the index manager is first initializing the index. This differs from the Create method in
  36  	// that it is called on every load, including the case the index was just created.
  37  	Init() error
  38  	// ConnectBlock is invoked when a new block has been connected to the main chain. The set of output spent within a
  39  	// block is also passed in so indexers can access the pevious output scripts input spent if required.
  40  	ConnectBlock(database.Tx, *block.Block, []blockchain.SpentTxOut) error
  41  	// DisconnectBlock is invoked when a block has been disconnected from the main chain. The set of outputs scripts
  42  	// that were spent within this block is also returned so indexers can clean up the prior index state for this block
  43  	DisconnectBlock(database.Tx, *block.Block, []blockchain.SpentTxOut) error
  44  }
  45  
  46  // AssertError identifies an error that indicates an internal code consistency issue and should be treated as a critical
  47  // and unrecoverable error.
  48  type AssertError string
  49  
  50  // DBError returns the assertion error as a huma-readable string and satisfies the error interface.
  51  func (e AssertError) Error() string {
  52  	return "assertion failed: " + string(e)
  53  }
  54  
  55  // errDeserialize signifies that a problem was encountered when deserializing data.
  56  type errDeserialize string
  57  
  58  // DBError implements the error interface.
  59  func (e errDeserialize) Error() string {
  60  	return string(e)
  61  }
  62  
  63  // isDeserializeErr returns whether or not the passed error is an errDeserialize error.
  64  func isDeserializeErr(e error) bool {
  65  	_, ok := e.(errDeserialize)
  66  	return ok
  67  }
  68  
  69  // internalBucket is an abstraction over a database bucket. It is used to make the code easier to test since it allows
  70  // mock objects in the tests to only implement these functions instead of everything a database.Bucket supports.
  71  type internalBucket interface {
  72  	Get(key []byte) []byte
  73  	Put(key []byte, value []byte) error
  74  	Delete(key []byte) error
  75  }
  76  
  77  // interruptRequested returns true when the provided channel has been closed. This simplifies early shutdown slightly
  78  // since the caller can just use an if statement instead of a select.
  79  func interruptRequested(interrupted <-chan struct{}) bool {
  80  	select {
  81  	case <-interrupted:
  82  		return true
  83  	default:
  84  	}
  85  	return false
  86  }
  87