spvwallet

package module
v0.0.0-...-1d808d6 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2020 License: MIT Imports: 47 Imported by: 0

README

Build Status Coverage Status Go Report Card

spvwallet

Lightweight p2p SPV wallet and library in Go. It connects directly to the bitcoin p2p network to fetch headers, merkle blocks, and transactions.

It uses a number of utilities from btcsuite but natively handles blockchain and wallet.

Library Usage:

// Create a new config
config := spvwallet.NewDefaultConfig()

// Select network
config.Params = &chaincfg.TestNet3Params

// Select wallet datastore
sqliteDatastore, _ := db.Create(config.RepoPath)
config.DB = sqliteDatastore

// Create the wallet
wallet, _ := spvwallet.NewSPVWallet(config)

// Start it!
go wallet.Start()

Easy peasy

The wallet implements the following interface:


type BitcoinWallet interface {

	// Start the wallet
	Start()

	// Return the network parameters
	Params() *chaincfg.Params

	// Returns the type of crytocurrency this wallet implements
	CurrencyCode() string

	// Check if this amount is considered dust
	IsDust(amount int64) bool

	// Get the master private key
	MasterPrivateKey() *hd.ExtendedKey

	// Get the master public key
	MasterPublicKey() *hd.ExtendedKey

	// Get the current address for the given purpose
	CurrentAddress(purpose spvwallet.KeyPurpose) btc.Address

	// Returns a fresh address that has never been returned by this function
	NewAddress(purpose spvwallet.KeyPurpose) btc.Address

	// Parse the address string and return an address interface
	DecodeAddress(addr string) (btc.Address, error)

	// Turn the given output script into an address
	ScriptToAddress(script []byte) (btc.Address, error)

	// Turn the given address into an output script
	AddressToScript(addr btc.Address) ([]byte, error)

	// Returns if the wallet has the key for the given address
	HasKey(addr btc.Address) bool

	// Get the confirmed and unconfirmed balances
	Balance() (confirmed, unconfirmed int64)

	// Returns a list of transactions for this wallet
	Transactions() ([]spvwallet.Txn, error)

	// Get info on a specific transaction
	GetTransaction(txid chainhash.Hash) (spvwallet.Txn, error)

	// Get the height of the blockchain
	ChainTip() uint32

	// Get the current fee per byte
	GetFeePerByte(feeLevel spvwallet.FeeLevel) uint64

	// Send bitcoins to an external wallet
	Spend(amount int64, addr btc.Address, feeLevel spvwallet.FeeLevel) (*chainhash.Hash, error)

	// Bump the fee for the given transaction
	BumpFee(txid chainhash.Hash) (*chainhash.Hash, error)

	// Calculates the estimated size of the transaction and returns the total fee for the given feePerByte
	EstimateFee(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, feePerByte uint64) uint64

	// Build and broadcast a transaction that sweeps all coins from an address. If it is a p2sh multisig, the redeemScript must be included
	SweepAddress(utxos []spvwallet.Utxo, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel spvwallet.FeeLevel) (*chainhash.Hash, error)

	// Create a signature for a multisig transaction
	CreateMultisigSignature(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]spvwallet.Signature, error)

	// Combine signatures and optionally broadcast
	Multisign(ins []spvwallet.TransactionInput, outs []spvwallet.TransactionOutput, sigs1 []spvwallet.Signature, sigs2 []spvwallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error)

	// Generate a multisig script from public keys. If a timeout is included the returned script should be a timelocked escrow which releases using the timeoutKey.
	GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error)

	// Add a script to the wallet and get notifications back when coins are received or spent from it
	AddWatchedScript(script []byte) error

	// Add a callback for incoming transactions
	AddTransactionListener(func(spvwallet.TransactionCallback))

	// Use this to re-download merkle blocks in case of missed transactions
	ReSyncBlockchain(fromHeight int32)

	// Return the number of confirmations and the height for a transaction
	GetConfirmations(txid chainhash.Hash) (confirms, atHeight uint32, err error)

	// Cleanly disconnect from the wallet
	Close()
}

To create a wallet binary:

make install

Usage:

Usage:
  spvwallet [OPTIONS] <command>

