btcwallet

package module
v0.0.0-...-2c7e8b4 Latest Latest
Warning

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

Go to latest
Published: May 4, 2021 License: MIT Imports: 46 Imported by: 3

README

Bitcoin-Wallet

Модифицированный SPV Wallet для Bitcoin, использует наработки от Lighting Network, OpenBazaar и btcd проектов.

  1. Установить версию go. https://golang.org/doc/install
  2. Настроить GOPATH и для workspace проекта. Переходим в папку /src
  3. git clone https://github.com/OpenBazaar/Bitcoin-Wallet.git или go get github.com/OpenBazaar/Bitcoin-Wallet
  4. В папке workspace (там где GoPath) или в папке github переходим cd Bitcoin-Wallet/cmd/bitcoin
  5. go get установит все зависимости
  6. go build - соберет проект
  7. go install - установить проект
  8. Команда bitcoin запустить проект и grpc сервис.

В папке API лежит описание сервисов grpc, файл API.proto

API

  1. rpc Stop (Empty) returns (Empty) {} - остановить сервис

  2. rpc CurrentAddress (KeySelection) returns (Address) {} - получить текущий адрес. Адрес бывает двух видов внешний для получения денег и внутренний адрес. Для получения средств нужно указывать внешний - external в качестве параметра или 0 enum KeyPurpose { INTERNAL = 0; EXTERNAL = 1; }

  3. Получить новый адрес. Параметры аналогично External и Internal. rpc NewAddress (KeySelection) returns (Address) {} - основная функция для получения адреса

  4. Получить высоту цепочку (как правило используется для получения количества блоков в цепочке по отношению к текущему адреса (факт подтверждения) rpc ChainTip (Empty) returns (Height) {}

  5. Вернуть баланс кошелька rpc Balance (Empty) returns (Balances) {}

  6. Получить приватный master-ключ кошелька - требуется для бекапа rpc MasterPrivateKey (Empty) returns (Key) {}

  7. Получить публичный мастер-ключ кошелька - SID. rpc MasterPublicKey (Empty) returns (Key) {}

  8. Проверка наличия у адреса приватного адреса rpc HasKey (Address) returns (BoolResponse) {}

  9. Получить параметры конфигуарции rpc Params (Empty) returns (NetParams) {}

  10. Получить список транзакций (входящие и исходящие из кошелька) rpc Transactions (Empty) returns (TransactionList) {}

  11. Получить конкретную транзакцию rpc GetTransaction (Txid) returns (Tx) {}

  12. Получить размер комиссии оптимальный в данный момент в зависимости от размера транзакции в байтах rpc GetFeePerByte (FeeLevelSelection) returns (FeePerByte) {}

  13. Информация относительно сдачи в транзакции rpc Spend (SpendInfo) returns (Txid) {}

  14. Информация о комиссии в транзакции rpc BumpFee (Txid) returns (Txid) {}

  15. Список пиров rpc Peers (Empty) returns (PeerList) {}

  16. Добавить отслеживающий скрипт на адрес rpc AddWatchedScript (Address) returns (Empty) {}

  17. Получить количество подтверждений к транзакции rpc GetConfirmations (Txid) returns (Confirmations) {}

  18. Очистить адрес rpc SweepAddress (SweepInfo) returns (Txid) {}

  19. Синхронизировать блокчейн rpc ReSyncBlockchain (Height) returns (Empty) {}

  20. Создать мультиподпись rpc CreateMultisigSignature (CreateMultisigInfo) returns (SignatureList) {}

  21. Добавить мультиподпись rpc Multisign (MultisignInfo) returns (RawTx) {}

  22. Примерная стоимость комисии rpc EstimateFee (EstimateFeeData) returns (Fee) {}

  23. Получить приватный ключ rpc GetKey (Address) returns (Key) {}

  24. Список ключей rpc ListKeys (Empty) returns (Keys) {}

  25. Список адресов rpc ListAddresses (Empty) returns (Addresses) {}

Documentation

Index

Constants

View Source
const (
	SYNCING = 0
	WAITING = 1
)
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 (
	PRIOIRTY FeeLevel = 0
	NORMAL            = 1
	ECONOMIC          = 2
	FEE_BUMP          = 3
)
View Source
const LOOKAHEADWINDOW = 100
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 (
	ErrorInsuffientFunds error = errors.New("Insuffient funds")
	ErrorDustAmount      error = errors.New("Amount is below network dust treshold")
)

Errors

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 (
	MAX_UNCONFIRMED_TIME time.Duration = time.Hour * 24 * 7
)
View Source
var SFNodeBitcoinCash wire.ServiceFlag = 1 << 5

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) CalcMedianTimePast

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

