github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/types.go (about)

     1  package bchain
     2  
     3  import (
     4  	"context"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  
    11  	"github.com/trezor/blockbook/common"
    12  )
    13  
    14  // ChainType is type of the blockchain
    15  type ChainType int
    16  
    17  const (
    18  	// ChainBitcoinType is blockchain derived from bitcoin
    19  	ChainBitcoinType = ChainType(iota)
    20  	// ChainEthereumType is blockchain derived from ethereum
    21  	ChainEthereumType
    22  )
    23  
    24  // errors with specific meaning returned by blockchain rpc
    25  var (
    26  	// ErrBlockNotFound is returned when block is not found
    27  	// either unknown hash or too high height
    28  	// can be returned from GetBlockHash, GetBlockHeader, GetBlock
    29  	ErrBlockNotFound = errors.New("Block not found")
    30  	// ErrAddressMissing is returned if address is not specified
    31  	// for example To address in ethereum can be missing in case of contract transaction
    32  	ErrAddressMissing = errors.New("Address missing")
    33  	// ErrTxidMissing is returned if txid is not specified
    34  	// for example coinbase transactions in Bitcoin
    35  	ErrTxidMissing = errors.New("Txid missing")
    36  	// ErrTxNotFound is returned if transaction was not found
    37  	ErrTxNotFound = errors.New("Tx not found")
    38  )
    39  
    40  // Outpoint is txid together with output (or input) index
    41  type Outpoint struct {
    42  	Txid string
    43  	Vout int32
    44  }
    45  
    46  // ScriptSig contains data about input script
    47  type ScriptSig struct {
    48  	// Asm string `json:"asm"`
    49  	Hex string `json:"hex"`
    50  }
    51  
    52  // Vin contains data about tx input
    53  type Vin struct {
    54  	Coinbase  string    `json:"coinbase"`
    55  	Txid      string    `json:"txid"`
    56  	Vout      uint32    `json:"vout"`
    57  	ScriptSig ScriptSig `json:"scriptSig"`
    58  	Sequence  uint32    `json:"sequence"`
    59  	Addresses []string  `json:"addresses"`
    60  	Witness   [][]byte  `json:"-"`
    61  }
    62  
    63  // ScriptPubKey contains data about output script
    64  type ScriptPubKey struct {
    65  	// Asm       string   `json:"asm"`
    66  	Hex string `json:"hex,omitempty"`
    67  	// Type      string   `json:"type"`
    68  	Addresses []string `json:"addresses"`
    69  }
    70  
    71  // Vout contains data about tx output
    72  type Vout struct {
    73  	ValueSat     big.Int
    74  	JsonValue    common.JSONNumber `json:"value"`
    75  	N            uint32            `json:"n"`
    76  	ScriptPubKey ScriptPubKey      `json:"scriptPubKey"`
    77  }
    78  
    79  // Tx is blockchain transaction
    80  // unnecessary fields are commented out to avoid overhead
    81  type Tx struct {
    82  	Hex         string `json:"hex"`
    83  	Txid        string `json:"txid"`
    84  	Version     int32  `json:"version"`
    85  	LockTime    uint32 `json:"locktime"`
    86  	VSize       int64  `json:"vsize,omitempty"`
    87  	Vin         []Vin  `json:"vin"`
    88  	Vout        []Vout `json:"vout"`
    89  	BlockHeight uint32 `json:"blockHeight,omitempty"`
    90  	// BlockHash     string `json:"blockhash,omitempty"`
    91  	Confirmations    uint32      `json:"confirmations,omitempty"`
    92  	Time             int64       `json:"time,omitempty"`
    93  	Blocktime        int64       `json:"blocktime,omitempty"`
    94  	CoinSpecificData interface{} `json:"-"`
    95  }
    96  
    97  // MempoolVin contains data about tx input
    98  type MempoolVin struct {
    99  	Vin
   100  	AddrDesc AddressDescriptor `json:"-"`
   101  	ValueSat big.Int
   102  }
   103  
   104  // MempoolTx is blockchain transaction in mempool
   105  // optimized for onNewTx notification
   106  type MempoolTx struct {
   107  	Hex              string         `json:"hex"`
   108  	Txid             string         `json:"txid"`
   109  	Version          int32          `json:"version"`
   110  	LockTime         uint32         `json:"locktime"`
   111  	VSize            int64          `json:"vsize,omitempty"`
   112  	Vin              []MempoolVin   `json:"vin"`
   113  	Vout             []Vout         `json:"vout"`
   114  	Blocktime        int64          `json:"blocktime,omitempty"`
   115  	TokenTransfers   TokenTransfers `json:"-"`
   116  	CoinSpecificData interface{}    `json:"-"`
   117  }
   118  
   119  // TokenType - type of token
   120  type TokenType int
   121  
   122  // TokenType enumeration
   123  const (
   124  	FungibleToken    = TokenType(iota) // ERC20/BEP20
   125  	NonFungibleToken                   // ERC721/BEP721
   126  	MultiToken                         // ERC1155/BEP1155
   127  )
   128  
   129  // TokenTypeName specifies type of token
   130  type TokenTypeName string
   131  
   132  // Token types
   133  const (
   134  	UnknownTokenType TokenTypeName = ""
   135  
   136  	// XPUBAddressTokenType is address derived from xpub
   137  	XPUBAddressTokenType TokenTypeName = "XPUBAddress"
   138  )
   139  
   140  // TokenTransfers is array of TokenTransfer
   141  type TokenTransfers []*TokenTransfer
   142  
   143  func (a TokenTransfers) Len() int      { return len(a) }
   144  func (a TokenTransfers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
   145  func (a TokenTransfers) Less(i, j int) bool {
   146  	return a[i].Type < a[j].Type
   147  }
   148  
   149  // Block is block header and list of transactions
   150  type Block struct {
   151  	BlockHeader
   152  	Txs              []Tx        `json:"tx"`
   153  	CoinSpecificData interface{} `json:"-"`
   154  }
   155  
   156  // BlockHeader contains limited data (as needed for indexing) from backend block header
   157  type BlockHeader struct {
   158  	Hash          string `json:"hash"`
   159  	Prev          string `json:"previousblockhash"`
   160  	Next          string `json:"nextblockhash"`
   161  	Height        uint32 `json:"height"`
   162  	Confirmations int    `json:"confirmations"`
   163  	Size          int    `json:"size"`
   164  	Time          int64  `json:"time,omitempty"`
   165  }
   166  
   167  // BlockInfo contains extended block header data and a list of block txids
   168  type BlockInfo struct {
   169  	BlockHeader
   170  	Version    common.JSONNumber `json:"version"`
   171  	MerkleRoot string            `json:"merkleroot"`
   172  	Nonce      common.JSONNumber `json:"nonce"`
   173  	Bits       string            `json:"bits"`
   174  	Difficulty common.JSONNumber `json:"difficulty"`
   175  	Txids      []string          `json:"tx,omitempty"`
   176  }
   177  
   178  // MempoolEntry is used to get data about mempool entry
   179  type MempoolEntry struct {
   180  	Size            uint32 `json:"size"`
   181  	FeeSat          big.Int
   182  	Fee             common.JSONNumber `json:"fee"`
   183  	ModifiedFeeSat  big.Int
   184  	ModifiedFee     common.JSONNumber `json:"modifiedfee"`
   185  	Time            uint64            `json:"time"`
   186  	Height          uint32            `json:"height"`
   187  	DescendantCount uint32            `json:"descendantcount"`
   188  	DescendantSize  uint32            `json:"descendantsize"`
   189  	DescendantFees  uint32            `json:"descendantfees"`
   190  	AncestorCount   uint32            `json:"ancestorcount"`
   191  	AncestorSize    uint32            `json:"ancestorsize"`
   192  	AncestorFees    uint32            `json:"ancestorfees"`
   193  	Depends         []string          `json:"depends"`
   194  }
   195  
   196  // ChainInfo is used to get information about blockchain
   197  type ChainInfo struct {
   198  	Chain            string      `json:"chain"`
   199  	Blocks           int         `json:"blocks"`
   200  	Headers          int         `json:"headers"`
   201  	Bestblockhash    string      `json:"bestblockhash"`
   202  	Difficulty       string      `json:"difficulty"`
   203  	SizeOnDisk       int64       `json:"size_on_disk"`
   204  	Version          string      `json:"version"`
   205  	Subversion       string      `json:"subversion"`
   206  	ProtocolVersion  string      `json:"protocolversion"`
   207  	Timeoffset       float64     `json:"timeoffset"`
   208  	Warnings         string      `json:"warnings"`
   209  	ConsensusVersion string      `json:"consensus_version,omitempty"`
   210  	Consensus        interface{} `json:"consensus,omitempty"`
   211  }
   212  
   213  // RPCError defines rpc error returned by backend
   214  type RPCError struct {
   215  	Code    int    `json:"code"`
   216  	Message string `json:"message"`
   217  }
   218  
   219  func (e *RPCError) Error() string {
   220  	return fmt.Sprintf("%d: %s", e.Code, e.Message)
   221  }
   222  
   223  // AddressDescriptor is an opaque type obtained by parser.GetAddrDesc* methods
   224  type AddressDescriptor []byte
   225  
   226  func (ad AddressDescriptor) String() string {
   227  	return "ad:" + hex.EncodeToString(ad)
   228  }
   229  
   230  func (ad AddressDescriptor) IsTaproot() bool {
   231  	if len(ad) == 34 && ad[0] == 0x51 && ad[1] == 0x20 {
   232  		return true
   233  	}
   234  	return false
   235  }
   236  
   237  // AddressDescriptorFromString converts string created by AddressDescriptor.String to AddressDescriptor
   238  func AddressDescriptorFromString(s string) (AddressDescriptor, error) {
   239  	if len(s) > 3 && s[0:3] == "ad:" {
   240  		return hex.DecodeString(s[3:])
   241  	}
   242  	return nil, errors.New("invalid address descriptor")
   243  }
   244  
   245  // MempoolTxidEntry contains mempool txid with first seen time
   246  type MempoolTxidEntry struct {
   247  	Txid string
   248  	Time uint32
   249  }
   250  
   251  // ScriptType - type of output script parsed from xpub (descriptor)
   252  type ScriptType int
   253  
   254  // ScriptType enumeration
   255  const (
   256  	P2PK = ScriptType(iota)
   257  	P2PKH
   258  	P2SHWPKH
   259  	P2WPKH
   260  	P2TR
   261  )
   262  
   263  // XpubDescriptor contains parsed data from xpub descriptor
   264  type XpubDescriptor struct {
   265  	XpubDescriptor string // The whole descriptor
   266  	Xpub           string // Xpub part of the descriptor
   267  	Type           ScriptType
   268  	Bip            string
   269  	ChangeIndexes  []uint32
   270  	ExtKey         interface{} // extended key parsed from xpub, usually of type *hdkeychain.ExtendedKey
   271  }
   272  
   273  // MempoolTxidEntries is array of MempoolTxidEntry
   274  type MempoolTxidEntries []MempoolTxidEntry
   275  
   276  // MempoolTxidFilterEntries is a map of txids to mempool golomb filters
   277  // Also contains a flag whether constant zeroed key was used when calculating the filters
   278  type MempoolTxidFilterEntries struct {
   279  	Entries       map[string]string `json:"entries,omitempty"`
   280  	UsedZeroedKey bool              `json:"usedZeroedKey,omitempty"`
   281  }
   282  
   283  // OnNewBlockFunc is used to send notification about a new block
   284  type OnNewBlockFunc func(hash string, height uint32)
   285  
   286  // OnNewTxAddrFunc is used to send notification about a new transaction/address
   287  type OnNewTxAddrFunc func(tx *Tx, desc AddressDescriptor)
   288  
   289  // OnNewTxFunc is used to send notification about a new transaction/address
   290  type OnNewTxFunc func(tx *MempoolTx)
   291  
   292  // AddrDescForOutpointFunc returns address descriptor and value for given outpoint or nil if outpoint not found
   293  type AddrDescForOutpointFunc func(outpoint Outpoint) (AddressDescriptor, *big.Int)
   294  
   295  // BlockChain defines common interface to block chain daemon
   296  type BlockChain interface {
   297  	// life-cycle methods
   298  	// initialize the block chain connector
   299  	Initialize() error
   300  	// create mempool but do not initialize it
   301  	CreateMempool(BlockChain) (Mempool, error)
   302  	// initialize mempool, create ZeroMQ (or other) subscription
   303  	InitializeMempool(AddrDescForOutpointFunc, OnNewTxAddrFunc, OnNewTxFunc) error
   304  	// shutdown mempool, ZeroMQ and block chain connections
   305  	Shutdown(ctx context.Context) error
   306  	// chain info
   307  	IsTestnet() bool
   308  	GetNetworkName() string
   309  	GetSubversion() string
   310  	GetCoinName() string
   311  	GetChainInfo() (*ChainInfo, error)
   312  	// requests
   313  	GetBestBlockHash() (string, error)
   314  	GetBestBlockHeight() (uint32, error)
   315  	GetBlockHash(height uint32) (string, error)
   316  	GetBlockHeader(hash string) (*BlockHeader, error)
   317  	GetBlock(hash string, height uint32) (*Block, error)
   318  	GetBlockInfo(hash string) (*BlockInfo, error)
   319  	GetBlockRaw(hash string) (string, error)
   320  	GetMempoolTransactions() ([]string, error)
   321  	GetTransaction(txid string) (*Tx, error)
   322  	GetTransactionForMempool(txid string) (*Tx, error)
   323  	GetTransactionSpecific(tx *Tx) (json.RawMessage, error)
   324  	EstimateSmartFee(blocks int, conservative bool) (big.Int, error)
   325  	EstimateFee(blocks int) (big.Int, error)
   326  	SendRawTransaction(tx string) (string, error)
   327  	GetMempoolEntry(txid string) (*MempoolEntry, error)
   328  	GetContractInfo(contractDesc AddressDescriptor) (*ContractInfo, error)
   329  	// parser
   330  	GetChainParser() BlockChainParser
   331  	// EthereumType specific
   332  	EthereumTypeGetBalance(addrDesc AddressDescriptor) (*big.Int, error)
   333  	EthereumTypeGetNonce(addrDesc AddressDescriptor) (uint64, error)
   334  	EthereumTypeEstimateGas(params map[string]interface{}) (uint64, error)
   335  	EthereumTypeGetErc20ContractBalance(addrDesc, contractDesc AddressDescriptor) (*big.Int, error)
   336  	EthereumTypeGetSupportedStakingPools() []string
   337  	EthereumTypeGetStakingPoolsData(addrDesc AddressDescriptor) ([]StakingPoolData, error)
   338  	GetTokenURI(contractDesc AddressDescriptor, tokenID *big.Int) (string, error)
   339  }
   340  
   341  // BlockChainParser defines common interface to parsing and conversions of block chain data
   342  type BlockChainParser interface {
   343  	// type of the blockchain
   344  	GetChainType() ChainType
   345  	// KeepBlockAddresses returns number of blocks which are to be kept in blockTxs column
   346  	// to be used for rollbacks
   347  	KeepBlockAddresses() int
   348  	// AmountDecimals returns number of decimal places in coin amounts
   349  	AmountDecimals() int
   350  	// UseAddressAliases returns true if address aliases are enabled
   351  	UseAddressAliases() bool
   352  	// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
   353  	MinimumCoinbaseConfirmations() int
   354  	// SupportsVSize returns true if vsize of a transaction should be computed and returned by API
   355  	SupportsVSize() bool
   356  	// AmountToDecimalString converts amount in big.Int to string with decimal point in the correct place
   357  	AmountToDecimalString(a *big.Int) string
   358  	// AmountToBigInt converts amount in common.JSONNumber (string) to big.Int
   359  	// it uses string operations to avoid problems with rounding
   360  	AmountToBigInt(n common.JSONNumber) (big.Int, error)
   361  	// address descriptor conversions
   362  	GetAddrDescFromVout(output *Vout) (AddressDescriptor, error)
   363  	GetAddrDescFromAddress(address string) (AddressDescriptor, error)
   364  	GetAddressesFromAddrDesc(addrDesc AddressDescriptor) ([]string, bool, error)
   365  	GetScriptFromAddrDesc(addrDesc AddressDescriptor) ([]byte, error)
   366  	IsAddrDescIndexable(addrDesc AddressDescriptor) bool
   367  	// transactions
   368  	PackedTxidLen() int
   369  	PackTxid(txid string) ([]byte, error)
   370  	UnpackTxid(buf []byte) (string, error)
   371  	ParseTx(b []byte) (*Tx, error)
   372  	ParseTxFromJson(json.RawMessage) (*Tx, error)
   373  	PackTx(tx *Tx, height uint32, blockTime int64) ([]byte, error)
   374  	UnpackTx(buf []byte) (*Tx, uint32, error)
   375  	GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescriptor
   376  	// blocks
   377  	PackBlockHash(hash string) ([]byte, error)
   378  	UnpackBlockHash(buf []byte) (string, error)
   379  	ParseBlock(b []byte) (*Block, error)
   380  	// xpub
   381  	ParseXpub(xpub string) (*XpubDescriptor, error)
   382  	DerivationBasePath(descriptor *XpubDescriptor) (string, error)
   383  	DeriveAddressDescriptors(descriptor *XpubDescriptor, change uint32, indexes []uint32) ([]AddressDescriptor, error)
   384  	DeriveAddressDescriptorsFromTo(descriptor *XpubDescriptor, change uint32, fromIndex uint32, toIndex uint32) ([]AddressDescriptor, error)
   385  	// EthereumType specific
   386  	EthereumTypeGetTokenTransfersFromTx(tx *Tx) (TokenTransfers, error)
   387  	// AddressAlias
   388  	FormatAddressAlias(address string, name string) string
   389  }
   390  
   391  // Mempool defines common interface to mempool
   392  type Mempool interface {
   393  	Resync() (int, error)
   394  	GetTransactions(address string) ([]Outpoint, error)
   395  	GetAddrDescTransactions(addrDesc AddressDescriptor) ([]Outpoint, error)
   396  	GetAllEntries() MempoolTxidEntries
   397  	GetTransactionTime(txid string) uint32
   398  	GetTxidFilterEntries(filterScripts string, fromTimestamp uint32) (MempoolTxidFilterEntries, error)
   399  }