Help Options:
  -h, --help  Show this help message

Available commands:
  addwatchedscript         add a script to watch
  balance                  get the wallet balance
  bumpfee                  bump the tx fee
  chaintip                 return the height of the chain
  createmultisigsignature  create a p2sh multisig signature
  currentaddress           get the current bitcoin address
  dumpheaders              print the header database
  estimatefee              estimate the fee for a tx
  getconfirmations         get the number of confirmations for a tx
  getfeeperbyte            get the current bitcoin fee
  gettransaction           get a specific transaction
  haskey                   does key exist
  masterprivatekey         get the wallet's master private key
  masterpublickey          get the wallet's master public key
  multisign                combine multisig signatures
  newaddress               get a new bitcoin address
  peers                    get info about peers
  resyncblockchain         re-download the chain of headers
  spend                    send bitcoins
  start                    start the wallet
  stop                     stop the wallet
  sweepaddress             sweep all coins from an address
  transactions             get a list of transactions
  version                  print the version number

Finally a gRPC API is available on port 8234. The same interface is exposed via the API plus a streaming wallet notifier which fires when a new transaction (either incoming or outgoing) is recorded then again when it gains its first confirmation.

This library began it's life as a library called uspv written by Thaddeus Dryja for the lnd. Several files still contain the original code.

Documentation

Index

Constants

