bitcoin

package
v0.0.0-...-bcfd2cf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 10, 2023 License: GPL-3.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const FileKey = "file"

FileKey key for kv stored parsed files counter

Variables

View Source
var (
	// ErrEmptySliceParse cannot parse block from empty slice error
	ErrEmptySliceParse = errors.New("cannot parse block from empty slice")

	// ErrIncompleteBlockParse cannot parse block due to incomplete file error
	ErrIncompleteBlockParse = errors.New("cannot parse incomplete block")

	// ErrBlockParse cannot parse block error
	ErrBlockParse = errors.New("cannot parse block")

	// ErrBlockFromBytes cannot generate block from matched bytes error
	ErrBlockFromBytes = errors.New("cannot generate block from matched bytes")

	// ErrMagicBytesMatching cannot match magic bytes
	ErrMagicBytesMatching = errors.New("cannot match magic bytes")
)
View Source
var (
	// ErrInterrupt interrupt signal error
	ErrInterrupt = errors.New("parser input signal error")

	// ErrInterruptUnknown interrupt signal error
	ErrInterruptUnknown = errors.New("parser input signal unknown error")
)
View Source
var (
	// ErrExceededSize skipped blocks size error
	ErrExceededSize = errors.New("exceed skipped blocks size")

	// ErrCheckpointNotFound checkpoint not found error
	ErrCheckpointNotFound = fmt.Errorf("checkpoint %w", errorx.ErrNotFound)

	// ErrNoBitcoinData returned if no bitcoin data to read from
	ErrNoBitcoinData = errors.New("missing bitcoin data")
)
View Source
var Block100000 = wire.MsgBlock{
	Header: wire.BlockHeader{
		Version: 1,
		PrevBlock: chainhash.Hash([32]byte{
			0x50, 0x12, 0x01, 0x19, 0x17, 0x2a, 0x61, 0x04,
			0x21, 0xa6, 0xc3, 0x01, 0x1d, 0xd3, 0x30, 0xd9,
			0xdf, 0x07, 0xb6, 0x36, 0x16, 0xc2, 0xcc, 0x1f,
			0x1c, 0xd0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
		}),
		MerkleRoot: chainhash.Hash([32]byte{
			0x66, 0x57, 0xa9, 0x25, 0x2a, 0xac, 0xd5, 0xc0,
			0xb2, 0x94, 0x09, 0x96, 0xec, 0xff, 0x95, 0x22,
			0x28, 0xc3, 0x06, 0x7c, 0xc3, 0x8d, 0x48, 0x85,
			0xef, 0xb5, 0xa4, 0xac, 0x42, 0x47, 0xe9, 0xf3,
		}),
		Timestamp: time.Unix(1293623863, 0),
		Bits:      0x1b04864c,
		Nonce:     0x10572b0f,
	},
	Transactions: []*wire.MsgTx{
		{
			Version: 1,
			TxIn: []*wire.TxIn{
				{
					PreviousOutPoint: wire.OutPoint{
						Hash:  chainhash.Hash{},
						Index: 0xffffffff,
					},
					SignatureScript: []byte{
						0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02,
					},
					Sequence: 0xffffffff,
				},
			},
			TxOut: []*wire.TxOut{
				{
					Value: 0x12a05f200,
					PkScript: []byte{
						0x41,
						0x04, 0x1b, 0x0e, 0x8c, 0x25, 0x67, 0xc1, 0x25,
						0x36, 0xaa, 0x13, 0x35, 0x7b, 0x79, 0xa0, 0x73,
						0xdc, 0x44, 0x44, 0xac, 0xb8, 0x3c, 0x4e, 0xc7,
						0xa0, 0xe2, 0xf9, 0x9d, 0xd7, 0x45, 0x75, 0x16,
						0xc5, 0x81, 0x72, 0x42, 0xda, 0x79, 0x69, 0x24,
						0xca, 0x4e, 0x99, 0x94, 0x7d, 0x08, 0x7f, 0xed,
						0xf9, 0xce, 0x46, 0x7c, 0xb9, 0xf7, 0xc6, 0x28,
						0x70, 0x78, 0xf8, 0x01, 0xdf, 0x27, 0x6f, 0xdf,
						0x84,
						0xac,
					},
				},
			},
			LockTime: 0,
		},
		{
			Version: 1,
			TxIn: []*wire.TxIn{
				{
					PreviousOutPoint: wire.OutPoint{
						Hash: chainhash.Hash([32]byte{
							0x03, 0x2e, 0x38, 0xe9, 0xc0, 0xa8, 0x4c, 0x60,
							0x46, 0xd6, 0x87, 0xd1, 0x05, 0x56, 0xdc, 0xac,
							0xc4, 0x1d, 0x27, 0x5e, 0xc5, 0x5f, 0xc0, 0x07,
							0x79, 0xac, 0x88, 0xfd, 0xf3, 0x57, 0xa1, 0x87,
						}),
						Index: 0,
					},
					SignatureScript: []byte{
						0x49,
						0x30, 0x46, 0x02, 0x21, 0x00, 0xc3, 0x52, 0xd3,
						0xdd, 0x99, 0x3a, 0x98, 0x1b, 0xeb, 0xa4, 0xa6,
						0x3a, 0xd1, 0x5c, 0x20, 0x92, 0x75, 0xca, 0x94,
						0x70, 0xab, 0xfc, 0xd5, 0x7d, 0xa9, 0x3b, 0x58,
						0xe4, 0xeb, 0x5d, 0xce, 0x82, 0x02, 0x21, 0x00,
						0x84, 0x07, 0x92, 0xbc, 0x1f, 0x45, 0x60, 0x62,
						0x81, 0x9f, 0x15, 0xd3, 0x3e, 0xe7, 0x05, 0x5c,
						0xf7, 0xb5, 0xee, 0x1a, 0xf1, 0xeb, 0xcc, 0x60,
						0x28, 0xd9, 0xcd, 0xb1, 0xc3, 0xaf, 0x77, 0x48,
						0x01,
						0x41,
						0x04, 0xf4, 0x6d, 0xb5, 0xe9, 0xd6, 0x1a, 0x9d,
						0xc2, 0x7b, 0x8d, 0x64, 0xad, 0x23, 0xe7, 0x38,
						0x3a, 0x4e, 0x6c, 0xa1, 0x64, 0x59, 0x3c, 0x25,
						0x27, 0xc0, 0x38, 0xc0, 0x85, 0x7e, 0xb6, 0x7e,
						0xe8, 0xe8, 0x25, 0xdc, 0xa6, 0x50, 0x46, 0xb8,
						0x2c, 0x93, 0x31, 0x58, 0x6c, 0x82, 0xe0, 0xfd,
						0x1f, 0x63, 0x3f, 0x25, 0xf8, 0x7c, 0x16, 0x1b,
						0xc6, 0xf8, 0xa6, 0x30, 0x12, 0x1d, 0xf2, 0xb3,
						0xd3,
					},
					Sequence: 0xffffffff,
				},
			},
			TxOut: []*wire.TxOut{
				{
					Value: 0x2123e300,
					PkScript: []byte{
						0x76,
						0xa9,
						0x14,
						0xc3, 0x98, 0xef, 0xa9, 0xc3, 0x92, 0xba, 0x60,
						0x13, 0xc5, 0xe0, 0x4e, 0xe7, 0x29, 0x75, 0x5e,
						0xf7, 0xf5, 0x8b, 0x32,
						0x88,
						0xac,
					},
				},
				{
					Value: 0x108e20f00,
					PkScript: []byte{
						0x76,
						0xa9,
						0x14,
						0x94, 0x8c, 0x76, 0x5a, 0x69, 0x14, 0xd4, 0x3f,
						0x2a, 0x7a, 0xc1, 0x77, 0xda, 0x2c, 0x2f, 0x6b,
						0x52, 0xde, 0x3d, 0x7c,
						0x88,
						0xac,
					},
				},
			},
			LockTime: 0,
		},
		{
			Version: 1,
			TxIn: []*wire.TxIn{
				{
					PreviousOutPoint: wire.OutPoint{
						Hash: chainhash.Hash([32]byte{
							0xc3, 0x3e, 0xbf, 0xf2, 0xa7, 0x09, 0xf1, 0x3d,
							0x9f, 0x9a, 0x75, 0x69, 0xab, 0x16, 0xa3, 0x27,
							0x86, 0xaf, 0x7d, 0x7e, 0x2d, 0xe0, 0x92, 0x65,
							0xe4, 0x1c, 0x61, 0xd0, 0x78, 0x29, 0x4e, 0xcf,
						}),
						Index: 1,
					},
					SignatureScript: []byte{
						0x47,
						0x30, 0x44, 0x02, 0x20, 0x03, 0x2d, 0x30, 0xdf,
						0x5e, 0xe6, 0xf5, 0x7f, 0xa4, 0x6c, 0xdd, 0xb5,
						0xeb, 0x8d, 0x0d, 0x9f, 0xe8, 0xde, 0x6b, 0x34,
						0x2d, 0x27, 0x94, 0x2a, 0xe9, 0x0a, 0x32, 0x31,
						0xe0, 0xba, 0x33, 0x3e, 0x02, 0x20, 0x3d, 0xee,
						0xe8, 0x06, 0x0f, 0xdc, 0x70, 0x23, 0x0a, 0x7f,
						0x5b, 0x4a, 0xd7, 0xd7, 0xbc, 0x3e, 0x62, 0x8c,
						0xbe, 0x21, 0x9a, 0x88, 0x6b, 0x84, 0x26, 0x9e,
						0xae, 0xb8, 0x1e, 0x26, 0xb4, 0xfe, 0x01,
						0x41,
						0x04, 0xae, 0x31, 0xc3, 0x1b, 0xf9, 0x12, 0x78,
						0xd9, 0x9b, 0x83, 0x77, 0xa3, 0x5b, 0xbc, 0xe5,
						0xb2, 0x7d, 0x9f, 0xff, 0x15, 0x45, 0x68, 0x39,
						0xe9, 0x19, 0x45, 0x3f, 0xc7, 0xb3, 0xf7, 0x21,
						0xf0, 0xba, 0x40, 0x3f, 0xf9, 0x6c, 0x9d, 0xee,
						0xb6, 0x80, 0xe5, 0xfd, 0x34, 0x1c, 0x0f, 0xc3,
						0xa7, 0xb9, 0x0d, 0xa4, 0x63, 0x1e, 0xe3, 0x95,
						0x60, 0x63, 0x9d, 0xb4, 0x62, 0xe9, 0xcb, 0x85,
						0x0f,
					},
					Sequence: 0xffffffff,
				},
			},
			TxOut: []*wire.TxOut{
				{
					Value: 0xf4240,
					PkScript: []byte{
						0x76,
						0xa9,
						0x14,
						0xb0, 0xdc, 0xbf, 0x97, 0xea, 0xbf, 0x44, 0x04,
						0xe3, 0x1d, 0x95, 0x24, 0x77, 0xce, 0x82, 0x2d,
						0xad, 0xbe, 0x7e, 0x10,
						0x88,
						0xac,
					},
				},
				{
					Value: 0x11d260c0,
					PkScript: []byte{
						0x76,
						0xa9,
						0x14,
						0x6b, 0x12, 0x81, 0xee, 0xc2, 0x5a, 0xb4, 0xe1,
						0xe0, 0x79, 0x3f, 0xf4, 0xe0, 0x8a, 0xb1, 0xab,
						0xb3, 0x40, 0x9c, 0xd9,
						0x88,
						0xac,
					},
				},
			},
			LockTime: 0,
		},
		{
			Version: 1,
			TxIn: []*wire.TxIn{
				{
					PreviousOutPoint: wire.OutPoint{
						Hash: chainhash.Hash([32]byte{
							0x0b, 0x60, 0x72, 0xb3, 0x86, 0xd4, 0xa7, 0x73,
							0x23, 0x52, 0x37, 0xf6, 0x4c, 0x11, 0x26, 0xac,
							0x3b, 0x24, 0x0c, 0x84, 0xb9, 0x17, 0xa3, 0x90,
							0x9b, 0xa1, 0xc4, 0x3d, 0xed, 0x5f, 0x51, 0xf4,
						}),
						Index: 0,
					},
					SignatureScript: []byte{
						0x49,
						0x30, 0x46, 0x02, 0x21, 0x00, 0xbb, 0x1a, 0xd2,
						0x6d, 0xf9, 0x30, 0xa5, 0x1c, 0xce, 0x11, 0x0c,
						0xf4, 0x4f, 0x7a, 0x48, 0xc3, 0xc5, 0x61, 0xfd,
						0x97, 0x75, 0x00, 0xb1, 0xae, 0x5d, 0x6b, 0x6f,
						0xd1, 0x3d, 0x0b, 0x3f, 0x4a, 0x02, 0x21, 0x00,
						0xc5, 0xb4, 0x29, 0x51, 0xac, 0xed, 0xff, 0x14,
						0xab, 0xba, 0x27, 0x36, 0xfd, 0x57, 0x4b, 0xdb,
						0x46, 0x5f, 0x3e, 0x6f, 0x8d, 0xa1, 0x2e, 0x2c,
						0x53, 0x03, 0x95, 0x4a, 0xca, 0x7f, 0x78, 0xf3,
						0x01,
						0x41,
						0x04, 0xa7, 0x13, 0x5b, 0xfe, 0x82, 0x4c, 0x97,
						0xec, 0xc0, 0x1e, 0xc7, 0xd7, 0xe3, 0x36, 0x18,
						0x5c, 0x81, 0xe2, 0xaa, 0x2c, 0x41, 0xab, 0x17,
						0x54, 0x07, 0xc0, 0x94, 0x84, 0xce, 0x96, 0x94,
						0xb4, 0x49, 0x53, 0xfc, 0xb7, 0x51, 0x20, 0x65,
						0x64, 0xa9, 0xc2, 0x4d, 0xd0, 0x94, 0xd4, 0x2f,
						0xdb, 0xfd, 0xd5, 0xaa, 0xd3, 0xe0, 0x63, 0xce,
						0x6a, 0xf4, 0xcf, 0xaa, 0xea, 0x4e, 0xa1, 0x4f,
						0xbb,
					},
					Sequence: 0xffffffff,
				},
			},
			TxOut: []*wire.TxOut{
				{
					Value: 0xf4240,
					PkScript: []byte{
						0x76,
						0xa9,
						0x14,
						0x39, 0xaa, 0x3d, 0x56, 0x9e, 0x06, 0xa1, 0xd7,
						0x92, 0x6d, 0xc4, 0xbe, 0x11, 0x93, 0xc9, 0x9b,
						0xf2, 0xeb, 0x9e, 0xe0,
						0x88,
						0xac,
					},
				},
			},
			LockTime: 0,
		},
	},
}

