neutrino

package module
v0.0.0-...-f0bdd0e Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2017 License: MIT Imports: 29 Imported by: 0

README

Neutrino: Privacy-Preserving Bitcoin Light Client

Neutrino is an experimental Bitcoin light client written in Go and designed with mobile Lightning Network clients in mind. It uses a new proposal for compact block filters to minimize bandwidth and storage use on the client side, while attempting to preserve privacy and minimize processor load on full nodes serving light clients.

Mechanism of operation

The light client synchronizes only block headers and a chain of compact block filter headers specifying the correct filters for each block. Filters are loaded lazily and stored in the database upon request; blocks are loaded lazily and not saved. There are multiple known major issues with the client, so it is not recommended to use it with real money at this point.

Usage

The client is instantiated as an object using NewChainService and then started. Upon start, the client sets up its database and other relevant files and connects to the p2p network. At this point, it becomes possible to query the client.

Queries

There are various types of queries supported by the client. There are many ways to access the database, for example, to get block headers by height and hash; in addition, it's possible to get a full block from the network using GetBlockFromNetwork by hash. However, the most useful methods are specifically tailored to scan the blockchain for data relevant to a wallet or a smart contract platform such as a Lightning Network node like lnd. These are described below.

Rescan

Rescan allows a wallet to scan a chain for specific TXIDs, outputs, and addresses. A start and end block may be specified along with other options. If no end block is specified, the rescan continues until stopped. If no start block is specified, the rescan begins with the latest known block. While a rescan runs, it notifies the client of each connected and disconnected block; the notifications follow the btcjson format with the option to use any of the relevant notifications. It's important to note that "recvtx" and "redeemingtx" notifications are only sent when a transaction is confirmed, not when it enters the mempool; the client does not currently support accepting 0-confirmation transactions.

GetUtxo

GetUtxo allows a wallet or smart contract platform to check that a UTXO exists on the blockchain and has not been spent. It is highly recommended to specify a start block; otherwise, in the event that the UTXO doesn't exist on the blockchain, the client will download all the filters back to block 1 searching for it. The client scans from the tip of the chain backwards, stopping when it finds the UTXO having been either spent or created; if it finds neither, it keeps scanning backwards until it hits the specified start block or, if a start block isn't specified, the first block in the blockchain. It returns a SpendReport containing either a TxOut including the PkScript required to spend the output, or containing information about the spending transaction, spending input, and block height in which the spending transaction was seen.

Stopping the client

Calling Stop on the ChainService client allows the user to stop the client; the method doesn't return until the ChainService is cleanly shut down.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ConnectionRetryInterval is the base amount of time to wait in
	// between retries when connecting to persistent peers.  It is adjusted
	// by the number of retries such that there is a retry backoff.
	ConnectionRetryInterval = time.Second * 5

	// UserAgentName is the user agent name and is used to help identify
	// ourselves to other bitcoin peers.
	UserAgentName = "neutrino"

	// UserAgentVersion is the user agent version and is used to help
	// identify ourselves to other bitcoin peers.
	UserAgentVersion = "0.0.1-alpha"

	// Services describes the services that are supported by the server.
	Services = wire.SFNodeWitness | wire.SFNodeCF

	// RequiredServices describes the services that are required to be
	// supported by outbound peers.
	RequiredServices = wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeCF

	// BanThreshold is the maximum ban score before a peer is banned.
	BanThreshold = uint32(100)

	// BanDuration is the duration of a ban.
	BanDuration = time.Hour * 24

	// TargetOutbound is the number of outbound peers to target.
	TargetOutbound = 8

	// MaxPeers is the maximum number of connections the client maintains.
	MaxPeers = 125

	// DisableDNSSeed disables getting initial addresses for Bitcoin nodes
	// from DNS.
	DisableDNSSeed = false
)

These are exported variables so they can be changed by users.

TODO: Export functional options for these as much as possible so they can be changed call-to-call.

View Source
var (
	// QueryTimeout specifies how long to wait for a peer to answer a
	// query.
	QueryTimeout = time.Second * 3

	// QueryNumRetries specifies how many times to retry sending a query to
	// each peer before we've concluded we aren't going to get a valid
	// response. This allows to make up for missed messages in some
	// instances.
	QueryNumRetries = 2
)
View Source
var (
	// WaitForMoreCFHeaders is a configurable time to wait for CFHeaders
	// messages from peers. It defaults to 3 seconds but can be increased
	// for higher security and decreased for faster synchronization.
	WaitForMoreCFHeaders = 3 * time.Second
)