View Source
const (
	MAX_HEADERS = 2000
	CACHE_SIZE  = 100
)
View Source
const (
	// RedeemP2PKHSigScriptSize is the worst case (largest) serialize size
	// of a transaction input script that redeems a compressed P2PKH output.
	// It is calculated as:
	//
	//   - OP_DATA_73
	//   - 72 bytes DER signature + 1 byte sighash
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	RedeemP2PKHSigScriptSize = 1 + 73 + 1 + 33

	// RedeemP2SHMultisigSigScriptSize is the worst case (largest) serialize size
	// of a transaction input script that redeems a 2 of 3 P2SH multisig output with compressed keys.
	// It is calculated as:
	//
	//   - OP_0
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_PUSHDATA
	//   - OP_2
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP3
	//   - OP_CHECKMULTISIG
	RedeemP2SH2of3MultisigSigScriptSize = 1 + 1 + 72 + 1 + 72 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1

	// RedeemP2SH1of2MultisigSigScriptSize is the worst case (largest) serialize size
	// of a transaction input script that redeems a 1 of 2 P2SH multisig output with compressed keys.
	// It is calculated as:
	//
	//   - OP_0
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_PUSHDATA
	//   - OP_1
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP2
	//   - OP_CHECKMULTISIG
	RedeemP2SH1of2MultisigSigScriptSize = 1 + 1 + 72 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 1

	// RedeemP2SHMultisigTimelock1SigScriptSize is the worst case (largest) serialize size
	// of a transaction input script that redeems a compressed P2SH timelocked multisig using the timeout.
	// It is calculated as:
	//
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_0
	//   - OP_PUSHDATA
	//   - OP_IF
	//   - OP_2
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP3
	//   - OP_CHECKMULTISIG
	//   - OP_ELSE
	//   - OP_PUSHDATA
	//   - 2 byte block height
	//   - OP_CHECKSEQUENCEVERIFY
	//   - OP_DROP
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_CHECKSIG
	//   - OP_ENDIF
	RedeemP2SHMultisigTimelock1SigScriptSize = 1 + 72 + 1 + 1 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 + 33 + 1 + 1

	// RedeemP2SHMultisigTimelock2SigScriptSize is the worst case (largest) serialize size
	// of a transaction input script that redeems a compressed P2SH timelocked multisig without using the timeout.
	// It is calculated as:
	//
	//   - OP_0
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_DATA_72
	//   - 72 bytes DER signature
	//   - OP_1
	//   - OP_PUSHDATA
	//   - OP_IF
	//   - OP_2
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP3
	//   - OP_CHECKMULTISIG
	//   - OP_ELSE
	//   - OP_PUSHDATA
	//   - 2 byte block height
	//   - OP_CHECKSEQUENCEVERIFY
	//   - OP_DROP
	//   - OP_DATA_33
	//   - 33 bytes serialized compressed pubkey
	//   - OP_CHECKSIG
	//   - OP_ENDIF
	RedeemP2SHMultisigTimelock2SigScriptSize = 1 + 1 + 72 + +1 + 72 + 1 + 1 + 1 + 1 + 1 + 33 + 1 + 33 + 1 + 33 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + 1 + 33 + 1 + 1

	// P2PKHPkScriptSize is the size of a transaction output script that
	// pays to a compressed pubkey hash.  It is calculated as:
	//
	//   - OP_DUP
	//   - OP_HASH160
	//   - OP_DATA_20
	//   - 20 bytes pubkey hash
	//   - OP_EQUALVERIFY
	//   - OP_CHECKSIG
	P2PKHPkScriptSize = 1 + 1 + 1 + 20 + 1 + 1

	// RedeemP2PKHInputSize is the worst case (largest) serialize size of a
	// transaction input redeeming a compressed P2PKH output.  It is
	// calculated as:
	//
	//   - 32 bytes previous tx
	//   - 4 bytes output index
	//   - 1 byte script len
	//   - signature script
	//   - 4 bytes sequence
	RedeemP2PKHInputSize = 32 + 4 + 1 + RedeemP2PKHSigScriptSize + 4

	// RedeemP2SH2of3MultisigInputSize is the worst case (largest) serialize size of a
	// transaction input redeeming a compressed P2SH 2 of 3 multisig output.  It is
	// calculated as:
	//
	//   - 32 bytes previous tx
	//   - 4 bytes output index
	//   - 1 byte script len
	//   - 4 bytes sequence
	///  - witness discounted signature script
	RedeemP2SH2of3MultisigInputSize = 32 + 4 + 1 + 4 + (RedeemP2SH2of3MultisigSigScriptSize / 4)

	// RedeemP2SH1of2MultisigInputSize is the worst case (largest) serialize size of a
	// transaction input redeeming a compressed P2SH 2 of 3 multisig output.  It is
	// calculated as:
	//
	//   - 32 bytes previous tx
	//   - 4 bytes output index
	//   - 1 byte script len
	//   - 4 bytes sequence
	///  - witness discounted signature script
	RedeemP2SH1of2MultisigInputSize = 32 + 4 + 1 + 4 + (RedeemP2SH1of2MultisigSigScriptSize / 4)

	// RedeemP2SHMultisigTimelock1InputSize is the worst case (largest) serialize size of a
	// transaction input redeeming a compressed p2sh timelocked multig output with using the timeout.  It is
	// calculated as:
	//
	//   - 32 bytes previous tx
	//   - 4 bytes output index
	//   - 1 byte script len
	//   - 4 bytes sequence
	///  - witness discounted signature script
	RedeemP2SHMultisigTimelock1InputSize = 32 + 4 + 1 + 4 + (RedeemP2SHMultisigTimelock1SigScriptSize / 4)

	// RedeemP2SHMultisigTimelock2InputSize is the worst case (largest) serialize size of a
	// transaction input redeeming a compressed P2SH timelocked multisig output without using the timeout.  It is
	// calculated as:
	//
	//   - 32 bytes previous tx
	//   - 4 bytes output index
	//   - 1 byte script len
	//   - 4 bytes sequence
	///  - witness discounted signature script
	RedeemP2SHMultisigTimelock2InputSize = 32 + 4 + 1 + 4 + (RedeemP2SHMultisigTimelock2SigScriptSize / 4)

	// P2PKHOutputSize is the serialize size of a transaction output with a
	// P2PKH output script.  It is calculated as:
	//
	//   - 8 bytes output value
	//   - 1 byte compact int encoding value 25
	//   - 25 bytes P2PKH output script
	P2PKHOutputSize = 8 + 1 + P2PKHPkScriptSize
)

Worst case script and input/output size estimates.

View Source
const LOOKAHEADWINDOW = 100
View Source
const MaxGetAddressAttempts = 10
View Source
const WALLET_VERSION = "0.1.0"

Variables