func (*Blockchain) ChainState

func (b *Blockchain) ChainState() ChainState

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) GetBlockLocatorHashes

func (b *Blockchain) GetBlockLocatorHashes() []*chainhash.Hash

func (*Blockchain) GetCommonAncestor

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

Returns last header before reorg point

func (*Blockchain) GetEpoch

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

func (*Blockchain) GetNPrevBlockHashes

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

func (*Blockchain) SetChainState

func (b *Blockchain) SetChainState(state ChainState)

type ChainState

type ChainState int

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
}

func NewDefaultConfig

func NewDefaultConfig() *Config

type Datastore

type Datastore interface {
	Utxos() Utxos
	Stxos() Stxos
	Txns() Txns
	Keys() Keys
	WatchedScripts() WatchedScripts
}

type FeeLevel

type FeeLevel int

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) 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

	// 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 KeyPath

type KeyPath struct {
	Purpose KeyPurpose
	Index   int
}

type KeyPurpose

type KeyPurpose int

The end leaves on the HD wallet have only two possible values. External keys are those given to other people for the purpose of receiving transactions. These may include keys used for refund addresses. Internal keys are used only by the wallet, primarily for change addresses but could also be used for shuffling around UTXOs.

const (
	EXTERNAL KeyPurpose = 0
	INTERNAL            = 1
)

type Keys

type Keys interface {
	// Put a bip32 key to the database
	Put(hash160 []byte, keyPath KeyPath) error

	// Import a loose private key not part of the keychain
	ImportKey(scriptAddress []byte, key *btcec.PrivateKey) error

	// Mark the script as used
	MarkKeyAsUsed(scriptAddress []byte) error

	// Fetch the last index for the given key purpose
	// The bool should state whether the key has been used or not
	GetLastKeyIndex(purpose KeyPurpose) (int, bool, error)

	// Returns the first unused path for the given purpose
	GetPathForKey(scriptAddress []byte) (KeyPath, error)

	// Returns an imported private key given a script address
	GetKey(scriptAddress []byte) (*btcec.PrivateKey, error)

	// Returns all imported keys
	GetImported() ([]*btcec.PrivateKey, error)

	// Get a list of unused key indexes for the given purpose
	GetUnused(purpose KeyPurpose) ([]int, error)

	// Fetch all key paths
	GetAll() ([]KeyPath, error)

	// Get the number of unused keys following the last used key
	// for each key purpose.
	GetLookaheadWindows() map[KeyPurpose]int
}

Keys provides a database interface for the wallet to save key material, track used keys, and manage the look ahead 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) BlockQueue

func (pm *PeerManager) BlockQueue() chan chainhash.Hash

func (*PeerManager) CheckForMoreBlocks

func (pm *PeerManager) CheckForMoreBlocks(height uint32) bool

Iterates over our peers and sees if any are reporting a height greater than our height. If so switch them to the download peer and start the chain download again.

func (*PeerManager) DequeueTx

func (pm *PeerManager) DequeueTx(peer *peer.Peer, txid chainhash.Hash) (int32, error)

func (*PeerManager) DownloadPeer

func (pm *PeerManager) DownloadPeer() *peer.Peer

func (*PeerManager) QueueTxForDownload

func (pm *PeerManager) QueueTxForDownload(peer *peer.Peer, txid chainhash.Hash, height int32)

func (*PeerManager) ReadyPeers

func (pm *PeerManager) ReadyPeers() []*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

	// Function to get bloom filter to give to peers
	GetFilter func() (*bloom.Filter, error)

	// Function to beging chain download
	StartChainDownload func(*peer.Peer)

	// Functon returns info about the last block in the chain
	GetNewestBlock func() (hash *chainhash.Hash, height int32, err error)

	// 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
}

type SPVWallet

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

func NewSPVWallet

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

func (*SPVWallet) AddTransactionListener

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

func (*SPVWallet) AddWatchedScript

func (w *SPVWallet) AddWatchedScript(script []byte) error

func (*SPVWallet) AddressToScript

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

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) 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) 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) 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) Rebroadcast

func (w *SPVWallet) Rebroadcast()

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) (*chainhash.Hash, error)

func (*SPVWallet) Start

func (w *SPVWallet) Start()

func (*SPVWallet) SweepAddress