TODO: Redo this using query API.

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until either UseLogger or SetLogWriter are called.

func UseLogger

func UseLogger(logger btclog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using btclog.

Types

type ChainService

type ChainService struct {
	FilterDB         filterdb.FilterDatabase
	BlockHeaders     *headerfs.BlockHeaderStore
	RegFilterHeaders *headerfs.FilterHeaderStore
	ExtFilterHeaders *headerfs.FilterHeaderStore
	// contains filtered or unexported fields
}

ChainService is instantiated with functional options

func NewChainService

func NewChainService(cfg Config) (*ChainService, error)

NewChainService returns a new chain service configured to connect to the bitcoin network type specified by chainParams. Use start to begin syncing with peers.

func (*ChainService) AddBytesReceived

func (s *ChainService) AddBytesReceived(bytesReceived uint64)

AddBytesReceived adds the passed number of bytes to the total bytes received counter for the server. It is safe for concurrent access.

func (*ChainService) AddBytesSent

func (s *ChainService) AddBytesSent(bytesSent uint64)

AddBytesSent adds the passed number of bytes to the total bytes sent counter for the server. It is safe for concurrent access.

func (*ChainService) AddPeer

func (s *ChainService) AddPeer(sp *serverPeer)

AddPeer adds a new peer that has already been connected to the server.

func (*ChainService) AddedNodeInfo

func (s *ChainService) AddedNodeInfo() []*serverPeer

AddedNodeInfo returns an array of btcjson.GetAddedNodeInfoResult structures describing the persistent (added) nodes.

func (*ChainService) BanPeer

func (s *ChainService) BanPeer(sp *serverPeer)

BanPeer bans a peer that has already been connected to the server by ip.

func (*ChainService) BestSnapshot

func (s *ChainService) BestSnapshot() (*waddrmgr.BlockStamp, error)

BestSnapshot retrieves the most recent block's height and hash.

func (*ChainService) ChainParams

func (s *ChainService) ChainParams() chaincfg.Params

ChainParams returns a copy of the ChainService's chaincfg.Params.

func (*ChainService) ConnectNode

func (s *ChainService) ConnectNode(addr string, permanent bool) error

ConnectNode adds `addr' as a new outbound peer. If permanent is true then the peer will be persistent and reconnect if the connection is lost. It is an error to call this with an already existing peer.

func (*ChainService) ConnectedCount

func (s *ChainService) ConnectedCount() int32

ConnectedCount returns the number of currently connected peers.

func (*ChainService) DisconnectNodeByAddr

func (s *ChainService) DisconnectNodeByAddr(addr string) error

DisconnectNodeByAddr disconnects a peer by target address. Both outbound and inbound nodes will be searched for the target node. An error message will be returned if the peer was not found.

func (*ChainService) DisconnectNodeByID

func (s *ChainService) DisconnectNodeByID(id int32) error

DisconnectNodeByID disconnects a peer by target node id. Both outbound and inbound nodes will be searched for the target node. An error message will be returned if the peer was not found.

func (*ChainService) ForAllPeers

func (s *ChainService) ForAllPeers(closure func(sp *serverPeer))

ForAllPeers runs a closure over all peers (outbound and persistent) to which the ChainService is connected. Nothing is returned because the peerState's ForAllPeers method doesn't return anything as the closure passed to it doesn't return anything.

func (*ChainService) GetBlockFromNetwork

func (s *ChainService) GetBlockFromNetwork(blockHash chainhash.Hash,
	options ...QueryOption) (*btcutil.Block, error)

GetBlockFromNetwork gets a block by requesting it from the network, one peer at a time, until one answers.

TODO(roasbeef): add query option to indicate if the caller wants witness data or not.

func (*ChainService) GetCFilter

func (s *ChainService) GetCFilter(blockHash chainhash.Hash, extended bool,
	options ...QueryOption) (*gcs.Filter, error)

GetCFilter gets a cfilter from the database. Failing that, it requests the cfilter from the network and writes it to the database. If extended is true, an extended filter will be queried for. Otherwise, we'll fetch the regular filter.

func (*ChainService) GetUtxo

func (s *ChainService) GetUtxo(options ...RescanOption) (*SpendReport, error)

GetUtxo gets the appropriate TxOut or errors if it's spent. The option WatchOutPoints (with a single outpoint) is required. StartBlock can be used to give a hint about which block the transaction is in, and TxIdx can be used to give a hint of which transaction in the block matches it (coinbase is 0, first normal transaction is 1, etc.).

TODO(roasbeef): WTB utxo-commitments

func (*ChainService) IsCurrent

func (s *ChainService) IsCurrent() bool

IsCurrent lets the caller know whether the chain service's block manager thinks its view of the network is current.

func (*ChainService) NetTotals

func (s *ChainService) NetTotals() (uint64, uint64)

NetTotals returns the sum of all bytes received and sent across the network for all peers. It is safe for concurrent access.

func (*ChainService) NewRescan

func (s *ChainService) NewRescan(options ...RescanOption) Rescan

NewRescan returns a rescan object that runs in another goroutine and has an updateable filter. It returns the long-running rescan object, and a channel which returns any error on termination of the rescan prcess.

func (*ChainService) OutboundGroupCount

func (s *ChainService) OutboundGroupCount(key string) int

OutboundGroupCount returns the number of peers connected to the given outbound group key.

func (*ChainService) Peers

func (s *ChainService) Peers() []*serverPeer

Peers returns an array of all connected peers.

func (*ChainService) PublishTransaction

func (s *ChainService) PublishTransaction(tx *wire.MsgTx) error

PublishTransaction sends the transaction to the consensus RPC server so it can be propigated to other nodes and eventually mined.

func (*ChainService) RemoveNodeByAddr

func (s *ChainService) RemoveNodeByAddr(addr string) error

RemoveNodeByAddr removes a peer from the list of persistent peers if present. An error will be returned if the peer was not found.

func (*ChainService) RemoveNodeByID

func (s *ChainService) RemoveNodeByID(id int32) error

RemoveNodeByID removes a peer by node ID from the list of persistent peers if present. An error will be returned if the peer was not found.

func (*ChainService) Rescan

func (s *ChainService) Rescan(options ...RescanOption) error

Rescan is a single-threaded function that uses headers from the database and functional options as arguments.

func (*ChainService) SendTransaction

func (s *ChainService) SendTransaction(tx *wire.MsgTx, options ...QueryOption) error

SendTransaction sends a transaction to each peer. It returns an error if any peer rejects the transaction for any reason than that it's already known.

TODO: Better privacy by sending to only one random peer and watching propagation, requires better peer selection support in query API.

func (*ChainService) Start

func (s *ChainService) Start()

Start begins connecting to peers and syncing the blockchain.

func (*ChainService) Stop

func (s *ChainService) Stop() error

Stop gracefully shuts down the server by stopping and disconnecting all peers and the main listener.

func (*ChainService) UpdatePeerHeights

func (s *ChainService) UpdatePeerHeights(latestBlkHash *chainhash.Hash, latestHeight int32, updateSource *serverPeer)

UpdatePeerHeights updates the heights of all peers who have have announced the latest connected main chain block, or a recognized orphan. These height updates allow us to dynamically refresh peer heights, ensuring sync peer selection has access to the latest block heights for each peer.

type Config

type Config struct {
	DataDir      string
	Database     walletdb.DB
	Namespace    []byte
	ChainParams  chaincfg.Params
	ConnectPeers []string
	AddPeers     []string
}

Config is a struct detailing the configuration of the chain service.

type QueryOption

type QueryOption func(*queryOptions)

QueryOption is a functional option argument to any of the network query methods, such as GetBlockFromNetwork and GetCFilter (when that resorts to a network query). These are always processed in order, with later options overriding earlier ones.

func DoneChan

func DoneChan(doneChan chan<- struct{}) QueryOption

DoneChan allows the caller to pass a channel that will get closed when the query is finished.

func NumRetries

func NumRetries(numRetries uint8) QueryOption

NumRetries is a query option that lets the query know the maximum number of times each peer should be queried. The default is one.

func Timeout

func Timeout(timeout time.Duration) QueryOption

Timeout is a query option that lets the query know how long to wait for each peer we ask the query to answer it before moving on.

type Rescan

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

Rescan is an object that represents a long-running rescan/notification client with updateable filters. It's meant to be close to a drop-in replacement for the btcd rescan and notification functionality used in wallets. It only contains information about whether a goroutine is running.

func (*Rescan) Start

func (r *Rescan) Start() <-chan error

Start kicks off the rescan goroutine, which will begin to scan the chain according to the specified rescan options.

func (*Rescan) Update

func (r *Rescan) Update(options ...UpdateOption) error

Update sends an update to a long-running rescan/notification goroutine.

func (*Rescan) WaitForShutdown

func (r *Rescan) WaitForShutdown()

WaitForShutdown waits until all goroutines associated with the rescan have exited. This method is to be called once the passed quitchan (if any) has been closed.

type RescanOption

type RescanOption func(ro *rescanOptions)

RescanOption is a functional option argument to any of the rescan and notification subscription methods. These are always processed in order, with later options overriding earlier ones.

func EndBlock

func EndBlock(endBlock *waddrmgr.BlockStamp) RescanOption

EndBlock specifies the end block. The hash is checked first; if there's no such hash (zero hash avoids lookup), the height is checked next. If the height is 0 or in the future or the end block isn't specified, the quit channel MUST be specified as Rescan will sync to the tip of the blockchain and continue to stay in sync and pass notifications. This is enforced at runtime.

func NotificationHandlers

func NotificationHandlers(ntfn btcrpcclient.NotificationHandlers) RescanOption

NotificationHandlers specifies notification handlers for the rescan. These will always run in the same goroutine as the caller.

func QueryOptions

func QueryOptions(options ...QueryOption) RescanOption

QueryOptions pass onto the underlying queries.

func QuitChan

func QuitChan(quit <-chan struct{}) RescanOption

QuitChan specifies the quit channel. This can be used by the caller to let an indefinite rescan (one with no EndBlock set) know it should gracefully shut down. If this isn't specified, an end block MUST be specified as Rescan must know when to stop. This is enforced at runtime.

func StartBlock

func StartBlock(startBlock *waddrmgr.BlockStamp) RescanOption

StartBlock specifies the start block. The hash is checked first; if there's no such hash (zero hash avoids lookup), the height is checked next. If the height is 0 or the start block isn't specified, starts from the genesis block. This block is assumed to already be known, and no notifications will be sent for this block.

func TxIdx

func TxIdx(txIdx uint32) RescanOption

TxIdx specifies a hint transaction index into the block in which the UTXO is created (eg, coinbase is 0, next transaction is 1, etc.)

func WatchAddrs

func WatchAddrs(watchAddrs ...btcutil.Address) RescanOption

WatchAddrs specifies the addresses to watch/filter for. Each call to this function adds to the list of addresses being watched rather than replacing the list. Each time a transaction spends to the specified address, the outpoint is added to the WatchOutPoints list.

func WatchOutPoints

func WatchOutPoints(watchOutPoints ...wire.OutPoint) RescanOption

WatchOutPoints specifies the outpoints to watch for on-chain spends. Each call to this function adds to the list of outpoints being watched rather than replacing the list.

func WatchTxIDs

func WatchTxIDs(watchTxIDs ...chainhash.Hash) RescanOption

WatchTxIDs specifies the outpoints to watch for on-chain spends. Each call to this function adds to the list of outpoints being watched rather than replacing the list.

type SpendReport

type SpendReport struct {
	// SpendingTx is the transaction that spent the output that a spend
	// report was requested for.
	//
	// NOTE: This field will only be populated if the target output has
	// been spent.
	SpendingTx *wire.MsgTx

	// SpendingTxIndex is the input index of the transaction above which
	// spends the target output.
	//
	// NOTE: This field will only be populated if the target output has
	// been spent.
	SpendingInputIndex uint32

	// SpendingTxHeight is the hight of the block that included the
	// transaction  above which spent the target output.
	//
	// NOTE: This field will only be populated if the target output has
	// been spent.
	SpendingTxHeight uint32

	// Output is the raw output of the target outpoint.
	//
	// NOTE: This field will only be populated if the target is still
	// unspent.
	Output *wire.TxOut
}

SpendReport is a struct which describes the current spentness state of a particular output. In the case that an output is spent, then the spending transaction and related details will be populated. Otherwise, only the target unspent output in the chain will be returned.

type UpdateOption

type UpdateOption func(uo *updateOptions)

UpdateOption is a functional option argument for the Rescan.Update method.

func AddAddrs

func AddAddrs(addrs ...btcutil.Address) UpdateOption

AddAddrs adds addresses to the filter.

func AddOutPoints

func AddOutPoints(outPoints ...wire.OutPoint) UpdateOption

AddOutPoints adds outpoints to the filter.

func AddTxIDs

func AddTxIDs(txIDs ...chainhash.Hash) UpdateOption

AddTxIDs adds TxIDs to the filter.

func Rewind

func Rewind(height uint32) UpdateOption

Rewind rewinds the rescan to the specified height (meaning, disconnects down to the block immediately after the specified height) and restarts it from that point with the (possibly) newly expanded filter. Especially useful when called in the same Update() as one of the previous three options.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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