View Source
var (
	BKTHeaders  = []byte("Headers")
	BKTChainTip = []byte("ChainTip")
	KEYChainTip = []byte("ChainTip")
)
View Source
var (
	// ErrTorInvalidAddressResponse indicates an invalid address was
	// returned by the Tor DNS resolver.
	ErrTorInvalidAddressResponse = errors.New("invalid address response")

	// ErrTorInvalidProxyResponse indicates the Tor proxy returned a
	// response in an unexpected format.
	ErrTorInvalidProxyResponse = errors.New("invalid proxy response")

	// ErrTorUnrecognizedAuthMethod indicates the authentication method
	// provided is not recognized.
	ErrTorUnrecognizedAuthMethod = errors.New("invalid proxy authentication method")
)
View Source
var BumpFeeAlreadyConfirmedError = errors.New("Transaction is confirmed, cannot bump fee")
View Source
var BumpFeeNotFoundError = errors.New("Transaction either doesn't exist or has already been spent")
View Source
var BumpFeeTransactionDeadError = errors.New("Cannot bump fee of dead transaction")
View Source
var IntervalToScanBlock = time.Second * 5
View Source
var OrphanHeaderError = errors.New("header does not extend any known headers")
View Source
var SFNodeBitcoinCash wire.ServiceFlag = 1 << 5
View Source
var ScryStartBlock = 643000
View Source
var TargetScanAddresses []string

Functions

func Bip44Derivation

func Bip44Derivation(masterPrivKey *hd.ExtendedKey) (internal, external *hd.ExtendedKey, err error)

m / purpose' / coin_type' / account' / change / address_index

func EstimateSerializeSize

func EstimateSerializeSize(inputCount int, txOuts []*wire.TxOut, addChangeOutput bool, inputType InputType) int

EstimateSerializeSize returns a worst case serialize size estimate for a signed transaction that spends inputCount number of compressed P2PKH outputs and contains each transaction output from txOuts. The estimated size is incremented for an additional P2PKH change output if addChangeOutput is true.

func LockTimeFromRedeemScript

func LockTimeFromRedeemScript(redeemScript []byte) (uint32, error)

func MakeMerkleParent

func MakeMerkleParent(left *chainhash.Hash, right *chainhash.Hash) (*chainhash.Hash, error)

func NewCoin

func NewCoin(txid []byte, index uint32, value btc.Amount, numConfs int64, scriptPubKey []byte) coinset.Coin

func NewUnsignedTransaction

func NewUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInputs txauthor.InputSource, fetchChange txauthor.ChangeSource) (*txauthor.AuthoredTx, error)

func SumOutputSerializeSizes

func SumOutputSerializeSizes(outputs []*wire.TxOut) (serializeSize int)

SumOutputSerializeSizes sums up the serialized size of the supplied outputs.

func TestStxo_IsEqual

func TestStxo_IsEqual(t *testing.T)

func TestUtxo_IsEqual

func TestUtxo_IsEqual(t *testing.T)

func TorLookupIP

func TorLookupIP(host string) ([]net.IP, error)

TorLookupIP uses Tor to resolve DNS via the SOCKS extension they provide for resolution over the Tor network. Tor itself doesn't support ipv6 so this doesn't either.

Types

type Blockchain

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

Wrapper around Headers implementation that handles all blockchain operations

func NewBlockchain

func NewBlockchain(filePath string, walletCreationDate time.Time, params *chaincfg.Params) (*Blockchain, error)

func (*Blockchain) BestBlock

func (b *Blockchain) BestBlock() (StoredHeader, error)

func (*Blockchain) CalcMedianTimePast

func (b *Blockchain) CalcMedianTimePast(header wire.BlockHeader) (time.Time, error)

func (*Blockchain) CheckHeader

func (b *Blockchain) CheckHeader(header wire.BlockHeader, prevHeader StoredHeader) bool

func (*Blockchain) Close

func (b *Blockchain) Close()

func (*Blockchain) CommitHeader

func (b *Blockchain) CommitHeader(header wire.BlockHeader) (bool, *StoredHeader, uint32, error)

func (*Blockchain) GetBlockLocator

func (b *Blockchain) GetBlockLocator() blockchain.BlockLocator

func (*Blockchain) GetCommonAncestor

