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