Block100000 defines block 100,000 of the block chain. It is used to test Block operations.

View Source
var Block181Bytes = []byte{}/* 490 elements not displayed */

Block181Bytes defines block 181 of the block chain (was helpful with my dataset). It is used to test Block operations.

View Source
var BlockOne = wire.MsgBlock{
	Header: wire.BlockHeader{
		Version: 1,
		PrevBlock: chainhash.Hash([chainhash.HashSize]byte{
			0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72,
			0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f,
			0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
			0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
		}),
		MerkleRoot: chainhash.Hash([chainhash.HashSize]byte{
			0x98, 0x20, 0x51, 0xfd, 0x1e, 0x4b, 0xa7, 0x44,
			0xbb, 0xbe, 0x68, 0x0e, 0x1f, 0xee, 0x14, 0x67,
			0x7b, 0xa1, 0xa3, 0xc3, 0x54, 0x0b, 0xf7, 0xb1,
			0xcd, 0xb6, 0x06, 0xe8, 0x57, 0x23, 0x3e, 0x0e,
		}),

		Timestamp: time.Unix(0x4966bc61, 0),
		Bits:      0x1d00ffff,
		Nonce:     0x9962e301,
	},
	Transactions: []*wire.MsgTx{
		{
			Version: 1,
			TxIn: []*wire.TxIn{
				{
					PreviousOutPoint: wire.OutPoint{
						Hash:  chainhash.Hash{},
						Index: 0xffffffff,
					},
					SignatureScript: []byte{
						0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04,
					},
					Sequence: 0xffffffff,
				},
			},
			TxOut: []*wire.TxOut{
				{
					Value: 0x12a05f200,
					PkScript: []byte{
						0x41,
						0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c,
						0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16,
						0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c,
						0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c,
						0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4,
						0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6,
						0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e,
						0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58,
						0xee,
						0xac,
					},
				},
			},
			LockTime: 0,
		},
	},
}