func (b *Blockchain) GetCommonAncestor(bestHeader, prevBestHeader StoredHeader) (*StoredHeader, error)

GetCommonAncestor returns last header before reorg point

func (*Blockchain) GetEpoch

func (b *Blockchain) GetEpoch() (*wire.BlockHeader, error)

func (*Blockchain) GetHeader

func (b *Blockchain) GetHeader(hash *chainhash.Hash) (StoredHeader, error)

func (*Blockchain) GetNPrevBlockHashes

func (b *Blockchain) GetNPrevBlockHashes(n int) []*chainhash.Hash

func (*Blockchain) Rollback

func (b *Blockchain) Rollback(t time.Time) error

Rollback the header database to the last header before time t. We shouldn't go back further than the checkpoint

type Checkpoint

type Checkpoint struct {
	Height uint32
	Header wire.BlockHeader
}

func GetCheckpoint

func GetCheckpoint(walletCreationDate time.Time, params *chaincfg.Params) Checkpoint

type Coin

type Coin struct {
	TxHash       *chainhash.Hash
	TxIndex      uint32
	TxValue      btc.Amount
	TxNumConfs   int64
	ScriptPubKey []byte
}

func (*Coin) Hash

func (c *Coin) Hash() *chainhash.Hash

func (*Coin) Index

func (c *Coin) Index() uint32

func (*Coin) NumConfs

func (c *Coin) NumConfs() int64

func (*Coin) PkScript

func (c *Coin) PkScript() []byte

func (*Coin) Value

func (c *Coin) Value() btc.Amount

func (*Coin) ValueAge

func (c *Coin) ValueAge() int64

type Config

type Config struct {
	// Network parameters. Set mainnet, testnet, or regtest using this.
	Params *chaincfg.Params

	// Bip39 mnemonic string. If empty a new mnemonic will be created.
	Mnemonic string

	// The date the wallet was created.
	// If before the earliest checkpoint the chain will be synced using the earliest checkpoint.
	CreationDate time.Time

	// The user-agent that shall be visible to peers
	UserAgent string

	// Location of the data directory
	RepoPath string

	// An implementation of the Datastore interface
	DB wallet.Datastore

	// If you wish to connect to a single trusted peer set this. Otherwise leave nil.
	TrustedPeer net.Addr

	// A Tor proxy can be set here causing the wallet will use Tor
	Proxy proxy.Dialer

	// The default fee-per-byte for each level
	LowFee    uint64
	MediumFee uint64
	HighFee   uint64

	// The highest allowable fee-per-byte
	MaxFee uint64

	// External API to query to look up fees. If this field is nil then the default fees will be used.
	// If the API is unreachable then the default fees will likewise be used. If the API returns a fee
	// greater than MaxFee then the MaxFee will be used in place. The API response must be formatted as
	// { "fastestFee": 40, "halfHourFee": 20, "hourFee": 10 }
	FeeAPI url.URL

	// A logger. You can write the logs to file or stdout or however else you want.
	Logger logging.Backend

	// Disable the exchange rate provider
	DisableExchangeRates bool
}

func NewDefaultConfig

func NewDefaultConfig() *Config

type FeeProvider

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

func NewFeeProvider

func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee uint64, feeAPI string, proxy proxy.Dialer) *FeeProvider

func (*FeeProvider) GetFeePerByte

func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64

type Fees

type Fees struct {
	Priority uint64 `json:"priority"`
	Normal   uint64 `json:"normal"`
	Economic uint64 `json:"economic"`
}

type HeaderCache

type HeaderCache struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

func (*HeaderCache) Get

func (h *HeaderCache) Get(hash chainhash.Hash) (StoredHeader, error)

func (*HeaderCache) Set

func (h *HeaderCache) Set(sh StoredHeader)

type HeaderDB

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

HeaderDB implements Headers using bolt DB

func NewHeaderDB

func NewHeaderDB(filePath string) (*HeaderDB, error)

func (*HeaderDB) Close

func (h *HeaderDB) Close()

func (*HeaderDB) DeleteAfter

func (h *HeaderDB) DeleteAfter(height uint32) error

func (*HeaderDB) GetBestHeader