func (w *SPVWallet) SweepAddress(utxos []wallet.Utxo, 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 Signature

type Signature struct {
	InputIndex uint32
	Signature  []byte
}

This object contains a single signature for a multisig transaction. InputIndex specifies the index for which this signature applies.

type StoredHeader

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

type Stxo

type Stxo struct {
	// When it used to be a UTXO
	Utxo Utxo

	// The height at which it met its demise
	SpendHeight int32

	// The tx that consumed it
	SpendTxid chainhash.Hash
}

func (*Stxo) IsEqual

func (stxo *Stxo) IsEqual(alt *Stxo) bool

type Stxos

type Stxos interface {
	// Put a stxo to the database
	Put(stxo Stxo) error

	// Fetch all stxos from the db
	GetAll() ([]Stxo, error)

	// Delete a stxo from the db
	Delete(stxo Stxo) error
}

type TransactionCallback

type TransactionCallback struct {
	Txid      []byte
	Outputs   []TransactionOutput
	Inputs    []TransactionInput
	Height    int32
	Timestamp time.Time
	Value     int64
	WatchOnly bool
}

This callback is passed to any registered transaction listeners when a transaction is detected for the wallet.

type TransactionInput

type TransactionInput struct {
	OutpointHash       []byte
	OutpointIndex      uint32
	LinkedScriptPubKey []byte
	Value              int64
}

type TransactionOutput

type TransactionOutput struct {
	ScriptPubKey []byte
	Value        int64
	Index        uint32
}

type TransactionRecord

type TransactionRecord struct {
	Txid         string
	Index        uint32
	Value        int64
	ScriptPubKey string
	Spent        bool
	Timestamp    time.Time
}

OpenBazaar uses p2sh addresses for escrow. This object can be used to store a record of a transaction going into or out of such an address. Incoming transactions should have a positive value and be market as spent when the UXTO is spent. Outgoing transactions should have a negative value. The spent field isn't relevant for outgoing transactions.

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)

GetDoubleSpends 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) (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 Txn

type Txn struct {
	// Transaction ID
	Txid string

	// The value relevant to the wallet
	Value int64

	// The height at which it was mined
	Height int32

	// The time the transaction was first seen
	Timestamp time.Time

	// This transaction only involves a watch only address
	WatchOnly bool

	// Raw transaction bytes
	Bytes []byte
}

type Txns

type Txns interface {
	// Put a new transaction to the database
	Put(txn *wire.MsgTx, value, height int, timestamp time.Time, watchOnly bool) error

	// Fetch a raw tx and it's metadata given a hash
	Get(txid chainhash.Hash) (*wire.MsgTx, Txn, error)

	// Fetch all transactions from the db
	GetAll(includeWatchOnly bool) ([]Txn, error)

	// Update the height of a transaction
	UpdateHeight(txid chainhash.Hash, height int) error

	// Delete a transactions from the db
	Delete(txid *chainhash.Hash) error
}

type Utxo

type Utxo struct {
	// Previous txid and output index
	Op wire.OutPoint

	// Block height where this tx was confirmed, 0 for unconfirmed
	AtHeight int32

	// The higher the better
	Value int64

	// Output script
	ScriptPubkey []byte

	// If true this utxo will not be selected for spending. The primary
	// purpose is track multisig UTXOs which must have separate handling
	// to spend.
	WatchOnly bool
}

func (*Utxo) IsEqual

func (utxo *Utxo) IsEqual(alt *Utxo) bool

type Utxos

type Utxos interface {
	// Put a utxo to the database
	Put(utxo Utxo) error

	// Fetch all utxos from the db
	GetAll() ([]Utxo, error)

	// Make a utxo unspendable
	SetWatchOnly(utxo Utxo) error

	// Delete a utxo from the db
	Delete(utxo Utxo) error
}

type Wallet

type Wallet 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 KeyPurpose) btc.Address

	// Returns a fresh address that has never been returned by this function
	NewAddress(purpose 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() ([]Txn, error)

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

	// Get the height and best hash of the blockchain
	ChainTip() (uint32, chainhash.Hash)

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

	// Send bitcoins to an external wallet
	Spend(amount int64, addr btc.Address, feeLevel 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 []TransactionInput, outs []TransactionOutput, feePerByte uint64) uint64

	// Build a spend transaction for the amount and return the transaction fee
	EstimateSpendFee(amount int64, feeLevel FeeLevel) (uint64, error)

	// 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 []Utxo, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel FeeLevel) (*chainhash.Hash, error)

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

	// Combine signatures and optionally broadcast
	Multisign(ins []TransactionInput, outs []TransactionOutput, sigs1 []Signature, sigs2 []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(TransactionCallback))

	// Use this to re-download merkle blocks in case of missed transactions
	ReSyncBlockchain(fromTime time.Time)

	// 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()
}

type WatchedScripts

type WatchedScripts interface {
	// Add a script to watch
	Put(scriptPubKey []byte) error

	// Return all watched scripts
	GetAll() ([][]byte, error)

	// Delete a watched script
	Delete(scriptPubKey []byte) error
}

Directories

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

Jump to

Keyboard shortcuts

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