BlockOne is the first block in the mainnet blockchain.

View Source
var BlockOneBytes = []byte{}/* 215 elements not displayed */

BlockOneBytes one serialized bytes.

Functions

func ClientConfig

func ClientConfig() *rpcclient.ConnConfig

ClientConfig returns bitcoin client config object

func CoinbaseValue

func CoinbaseValue(height int32) int64

CoinbaseValue returns the value the block should receive from a coinbase transaction based on number of halving happened due to block height

func GetFileParsed

func GetFileParsed(db kv.DB) (file int, err error)

GetFileParsed returnes the file parsed so far

func Itoa

func Itoa(n int32) string

Itoa utility function to convert height (int32) to string to easily print it

func NewClient

func NewClient() (*rpcclient.Client, error)

NewClient returns new instance of bitcoin client

func PrepareTransactions

func PrepareTransactions(db kv.DB, txs []*btcutil.Tx) (transactions []tx.Tx, err error)

PrepareTransactions parses the btcutil.TX array of structs and convert them in Transaction object compatible with dgraph schema TODO: here I have to provide a solution in case the parsed block contains transactions which spend each other, e.g a transaction has inputs spending output from a tx in the same block. In this case utxo are not found and txin is not prepared. To fix this I have to define the id of the transaction with interested output and link the culprit inputs through that it. The approach are two: 1) my current solution starts from the assumption that this situation is uncommon, so is better to handle it just in those uncommon cases 2) if this situation is more common than I though, well is better to check this condition before to start parsing the tx, so I'll refactor