func (h *HeaderDB) GetBestHeader() (sh StoredHeader, err error)

func (*HeaderDB) GetHeader

func (h *HeaderDB) GetHeader(hash chainhash.Hash) (sh StoredHeader, err error)

func (*HeaderDB) GetPreviousHeader

func (h *HeaderDB) GetPreviousHeader(header wire.BlockHeader) (sh StoredHeader, err error)

func (*HeaderDB) Height

func (h *HeaderDB) Height() (uint32, error)

func (*HeaderDB) Print

func (h *HeaderDB) Print(w io.Writer)

func (*HeaderDB) Prune

func (h *HeaderDB) Prune() error

func (*HeaderDB) Put

func (h *HeaderDB) Put(sh StoredHeader, newBestHeader bool) error

type Headers

type Headers interface {
	// Put a block header to the database
	// Total work and height are required to be calculated prior to insertion
	// If this is the new best header, the chain tip should also be updated
	Put(header StoredHeader, newBestHeader bool) error

	// Delete all headers after the MAX_HEADERS most recent
	Prune() error

	// Delete all headers after the given height
	DeleteAfter(height uint32) error

	// Returns all information about the previous header
	GetPreviousHeader(header wire.BlockHeader) (StoredHeader, error)

	// Grab a header given hash
	GetHeader(hash chainhash.Hash) (StoredHeader, error)

	// Retrieve the best header from the database
	GetBestHeader() (StoredHeader, error)

	// Get the height of chain
	Height() (uint32, error)

	// Cleanly close the db
	Close()

	// Print all headers
	Print(io.Writer)
}

Database interface for storing block headers

type InputType

type InputType int
const (
	P2PKH InputType = iota
	P2SH_1of2_Multisig
	P2SH_2of3_Multisig
	P2SH_Multisig_Timelock_1Sig
	P2SH_Multisig_Timelock_2Sigs
)

type KeyManager

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

func NewKeyManager

func NewKeyManager(db wallet.Keys, params *chaincfg.Params, masterPrivKey *hd.ExtendedKey) (*KeyManager, error)

func (*KeyManager) GetCurrentKey

func (km *KeyManager) GetCurrentKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error)

func (*KeyManager) GetFreshKey

func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error)

func (*KeyManager) GetKeyForScript

func (km *KeyManager) GetKeyForScript(scriptAddress []byte) (*hd.ExtendedKey, error)

func (*KeyManager) GetKeys

func (km *KeyManager) GetKeys() []*hd.ExtendedKey

func (*KeyManager) MarkKeyAsUsed

func (km *KeyManager) MarkKeyAsUsed(scriptAddress []byte) error

Mark the given key as used and extend the lookahead window

type MockDatastore

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

func (*MockDatastore) Keys

func (m *MockDatastore) Keys() wallet.Keys

func (*MockDatastore) Stxos

func (m *MockDatastore) Stxos() wallet.Stxos

func (*MockDatastore) Txns

func (m *MockDatastore) Txns() wallet.Txns

func (*MockDatastore) Utxos

func (m *MockDatastore) Utxos() wallet.Utxos

func (*MockDatastore) WatchedScripts

func (m *MockDatastore) WatchedScripts() wallet.WatchedScripts

type PeerManager

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

func NewPeerManager

func NewPeerManager(config *PeerManagerConfig) (*PeerManager, error)

func (*PeerManager) ConnectedPeers

func (pm *PeerManager) ConnectedPeers() []*peer.Peer

func (*PeerManager) Start

func (pm *PeerManager) Start()

func (*PeerManager) Stop

func (pm *PeerManager) Stop()

type PeerManagerConfig

type PeerManagerConfig struct {
	// The network parameters to use
	Params *chaincfg.Params

	// The target number of outbound peers. Defaults to 10.
	TargetOutbound uint32

	// Duration of time to retry a connection. Defaults to 5 seconds.
	RetryDuration time.Duration

	// UserAgentName specifies the user agent name to advertise.  It is
	// highly recommended to specify this value.
	UserAgentName string

	// UserAgentVersion specifies the user agent version to advertise.  It
	// is highly recommended to specify this value and that it follows the
	// form "major.minor.revision" e.g. "2.6.41".
	UserAgentVersion string

	// The directory to store cached peers
	AddressCacheDir string

	// If this field is not nil the PeerManager will only connect to this address
	TrustedPeer net.Addr

	// Listeners to handle messages from peers. If nil, no messages will be handled.
	Listeners *peer.MessageListeners

	// An optional proxy dialer. Will use net.Dial if nil.
	Proxy proxy.Dialer

	// Function to return current block hash and height
	GetNewestBlock func() (hash *chainhash.Hash, height int32, err error)

	// The main channel over which to send outgoing events
	MsgChan chan interface{}
}

type SPVWallet

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

func NewSPVWallet

func NewSPVWallet(config *Config) (*SPVWallet, error)

func (*SPVWallet) AddScanBlockHeadsCallBack

func (w *SPVWallet) AddScanBlockHeadsCallBack(callbackFunc func(ScanBlockStruct, error) bool)

func (*SPVWallet) AddScanTxsCallBack

func (w *SPVWallet) AddScanTxsCallBack(callbackFunc func(ScanTxStruct, error) bool)

func (*SPVWallet) AddTransactionListener

func (w *SPVWallet) AddTransactionListener(callback func(wallet.TransactionCallback))

func (*SPVWallet) AddWatchedAddresses

func (w *SPVWallet) AddWatchedAddresses(addrs ...btc.Address) error

func (*SPVWallet) AddressToScript

func (w *SPVWallet) AddressToScript(addr btc.Address) ([]byte, error)

func (*SPVWallet) AssociateTransactionWithOrder

func (w *SPVWallet) AssociateTransactionWithOrder(cb wallet.TransactionCallback)

AssociateTransactionWithOrder used for ORDER_PAYMENT message

func (*SPVWallet) Balance

func (w *SPVWallet) Balance() (confirmed, unconfirmed int64)

func (*SPVWallet) Broadcast

func (s *SPVWallet) Broadcast(tx *wire.MsgTx) error

func (*SPVWallet) BumpFee

func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error)

func (*SPVWallet) ChainTip

func (w *SPVWallet) ChainTip() (uint32, chainhash.Hash)

func (*SPVWallet) ChildKey

func (w *SPVWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error)

func (*SPVWallet) Close

func (w *SPVWallet) Close()

func (*SPVWallet) ConnectedPeers

func (w *SPVWallet) ConnectedPeers() []*peer.Peer

func (*SPVWallet) CreateMultisigSignature

func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error)

func (*SPVWallet) CurrencyCode

func (w *SPVWallet) CurrencyCode() string

func (*SPVWallet) CurrentAddress