func StoreFileParsed

func StoreFileParsed(db kv.DB, file int) (err error)

StoreFileParsed set file stored so far

Types

type Block

type Block struct {
	btcutil.Block
}

Block composition to enhance btcutil.Block with other receivers

func ExtractBlockFromFile

func ExtractBlockFromFile(file *[]uint8) (blk *Block, err error)

ExtractBlockFromFile reads and remove magic bytes and size from file and returns Block through btcutil.NewBlockFromBytes

func (*Block) CheckBlock

func (b *Block) CheckBlock() bool

CheckBlock checks if block is correctly initialized just checking hash and height fields have some value

func (*Block) Store

func (b *Block) Store(db kv.DB, height int32) (err error)

Store prepares the block struct and and call StoreBlock to store it

type Blockchain

type Blockchain struct {
	Maps    []mmap.MMap
	Network chaincfg.Params
	// contains filtered or unexported fields
}

Blockchain data structure composed by the memory mapped files in array of mmaps and network conofiguration

func NewBlockchain

func NewBlockchain(db kv.DB, network chaincfg.Params) *Blockchain

NewBlockchain singleton pattern return always the same instance of blockchain. In the first time initializes the blockchain

func (*Blockchain) Head

func (b *Blockchain) Head() (last block.Block, err error)