func (w *SPVWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address

func (*SPVWallet) DecodeAddress

func (w *SPVWallet) DecodeAddress(addr string) (btc.Address, error)

func (*SPVWallet) DumpHeaders

func (w *SPVWallet) DumpHeaders(writer io.Writer)

func (*SPVWallet) EstimateFee

func (w *SPVWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64

func (*SPVWallet) EstimateSpendFee

func (w *SPVWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error)

Build a spend transaction for the amount and return the transaction fee

func (*SPVWallet) ExchangeRates

func (w *SPVWallet) ExchangeRates() wallet.ExchangeRates

func (*SPVWallet) GenerateMultisigScript

func (w *SPVWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error)

func (*SPVWallet) GetConfirmations

func (w *SPVWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error)

func (*SPVWallet) GetFeePerByte

func (w *SPVWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64

func (*SPVWallet) GetKey

func (w *SPVWallet) GetKey(addr btc.Address) (*btcec.PrivateKey, error)

func (*SPVWallet) GetTransaction

func (w *SPVWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error)

func (*SPVWallet) HasKey

func (w *SPVWallet) HasKey(addr btc.Address) bool

func (*SPVWallet) IsDust

func (w *SPVWallet) IsDust(amount int64) bool

func (*SPVWallet) ListAddresses

func (w *SPVWallet) ListAddresses() []btc.Address

func (*SPVWallet) ListKeys

func (w *SPVWallet) ListKeys() []btcec.PrivateKey

func (*SPVWallet) LoadConfig

func (w *SPVWallet) LoadConfig(scryStartBlock int, intervalScanBlock time.Duration, targetScanAddress []string)

func (*SPVWallet) MasterPrivateKey

func (w *SPVWallet) MasterPrivateKey() *hd.ExtendedKey

func (*SPVWallet) MasterPublicKey

func (w *SPVWallet) MasterPublicKey() *hd.ExtendedKey

func (*SPVWallet) Mnemonic

func (w *SPVWallet) Mnemonic() string

func (*SPVWallet) Multisign

func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error)

func (*SPVWallet) NewAddress

func (w *SPVWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address

func (*SPVWallet) Params

func (w *SPVWallet) Params() *chaincfg.Params

func (*SPVWallet) ReSyncBlockchain

func (w *SPVWallet) ReSyncBlockchain(fromDate time.Time)

func (*SPVWallet) ScriptToAddress

func (w *SPVWallet) ScriptToAddress(script []byte) (btc.Address, error)

func (*SPVWallet) Spend

func (w *SPVWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error)

func (*SPVWallet) Start

func (w *SPVWallet) Start()

func (*SPVWallet) SweepAddress

func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error)

func (*SPVWallet) Transactions

func (w *SPVWallet) Transactions() ([]wallet.Txn, error)

type ScanBlockStruct

type ScanBlockStruct struct {
	BlockHash   string
	BlockHeight int
	IsScan      int
}

type ScanTxStruct

type ScanTxStruct struct {
	TxHash        string
	Value         int
	WechatTxId    string
	TargetAddress string
	IsNotice      int
	NoticedCount  int
}

type StoredHeader

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

type TxStore

type TxStore struct {
	wallet.Datastore
	// contains filtered or unexported fields
}

func NewTxStore

func NewTxStore(p *chaincfg.Params, db wallet.Datastore, keyManager *KeyManager) (*TxStore, error)

func (*TxStore) CheckDoubleSpends

func (ts *TxStore) CheckDoubleSpends(argTx *wire.MsgTx) ([]*chainhash.Hash, error)

CheckDoubleSpends takes a transaction and compares it with all transactions in the db. It returns a slice of all txids in the db which are double spent by the received tx.

func (*TxStore) GetPendingInv

func (ts *TxStore) GetPendingInv() (*wire.MsgInv, error)

GetPendingInv returns an inv message containing all txs known to the db which are at height 0 (not known to be confirmed). This can be useful on startup or to rebroadcast unconfirmed txs.

func (*TxStore) GimmeFilter

func (ts *TxStore) GimmeFilter() (*bloom.Filter, error)

... or I'm gonna fade away

func (*TxStore) Ingest

func (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (uint32, error)

Ingest puts a tx into the DB atomically. This can result in a gain, a loss, or no result. Gain or loss in satoshis is returned.

func (*TxStore) PopulateAdrs

func (ts *TxStore) PopulateAdrs() error

PopulateAdrs just puts a bunch of adrs in ram; it doesn't touch the DB

type WireService

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

func NewWireService

func NewWireService(config *WireServiceConfig) *WireService

func (*WireService) AddScanBlockHeadsCallBack

func (ws *WireService) AddScanBlockHeadsCallBack(callback func(ScanBlockStruct, error) bool)

func (*WireService) AddScanTxsCallBack

func (ws *WireService) AddScanTxsCallBack(callback func(ScanTxStruct, error) bool)

func (*WireService) Current

func (ws *WireService) Current() bool

func (*WireService) MsgChan

func (ws *WireService) MsgChan() chan interface{}

func (*WireService) Rebroadcast

func (ws *WireService) Rebroadcast()

func (*WireService) Resync

func (ws *WireService) Resync()

func (*WireService) Start

func (ws *WireService) Start()

The start function must be run in its own goroutine. The entire WireService is single threaded which means all messages are processed sequentially removing the need for complex locking.

func (*WireService) Stop

func (ws *WireService) Stop()

type WireServiceConfig

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

Directories

Path Synopsis
api
pb
Package pb is a generated protocol buffer package.
Package pb is a generated protocol buffer package.
cmd
gui

Jump to

Keyboard shortcuts

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