Head returns the last block in the blockchain

func (*Blockchain) Height

func (b *Blockchain) Height() (h int32, err error)

Height returns the height of the last block in the blockchain (currently synced)

func (*Blockchain) Read

func (b *Blockchain) Read(path string, from int) error

type CheckPoint

type CheckPoint struct {
	// contains filtered or unexported fields
}

CheckPoint represents the last parse state

func ParseFile

func ParseFile(p *Parser, c CheckPoint, file *[]uint8) (check CheckPoint, err error)

ParseFile walks through the raw file and extract blocks

type InputParser

type InputParser struct {
	Index  int
	Input  *wire.TxIn
	Inputs []tx.Input
}

InputParser worker wrapper for parsing inputs in sync pool

func (*InputParser) Work

func (w *InputParser) Work() (err error)

Work interface to execute input parser worker operations

type OutputParser

type OutputParser struct {
	Index   int
	Output  *wire.TxOut
	TxHash  string
	Outputs []tx.Output
}

OutputParser worker wrapper for parsing inputs in sync pool

func (*OutputParser) Work

func (w *OutputParser) Work() (err error)

Work interface to execute output parser worker operations

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser defines the objects involved in the parsing of Bitcoin blockchain The involved objects include the parsed structure, the kind of parser, storage instances and some channel to manage the state of the parsing session

func NewParser

func NewParser(blockchain *Blockchain, client *rpcclient.Client, db kv.DB, skipped *Skipped, utxoset *utxoset.UtxoSet, c *cache.Cache, interrupt chan int) Parser

NewParser return a new instance to Bitcoin blockchai parser

func (*Parser) FindCheckPoint

func (p *Parser) FindCheckPoint(rawChain [][]uint8) (check CheckPoint, err error)

FindCheckPoint restores the parsed files' state from last parsing and return a CheckPoint instance the keep parsing

func (*Parser) InfinitelyParse

func (p *Parser) InfinitelyParse() (err error)

InfinitelyParse parses the blockchain starting from scratch when it reaches the end in order to implement a real time mechanism

func (*Parser) Parse

func (p *Parser) Parse() (err error)

Parse goes through the blockchain block by block

type Skipped

type Skipped struct {
	// contains filtered or unexported fields
}

Skipped instance of key value store designed to treat block structs

func NewSkipped

func NewSkipped() (s *Skipped)

NewSkipped creates a new instance of Skipped

func (*Skipped) DeleteBlock

func (s *Skipped) DeleteBlock(hash *chainhash.Hash)

DeleteBlock inserts in the db the block as []byte passed

func (*Skipped) Empty

func (s *Skipped) Empty()

Empty set blocks map to empty map

func (*Skipped) GetBlock

func (s *Skipped) GetBlock(hash *chainhash.Hash) (block Block, err error)

GetBlock returns a *Block looking for the block corresponding to the hash passed

func (*Skipped) GetStoredBlocks

func (s *Skipped) GetStoredBlocks() (blocks []string)

GetStoredBlocks is an utility functions that returns the list of stored blocks hash

func (*Skipped) IsStored

func (s *Skipped) IsStored(hash *chainhash.Hash) bool

IsStored returns true if the block corresponding to passed hash is stored in db

func (*Skipped) Len

func (s *Skipped) Len() int

Len returns number of stored blocks

func (*Skipped) StoreBlock

func (s *Skipped) StoreBlock(v interface{}) (err error)

StoreBlock inserts in the db the block as []byte passed

func (*Skipped) StoreBlockPrevHash

func (s *Skipped) StoreBlockPrevHash(b *Block)

StoreBlockPrevHash inserts in the db the block as []byte passed, using the previous hash as key

type TransactionsParser

type TransactionsParser struct {
	Index        int
	Tx           *btcutil.Tx
	Transactions []tx.Tx
}

TransactionsParser worker wrapper for parsing transactions in sync pool

func (*TransactionsParser) Work

func (w *TransactionsParser) Work() (err error)

Work interface to execute transactions parser worker operations

type Tx

type Tx struct {
	btcutil.Tx
}

Tx transaction type

func (*Tx) IsCoinbase

func (tx *Tx) IsCoinbase() bool

IsCoinbase returns true if the transaction is a coinbase transaction

func (*Tx) IsCoinjoin

func (tx *Tx) IsCoinjoin() bool

IsCoinjoin returns true is the tx is a coinjoin transaction

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL