diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 4b970a0bea..141f8a58b0 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -337,16 +337,6 @@
"Comment": "v1.0.0",
"Rev": "d2cf3cdd35ce0d789056c4bc02a4d6349c947caf"
},
- {
- "ImportPath": "github.com/cpacia/BitcoinCash-Wallet",
- "Comment": "v0.3.0-59-g4c3046e",
- "Rev": "4c3046e2214e1761986809a54c3179f9a1d9cfd5"
- },
- {
- "ImportPath": "github.com/cpacia/BitcoinCash-Wallet/exchangerates",
- "Comment": "v0.3.0-59-g4c3046e",
- "Rev": "4c3046e2214e1761986809a54c3179f9a1d9cfd5"
- },
{
"ImportPath": "github.com/cpacia/bchutil",
"Rev": "b126f6a35b6c2968c0877cb4d2ac5dcf67682d27"
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/.gitignore b/vendor/github.com/cpacia/BitcoinCash-Wallet/.gitignore
deleted file mode 100644
index 66c9067146..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/.gitignore
+++ /dev/null
@@ -1,27 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
-*.prof
-.idea/
-*.iml
-.gx/
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/.travis.yml b/vendor/github.com/cpacia/BitcoinCash-Wallet/.travis.yml
deleted file mode 100644
index 6173aadd21..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: go
-go:
- - 1.7
-sudo: required
-services:
- - docker
-env:
- - "PATH=/home/travis/gopath/bin:$PATH"
-before_install:
- - go get github.com/tcnksm/ghr
- - go get github.com/axw/gocov/gocov
- - go get github.com/mattn/goveralls
-script:
- - diff -u <(echo -n) <(gofmt -d -s $(find . -type f -name '*.go' -not -path "./cmd/spvwallet/vendor/*" -not -path "./gui/resources.go" ))
- - cd $TRAVIS_BUILD_DIR && chmod a+x test_compile.sh && ./test_compile.sh
- - goveralls -coverprofile=coverage.out -service travis-ci
\ No newline at end of file
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE b/vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE
deleted file mode 100644
index 1992900d2e..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-The MIT License (MIT)
-
-Copyright (C) 2015-2016 The Lightning Network Developers
-Copyright (c) 2016-2017 The OpenBazaar Developers
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md b/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md
deleted file mode 100644
index 3429b6bfca..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Bitcoin Cash Wallet
-
-
-
-This is a fork of https://github.com/OpenBazaar/spvwallet modfied for Bitcoin Cash. It includes a fully functional GUI wallet and CLI.
-
-It uses stock btcd plus a few cash specific modifications found in the [bchutil](https://github.com/cpacia/bchutil) package.
-
-To compile and run:
-```bash
-go get github.com/cpacia/BitcoinCash-Wallet
-make install
-bitcoincash
-```
-Or download a pre-compiled version from [releases](https://github.com/cpacia/BitcoinCash-Wallet/releases).
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go
deleted file mode 100644
index adaa0aaad5..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/blockchain.go
+++ /dev/null
@@ -1,488 +0,0 @@
-// Copyright (C) 2015-2016 The Lightning Network Developers
-// Copyright (c) 2016-2017 The OpenBazaar Developers
-
-package bitcoincash
-
-import (
- "errors"
- "fmt"
- "github.com/btcsuite/btcd/blockchain"
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/wire"
- "math/big"
- "sort"
- "sync"
- "time"
-)
-
-// Blockchain settings. These are kindof Bitcoin specific, but not contained in
-// chaincfg.Params so they'll go here. If you're into the [ANN]altcoin scene,
-// you may want to paramaterize these constants.
-const (
- targetSpacing = 600
- medianTimeBlocks = 11
-)
-
-var OrphanHeaderError = errors.New("header does not extend any known headers")
-
-// Wrapper around Headers implementation that handles all blockchain operations
-type Blockchain struct {
- lock *sync.Mutex
- params *chaincfg.Params
- db Headers
- crationDate time.Time
- checkpoint Checkpoint
-}
-
-func NewBlockchain(filePath string, walletCreationDate time.Time, params *chaincfg.Params) (*Blockchain, error) {
- hdb, err := NewHeaderDB(filePath)
- if err != nil {
- return nil, err
- }
- b := &Blockchain{
- lock: new(sync.Mutex),
- params: params,
- db: hdb,
- crationDate: walletCreationDate,
- }
- b.checkpoint = GetCheckpoint(walletCreationDate, params)
-
- h, err := b.db.Height()
- if h == 0 || err != nil {
- log.Info("Initializing headers db with checkpoints")
- // Put the checkpoint to the db
- sh := StoredHeader{
- header: b.checkpoint.Header,
- height: b.checkpoint.Height,
- totalWork: big.NewInt(0),
- }
- err := b.db.Put(sh, true)
- if err != nil {
- return nil, err
- }
- }
- return b, nil
-}
-
-func (b *Blockchain) CommitHeader(header wire.BlockHeader) (bool, *StoredHeader, uint32, error) {
- b.lock.Lock()
- defer b.lock.Unlock()
- newTip := false
- var commonAncestor *StoredHeader
- // Fetch our current best header from the db
- bestHeader, err := b.db.GetBestHeader()
- if err != nil {
- return false, nil, 0, err
- }
- tipHash := bestHeader.header.BlockHash()
- var parentHeader StoredHeader
-
- // If the tip is also the parent of this header, then we can save a database read by skipping
- // the lookup of the parent header. Otherwise (ophan?) we need to fetch the parent.
- if header.PrevBlock.IsEqual(&tipHash) {
- parentHeader = bestHeader
- } else {
- parentHeader, err = b.db.GetPreviousHeader(header)
- if err != nil {
- return false, nil, 0, fmt.Errorf("Header %s does not extend any known headers", header.BlockHash().String())
- }
- }
- valid := b.CheckHeader(header, parentHeader)
- if !valid {
- return false, nil, 0, nil
- }
- // If this block is already the tip, return
- headerHash := header.BlockHash()
- if tipHash.IsEqual(&headerHash) {
- return newTip, nil, 0, nil
- }
- // Add the work of this header to the total work stored at the previous header
- cumulativeWork := new(big.Int).Add(parentHeader.totalWork, blockchain.CalcWork(header.Bits))
-
- // If the cumulative work is greater than the total work of our best header
- // then we have a new best header. Update the chain tip and check for a reorg.
- if cumulativeWork.Cmp(bestHeader.totalWork) == 1 {
- newTip = true
- prevHash := parentHeader.header.BlockHash()
- // If this header is not extending the previous best header then we have a reorg.
- if !tipHash.IsEqual(&prevHash) {
- commonAncestor, err = b.GetCommonAncestor(StoredHeader{header: header, height: parentHeader.height + 1}, bestHeader)
- if err != nil {
- log.Errorf("Error calculating common ancestor: %s", err.Error())
- return newTip, commonAncestor, 0, err
- }
- log.Warningf("REORG!!! REORG!!! REORG!!! At block %d, Wiped out %d blocks", int(bestHeader.height), int(bestHeader.height-commonAncestor.height))
- }
- }
- newHeight := parentHeader.height + 1
- // Put the header to the database
- err = b.db.Put(StoredHeader{
- header: header,
- height: newHeight,
- totalWork: cumulativeWork,
- }, newTip)
- if err != nil {
- return newTip, commonAncestor, 0, err
- }
- return newTip, commonAncestor, newHeight, nil
-}
-
-func (b *Blockchain) CheckHeader(header wire.BlockHeader, prevHeader StoredHeader) bool {
- height := prevHeader.height
-
- // Due to the rolling difficulty period our checkpoint block consists of a block and a hash of a block 146 blocks later
- // During this period we can skip the validity checks as long as block checkpoint + 146 matches the hardcoded hash.
- if height+1 <= b.checkpoint.Height+147 {
- h := header.BlockHash()
- if b.checkpoint.Check2 != nil && height+1 == b.checkpoint.Height+147 && !b.checkpoint.Check2.IsEqual(&h) {
- return false
- }
- return true
- }
-
- // Get hash of n-1 header
- prevHash := prevHeader.header.BlockHash()
-
- // Check if headers link together. That whole 'blockchain' thing.
- if prevHash.IsEqual(&header.PrevBlock) == false {
- log.Errorf("Headers %d and %d don't link.\n", height, height+1)
- return false
- }
-
- // Check the header meets the difficulty requirement
- if b.params.Name != chaincfg.RegressionNetParams.Name { // Don't need to check difficulty on regtest
- diffTarget, err := b.calcRequiredWork(header, int32(height+1), prevHeader)
- if err != nil {
- log.Errorf("Error calclating difficulty", err)
- return false
- }
- if header.Bits != diffTarget && b.params.Name == chaincfg.MainNetParams.Name {
- log.Warningf("Block %d %s incorrect difficulty. Read %d, expect %d\n",
- height+1, header.BlockHash().String(), header.Bits, diffTarget)
- return false
- } else if diffTarget == b.params.PowLimitBits && header.Bits > diffTarget && b.params.Name == chaincfg.TestNet3Params.Name {
- log.Warningf("Block %d %s incorrect difficulty. Read %d, expect %d\n",
- height+1, header.BlockHash().String(), header.Bits, diffTarget)
- return false
- }
- }
-
- // Check if there's a valid proof of work. That whole "Bitcoin" thing.
- if !checkProofOfWork(header, b.params) {
- log.Debugf("Block %d bad proof of work.\n", height+1)
- return false
- }
-
- return true // it must have worked if there's no errors and got to the end.
-}
-
-// Get the PoW target this block should meet. We may need to handle a difficulty adjustment
-// or testnet difficulty rules.
-func (b *Blockchain) calcRequiredWork(header wire.BlockHeader, height int32, prevHeader StoredHeader) (uint32, error) {
- // Special difficulty rule for testnet
- if b.params.ReduceMinDifficulty && header.Timestamp.After(prevHeader.header.Timestamp.Add(targetSpacing*2)) {
- return b.params.PowLimitBits, nil
- }
-
- suitableHeader, err := b.GetSuitableBlock(prevHeader)
- if err != nil {
- log.Error(err)
- return 0, err
- }
- epoch, err := b.GetEpoch(prevHeader.header)
- if err != nil {
- log.Error(err)
- return 0, err
- }
- return calcDiffAdjust(epoch, suitableHeader, b.params), nil
-}
-
-func (b *Blockchain) CalcMedianTimePast(header wire.BlockHeader) (time.Time, error) {
- timestamps := make([]int64, medianTimeBlocks)
- numNodes := 0
- iterNode := StoredHeader{header: header}
- var err error
-
- for i := 0; i < medianTimeBlocks; i++ {
- numNodes++
- timestamps[i] = iterNode.header.Timestamp.Unix()
- iterNode, err = b.db.GetPreviousHeader(iterNode.header)
- if err != nil {
- return time.Time{}, err
- }
- }
- timestamps = timestamps[:numNodes]
- sort.Sort(timeSorter(timestamps))
- medianTimestamp := timestamps[numNodes/2]
- return time.Unix(medianTimestamp, 0), nil
-}
-
-// Rollsback and grabs block n-144, n-145, and n-146, sorts them by timestamps and returns the middle header.
-func (b *Blockchain) GetEpoch(hdr wire.BlockHeader) (StoredHeader, error) {
- sh := StoredHeader{header: hdr}
- var err error
- for i := 0; i < 144; i++ {
- sh, err = b.db.GetPreviousHeader(sh.header)
- if err != nil {
- return sh, err
- }
- }
- oneFourtyFour := sh
- sh, err = b.db.GetPreviousHeader(oneFourtyFour.header)
- if err != nil {
- return sh, err
- }
- oneFourtyFive := sh
- sh, err = b.db.GetPreviousHeader(oneFourtyFive.header)
- if err != nil {
- return sh, err
- }
- oneFourtySix := sh
- headers := []StoredHeader{oneFourtyFour, oneFourtyFive, oneFourtySix}
- sort.Sort(blockSorter(headers))
- return headers[1], nil
-}
-
-// Rollsback grabs the last two headers before this one. Sorts the three and returns the mid.
-func (b *Blockchain) GetSuitableBlock(hdr StoredHeader) (StoredHeader, error) {
- n := hdr
- sh, err := b.db.GetPreviousHeader(hdr.header)
- if err != nil {
- return sh, err
- }
- n1 := sh
- sh, err = b.db.GetPreviousHeader(n1.header)
- if err != nil {
- return sh, err
- }
- n2 := sh
- headers := []StoredHeader{n, n1, n2}
- sort.Sort(blockSorter(headers))
- return headers[1], nil
-}
-
-func (b *Blockchain) GetNPrevBlockHashes(n int) []*chainhash.Hash {
- var ret []*chainhash.Hash
- hdr, err := b.db.GetBestHeader()
- if err != nil {
- return ret
- }
- tipSha := hdr.header.BlockHash()
- ret = append(ret, &tipSha)
- for i := 0; i < n-1; i++ {
- hdr, err = b.db.GetPreviousHeader(hdr.header)
- if err != nil {
- return ret
- }
- shaHash := hdr.header.BlockHash()
- ret = append(ret, &shaHash)
- }
- return ret
-}
-
-func (b *Blockchain) GetBlockLocator() blockchain.BlockLocator {
- var ret []*chainhash.Hash
- parent, err := b.db.GetBestHeader()
- if err != nil {
- return ret
- }
-
- rollback := func(parent StoredHeader, n int) (StoredHeader, error) {
- for i := 0; i < n; i++ {
- parent, err = b.db.GetPreviousHeader(parent.header)
- if err != nil {
- return parent, err
- }
- }
- return parent, nil
- }
-
- step := 1
- start := 0
- for {
- if start >= 9 {
- step *= 2
- start = 0
- }
- hash := parent.header.BlockHash()
- ret = append(ret, &hash)
- if len(ret) == 500 {
- break
- }
- parent, err = rollback(parent, step)
- if err != nil {
- break
- }
- start += 1
- }
- return blockchain.BlockLocator(ret)
-}
-
-// Returns last header before reorg point
-func (b *Blockchain) GetCommonAncestor(bestHeader, prevBestHeader StoredHeader) (*StoredHeader, error) {
- var err error
- rollback := func(parent StoredHeader, n int) (StoredHeader, error) {
- for i := 0; i < n; i++ {
- parent, err = b.db.GetPreviousHeader(parent.header)
- if err != nil {
- return parent, err
- }
- }
- return parent, nil
- }
-
- majority := bestHeader
- minority := prevBestHeader
- if bestHeader.height > prevBestHeader.height {
- majority, err = rollback(majority, int(bestHeader.height-prevBestHeader.height))
- if err != nil {
- return nil, err
- }
- } else if prevBestHeader.height > bestHeader.height {
- minority, err = rollback(minority, int(prevBestHeader.height-bestHeader.height))
- if err != nil {
- return nil, err
- }
- }
-
- for {
- majorityHash := majority.header.BlockHash()
- minorityHash := minority.header.BlockHash()
- if majorityHash.IsEqual(&minorityHash) {
- return &majority, nil
- }
- majority, err = b.db.GetPreviousHeader(majority.header)
- if err != nil {
- return nil, err
- }
- minority, err = b.db.GetPreviousHeader(minority.header)
- if err != nil {
- return nil, err
- }
- }
-}
-
-// Rollback the header database to the last header before time t.
-// We shouldn't go back further than the checkpoint
-func (b *Blockchain) Rollback(t time.Time) error {
- b.lock.Lock()
- defer b.lock.Unlock()
- checkpoint := GetCheckpoint(b.crationDate, b.params)
- checkPointHash := checkpoint.Header.BlockHash()
- sh, err := b.db.GetBestHeader()
- if err != nil {
- return err
- }
- // If t is greater than the timestamp at the tip then do nothing
- if sh.header.Timestamp.Before(t) {
- return nil
- }
- // If the tip is our checkpoint then do nothing
- checkHash := sh.header.BlockHash()
- if checkHash.IsEqual(&checkPointHash) {
- return nil
- }
- rollbackHeight := uint32(0)
- for i := 0; i < 1000000000; i++ {
- sh, err = b.db.GetPreviousHeader(sh.header)
- if err != nil {
- return err
- }
- checkHash := sh.header.BlockHash()
- // If we rolled back to the checkpoint then stop here and set the checkpoint as the tip
- if checkHash.IsEqual(&checkPointHash) {
- rollbackHeight = checkpoint.Height
- break
- }
- // If we hit a header created before t then stop here and set this header as the tip
- if sh.header.Timestamp.Before(t) {
- rollbackHeight = sh.height
- break
- }
- }
- err = b.db.DeleteAfter(rollbackHeight)
- if err != nil {
- return err
- }
- return b.db.Put(sh, true)
-}
-
-func (b *Blockchain) BestBlock() (StoredHeader, error) {
- sh, err := b.db.GetBestHeader()
- if err != nil {
- return StoredHeader{}, err
- }
- return sh, nil
-}
-
-func (b *Blockchain) GetHeader(hash *chainhash.Hash) (StoredHeader, error) {
- sh, err := b.db.GetHeader(*hash)
- if err != nil {
- return sh, err
- }
- return sh, nil
-}
-
-func (b *Blockchain) Close() {
- b.lock.Lock()
- b.db.Close()
-}
-
-// Verifies the header hashes into something lower than specified by the 4-byte bits field.
-func checkProofOfWork(header wire.BlockHeader, p *chaincfg.Params) bool {
- target := blockchain.CompactToBig(header.Bits)
-
- // The target must more than 0. Why can you even encode negative...
- if target.Sign() <= 0 {
- log.Debugf("Block target %064x is neagtive(??)\n", target.Bytes())
- return false
- }
- // The target must be less than the maximum allowed (difficulty 1)
- if target.Cmp(p.PowLimit) > 0 {
- log.Debugf("Block target %064x is "+
- "higher than max of %064x", target, p.PowLimit.Bytes())
- return false
- }
- // The header hash must be less than the claimed target in the header.
- blockHash := header.BlockHash()
- hashNum := blockchain.HashToBig(&blockHash)
- if hashNum.Cmp(target) > 0 {
- log.Debugf("Block hash %064x is higher than "+
- "required target of %064x", hashNum, target)
- return false
- }
- return true
-}
-
-// This function takes in a start and end block header and uses the timestamps in each
-// to calculate how much of a difficulty adjustment is needed. It returns a new compact
-// difficulty target.
-func calcDiffAdjust(start, end StoredHeader, p *chaincfg.Params) uint32 {
- work := new(big.Int).Sub(end.totalWork, start.totalWork)
-
- // In order to avoid difficulty cliffs, we bound the amplitude of the
- // adjustement we are going to do.
- duration := end.header.Timestamp.Unix() - start.header.Timestamp.Unix()
- if duration > 288*int64(targetSpacing) {
- duration = 288 * int64(targetSpacing)
- } else if duration < 72*int64(targetSpacing) {
- duration = 72 * int64(targetSpacing)
- }
-
- projectedWork := new(big.Int).Mul(work, big.NewInt(int64(targetSpacing)))
-
- pw := new(big.Int).Div(projectedWork, big.NewInt(duration))
-
- e := new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil)
-
- nt := new(big.Int).Sub(e, pw)
-
- newTarget := new(big.Int).Div(nt, pw)
-
- // clip again if above minimum target (too easy)
- if newTarget.Cmp(p.PowLimit) > 0 {
- newTarget.Set(p.PowLimit)
- }
- return blockchain.BigToCompact(newTarget)
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go
deleted file mode 100644
index 67322f1af2..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/checkpoints.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package bitcoincash
-
-import (
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/wire"
- "time"
-)
-
-type Checkpoint struct {
- Height uint32
- Header wire.BlockHeader
- Check2 *chainhash.Hash
-}
-
-var mainnetCheckpoints []Checkpoint
-var testnet3Checkpoints []Checkpoint
-var regtestCheckpoint Checkpoint
-
-func init() {
- // Mainnet
- mainnetPrev, _ := chainhash.NewHashFromStr("0000000000000000011ebf65b60d0a3de80b8175be709d653b4c1a1beeb6ab9c")
- mainnetMerk, _ := chainhash.NewHashFromStr("8ebf2179d8b1ba0aaf5f15357f963b56f53a8c6207e0156b4b6def119be61bee")
- check2, _ := chainhash.NewHashFromStr("000000000000000001250f09f253d22d6ef14e924eccb7c1bbaa0695269cef59")
- mainnetCheckpoints = append(mainnetCheckpoints, Checkpoint{
- Height: 504032,
- Header: wire.BlockHeader{
- Version: 536870912,
- PrevBlock: *mainnetPrev,
- MerkleRoot: *mainnetMerk,
- Timestamp: time.Unix(1510606995, 0),
- Bits: 403026987,
- Nonce: 273755974,
- },
- Check2: check2,
- })
- if mainnetCheckpoints[0].Header.BlockHash().String() != "00000000000000000343e9875012f2062554c8752929892c82a0c0743ac7dcfd" {
- panic("Invalid checkpoint")
- }
-
- // Testnet3
- testnet3Prev, _ := chainhash.NewHashFromStr("00000000824633a21bc41dccbd7a6d159a4deebaece6f6dcf2093301aea040a5")
- testnet3Merk, _ := chainhash.NewHashFromStr("d69264d97d77da1b9bf0ae031512a89e0607e8200be29a74163a39b8558f5714")
- testnetCheck2, _ := chainhash.NewHashFromStr("00000000000044040acf28b1bab8706f09f7862275b65a03580b6db136ad2dbd")
- testnet3Checkpoints = append(testnet3Checkpoints, Checkpoint{
- Height: 1189213,
- Header: wire.BlockHeader{
- Version: 536870912,
- PrevBlock: *testnet3Prev,
- MerkleRoot: *testnet3Merk,
- Timestamp: time.Unix(1510739152, 0),
- Bits: 486604799,
- Nonce: 2325788686,
- },
- Check2: testnetCheck2,
- })
- if testnet3Checkpoints[0].Header.BlockHash().String() != "000000001f734385476b82be8eb10512c9fb5bd1534cf3ceb4af2d47a7b20ff7" {
- panic("Invalid checkpoint")
- }
-
- // Regtest
- regtestCheckpoint = Checkpoint{0, chaincfg.RegressionNetParams.GenesisBlock.Header, nil}
-}
-
-func GetCheckpoint(walletCreationDate time.Time, params *chaincfg.Params) Checkpoint {
- switch params.Name {
- case chaincfg.MainNetParams.Name:
- for i := len(mainnetCheckpoints) - 1; i >= 0; i-- {
- if walletCreationDate.After(mainnetCheckpoints[i].Header.Timestamp) {
- return mainnetCheckpoints[i]
- }
- }
- return mainnetCheckpoints[0]
- case chaincfg.TestNet3Params.Name:
- for i := len(testnet3Checkpoints) - 1; i >= 0; i-- {
- if walletCreationDate.After(testnet3Checkpoints[i].Header.Timestamp) {
- return testnet3Checkpoints[i]
- }
- }
- return testnet3Checkpoints[0]
-
- default:
- return regtestCheckpoint
- }
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go
deleted file mode 100644
index bb8eaccaee..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/config.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package bitcoincash
-
-import (
- "github.com/OpenBazaar/wallet-interface"
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/mitchellh/go-homedir"
- "github.com/op/go-logging"
- "golang.org/x/net/proxy"
- "net"
- "net/url"
- "os"
- "path/filepath"
- "runtime"
- "time"
-)
-
-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
-
- // A slice of additional items to add to the bloom filter
- AdditionalFilters [][]byte
-
- // Disable exchange rate provider
- DisableExchangeRates bool
-}
-
-func NewDefaultConfig() *Config {
- repoPath, _ := getRepoPath()
- _, ferr := os.Stat(repoPath)
- if os.IsNotExist(ferr) {
- os.Mkdir(repoPath, os.ModePerm)
- }
- feeApi, _ := url.Parse("https://bitcoinfees.21.co/api/v1/fees/recommended")
- return &Config{
- Params: &chaincfg.MainNetParams,
- UserAgent: "spvwallet",
- RepoPath: repoPath,
- LowFee: 140,
- MediumFee: 160,
- HighFee: 180,
- MaxFee: 2000,
- FeeAPI: *feeApi,
- Logger: logging.NewLogBackend(os.Stdout, "", 0),
- }
-}
-
-func getRepoPath() (string, error) {
- // Set default base path and directory name
- path := "~"
- directoryName := "bitcoincash"
-
- // Override OS-specific names
- switch runtime.GOOS {
- case "linux":
- directoryName = ".bitcoincash"
- case "darwin":
- path = "~/Library/Application Support"
- }
-
- // Join the path and directory name, then expand the home path
- fullPath, err := homedir.Expand(filepath.Join(path, directoryName))
- if err != nil {
- return "", err
- }
-
- // Return the shortest lexical representation of the path
- return filepath.Clean(fullPath), nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go
deleted file mode 100644
index 93e7109bde..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/eight333.go
+++ /dev/null
@@ -1,777 +0,0 @@
-package bitcoincash
-
-import (
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- peerpkg "github.com/btcsuite/btcd/peer"
- "github.com/btcsuite/btcd/wire"
- "net"
- "time"
-)
-
-const (
- maxRequestedTxns = wire.MaxInvPerMsg
- maxFalsePositives = 7
-)
-
-// newPeerMsg signifies a newly connected peer to the block handler.
-type newPeerMsg struct {
- peer *peerpkg.Peer
-}
-
-// donePeerMsg signifies a newly disconnected peer to the block handler.
-type donePeerMsg struct {
- peer *peerpkg.Peer
-}
-
-// headersMsg packages a bitcoin headers message and the peer it came from
-// together so the handler has access to that information.
-type headersMsg struct {
- headers *wire.MsgHeaders
- peer *peerpkg.Peer
-}
-
-// merkleBlockMsg packages a merkle block message and the peer it came from
-// together so the handler has access to that information.
-type merkleBlockMsg struct {
- merkleBlock *wire.MsgMerkleBlock
- peer *peerpkg.Peer
-}
-
-// invMsg packages a bitcoin inv message and the peer it came from together
-// so the handler has access to that information.
-type invMsg struct {
- inv *wire.MsgInv
- peer *peerpkg.Peer
-}
-
-type heightAndTime struct {
- height uint32
- timestamp time.Time
-}
-
-// txMsg packages a bitcoin tx message and the peer it came from together
-// so the handler has access to that information.
-type txMsg struct {
- tx *wire.MsgTx
- peer *peerpkg.Peer
- reply chan struct{}
-}
-
-type updateFiltersMsg struct{}
-
-type WireServiceConfig struct {
- params *chaincfg.Params
- chain *Blockchain
- txStore *TxStore
- walletCreationDate time.Time
- minPeersForSync int
-}
-
-// peerSyncState stores additional information that the WireService tracks
-// about a peer.
-type peerSyncState struct {
- syncCandidate bool
- requestQueue []*wire.InvVect
- requestedTxns map[chainhash.Hash]heightAndTime
- requestedBlocks map[chainhash.Hash]struct{}
- falsePositives uint32
- blockScore int32
-}
-
-type WireService struct {
- params *chaincfg.Params
- chain *Blockchain
- txStore *TxStore
- walletCreationDate time.Time
- syncPeer *peerpkg.Peer
- peerStates map[*peerpkg.Peer]*peerSyncState
- requestedTxns map[chainhash.Hash]heightAndTime
- requestedBlocks map[chainhash.Hash]struct{}
- mempool map[chainhash.Hash]struct{}
- msgChan chan interface{}
- quit chan struct{}
- minPeersForSync int
- zeroHash chainhash.Hash
-}
-
-func NewWireService(config *WireServiceConfig) *WireService {
- return &WireService{
- params: config.params,
- chain: config.chain,
- walletCreationDate: config.walletCreationDate,
- minPeersForSync: config.minPeersForSync,
- txStore: config.txStore,
- peerStates: make(map[*peerpkg.Peer]*peerSyncState),
- requestedTxns: make(map[chainhash.Hash]heightAndTime),
- requestedBlocks: make(map[chainhash.Hash]struct{}),
- mempool: make(map[chainhash.Hash]struct{}),
- msgChan: make(chan interface{}),
- }
-}
-
-func (ws *WireService) MsgChan() chan interface{} {
- return ws.msgChan
-}
-
-// 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 (ws *WireService) Start() {
- ws.quit = make(chan struct{})
- best, err := ws.chain.BestBlock()
- if err != nil {
- log.Error(err)
- }
- log.Infof("Starting wire service at height %d", int(best.height))
-out:
- for {
- select {
- case m := <-ws.msgChan:
- switch msg := m.(type) {
- case newPeerMsg:
- ws.handleNewPeerMsg(msg.peer)
- case donePeerMsg:
- ws.handleDonePeerMsg(msg.peer)
- case headersMsg:
- ws.handleHeadersMsg(&msg)
- case merkleBlockMsg:
- ws.handleMerkleBlockMsg(&msg)
- case invMsg:
- ws.handleInvMsg(&msg)
- case txMsg:
- ws.handleTxMsg(&msg)
- case updateFiltersMsg:
- ws.handleUpdateFiltersMsg()
- default:
- log.Warningf("Unknown message type sent to WireService message chan: %T", msg)
- }
- case <-ws.quit:
- break out
- }
- }
-}
-
-func (ws *WireService) Stop() {
- ws.syncPeer = nil
- close(ws.quit)
-}
-
-func (ws *WireService) Resync() {
- ws.startSync(ws.syncPeer)
-}
-
-func (ws *WireService) handleNewPeerMsg(peer *peerpkg.Peer) {
- // Initialize the peer state
- ws.peerStates[peer] = &peerSyncState{
- syncCandidate: ws.isSyncCandidate(peer),
- requestedTxns: make(map[chainhash.Hash]heightAndTime),
- requestedBlocks: make(map[chainhash.Hash]struct{}),
- }
-
- ws.updateFilterAndSend(peer)
-
- // If we don't have a sync peer and we are not current we should start a sync
- if ws.syncPeer == nil && !ws.Current() {
- ws.startSync(nil)
- }
-}
-
-// isSyncCandidate returns whether or not the peer is a candidate to consider
-// syncing from.
-func (ws *WireService) isSyncCandidate(peer *peerpkg.Peer) bool {
- // Typically a peer is not a candidate for sync if it's not a full node,
- // however regression test is special in that the regression tool is
- // not a full node and still needs to be considered a sync candidate.
- if ws.params.Name == chaincfg.RegressionNetParams.Name {
- // The peer is not a candidate if it's not coming from localhost
- // or the hostname can't be determined for some reason.
- host, _, err := net.SplitHostPort(peer.Addr())
- if err != nil {
- return false
- }
-
- if host != "127.0.0.1" && host != "localhost" {
- return false
- }
- } else {
- // The peer is not a candidate for sync if it's not a full node
- nodeServices := peer.Services()
- if nodeServices&wire.SFNodeNetwork != wire.SFNodeNetwork {
- return false
- }
- }
-
- // Candidate if all checks passed.
- return true
-}
-
-func (ws *WireService) startSync(syncPeer *peerpkg.Peer) {
- // Wait for a minimum number of peers to connect. This makes sure we have a good
- // selection to choose from before starting the sync.
- if len(ws.peerStates) < ws.minPeersForSync {
- return
- }
- ws.Rebroadcast()
- bestBlock, err := ws.chain.BestBlock()
- if err != nil {
- log.Error(err)
- return
- }
- var bestPeer *peerpkg.Peer
- if syncPeer == nil {
- var bestPeerHeight int32
- for peer, state := range ws.peerStates {
- if !state.syncCandidate {
- continue
- }
-
- // Remove sync candidate peers that are no longer candidates due
- // to passing their latest known block. NOTE: The < is
- // intentional as opposed to <=. While technically the peer
- // doesn't have a later block when it's equal, it will likely
- // have one soon so it is a reasonable choice. It also allows
- // the case where both are at 0 such as during regression test.
- if peer.LastBlock() < int32(bestBlock.height) {
- state.syncCandidate = false
- continue
- }
-
- // Select peer which is reporting the greatest height
- if peer.LastBlock() > bestPeerHeight {
- bestPeer = peer
- bestPeerHeight = peer.LastBlock()
- }
- }
- } else {
- bestPeer = syncPeer
- }
-
- // Start syncing this bitch
- if bestPeer != nil {
- // TODO: use checkpoints here
- ws.syncPeer = bestPeer
-
- // Clear the requestedBlocks if the sync peer changes, otherwise
- // we may ignore blocks we need that the last sync peer failed
- // to send.
- ws.requestedBlocks = make(map[chainhash.Hash]struct{})
-
- locator := ws.chain.GetBlockLocator()
-
- // If the best header we have was created before this wallet then we can sync just headers
- // up to the wallet creation date since we know there wont be any transactions in those
- // blocks we're interested in. However, if we're past the wallet creation date we need to
- // start downloading merkle blocks so we learn of the wallet's transactions. We'll use a
- // buffer of one week to make sure we don't miss anything.
- log.Infof("Starting chain download from %s", bestPeer)
- if bestBlock.header.Timestamp.Before(ws.walletCreationDate.Add(-time.Hour * 24 * 7)) {
- bestPeer.PushGetHeadersMsg(locator, &ws.zeroHash)
- } else {
- bestPeer.PushGetBlocksMsg(locator, &ws.zeroHash)
- }
- } else {
- log.Warning("No sync candidates available")
- }
-}
-
-func (ws *WireService) Current() bool {
- best, err := ws.chain.BestBlock()
- if err != nil {
- return false
- }
-
- // If our best header's timestamp was more than 24 hours ago, we're probably not current
- if best.header.Timestamp.Before(time.Now().Add(-24 * time.Hour)) {
- return false
- }
-
- // Check our other peers to see if any are reporting a greater height than we have
- for peer := range ws.peerStates {
- if int32(best.height) < peer.LastBlock() {
- return false
- }
- }
- return true
-}
-
-func (ws *WireService) handleDonePeerMsg(peer *peerpkg.Peer) {
- state, exists := ws.peerStates[peer]
- if !exists {
- return
- }
-
- // Remove the peer from the list of candidate peers.
- delete(ws.peerStates, peer)
-
- // Remove requested transactions from the global map so that they will
- // be fetched from elsewhere next time we get an inv.
- for txHash := range state.requestedTxns {
- delete(ws.requestedTxns, txHash)
- }
-
- // Remove requested blocks from the global map so that they will be
- // fetched from elsewhere next time we get an inv.
- // TODO: we could possibly here check which peers have these blocks
- // and request them now to speed things up a little.
- for blockHash := range state.requestedBlocks {
- delete(ws.requestedBlocks, blockHash)
- }
-
- // Attempt to find a new peer to sync from if the quitting peer is the
- // sync peer.
- if ws.syncPeer == peer && !ws.Current() {
- log.Info("Sync peer disconnected")
- ws.syncPeer = nil
- ws.startSync(nil)
- }
-}
-
-// handleHeadersMsg handles block header messages from all peers. Headers are
-// requested when performing a headers-first sync.
-func (ws *WireService) handleHeadersMsg(hmsg *headersMsg) {
- peer := hmsg.peer
- if peer != ws.syncPeer {
- log.Warning("Received header message from a peer that isn't our sync peer")
- peer.Disconnect()
- return
- }
- _, exists := ws.peerStates[peer]
- if !exists {
- log.Warningf("Received headers message from unknown peer %s", peer)
- peer.Disconnect()
- return
- }
-
- msg := hmsg.headers
- numHeaders := len(msg.Headers)
-
- // Nothing to do for an empty headers message
- if numHeaders == 0 {
- return
- }
-
- // Process each header we received. Make sure when check that each one is before our
- // wallet creation date (minus the buffer). If we pass the creation date we will exit
- // request merkle blocks from this point forward and exit the function.
- badHeaders := 0
- for _, blockHeader := range msg.Headers {
- if blockHeader.Timestamp.Before(ws.walletCreationDate.Add(-time.Hour * 24 * 7)) {
- _, _, height, err := ws.chain.CommitHeader(*blockHeader)
- if err != nil {
- badHeaders++
- log.Errorf("Commit header error: %s", err.Error())
- }
- log.Infof("Received header %s at height %d", blockHeader.BlockHash().String(), height)
- } else {
- log.Info("Switching to downloading merkle blocks")
- locator := ws.chain.GetBlockLocator()
- peer.PushGetBlocksMsg(locator, &ws.zeroHash)
- return
- }
- }
- // Usually the peer will send the header at the tip of the chain in each batch. This will trigger
- // one commit error so we'll consider that acceptable, but anything more than that suggests misbehavior
- // so we'll dump this peer.
- if badHeaders > 1 {
- log.Warningf("Disconnecting from peer %s because he sent us too many bad headers", peer)
- peer.Disconnect()
- return
- }
-
- // Request the next batch of headers
- locator := ws.chain.GetBlockLocator()
- err := peer.PushGetHeadersMsg(locator, &ws.zeroHash)
- if err != nil {
- log.Warningf("Failed to send getheaders message to peer %s: %v", peer.Addr(), err)
- return
- }
-}
-
-// handleMerkleBlockMsg handles merkle block messages from all peers. Merkle blocks are
-// requested in response to inv packets both during initial sync and after.
-func (ws *WireService) handleMerkleBlockMsg(bmsg *merkleBlockMsg) {
- peer := bmsg.peer
-
- // We don't need to process blocks when we're syncing. They wont connect anyway
- if peer != ws.syncPeer && !ws.Current() {
- log.Warningf("Received block from %s when we aren't current", peer)
- return
- }
- state, exists := ws.peerStates[peer]
- if !exists {
- log.Warningf("Received merkle block message from unknown peer %s", peer)
- peer.Disconnect()
- return
- }
-
- // If we didn't ask for this block then the peer is misbehaving.
- merkleBlock := bmsg.merkleBlock
- header := merkleBlock.Header
- blockHash := header.BlockHash()
- if _, exists = state.requestedBlocks[blockHash]; !exists {
- // The regression test intentionally sends some blocks twice
- // to test duplicate block insertion fails. Don't disconnect
- // the peer or ignore the block when we're in regression test
- // mode in this case so the chain code is actually fed the
- // duplicate blocks.
- if ws.params.Name != chaincfg.RegressionNetParams.Name {
- log.Warningf("Got unrequested block %v from %s -- "+
- "disconnecting", blockHash, peer.Addr())
- peer.Disconnect()
- return
- }
- }
-
- // Remove block from request maps. Either chain will know about it and
- // so we shouldn't have any more instances of trying to fetch it, or we
- // will fail the insert and thus we'll retry next time we get an inv.
- delete(state.requestedBlocks, blockHash)
- delete(ws.requestedBlocks, blockHash)
-
- txids, err := checkMBlock(merkleBlock)
- if err != nil {
- log.Warningf("Peer %s sent an invalid MerkleBlock", peer)
- peer.Disconnect()
- return
- }
-
- newBlock, reorg, newHeight, err := ws.chain.CommitHeader(header)
- // If this is an orphan block which doesn't connect to the chain, it's possible
- // that we might be synced on the longest chain, but not the most-work chain like
- // we should be. To make sure this isn't the case, let's sync from the peer who
- // sent us this orphan block.
- if err == OrphanHeaderError && ws.Current() {
- log.Debug("Received orphan header, checking peer for more blocks")
- state.requestQueue = []*wire.InvVect{}
- state.requestedBlocks = make(map[chainhash.Hash]struct{})
- ws.requestedBlocks = make(map[chainhash.Hash]struct{})
- ws.startSync(peer)
- return
- } else if err == OrphanHeaderError && !ws.Current() {
- // The sync peer sent us an orphan header in the middle of a sync. This could
- // just be the last block in the batch which represents the tip of the chain.
- // In either case let's adjust the score for this peer downwards. If it goes
- // negative it means he's slamming us with blocks that don't fit in our chain
- // so disconnect.
- state.blockScore--
- if state.blockScore < 0 {
- log.Warningf("Disconnecting from peer %s because he sent us too many bad blocks", peer)
- peer.Disconnect()
- return
- }
- log.Warningf("Received unrequested block from peer %s", peer)
- return
- } else if err != nil {
- log.Error(err)
- return
- }
- state.blockScore++
-
- if ws.Current() {
- peer.UpdateLastBlockHeight(int32(newHeight))
- }
-
- // Request the transactions in this block
- for _, txid := range txids {
- ws.requestedTxns[*txid] = heightAndTime{newHeight, header.Timestamp}
- limitMap(ws.requestedTxns, maxRequestedTxns)
- state.requestedTxns[*txid] = heightAndTime{newHeight, header.Timestamp}
- }
-
- // We can exit here if the block is already known
- if !newBlock {
- log.Debugf("Received duplicate block %s", blockHash.String())
- return
- }
-
- log.Infof("Received merkle block %s at height %d", blockHash.String(), newHeight)
-
- // Check reorg
- if reorg != nil && ws.Current() {
- // Rollback the appropriate transactions in our database
- err := ws.txStore.processReorg(reorg.height)
- if err != nil {
- log.Error(err)
- }
- // Set the reorg block as current best block in the header db
- // This will cause a new chain sync from the reorg point
- err = ws.chain.db.Put(*reorg, true)
- if err != nil {
- log.Error(err)
- }
-
- // Clear request state for new sync
- state.requestQueue = []*wire.InvVect{}
- state.requestedBlocks = make(map[chainhash.Hash]struct{})
- ws.requestedBlocks = make(map[chainhash.Hash]struct{})
- }
-
- // Clear mempool
- ws.mempool = make(map[chainhash.Hash]struct{})
-
- // If we're not current and we've downloaded everything we've requested send another getblocks message.
- // Otherwise we'll request the next block in the queue.
- if !ws.Current() && len(state.requestQueue) == 0 {
- locator := ws.chain.GetBlockLocator()
- peer.PushGetBlocksMsg(locator, &ws.zeroHash)
- log.Debug("Request queue at zero. Pushing new locator")
- } else if !ws.Current() && len(state.requestQueue) > 0 {
- iv := state.requestQueue[0]
- iv.Type = wire.InvTypeFilteredBlock
- state.requestQueue = state.requestQueue[1:]
- state.requestedBlocks[iv.Hash] = struct{}{}
- gdmsg2 := wire.NewMsgGetData()
- gdmsg2.AddInvVect(iv)
- peer.QueueMessage(gdmsg2, nil)
- log.Debugf("Requesting block %s, len request queue: %d", iv.Hash.String(), len(state.requestQueue))
- }
-}
-
-// handleInvMsg handles inv messages from all peers.
-// We examine the inventory advertised by the remote peer and act accordingly.
-func (ws *WireService) handleInvMsg(imsg *invMsg) {
- peer := imsg.peer
- state, exists := ws.peerStates[peer]
- if !exists {
- log.Warningf("Received inv message from unknown peer %s", peer)
- return
- }
-
- // Attempt to find the final block in the inventory list. There may
- // not be one.
- lastBlock := -1
- invVects := imsg.inv.InvList
- for i := len(invVects) - 1; i >= 0; i-- {
- if invVects[i].Type == wire.InvTypeBlock {
- lastBlock = i
- break
- }
- }
-
- // If this inv contains a block announcement, and this isn't coming from
- // our current sync peer or we're current, then update the last
- // announced block for this peer. We'll use this information later to
- // update the heights of peers based on blocks we've accepted that they
- // previously announced.
- if lastBlock != -1 && (peer != ws.syncPeer || ws.Current()) {
- peer.UpdateLastAnnouncedBlock(&invVects[lastBlock].Hash)
- }
-
- // Ignore invs from peers that aren't the sync if we are not current.
- // Helps prevent fetching a mass of orphans.
- if peer != ws.syncPeer && !ws.Current() {
- return
- }
-
- // If our chain is current and a peer announces a block we already
- // know of, then update their current block height.
- if lastBlock != -1 && ws.Current() {
- sh, err := ws.chain.GetHeader(&invVects[lastBlock].Hash)
- if err == nil {
- peer.UpdateLastBlockHeight(int32(sh.height))
- }
- }
-
- // Request the advertised inventory if we don't already have it
- gdmsg := wire.NewMsgGetData()
- numRequested := 0
- shouldSendGetData := false
- if len(state.requestQueue) == 0 {
- shouldSendGetData = true
- }
- for _, iv := range invVects {
-
- // Add the inventory to the cache of known inventory
- // for the peer.
- peer.AddKnownInventory(iv)
-
- // Request the inventory if we don't already have it.
- haveInv, err := ws.haveInventory(iv)
- if err != nil {
- log.Warningf("Unexpected failure when checking for "+
- "existing inventory during inv message "+
- "processing: %v", err)
- continue
- }
-
- switch iv.Type {
- case wire.InvTypeFilteredBlock:
- fallthrough
- case wire.InvTypeBlock:
- // Block inventory goes into a request queue to be downloaded
- // one at a time. Sadly we can't batch these because the remote
- // peer will not update the bloom filter until he's done processing
- // the batch which means we will have a super high false positive rate.
- if _, exists := ws.requestedBlocks[iv.Hash]; (!ws.Current() && !exists && !haveInv && shouldSendGetData) || ws.Current() {
- iv.Type = wire.InvTypeFilteredBlock
- state.requestQueue = append(state.requestQueue, iv)
- }
- case wire.InvTypeTx:
- // Transaction inventory can be requested in batches
- if _, exists := ws.requestedTxns[iv.Hash]; !exists && numRequested < wire.MaxInvPerMsg && !haveInv {
- ws.requestedTxns[iv.Hash] = heightAndTime{0, time.Now()} // unconfirmed tx
- limitMap(ws.requestedTxns, maxRequestedTxns)
- state.requestedTxns[iv.Hash] = heightAndTime{0, time.Now()}
-
- gdmsg.AddInvVect(iv)
- numRequested++
- }
- default:
- continue
- }
- }
-
- // Pop the first block off the queue and request it
- if len(state.requestQueue) > 0 && (shouldSendGetData || ws.Current()) {
- iv := state.requestQueue[0]
- gdmsg.AddInvVect(iv)
- if len(state.requestQueue) > 1 {
- state.requestQueue = state.requestQueue[1:]
- } else {
- state.requestQueue = []*wire.InvVect{}
- }
- log.Debugf("Requesting block %s, len request queue: %d", iv.Hash.String(), len(state.requestQueue))
- state.requestedBlocks[iv.Hash] = struct{}{}
- }
- if len(gdmsg.InvList) > 0 {
- peer.QueueMessage(gdmsg, nil)
- }
-}
-
-func (ws *WireService) handleTxMsg(tmsg *txMsg) {
- tx := tmsg.tx
- peer := tmsg.peer
- txHash := tx.TxHash()
-
- state, exists := ws.peerStates[peer]
- if !exists {
- log.Warningf("Received tx message from unknown peer %s", peer)
- return
- }
- ht, ok := state.requestedTxns[tx.TxHash()]
- if !ok {
- log.Warningf("Peer %s is sending us transactions we didn't request", peer)
- peer.Disconnect()
- return
- }
- ws.mempool[txHash] = struct{}{}
- hits, err := ws.txStore.Ingest(tx, int32(ht.height), ht.timestamp)
- if err != nil {
- log.Errorf("Error ingesting tx: %s\n", err.Error())
- }
-
- // Remove transaction from request maps. Either the mempool/chain
- // already knows about it and as such we shouldn't have any more
- // instances of trying to fetch it, or we failed to insert and thus
- // we'll retry next time we get an inv.
- delete(state.requestedTxns, txHash)
- delete(ws.requestedTxns, txHash)
-
- // If this transaction had no hits, update the peer's false positive counter
- if hits == 0 {
- log.Debugf("Tx %s from Peer%d had no hits, filter false positive.", txHash.String(), peer.ID())
- state.falsePositives++
- } else {
- log.Noticef("Ingested new tx %s at height %d", txHash.String(), ht.height)
- }
-
- // Check to see if false positives exceeds the maximum allowed. If so, reset and resend the filter.
- if state.falsePositives > maxFalsePositives {
- state.falsePositives = 0
- ws.updateFilterAndSend(peer)
- }
-}
-
-func (ws *WireService) Rebroadcast() {
- // get all unconfirmed txs
- invMsg, err := ws.txStore.GetPendingInv()
- if err != nil {
- log.Errorf("Rebroadcast error: %s", err.Error())
- }
- // Nothing to broadcast, so don't
- if len(invMsg.InvList) == 0 {
- return
- }
- for peer := range ws.peerStates {
- peer.QueueMessage(invMsg, nil)
- }
-}
-
-func (ws *WireService) updateFilterAndSend(peer *peerpkg.Peer) {
- if ws.txStore != nil {
- filter, err := ws.txStore.GimmeFilter()
- if err == nil {
- peer.QueueMessage(filter.MsgFilterLoad(), nil)
- } else {
- log.Errorf("Error loading bloom filter: %s", err.Error())
- }
- }
-}
-
-// handleUpdateFiltersMsg sends a filter update message to all peers
-func (ws *WireService) handleUpdateFiltersMsg() {
- for peer := range ws.peerStates {
- ws.updateFilterAndSend(peer)
- }
-}
-
-// haveInventory returns whether or not the inventory represented by the passed
-// inventory vector is known. This includes checking all of the various places
-// inventory can be when it is in different states such as blocks that are part
-// of the main chain, on a side chain, in the orphan pool, and transactions that
-// are in the memory pool (either the main pool or orphan pool).
-func (ws *WireService) haveInventory(invVect *wire.InvVect) (bool, error) {
- switch invVect.Type {
- case wire.InvTypeWitnessBlock:
- fallthrough
- case wire.InvTypeBlock:
- // Ask chain if the block is known to it in any form (main
- // chain, side chain, or orphan).
- _, err := ws.chain.GetHeader(&invVect.Hash)
- if err != nil {
- return false, nil
- }
- return true, nil
- case wire.InvTypeTx:
- // Is transaction already in mempool
- if _, ok := ws.mempool[invVect.Hash]; ok {
- return true, nil
- }
- return false, nil
- }
- // The requested inventory is is an unsupported type, so just claim
- // it is known to avoid requesting it.
- return true, nil
-}
-
-// limitMap is a helper function for maps that require a maximum limit by
-// evicting a random transaction if adding a new value would cause it to
-// overflow the maximum allowed.
-func limitMap(i interface{}, limit int) {
- m, ok := i.(map[chainhash.Hash]struct{})
- if ok {
- if len(m)+1 > limit {
- // Remove a random entry from the map. For most compilers, Go's
- // range statement iterates starting at a random item although
- // that is not 100% guaranteed by the spec. The iteration order
- // is not important here because an adversary would have to be
- // able to pull off preimage attacks on the hashing function in
- // order to target eviction of specific entries anyways.
- for txHash := range m {
- delete(m, txHash)
- return
- }
- }
- return
- }
- n, ok := i.(map[chainhash.Hash]uint32)
- if ok {
- if len(n)+1 > limit {
- for txHash := range n {
- delete(n, txHash)
- return
- }
- }
- }
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go
deleted file mode 100644
index cc458e6662..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/exchangerates/exchangerates.go
+++ /dev/null
@@ -1,241 +0,0 @@
-package exchangerates
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "golang.org/x/net/proxy"
- "net"
- "net/http"
- "reflect"
- "strconv"
- "sync"
- "time"
-)
-
-type ExchangeRateProvider struct {
- fetchUrl string
- cache map[string]float64
- client *http.Client
- decoder ExchangeRateDecoder
-}
-
-type ExchangeRateDecoder interface {
- decode(dat interface{}, cache map[string]float64) (err error)
-}
-
-type OpenBazaarDecoder struct{}
-type KrakenDecoder struct{}
-type BitfinexDecoder struct{}
-type BittrexDecoder struct{}
-type PoloniexDecoder struct{}
-
-type BitcoinCashPriceFetcher struct {
- sync.Mutex
- cache map[string]float64
- providers []*ExchangeRateProvider
-}
-
-func NewBitcoinCashPriceFetcher(dialer proxy.Dialer) *BitcoinCashPriceFetcher {
- b := BitcoinCashPriceFetcher{
- cache: make(map[string]float64),
- }
- dial := net.Dial
- if dialer != nil {
- dial = dialer.Dial
- }
- tbTransport := &http.Transport{Dial: dial}
- client := &http.Client{Transport: tbTransport, Timeout: time.Minute}
-
- b.providers = []*ExchangeRateProvider{
- {"https://ticker.openbazaar.org/api", b.cache, client, OpenBazaarDecoder{}},
- {"https://poloniex.com/public?command=returnTicker", b.cache, client, PoloniexDecoder{}},
- {"https://api.kraken.com/0/public/Ticker?pair=BCHUSD", b.cache, client, KrakenDecoder{}},
- }
- return &b
-}
-
-func (b *BitcoinCashPriceFetcher) GetExchangeRate(currencyCode string) (float64, error) {
- b.Lock()
- defer b.Unlock()
- price, ok := b.cache[currencyCode]
- if !ok {
- return 0, errors.New("Currency not tracked")
- }
- return price, nil
-}
-
-func (b *BitcoinCashPriceFetcher) GetLatestRate(currencyCode string) (float64, error) {
- b.fetchCurrentRates()
- b.Lock()
- defer b.Unlock()
- price, ok := b.cache[currencyCode]
- if !ok {
- return 0, errors.New("Currency not tracked")
- }
- return price, nil
-}
-
-func (b *BitcoinCashPriceFetcher) GetAllRates(cacheOK bool) (map[string]float64, error) {
- if !cacheOK {
- err := b.fetchCurrentRates()
- if err != nil {
- return nil, err
- }
- }
- b.Lock()
- defer b.Unlock()
- return b.cache, nil
-}
-
-func (b *BitcoinCashPriceFetcher) UnitsPerCoin() int {
- return 100000000
-}
-
-func (b *BitcoinCashPriceFetcher) fetchCurrentRates() error {
- b.Lock()
- defer b.Unlock()
- for _, provider := range b.providers {
- err := provider.fetch()
- if err == nil {
- return nil
- }
- fmt.Println(err)
- }
- return errors.New("All exchange rate API queries failed")
-}
-
-func (b *BitcoinCashPriceFetcher) Run() {
- b.fetchCurrentRates()
- ticker := time.NewTicker(time.Minute * 15)
- for range ticker.C {
- b.fetchCurrentRates()
- }
-}
-
-func (provider *ExchangeRateProvider) fetch() (err error) {
- if len(provider.fetchUrl) == 0 {
- err = errors.New("Provider has no fetchUrl")
- return err
- }
- resp, err := provider.client.Get(provider.fetchUrl)
- if err != nil {
- return err
- }
- decoder := json.NewDecoder(resp.Body)
- var dataMap interface{}
- err = decoder.Decode(&dataMap)
- if err != nil {
- return err
- }
- return provider.decoder.decode(dataMap, provider.cache)
-}
-
-func (b OpenBazaarDecoder) decode(dat interface{}, cache map[string]float64) (err error) {
- data, ok := dat.(map[string]interface{})
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- bch, ok := data["BCH"]
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'BCH' field")
- }
- val, ok := bch.(map[string]interface{})
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- bchRate, ok := val["last"].(float64)
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (float) field")
- }
- for k, v := range data {
- if k != "timestamp" {
- val, ok := v.(map[string]interface{})
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- price, ok := val["last"].(float64)
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (float) field")
- }
- cache[k] = price * (1 / bchRate)
- }
- }
- return nil
-}
-
-func (b KrakenDecoder) decode(dat interface{}, cache map[string]float64) (err error) {
- obj, ok := dat.(map[string]interface{})
- if !ok {
- return errors.New("KrackenDecoder type assertion failure")
- }
- result, ok := obj["result"]
- if !ok {
- return errors.New("KrakenDecoder: field `result` not found")
- }
- resultMap, ok := result.(map[string]interface{})
- if !ok {
- return errors.New("KrackenDecoder type assertion failure")
- }
- pair, ok := resultMap["BCHUSD"]
- if !ok {
- return errors.New("KrakenDecoder: field `BCHUSD` not found")
- }
- pairMap, ok := pair.(map[string]interface{})
- if !ok {
- return errors.New("KrackenDecoder type assertion failure")
- }
- c, ok := pairMap["c"]
- if !ok {
- return errors.New("KrakenDecoder: field `c` not found")
- }
- cList, ok := c.([]interface{})
- if !ok {
- return errors.New("KrackenDecoder type assertion failure")
- }
- rateStr, ok := cList[0].(string)
- if !ok {
- return errors.New("KrackenDecoder type assertion failure")
- }
- price, err := strconv.ParseFloat(rateStr, 64)
- if err != nil {
- return err
- }
- rate := price
-
- if rate == 0 {
- return errors.New("Bitcoin-BitcoinCash price data not available")
- }
- cache["USD"] = rate
- return nil
-}
-
-func (b PoloniexDecoder) decode(dat interface{}, cache map[string]float64) (err error) {
- data, ok := dat.(map[string]interface{})
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- var rate float64
- v, ok := data["USDT_BCH"]
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- val, ok := v.(map[string]interface{})
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed")
- }
- s, ok := val["last"].(string)
- if !ok {
- return errors.New(reflect.TypeOf(b).Name() + ".decode: Type assertion failed, missing 'last' (string) field")
- }
- price, err := strconv.ParseFloat(s, 64)
- if err != nil {
- return err
- }
- rate = price
- if rate == 0 {
- return errors.New("BitcoinCash price data not available")
- }
- cache["USD"] = rate
- return nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go
deleted file mode 100644
index c9e06fe8e3..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/fees.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package bitcoincash
-
-import (
- "github.com/OpenBazaar/wallet-interface"
- "net/http"
- "time"
-)
-
-type httpClient interface {
- Get(string) (*http.Response, error)
-}
-
-type feeCache struct {
- fees *Fees
- lastUpdated time.Time
-}
-
-type Fees struct {
- FastestFee uint64
- HalfHourFee uint64
- HourFee uint64
-}
-
-type FeeProvider struct {
- maxFee uint64
- priorityFee uint64
- normalFee uint64
- economicFee uint64
-
- exchangeRates wallet.ExchangeRates
-
- cache *feeCache
-}
-
-// We will target a fee per byte such that it would equal
-// 1 USD cent for economic, 5 USD cents for normal and
-// 10 USD cents for priority for a median (226 byte) transaction.
-type FeeTarget int
-
-const (
- EconomicTarget FeeTarget = 1
- NormalTarget FeeTarget = 5
- PriorityTarget FeeTarget = 10
-)
-
-func NewFeeProvider(maxFee, priorityFee, normalFee, economicFee uint64, exchangeRates wallet.ExchangeRates) *FeeProvider {
- return &FeeProvider{
- maxFee: maxFee,
- priorityFee: priorityFee,
- normalFee: normalFee,
- economicFee: economicFee,
- exchangeRates: exchangeRates,
- cache: new(feeCache),
- }
-}
-
-func (fp *FeeProvider) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 {
- defaultFee := func() uint64 {
- switch feeLevel {
- case wallet.PRIOIRTY:
- return fp.priorityFee
- case wallet.NORMAL:
- return fp.normalFee
- case wallet.ECONOMIC:
- return fp.economicFee
- case wallet.FEE_BUMP:
- return fp.priorityFee * 2
- default:
- return fp.normalFee
- }
- }
- if fp.exchangeRates == nil {
- return defaultFee()
- }
-
- rate, err := fp.exchangeRates.GetLatestRate("USD")
- if err != nil || rate == 0 {
- log.Errorf("Error using exchange rate to calculate fee: %s\n", err.Error())
- return defaultFee()
- }
-
- var target FeeTarget
- switch feeLevel {
- case wallet.PRIOIRTY:
- target = PriorityTarget
- case wallet.NORMAL:
- target = NormalTarget
- case wallet.ECONOMIC:
- target = EconomicTarget
- case wallet.FEE_BUMP:
- target = PriorityTarget * 2
- default:
- target = NormalTarget
- }
-
- feePerByte := (((float64(target) / 100) / rate) * 100000000) / 226
-
- if uint64(feePerByte) > fp.maxFee {
- return fp.maxFee
- }
-
- return uint64(feePerByte)
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go
deleted file mode 100644
index 7b8a949943..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/headers.go
+++ /dev/null
@@ -1,456 +0,0 @@
-package bitcoincash
-
-import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "math/big"
- "path"
- "sort"
- "sync"
-
- "github.com/boltdb/bolt"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/wire"
- "github.com/cevaris/ordered_map"
- "strings"
-)
-
-const (
- MAX_HEADERS = 2000
- CACHE_SIZE = 200
-)
-
-// Database interface for storing block 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)
-}
-
-type StoredHeader struct {
- header wire.BlockHeader
- height uint32
- totalWork *big.Int
-}
-
-// HeaderDB implements Headers using bolt DB
-type HeaderDB struct {
- lock *sync.Mutex
- db *bolt.DB
- filePath string
- bestCache *StoredHeader
- cache *HeaderCache
-}
-
-var (
- BKTHeaders = []byte("Headers")
- BKTChainTip = []byte("ChainTip")
- KEYChainTip = []byte("ChainTip")
-)
-
-func NewHeaderDB(filePath string) (*HeaderDB, error) {
- if !strings.Contains(filePath, ".bin") {
- filePath = path.Join(filePath, "headers.bin")
- }
- h := new(HeaderDB)
- db, err := bolt.Open(filePath, 0644, &bolt.Options{InitialMmapSize: 5000000})
- if err != nil {
- return nil, err
- }
- h.db = db
- h.lock = new(sync.Mutex)
- h.filePath = filePath
- h.cache = &HeaderCache{ordered_map.NewOrderedMap(), sync.RWMutex{}, CACHE_SIZE}
-
- db.Update(func(btx *bolt.Tx) error {
- _, err := btx.CreateBucketIfNotExists(BKTHeaders)
- if err != nil {
- return err
- }
- _, err = btx.CreateBucketIfNotExists(BKTChainTip)
- if err != nil {
- return err
- }
- return nil
- })
-
- h.initializeCache()
- return h, nil
-}
-
-func (h *HeaderDB) Put(sh StoredHeader, newBestHeader bool) error {
- h.lock.Lock()
- h.cache.Set(sh)
- if newBestHeader {
- h.bestCache = &sh
- }
- h.lock.Unlock()
- go func() {
- err := h.putToDB(sh, newBestHeader)
- if err != nil {
- log.Error(err)
- }
- }()
- return nil
-}
-
-func (h *HeaderDB) put(sh StoredHeader, newBestHeader bool) error {
- h.lock.Lock()
- h.cache.Set(sh)
- if newBestHeader {
- h.bestCache = &sh
- }
- h.lock.Unlock()
- err := h.putToDB(sh, newBestHeader)
- if err != nil {
- log.Error(err)
- }
- return nil
-}
-
-func (h *HeaderDB) putToDB(sh StoredHeader, newBestHeader bool) error {
- h.lock.Lock()
- defer h.lock.Unlock()
- return h.db.Update(func(btx *bolt.Tx) error {
- hdrs := btx.Bucket(BKTHeaders)
- ser, err := serializeHeader(sh)
- if err != nil {
- return err
- }
- hash := sh.header.BlockHash()
- err = hdrs.Put(hash.CloneBytes(), ser)
- if err != nil {
- return err
- }
- if newBestHeader {
- tip := btx.Bucket(BKTChainTip)
- err = tip.Put(KEYChainTip, ser)
- if err != nil {
- return err
- }
- }
- return nil
- })
-}
-
-func (h *HeaderDB) Prune() error {
- h.lock.Lock()
- defer h.lock.Unlock()
- return h.db.Update(func(btx *bolt.Tx) error {
- hdrs := btx.Bucket(BKTHeaders)
- numHeaders := hdrs.Stats().KeyN
- tip := btx.Bucket(BKTChainTip)
- b := tip.Get(KEYChainTip)
- if b == nil {
- return errors.New("ChainTip not set")
- }
- sh, err := deserializeHeader(b)
- if err != nil {
- return err
- }
- height := sh.height
- if numHeaders > MAX_HEADERS {
- var toDelete [][]byte
- pruneHeight := height - 2000
- err := hdrs.ForEach(func(k, v []byte) error {
- sh, err := deserializeHeader(v)
- if err != nil {
- return err
- }
- if sh.height <= pruneHeight {
- toDelete = append(toDelete, k)
- }
- return nil
- })
- if err != nil {
- return err
- }
- for _, k := range toDelete {
- err := hdrs.Delete(k)
- if err != nil {
- return err
- }
- }
-
- }
- return nil
- })
-}
-
-func (h *HeaderDB) DeleteAfter(height uint32) error {
- h.lock.Lock()
- defer h.lock.Unlock()
- return h.db.Update(func(btx *bolt.Tx) error {
- hdrs := btx.Bucket(BKTHeaders)
- var toDelete [][]byte
- err := hdrs.ForEach(func(k, v []byte) error {
- sh, err := deserializeHeader(v)
- if err != nil {
- return err
- }
- if sh.height > height {
- toDelete = append(toDelete, k)
- }
- return nil
- })
- if err != nil {
- return err
- }
- for _, k := range toDelete {
- err := hdrs.Delete(k)
- if err != nil {
- return err
- }
- }
- return nil
- })
-}
-
-func (h *HeaderDB) GetPreviousHeader(header wire.BlockHeader) (sh StoredHeader, err error) {
- hash := header.PrevBlock
- return h.GetHeader(hash)
-}
-
-func (h *HeaderDB) GetHeader(hash chainhash.Hash) (sh StoredHeader, err error) {
- h.lock.Lock()
- defer h.lock.Unlock()
- cachedHeader, cerr := h.cache.Get(hash)
- if cerr == nil {
- return cachedHeader, nil
- }
- err = h.db.View(func(btx *bolt.Tx) error {
- hdrs := btx.Bucket(BKTHeaders)
- b := hdrs.Get(hash.CloneBytes())
- if b == nil {
- return errors.New("Header does not exist in database")
- }
- sh, err = deserializeHeader(b)
- if err != nil {
- return err
- }
- return nil
- })
- if err != nil {
- return sh, err
- }
- return sh, nil
-}
-
-func (h *HeaderDB) GetBestHeader() (sh StoredHeader, err error) {
- h.lock.Lock()
- defer h.lock.Unlock()
- if h.bestCache != nil {
- best := h.bestCache
- return *best, nil
- }
- err = h.db.View(func(btx *bolt.Tx) error {
- tip := btx.Bucket(BKTChainTip)
- b := tip.Get(KEYChainTip)
- if b == nil {
- return errors.New("ChainTip not set")
- }
- sh, err = deserializeHeader(b)
- if err != nil {
- return err
- }
- return nil
- })
- if err != nil {
- return sh, err
- }
- return sh, nil
-}
-
-func (h *HeaderDB) Height() (uint32, error) {
- h.lock.Lock()
- defer h.lock.Unlock()
- if h.bestCache != nil {
- return h.bestCache.height, nil
- }
- var height uint32
- err := h.db.View(func(btx *bolt.Tx) error {
- tip := btx.Bucket(BKTChainTip)
- sh, err := deserializeHeader(tip.Get(KEYChainTip))
- if err != nil {
- return err
- }
- height = sh.height
- return nil
- })
- if err != nil {
- return height, err
- }
- return height, nil
-}
-
-func (h *HeaderDB) Print(w io.Writer) {
- h.lock.Lock()
- defer h.lock.Unlock()
- m := make(map[float64][]string)
- h.db.View(func(tx *bolt.Tx) error {
- // Assume bucket exists and has keys
- bkt := tx.Bucket(BKTHeaders)
- bkt.ForEach(func(k, v []byte) error {
- sh, _ := deserializeHeader(v)
- h := float64(sh.height)
- _, ok := m[h]
- if ok {
- for {
- h += .1
- _, ok := m[h]
- if !ok {
- break
- }
- }
- }
- m[h] = []string{sh.header.BlockHash().String(), sh.header.PrevBlock.String()}
- return nil
- })
-
- return nil
- })
- var keys []float64
- for k := range m {
- keys = append(keys, float64(k))
- }
- sort.Float64s(keys)
- for _, k := range keys {
- fmt.Fprintf(w, "Height: %.1f, Hash: %s, Parent: %s\n", k, m[k][0], m[k][1])
- }
-}
-
-func (h *HeaderDB) initializeCache() {
- best, err := h.GetBestHeader()
- if err != nil {
- return
- }
- h.bestCache = &best
- headers := []StoredHeader{best}
- for i := 0; i < 99; i++ {
- sh, err := h.GetPreviousHeader(best.header)
- if err != nil {
- break
- }
- headers = append(headers, sh)
- }
- for i := len(headers) - 1; i >= 0; i-- {
- h.cache.Set(headers[i])
- }
-}
-
-func (h *HeaderDB) Close() {
- h.lock.Lock()
- h.db.Close()
-}
-
-/*----- header serialization ------- */
-/* byteLength desc at offset
- 80 header 0
- 4 height 80
- 32 total work 84
-*/
-func serializeHeader(sh StoredHeader) ([]byte, error) {
- var buf bytes.Buffer
- err := sh.header.Serialize(&buf)
- if err != nil {
- return nil, err
- }
- err = binary.Write(&buf, binary.BigEndian, sh.height)
- if err != nil {
- return nil, err
- }
- biBytes := sh.totalWork.Bytes()
- pad := make([]byte, 32-len(biBytes))
- serializedBI := append(pad, biBytes...)
- buf.Write(serializedBI)
- return buf.Bytes(), nil
-}
-
-func deserializeHeader(b []byte) (sh StoredHeader, err error) {
- r := bytes.NewReader(b)
- hdr := new(wire.BlockHeader)
- err = hdr.Deserialize(r)
- if err != nil {
- return sh, err
- }
- var height uint32
- err = binary.Read(r, binary.BigEndian, &height)
- if err != nil {
- return sh, err
- }
- biBytes := make([]byte, 32)
- _, err = r.Read(biBytes)
- if err != nil {
- return sh, err
- }
- bi := new(big.Int)
- bi.SetBytes(biBytes)
- sh = StoredHeader{
- header: *hdr,
- height: height,
- totalWork: bi,
- }
- return sh, nil
-}
-
-type HeaderCache struct {
- headers *ordered_map.OrderedMap
- sync.RWMutex
- cacheSize int
-}
-
-func (h *HeaderCache) pop() {
- iter := h.headers.IterFunc()
- k, ok := iter()
- if ok {
- h.headers.Delete(k.Key)
- }
-}
-
-func (h *HeaderCache) Set(sh StoredHeader) {
- h.Lock()
- defer h.Unlock()
- if h.headers.Len() > h.cacheSize {
- h.pop()
- }
- hash := sh.header.BlockHash()
- h.headers.Set(hash.String(), sh)
-}
-
-func (h *HeaderCache) Get(hash chainhash.Hash) (StoredHeader, error) {
- h.RLock()
- defer h.RUnlock()
- sh, ok := h.headers.Get(hash.String())
- if !ok {
- return StoredHeader{}, errors.New("Not found")
- }
- return sh.(StoredHeader), nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go
deleted file mode 100644
index 14f5af1c79..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/keys.go
+++ /dev/null
@@ -1,189 +0,0 @@
-package bitcoincash
-
-import (
- "github.com/OpenBazaar/wallet-interface"
- "github.com/btcsuite/btcd/chaincfg"
- hd "github.com/btcsuite/btcutil/hdkeychain"
- "github.com/btcsuite/goleveldb/leveldb/errors"
-)
-
-const LOOKAHEADWINDOW = 100
-
-type KeyManager struct {
- datastore wallet.Keys
- params *chaincfg.Params
-
- internalKey *hd.ExtendedKey
- externalKey *hd.ExtendedKey
-}
-
-func NewKeyManager(db wallet.Keys, params *chaincfg.Params, masterPrivKey *hd.ExtendedKey) (*KeyManager, error) {
- internal, external, err := Bip44Derivation(masterPrivKey)
- if err != nil {
- return nil, err
- }
- km := &KeyManager{
- datastore: db,
- params: params,
- internalKey: internal,
- externalKey: external,
- }
- if err := km.lookahead(); err != nil {
- return nil, err
- }
- return km, nil
-}
-
-// m / purpose' / coin_type' / account' / change / address_index
-func Bip44Derivation(masterPrivKey *hd.ExtendedKey) (internal, external *hd.ExtendedKey, err error) {
- // Purpose = bip44
- fourtyFour, err := masterPrivKey.Child(hd.HardenedKeyStart + 44)
- if err != nil {
- return nil, nil, err
- }
- // Cointype = bitcoin
- bitcoin, err := fourtyFour.Child(hd.HardenedKeyStart + 145)
- if err != nil {
- return nil, nil, err
- }
- // Account = 0
- account, err := bitcoin.Child(hd.HardenedKeyStart + 0)
- if err != nil {
- return nil, nil, err
- }
- // Change(0) = external
- external, err = account.Child(0)
- if err != nil {
- return nil, nil, err
- }
- // Change(1) = internal
- internal, err = account.Child(1)
- if err != nil {
- return nil, nil, err
- }
- return internal, external, nil
-}
-
-func (km *KeyManager) GetCurrentKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) {
- i, err := km.datastore.GetUnused(purpose)
- if err != nil {
- return nil, err
- }
- if len(i) == 0 {
- return nil, errors.New("No unused keys in database")
- }
- return km.generateChildKey(purpose, uint32(i[0]))
-}
-
-func (km *KeyManager) GetFreshKey(purpose wallet.KeyPurpose) (*hd.ExtendedKey, error) {
- index, _, err := km.datastore.GetLastKeyIndex(purpose)
- var childKey *hd.ExtendedKey
- if err != nil {
- index = 0
- } else {
- index += 1
- }
- for {
- // There is a small possibility bip32 keys can be invalid. The procedure in such cases
- // is to discard the key and derive the next one. This loop will continue until a valid key
- // is derived.
- childKey, err = km.generateChildKey(purpose, uint32(index))
- if err == nil {
- break
- }
- index += 1
- }
- addr, err := childKey.Address(km.params)
- if err != nil {
- return nil, err
- }
- p := wallet.KeyPath{wallet.KeyPurpose(purpose), index}
- err = km.datastore.Put(addr.ScriptAddress(), p)
- if err != nil {
- return nil, err
- }
- return childKey, nil
-}
-
-func (km *KeyManager) GetKeys() []*hd.ExtendedKey {
- var keys []*hd.ExtendedKey
- keyPaths, err := km.datastore.GetAll()
- if err != nil {
- return keys
- }
- for _, path := range keyPaths {
- k, err := km.generateChildKey(path.Purpose, uint32(path.Index))
- if err != nil {
- continue
- }
- keys = append(keys, k)
- }
- imported, err := km.datastore.GetImported()
- if err != nil {
- return keys
- }
- for _, key := range imported {
- hdKey := hd.NewExtendedKey(
- km.params.HDPrivateKeyID[:],
- key.Serialize(),
- make([]byte, 32),
- []byte{0x00, 0x00, 0x00, 0x00},
- 0,
- 0,
- true)
- keys = append(keys, hdKey)
- }
- return keys
-}
-
-func (km *KeyManager) GetKeyForScript(scriptAddress []byte) (*hd.ExtendedKey, error) {
- keyPath, err := km.datastore.GetPathForKey(scriptAddress)
- if err != nil {
- key, err := km.datastore.GetKey(scriptAddress)
- if err != nil {
- return nil, err
- }
- hdKey := hd.NewExtendedKey(
- km.params.HDPrivateKeyID[:],
- key.Serialize(),
- make([]byte, 32),
- []byte{0x00, 0x00, 0x00, 0x00},
- 0,
- 0,
- true)
- return hdKey, nil
- }
- return km.generateChildKey(keyPath.Purpose, uint32(keyPath.Index))
-}
-
-// Mark the given key as used and extend the lookahead window
-func (km *KeyManager) MarkKeyAsUsed(scriptAddress []byte) error {
- if err := km.datastore.MarkKeyAsUsed(scriptAddress); err != nil {
- return err
- }
- return km.lookahead()
-}
-
-func (km *KeyManager) generateChildKey(purpose wallet.KeyPurpose, index uint32) (*hd.ExtendedKey, error) {
- if purpose == wallet.EXTERNAL {
- return km.externalKey.Child(index)
- } else if purpose == wallet.INTERNAL {
- return km.internalKey.Child(index)
- }
- return nil, errors.New("Unknown key purpose")
-}
-
-func (km *KeyManager) lookahead() error {
- lookaheadWindows := km.datastore.GetLookaheadWindows()
- for purpose, size := range lookaheadWindows {
- if size < LOOKAHEADWINDOW {
- for i := 0; i < (LOOKAHEADWINDOW - size); i++ {
- _, err := km.GetFreshKey(purpose)
- if err != nil {
- return err
- }
- }
- }
- }
- return nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile b/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile
deleted file mode 100644
index 30265908dc..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-install:
- cd cmd/bitcoincash && go install
-
-protos:
- cd api/pb && protoc --go_out=plugins=grpc:. api.proto
-
-resources:
- cd gui && go-bindata -o resources.go -pkg gui resources/...
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go
deleted file mode 100644
index ac60997196..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/mblock.go
+++ /dev/null
@@ -1,176 +0,0 @@
-package bitcoincash
-
-import (
- "fmt"
-
- "errors"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/wire"
-)
-
-func MakeMerkleParent(left *chainhash.Hash, right *chainhash.Hash) (*chainhash.Hash, error) {
- // dupes can screw things up; CVE-2012-2459. check for them
- if left != nil && right != nil && left.IsEqual(right) {
- return nil, errors.New("DUP HASH CRASH")
- }
- // if left child is nil, output nil. Need this for hard mode.
- if left == nil {
- return nil, errors.New("Left child is nil")
- }
- // if right is nil, hash left with itself
- if right == nil {
- right = left
- }
-
- // Concatenate the left and right nodes
- var sha [64]byte
- copy(sha[:32], left[:])
- copy(sha[32:], right[:])
-
- newSha := chainhash.DoubleHashH(sha[:])
- return &newSha, nil
-}
-
-type merkleNode struct {
- p uint32 // position in the binary tree
- h *chainhash.Hash // hash
-}
-
-// given n merkle leaves, how deep is the tree?
-// iterate shifting left until greater than n
-func treeDepth(n uint32) (e uint8) {
- for ; (1 << e) < n; e++ {
- }
- return
-}
-
-// smallest power of 2 that can contain n
-func nextPowerOfTwo(n uint32) uint32 {
- return 1 << treeDepth(n) // 2^exponent
-}
-
-// check if a node is populated based on node position and size of tree
-func inDeadZone(pos, size uint32) bool {
- msb := nextPowerOfTwo(size)
- last := size - 1 // last valid position is 1 less than size
- if pos > (msb<<1)-2 { // greater than root; not even in the tree
- log.Debug(" ?? greater than root ")
- return true
- }
- h := msb
- for pos >= h {
- h = h>>1 | msb
- last = last>>1 | msb
- }
- return pos > last
-}
-
-// take in a merkle block, parse through it, and return txids indicated
-// If there's any problem return an error. Checks self-consistency only.
-// doing it with a stack instead of recursion. Because...
-// OK I don't know why I'm just not in to recursion OK?
-func checkMBlock(m *wire.MsgMerkleBlock) ([]*chainhash.Hash, error) {
- if m.Transactions == 0 {
- return nil, fmt.Errorf("No transactions in merkleblock")
- }
- if len(m.Flags) == 0 {
- return nil, fmt.Errorf("No flag bits")
- }
- var s []merkleNode // the stack
- var r []*chainhash.Hash // slice to return; txids we care about
-
- // set initial position to root of merkle tree
- msb := nextPowerOfTwo(m.Transactions) // most significant bit possible
- pos := (msb << 1) - 2 // current position in tree
-
- var i uint8 // position in the current flag byte
- var tip int
- // main loop
- for {
- tip = len(s) - 1 // slice position of stack tip
- // First check if stack operations can be performed
- // is stack one filled item? that's complete.
- if tip == 0 && s[0].h != nil {
- if s[0].h.IsEqual(&m.Header.MerkleRoot) {
- return r, nil
- }
- return nil, fmt.Errorf("computed root %s but expect %s\n",
- s[0].h.String(), m.Header.MerkleRoot.String())
- }
- // is current position in the tree's dead zone? partial parent
- if inDeadZone(pos, m.Transactions) {
- // create merkle parent from single side (left)
- h, err := MakeMerkleParent(s[tip].h, nil)
- if err != nil {
- return r, err
- }
- s[tip-1].h = h
- s = s[:tip] // remove 1 from stack
- pos = s[tip-1].p | 1 // move position to parent's sibling
- continue
- }
- // does stack have 3+ items? and are last 2 items filled?
- if tip > 1 && s[tip-1].h != nil && s[tip].h != nil {
- //fmt.Printf("nodes %d and %d combine into %d\n",
- // s[tip-1].p, s[tip].p, s[tip-2].p)
- // combine two filled nodes into parent node
- h, err := MakeMerkleParent(s[tip-1].h, s[tip].h)
- if err != nil {
- return r, err
- }
- s[tip-2].h = h
- // remove children
- s = s[:tip-1]
- // move position to parent's sibling
- pos = s[tip-2].p | 1
- continue
- }
-
- // no stack ops to perform, so make new node from message hashes
- if len(m.Hashes) == 0 {
- return nil, fmt.Errorf("Ran out of hashes at position %d.", pos)
- }
- if len(m.Flags) == 0 {
- return nil, fmt.Errorf("Ran out of flag bits.")
- }
- var n merkleNode // make new node
- n.p = pos // set current position for new node
-
- if pos&msb != 0 { // upper non-txid hash
- if m.Flags[0]&(1<>1 | msb
- } else { // left side, go to sibling
- pos |= 1
- }
- } else { // flag bit says skip; put empty on stack and descend
- pos = (pos ^ msb) << 1 // descend to left
- }
- s = append(s, n) // push new node on stack
- } else { // bottom row txid; flag bit indicates tx of interest
- if pos >= m.Transactions {
- // this can't happen because we check deadzone above...
- return nil, fmt.Errorf("got into an invalid txid node")
- }
- n.h = m.Hashes[0] // copy hash from message
- m.Hashes = m.Hashes[1:] // pop off message
- if m.Flags[0]&(1< i {
- i = key.path.Index
- used = key.used
- }
- }
- if i == -1 {
- return i, used, errors.New("No saved keys")
- }
- return i, used, nil
-}
-
-func (m *mockKeyStore) GetPathForKey(scriptAddress []byte) (wallet.KeyPath, error) {
- key, ok := m.keys[hex.EncodeToString(scriptAddress)]
- if !ok || key.path.Index == -1 {
- return wallet.KeyPath{}, errors.New("key does not exist")
- }
- return key.path, nil
-}
-
-func (m *mockKeyStore) GetKey(scriptAddress []byte) (*btcec.PrivateKey, error) {
- for _, k := range m.keys {
- if k.path.Index == -1 && bytes.Equal(scriptAddress, k.scriptAddress) {
- return k.key, nil
- }
- }
- return nil, errors.New("Not found")
-}
-
-func (m *mockKeyStore) GetImported() ([]*btcec.PrivateKey, error) {
- var keys []*btcec.PrivateKey
- for _, k := range m.keys {
- if k.path.Index == -1 {
- keys = append(keys, k.key)
- }
- }
- return keys, nil
-}
-
-func (m *mockKeyStore) GetUnused(purpose wallet.KeyPurpose) ([]int, error) {
- var i []int
- for _, key := range m.keys {
- if !key.used && key.path.Purpose == purpose {
- i = append(i, key.path.Index)
- }
- }
- sort.Ints(i)
- return i, nil
-}
-
-func (m *mockKeyStore) GetAll() ([]wallet.KeyPath, error) {
- var kp []wallet.KeyPath
- for _, key := range m.keys {
- kp = append(kp, key.path)
- }
- return kp, nil
-}
-
-func (m *mockKeyStore) GetLookaheadWindows() map[wallet.KeyPurpose]int {
- internalLastUsed := -1
- externalLastUsed := -1
- for _, key := range m.keys {
- if key.path.Purpose == wallet.INTERNAL && key.used && key.path.Index > internalLastUsed {
- internalLastUsed = key.path.Index
- }
- if key.path.Purpose == wallet.EXTERNAL && key.used && key.path.Index > externalLastUsed {
- externalLastUsed = key.path.Index
- }
- }
- internalUnused := 0
- externalUnused := 0
- for _, key := range m.keys {
- if key.path.Purpose == wallet.INTERNAL && !key.used && key.path.Index > internalLastUsed {
- internalUnused++
- }
- if key.path.Purpose == wallet.EXTERNAL && !key.used && key.path.Index > externalLastUsed {
- externalUnused++
- }
- }
- mp := make(map[wallet.KeyPurpose]int)
- mp[wallet.INTERNAL] = internalUnused
- mp[wallet.EXTERNAL] = externalUnused
- return mp
-}
-
-type mockUtxoStore struct {
- utxos map[string]*wallet.Utxo
-}
-
-func (m *mockUtxoStore) Put(utxo wallet.Utxo) error {
- key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index))
- m.utxos[key] = &utxo
- return nil
-}
-
-func (m *mockUtxoStore) GetAll() ([]wallet.Utxo, error) {
- var utxos []wallet.Utxo
- for _, v := range m.utxos {
- utxos = append(utxos, *v)
- }
- return utxos, nil
-}
-
-func (m *mockUtxoStore) SetWatchOnly(utxo wallet.Utxo) error {
- key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index))
- u, ok := m.utxos[key]
- if !ok {
- return errors.New("Not found")
- }
- u.WatchOnly = true
- return nil
-}
-
-func (m *mockUtxoStore) Delete(utxo wallet.Utxo) error {
- key := utxo.Op.Hash.String() + ":" + strconv.Itoa(int(utxo.Op.Index))
- _, ok := m.utxos[key]
- if !ok {
- return errors.New("Not found")
- }
- delete(m.utxos, key)
- return nil
-}
-
-type mockStxoStore struct {
- stxos map[string]*wallet.Stxo
-}
-
-func (m *mockStxoStore) Put(stxo wallet.Stxo) error {
- m.stxos[stxo.SpendTxid.String()] = &stxo
- return nil
-}
-
-func (m *mockStxoStore) GetAll() ([]wallet.Stxo, error) {
- var stxos []wallet.Stxo
- for _, v := range m.stxos {
- stxos = append(stxos, *v)
- }
- return stxos, nil
-}
-
-func (m *mockStxoStore) Delete(stxo wallet.Stxo) error {
- _, ok := m.stxos[stxo.SpendTxid.String()]
- if !ok {
- return errors.New("Not found")
- }
- delete(m.stxos, stxo.SpendTxid.String())
- return nil
-}
-
-type txnStoreEntry struct {
- txn []byte
- txid string
- value int
- height int
- timestamp time.Time
- watchOnly bool
-}
-
-type mockTxnStore struct {
- txns map[string]*txnStoreEntry
-}
-
-func (m *mockTxnStore) Put(txn []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error {
- m.txns[txid] = &txnStoreEntry{
- txn: txn,
- txid: txid,
- value: value,
- height: height,
- timestamp: timestamp,
- watchOnly: watchOnly,
- }
- return nil
-}
-
-func (m *mockTxnStore) Get(txid chainhash.Hash) (wallet.Txn, error) {
- t, ok := m.txns[txid.String()]
- if !ok {
- return wallet.Txn{}, errors.New("Not found")
- }
- return wallet.Txn{
- Txid: t.txid,
- Value: int64(t.value),
- Height: int32(t.height),
- Timestamp: t.timestamp,
- WatchOnly: t.watchOnly,
- Bytes: t.txn,
- }, nil
-}
-
-func (m *mockTxnStore) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) {
- var txns []wallet.Txn
- for _, t := range m.txns {
- txn := wallet.Txn{
- Txid: t.txid,
- Value: int64(t.value),
- Height: int32(t.height),
- Timestamp: t.timestamp,
- WatchOnly: t.watchOnly,
- Bytes: t.txn,
- }
- txns = append(txns, txn)
- }
- return txns, nil
-}
-
-func (m *mockTxnStore) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error {
- txn, ok := m.txns[txid.String()]
- if !ok {
- return errors.New("Not found")
- }
- txn.height = height
- txn.timestamp = timestamp
- return nil
-}
-
-func (m *mockTxnStore) Delete(txid *chainhash.Hash) error {
- _, ok := m.txns[txid.String()]
- if !ok {
- return errors.New("Not found")
- }
- delete(m.txns, txid.String())
- return nil
-}
-
-type mockWatchedScriptsStore struct {
- scripts map[string][]byte
-}
-
-func (m *mockWatchedScriptsStore) Put(scriptPubKey []byte) error {
- m.scripts[hex.EncodeToString(scriptPubKey)] = scriptPubKey
- return nil
-}
-
-func (m *mockWatchedScriptsStore) GetAll() ([][]byte, error) {
- var ret [][]byte
- for _, b := range m.scripts {
- ret = append(ret, b)
- }
- return ret, nil
-}
-
-func (m *mockWatchedScriptsStore) Delete(scriptPubKey []byte) error {
- enc := hex.EncodeToString(scriptPubKey)
- _, ok := m.scripts[enc]
- if !ok {
- return errors.New("Not found")
- }
- delete(m.scripts, enc)
- return nil
-}
-
-func TestUtxo_IsEqual(t *testing.T) {
- h, err := chainhash.NewHashFromStr("16bed6368b8b1542cd6eb87f5bc20dc830b41a2258dde40438a75fa701d24e9a")
- if err != nil {
- t.Error(err)
- }
- u := &wallet.Utxo{
- Op: *wire.NewOutPoint(h, 0),
- ScriptPubkey: make([]byte, 32),
- AtHeight: 400000,
- Value: 1000000,
- }
- if !u.IsEqual(u) {
- t.Error("Failed to return utxos as equal")
- }
- testUtxo := *u
- testUtxo.Op.Index = 3
- if u.IsEqual(&testUtxo) {
- t.Error("Failed to return utxos as not equal")
- }
- testUtxo = *u
- testUtxo.AtHeight = 1
- if u.IsEqual(&testUtxo) {
- t.Error("Failed to return utxos as not equal")
- }
- testUtxo = *u
- testUtxo.Value = 4
- if u.IsEqual(&testUtxo) {
- t.Error("Failed to return utxos as not equal")
- }
- testUtxo = *u
- ch2, err := chainhash.NewHashFromStr("1f64249abbf2fcc83fc060a64f69a91391e9f5d98c5d3135fe9716838283aa4c")
- if err != nil {
- t.Error(err)
- }
- testUtxo.Op.Hash = *ch2
- if u.IsEqual(&testUtxo) {
- t.Error("Failed to return utxos as not equal")
- }
- testUtxo = *u
- testUtxo.ScriptPubkey = make([]byte, 4)
- if u.IsEqual(&testUtxo) {
- t.Error("Failed to return utxos as not equal")
- }
- if u.IsEqual(nil) {
- t.Error("Failed to return utxos as not equal")
- }
-}
-
-func TestStxo_IsEqual(t *testing.T) {
- h, err := chainhash.NewHashFromStr("16bed6368b8b1542cd6eb87f5bc20dc830b41a2258dde40438a75fa701d24e9a")
- if err != nil {
- t.Error(err)
- }
- u := &wallet.Utxo{
- Op: *wire.NewOutPoint(h, 0),
- ScriptPubkey: make([]byte, 32),
- AtHeight: 400000,
- Value: 1000000,
- }
- h2, err := chainhash.NewHashFromStr("1f64249abbf2fcc83fc060a64f69a91391e9f5d98c5d3135fe9716838283aa4c")
- s := &wallet.Stxo{
- Utxo: *u,
- SpendHeight: 400001,
- SpendTxid: *h2,
- }
- if !s.IsEqual(s) {
- t.Error("Failed to return stxos as equal")
- }
-
- testStxo := *s
- testStxo.SpendHeight = 5
- if s.IsEqual(&testStxo) {
- t.Error("Failed to return stxos as not equal")
- }
- h3, err := chainhash.NewHashFromStr("3c5cea030a432ba9c8cf138a93f7b2e5b28263ea416894ee0bdf91bc31bb04f2")
- testStxo = *s
- testStxo.SpendTxid = *h3
- if s.IsEqual(&testStxo) {
- t.Error("Failed to return stxos as not equal")
- }
- if s.IsEqual(nil) {
- t.Error("Failed to return stxos as not equal")
- }
- testStxo = *s
- testStxo.Utxo.AtHeight = 7
- if s.IsEqual(&testStxo) {
- t.Error("Failed to return stxos as not equal")
- }
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go
deleted file mode 100644
index 5dc120000b..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/peers.go
+++ /dev/null
@@ -1,409 +0,0 @@
-package bitcoincash
-
-import (
- "errors"
- "net"
- "strconv"
- "sync"
- "time"
-
- "fmt"
- "github.com/btcsuite/btcd/addrmgr"
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/connmgr"
- "github.com/btcsuite/btcd/peer"
- "github.com/btcsuite/btcd/wire"
- "github.com/cpacia/bchutil"
- "golang.org/x/net/proxy"
-)
-
-var (
- // Default number of outbound peers
- defaultTargetOutbound = uint32(12)
-
- // Default duration of time for retrying a connection
- defaultRetryDuration = time.Second * 5
-
- // Default port per chain params
- defaultPort uint16
-)
-
-const MaxGetAddressAttempts = 10
-
-var SFNodeBitcoinCash wire.ServiceFlag = 1 << 5
-
-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 PeerManager struct {
- addrManager *addrmgr.AddrManager
- connManager *connmgr.ConnManager
- sourceAddr *wire.NetAddress
- peerConfig *peer.Config
- peerMutex *sync.RWMutex
- trustedPeer net.Addr
- targetOutbound uint32
- proxy proxy.Dialer
- recentlyTriedAddresses map[string]bool
- connectedPeers map[uint64]*peer.Peer
- msgChan chan interface{}
-}
-
-func NewPeerManager(config *PeerManagerConfig) (*PeerManager, error) {
- port, err := strconv.Atoi(config.Params.DefaultPort)
- defaultPort = uint16(port)
- if err != nil {
- return nil, err
- }
-
- pm := &PeerManager{
- addrManager: addrmgr.New(config.AddressCacheDir, nil),
- peerMutex: new(sync.RWMutex),
- sourceAddr: wire.NewNetAddressIPPort(net.ParseIP("0.0.0.0"), defaultPort, 0),
- trustedPeer: config.TrustedPeer,
- proxy: config.Proxy,
- recentlyTriedAddresses: make(map[string]bool),
- connectedPeers: make(map[uint64]*peer.Peer),
- msgChan: config.MsgChan,
- }
-
- targetOutbound := config.TargetOutbound
- if config.TargetOutbound == 0 {
- targetOutbound = defaultTargetOutbound
- }
-
- if config.TrustedPeer != nil {
- targetOutbound = 1
- }
- pm.targetOutbound = targetOutbound
-
- retryDuration := config.RetryDuration
- if config.RetryDuration <= 0 {
- retryDuration = defaultRetryDuration
- }
-
- dial := net.Dial
- if config.Proxy != nil {
- dial = config.Proxy.Dial
- }
-
- connMgrConfig := &connmgr.Config{
- TargetOutbound: targetOutbound,
- RetryDuration: retryDuration,
- OnConnection: pm.onConnection,
- OnDisconnection: pm.onDisconnection,
- GetNewAddress: pm.getNewAddress,
- Dial: func(addr net.Addr) (net.Conn, error) {
- return dial("tcp", addr.String())
- },
- }
-
- connMgr, err := connmgr.New(connMgrConfig)
- if err != nil {
- return nil, err
- }
- pm.connManager = connMgr
-
- var listeners *peer.MessageListeners = config.Listeners
- if listeners == nil {
- listeners = &peer.MessageListeners{}
- }
- listeners.OnVerAck = pm.onVerack
- listeners.OnAddr = pm.onAddr
- listeners.OnHeaders = pm.onHeaders
- listeners.OnMerkleBlock = pm.onMerkleBlock
- listeners.OnInv = pm.onInv
- listeners.OnTx = pm.onTx
- listeners.OnReject = pm.onReject
-
- pm.peerConfig = &peer.Config{
- UserAgentName: config.UserAgentName,
- UserAgentVersion: config.UserAgentVersion,
- ChainParams: config.Params,
- DisableRelayTx: true,
- NewestBlock: config.GetNewestBlock,
- Listeners: *listeners,
- }
- if config.Proxy != nil {
- pm.peerConfig.Proxy = "0.0.0.0"
- }
- return pm, nil
-}
-
-func (pm *PeerManager) ConnectedPeers() []*peer.Peer {
- pm.peerMutex.RLock()
- defer pm.peerMutex.RUnlock()
- var ret []*peer.Peer
- for _, p := range pm.connectedPeers {
- ret = append(ret, p)
- }
- return ret
-}
-
-func (pm *PeerManager) onConnection(req *connmgr.ConnReq, conn net.Conn) {
- pm.peerMutex.Lock()
- defer pm.peerMutex.Unlock()
-
- // Create a new peer for this connection
- p, err := peer.NewOutboundPeer(pm.peerConfig, conn.RemoteAddr().String())
- if err != nil {
- pm.connManager.Disconnect(req.ID())
- return
- }
-
- // Associate the connection with the peer
- p.AssociateConnection(conn)
-
- pm.connectedPeers[req.ID()] = p
-
- // Tell the addr manager we made a connection
- pm.addrManager.Connected(p.NA())
-
- // Handle disconnect
- go func() {
- p.WaitForDisconnect()
- pm.connManager.Disconnect(req.ID())
- }()
-}
-
-func (pm *PeerManager) onVerack(p *peer.Peer, msg *wire.MsgVerAck) {
- // Check this peer offers bloom filtering services. If not dump them.
- p.NA().Services = p.Services()
- if !(p.NA().HasService(wire.SFNodeBloom) && p.NA().HasService(wire.SFNodeNetwork) && p.NA().HasService(bchutil.SFNodeBitcoinCash)) {
- // onDisconnection will be called
- // which will remove the peer from openPeers
- log.Warningf("Peer %s does not support bloom filtering, diconnecting", p)
- p.Disconnect()
- return
- }
- log.Debugf("Connected to %s - %s\n", p.Addr(), p.UserAgent())
- // Tell the addr manager this is a good address
- pm.addrManager.Good(p.NA())
- if pm.msgChan != nil {
- pm.msgChan <- newPeerMsg{p}
- }
-}
-
-func (pm *PeerManager) onDisconnection(req *connmgr.ConnReq) {
- // Remove from connected peers
- pm.peerMutex.Lock()
- defer pm.peerMutex.Unlock()
- peer, ok := pm.connectedPeers[req.ID()]
- if !ok {
- return
- }
- log.Debugf("Peer %s disconnected", peer)
- delete(pm.connectedPeers, req.ID())
- if pm.msgChan != nil {
- pm.msgChan <- donePeerMsg{peer}
- }
-}
-
-// Called by connManager when it adds a new connection
-func (pm *PeerManager) getNewAddress() (net.Addr, error) {
- // If we have a trusted peer we'll just return it
- if pm.trustedPeer == nil {
- pm.peerMutex.Lock()
- defer pm.peerMutex.Unlock()
- // We're going to loop here and pull addresses from the addrManager until we get one that we
- // are not currently connect to or haven't recently tried.
- loop:
- for tries := 0; tries < 100; tries++ {
- ka := pm.addrManager.GetAddress()
- if ka == nil {
- continue
- }
-
- // only allow recent nodes (10mins) after we failed 30
- // times
- if tries < 30 && time.Since(ka.LastAttempt()) < 10*time.Minute {
- continue
- }
-
- // allow nondefault ports after 50 failed tries.
- if tries < 50 && fmt.Sprintf("%d", ka.NetAddress().Port) != pm.peerConfig.ChainParams.DefaultPort {
- continue
- }
-
- knownAddress := ka.NetAddress()
-
- // Don't return addresses we're still connected to
- for _, p := range pm.connectedPeers {
- if p.NA().IP.String() == knownAddress.IP.String() {
- continue loop
- }
- }
- addr := &net.TCPAddr{
- Port: int(knownAddress.Port),
- IP: knownAddress.IP,
- }
- pm.addrManager.Attempt(knownAddress)
- return addr, nil
- }
- return nil, errors.New("failed to find appropriate address to return")
- } else {
- return pm.trustedPeer, nil
- }
-}
-
-// Query the DNS seeds and pass the addresses into the address manager.
-func (pm *PeerManager) queryDNSSeeds() {
- wg := new(sync.WaitGroup)
- for _, seed := range bchutil.GetDNSSeed(pm.peerConfig.ChainParams) {
- wg.Add(1)
- go func(host string) {
- returnedAddresses := 0
- var addrs []string
- var err error
- if pm.proxy != nil {
- for i := 0; i < 5; i++ {
- ips, err := TorLookupIP(host)
- if err != nil {
- wg.Done()
- return
- }
- for _, ip := range ips {
- addrs = append(addrs, ip.String())
- }
- }
- } else {
- addrs, err = net.LookupHost(host)
- if err != nil {
- wg.Done()
- return
- }
- }
- for _, addr := range addrs {
- netAddr := wire.NewNetAddressIPPort(net.ParseIP(addr), defaultPort, 0)
- pm.addrManager.AddAddress(netAddr, pm.sourceAddr)
- returnedAddresses++
- }
- log.Debugf("%s returned %s addresses\n", host, strconv.Itoa(returnedAddresses))
- wg.Done()
- }(seed.Host)
- }
- wg.Wait()
-}
-
-// If we have connected peers let's use them to get more addresses. If not, use the DNS seeds
-func (pm *PeerManager) getMoreAddresses() {
- if pm.addrManager.NeedMoreAddresses() {
- pm.peerMutex.RLock()
- defer pm.peerMutex.RUnlock()
- if len(pm.connectedPeers) > 0 {
- log.Debug("Querying peers for more addresses")
- for _, p := range pm.connectedPeers {
- p.QueueMessage(wire.NewMsgGetAddr(), nil)
- }
- } else {
- pm.queryDNSSeeds()
- }
- }
-}
-
-func (pm *PeerManager) onAddr(p *peer.Peer, msg *wire.MsgAddr) {
- pm.addrManager.AddAddresses(msg.AddrList, pm.sourceAddr)
-}
-
-func (pm *PeerManager) onHeaders(p *peer.Peer, msg *wire.MsgHeaders) {
- if pm.msgChan != nil {
- pm.msgChan <- headersMsg{msg, p}
- }
-}
-
-func (pm *PeerManager) onMerkleBlock(p *peer.Peer, msg *wire.MsgMerkleBlock) {
- if pm.msgChan != nil {
- pm.msgChan <- merkleBlockMsg{msg, p}
- }
-}
-
-func (pm *PeerManager) onInv(p *peer.Peer, msg *wire.MsgInv) {
- if pm.msgChan != nil {
- pm.msgChan <- invMsg{msg, p}
- }
-}
-
-func (pm *PeerManager) onTx(p *peer.Peer, msg *wire.MsgTx) {
- if pm.msgChan != nil {
- pm.msgChan <- txMsg{msg, p, nil}
- }
-}
-
-func (pm *PeerManager) onReject(p *peer.Peer, msg *wire.MsgReject) {
- log.Warningf("Received reject message from peer %d: Code: %s, Hash %s, Reason: %s", int(p.ID()), msg.Code.String(), msg.Hash.String(), msg.Reason)
-}
-
-func (pm *PeerManager) Start() {
- pm.addrManager.Start()
- log.Infof("Loaded %d peers from cache\n", pm.addrManager.NumAddresses())
- if pm.trustedPeer == nil && pm.addrManager.NeedMoreAddresses() {
- log.Info("Querying DNS seeds")
- pm.queryDNSSeeds()
- }
- pm.connManager.Start()
- go func() {
- tick := time.NewTicker(time.Minute)
- defer tick.Stop()
- for {
- select {
- case <-tick.C:
- pm.getMoreAddresses()
- }
- }
- }()
-}
-
-func (pm *PeerManager) Stop() {
- pm.peerMutex.Lock()
- defer pm.peerMutex.Unlock()
- wg := new(sync.WaitGroup)
- for _, peer := range pm.connectedPeers {
- wg.Add(1)
- go func() {
- // onDisconnection will be called.
- peer.Disconnect()
- peer.WaitForDisconnect()
- wg.Done()
- }()
- }
- pm.addrManager.Stop()
- pm.connectedPeers = make(map[uint64]*peer.Peer)
- wg.Wait()
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go
deleted file mode 100644
index 8fe3d85ea0..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/sortsignsend.go
+++ /dev/null
@@ -1,887 +0,0 @@
-// Copyright (C) 2015-2016 The Lightning Network Developers
-// Copyright (c) 2016-2017 The OpenBazaar Developers
-
-package bitcoincash
-
-import (
- "bytes"
- "encoding/hex"
- "errors"
- "fmt"
- "time"
-
- "github.com/OpenBazaar/wallet-interface"
- "github.com/btcsuite/btcd/blockchain"
- "github.com/btcsuite/btcd/btcec"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/txscript"
- "github.com/btcsuite/btcd/wire"
- btc "github.com/btcsuite/btcutil"
- "github.com/btcsuite/btcutil/coinset"
- hd "github.com/btcsuite/btcutil/hdkeychain"
- "github.com/btcsuite/btcutil/txsort"
- "github.com/btcsuite/btcwallet/wallet/txauthor"
- "github.com/btcsuite/btcwallet/wallet/txrules"
- "github.com/cpacia/bchutil"
-)
-
-func (s *SPVWallet) Broadcast(tx *wire.MsgTx) error {
-
- // Our own tx; don't keep track of false positives
- _, err := s.txstore.Ingest(tx, 0, time.Now())
- if err != nil {
- return err
- }
-
- // make an inv message instead of a tx message to be polite
- txid := tx.TxHash()
- iv1 := wire.NewInvVect(wire.InvTypeTx, &txid)
- invMsg := wire.NewMsgInv()
- err = invMsg.AddInvVect(iv1)
- if err != nil {
- return err
- }
-
- s.wireService.MsgChan() <- updateFiltersMsg{}
- log.Debugf("Broadcasting tx %s to peers", tx.TxHash().String())
- for _, peer := range s.peerManager.ConnectedPeers() {
- peer.QueueMessage(tx, nil)
- }
- return nil
-}
-
-type Coin struct {
- TxHash *chainhash.Hash
- TxIndex uint32
- TxValue btc.Amount
- TxNumConfs int64
- ScriptPubKey []byte
-}
-
-func (c *Coin) Hash() *chainhash.Hash { return c.TxHash }
-func (c *Coin) Index() uint32 { return c.TxIndex }
-func (c *Coin) Value() btc.Amount { return c.TxValue }
-func (c *Coin) PkScript() []byte { return c.ScriptPubKey }
-func (c *Coin) NumConfs() int64 { return c.TxNumConfs }
-func (c *Coin) ValueAge() int64 { return int64(c.TxValue) * c.TxNumConfs }
-
-func NewCoin(txid []byte, index uint32, value btc.Amount, numConfs int64, scriptPubKey []byte) coinset.Coin {
- shaTxid, _ := chainhash.NewHash(txid)
- c := &Coin{
- TxHash: shaTxid,
- TxIndex: index,
- TxValue: value,
- TxNumConfs: numConfs,
- ScriptPubKey: scriptPubKey,
- }
- return coinset.Coin(c)
-}
-
-func (w *SPVWallet) gatherCoins() map[coinset.Coin]*hd.ExtendedKey {
- height, _ := w.blockchain.db.Height()
- utxos, _ := w.txstore.Utxos().GetAll()
- m := make(map[coinset.Coin]*hd.ExtendedKey)
- for _, u := range utxos {
- if u.WatchOnly {
- continue
- }
- var confirmations int32
- if u.AtHeight > 0 {
- confirmations = int32(height) - u.AtHeight
- }
- c := NewCoin(u.Op.Hash.CloneBytes(), u.Op.Index, btc.Amount(u.Value), int64(confirmations), u.ScriptPubkey)
- addr, err := w.ScriptToAddress(u.ScriptPubkey)
- if err != nil {
- continue
- }
- key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress())
- if err != nil {
- continue
- }
- m[c] = key
- }
- return m
-}
-
-func (w *SPVWallet) Spend(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, referenceID string, spendAll bool) (*chainhash.Hash, error) {
- var (
- tx *wire.MsgTx
- err error
- )
- if spendAll {
- tx, err = w.buildSpendAllTx(addr, feeLevel)
- if err != nil {
- return nil, err
- }
- } else {
- tx, err = w.buildTx(amount, addr, feeLevel, nil)
- if err != nil {
- return nil, err
- }
- }
-
- // Broadcast
- if err := w.Broadcast(tx); err != nil {
- return nil, err
- }
-
- ch := tx.TxHash()
- return &ch, nil
-}
-
-var BumpFeeAlreadyConfirmedError = errors.New("Transaction is confirmed, cannot bump fee")
-var BumpFeeTransactionDeadError = errors.New("Cannot bump fee of dead transaction")
-var BumpFeeNotFoundError = errors.New("Transaction either doesn't exist or has already been spent")
-
-func (w *SPVWallet) BumpFee(txid chainhash.Hash) (*chainhash.Hash, error) {
- txn, err := w.txstore.Txns().Get(txid)
- if err != nil {
- return nil, err
- }
- if txn.Height > 0 {
- return nil, BumpFeeAlreadyConfirmedError
- }
- if txn.Height < 0 {
- return nil, BumpFeeTransactionDeadError
- }
- // Check stxos for RBF opportunity
- /*stxos, _ := w.txstore.Stxos().GetAll()
- for _, s := range stxos {
- if s.SpendTxid.IsEqual(&txid) {
- r := bytes.NewReader(txn.Bytes)
- msgTx := wire.NewMsgTx(1)
- msgTx.BtcDecode(r, 1)
- for i, output := range msgTx.TxOut {
- key, err := w.txstore.GetKeyForScript(output.PkScript)
- if key != nil && err == nil { // This is our change output
- // Calculate change - additional fee
- feePerByte := w.GetFeePerByte(PRIOIRTY)
- estimatedSize := EstimateSerializeSize(len(msgTx.TxIn), msgTx.TxOut, false)
- fee := estimatedSize * int(feePerByte)
- newValue := output.Value - int64(fee)
-
- // Check if still above dust value
- if newValue <= 0 || txrules.IsDustAmount(btc.Amount(newValue), len(output.PkScript), txrules.DefaultRelayFeePerKb) {
- msgTx.TxOut = append(msgTx.TxOut[:i], msgTx.TxOut[i+1:]...)
- } else {
- output.Value = newValue
- }
-
- // Bump sequence number
- optInRBF := false
- for _, input := range msgTx.TxIn {
- if input.Sequence < 4294967294 {
- input.Sequence++
- optInRBF = true
- }
- }
- if !optInRBF {
- break
- }
-
- //TODO: Re-sign transaction
-
- // Mark original tx as dead
- if err = w.txstore.markAsDead(txid); err != nil {
- return nil, err
- }
-
- // Broadcast new tx
- if err := w.Broadcast(msgTx); err != nil {
- return nil, err
- }
- newTxid := msgTx.TxHash()
- return &newTxid, nil
- }
- }
- }
- }*/
- // Check utxos for CPFP
- utxos, _ := w.txstore.Utxos().GetAll()
- for _, u := range utxos {
- if u.Op.Hash.IsEqual(&txid) && u.AtHeight == 0 {
- addr, err := w.ScriptToAddress(u.ScriptPubkey)
- if err != nil {
- return nil, err
- }
- key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress())
- if err != nil {
- return nil, err
- }
- h, err := hex.DecodeString(u.Op.Hash.String())
- if err != nil {
- return nil, err
- }
- in := wallet.TransactionInput{
- LinkedAddress: addr,
- OutpointIndex: u.Op.Index,
- OutpointHash: h,
- Value: u.Value,
- }
- transactionID, err := w.SweepAddress([]wallet.TransactionInput{in}, nil, key, nil, wallet.FEE_BUMP)
- if err != nil {
- return nil, err
- }
- return transactionID, nil
- }
- }
- return nil, BumpFeeNotFoundError
-}
-
-func (w *SPVWallet) EstimateFee(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, feePerByte uint64) uint64 {
- tx := wire.NewMsgTx(1)
- for _, out := range outs {
- scriptPubKey, _ := bchutil.PayToAddrScript(out.Address)
- output := wire.NewTxOut(out.Value, scriptPubKey)
- tx.TxOut = append(tx.TxOut, output)
- }
- estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, P2PKH)
- fee := estimatedSize * int(feePerByte)
- return uint64(fee)
-}
-
-// Build a spend transaction for the amount and return the transaction fee
-func (w *SPVWallet) EstimateSpendFee(amount int64, feeLevel wallet.FeeLevel) (uint64, error) {
- // Since this is an estimate we can use a dummy output address. Let's use a long one so we don't under estimate.
- addr, err := btc.DecodeAddress("114K8nZhYcG1rsxcc1YGujFwWj5NLByc5v", w.params)
- if err != nil {
- return 0, err
- }
- tx, err := w.buildTx(amount, addr, feeLevel, nil)
- if err != nil {
- return 0, err
- }
- var outval int64
- for _, output := range tx.TxOut {
- outval += output.Value
- }
- var inval int64
- utxos, err := w.txstore.Utxos().GetAll()
- if err != nil {
- return 0, err
- }
- for _, input := range tx.TxIn {
- for _, utxo := range utxos {
- if utxo.Op.Hash.IsEqual(&input.PreviousOutPoint.Hash) && utxo.Op.Index == input.PreviousOutPoint.Index {
- inval += utxo.Value
- break
- }
- }
- }
- if inval < outval {
- return 0, errors.New("Error building transaction: inputs less than outputs")
- }
- return uint64(inval - outval), err
-}
-
-func (w *SPVWallet) GenerateMultisigScript(keys []hd.ExtendedKey, threshold int, timeout time.Duration, timeoutKey *hd.ExtendedKey) (addr btc.Address, redeemScript []byte, err error) {
- if uint32(timeout.Hours()) > 0 && timeoutKey == nil {
- return nil, nil, errors.New("Timeout key must be non nil when using an escrow timeout")
- }
-
- if len(keys) < threshold {
- return nil, nil, fmt.Errorf("unable to generate multisig script with "+
- "%d required signatures when there are only %d public "+
- "keys available", threshold, len(keys))
- }
-
- var ecKeys []*btcec.PublicKey
- for _, key := range keys {
- ecKey, err := key.ECPubKey()
- if err != nil {
- return nil, nil, err
- }
- ecKeys = append(ecKeys, ecKey)
- }
-
- builder := txscript.NewScriptBuilder()
- if uint32(timeout.Hours()) == 0 {
-
- builder.AddInt64(int64(threshold))
- for _, key := range ecKeys {
- builder.AddData(key.SerializeCompressed())
- }
- builder.AddInt64(int64(len(ecKeys)))
- builder.AddOp(txscript.OP_CHECKMULTISIG)
-
- } else {
- ecKey, err := timeoutKey.ECPubKey()
- if err != nil {
- return nil, nil, err
- }
- sequenceLock := blockchain.LockTimeToSequence(false, uint32(timeout.Hours()*6))
- builder.AddOp(txscript.OP_IF)
- builder.AddInt64(int64(threshold))
- for _, key := range ecKeys {
- builder.AddData(key.SerializeCompressed())
- }
- builder.AddInt64(int64(len(ecKeys)))
- builder.AddOp(txscript.OP_CHECKMULTISIG)
- builder.AddOp(txscript.OP_ELSE).
- AddInt64(int64(sequenceLock)).
- AddOp(txscript.OP_CHECKSEQUENCEVERIFY).
- AddOp(txscript.OP_DROP).
- AddData(ecKey.SerializeCompressed()).
- AddOp(txscript.OP_CHECKSIG).
- AddOp(txscript.OP_ENDIF)
- }
- redeemScript, err = builder.Script()
- if err != nil {
- return nil, nil, err
- }
- addr, err = bchutil.NewCashAddressScriptHash(redeemScript, w.params)
- if err != nil {
- return nil, nil, err
- }
- return addr, redeemScript, nil
-}
-
-func (w *SPVWallet) CreateMultisigSignature(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, key *hd.ExtendedKey, redeemScript []byte, feePerByte uint64) ([]wallet.Signature, error) {
- var sigs []wallet.Signature
- tx := wire.NewMsgTx(1)
- for _, in := range ins {
- ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash))
- if err != nil {
- return sigs, err
- }
- outpoint := wire.NewOutPoint(ch, in.OutpointIndex)
- input := wire.NewTxIn(outpoint, []byte{}, [][]byte{})
- tx.TxIn = append(tx.TxIn, input)
- }
- for _, out := range outs {
- scriptPubkey, err := bchutil.PayToAddrScript(out.Address)
- if err != nil {
- return sigs, err
- }
- output := wire.NewTxOut(out.Value, scriptPubkey)
- tx.TxOut = append(tx.TxOut, output)
- }
-
- // Subtract fee
- txType := P2SH_2of3_Multisig
- _, err := LockTimeFromRedeemScript(redeemScript)
- if err == nil {
- txType = P2SH_Multisig_Timelock_2Sigs
- }
- estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType)
- fee := estimatedSize * int(feePerByte)
- if len(tx.TxOut) > 0 {
- feePerOutput := fee / len(tx.TxOut)
- for _, output := range tx.TxOut {
- output.Value -= int64(feePerOutput)
- }
- }
-
- // BIP 69 sorting
- txsort.InPlaceSort(tx)
-
- signingKey, err := key.ECPrivKey()
- if err != nil {
- return sigs, err
- }
-
- for i := range tx.TxIn {
- sig, err := bchutil.RawTxInSignature(tx, i, redeemScript, txscript.SigHashAll, signingKey, ins[i].Value)
- if err != nil {
- continue
- }
- bs := wallet.Signature{InputIndex: uint32(i), Signature: sig}
- sigs = append(sigs, bs)
- }
- return sigs, nil
-}
-
-func (w *SPVWallet) Multisign(ins []wallet.TransactionInput, outs []wallet.TransactionOutput, sigs1 []wallet.Signature, sigs2 []wallet.Signature, redeemScript []byte, feePerByte uint64, broadcast bool) ([]byte, error) {
- tx := wire.NewMsgTx(1)
- for _, in := range ins {
- ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash))
- if err != nil {
- return nil, err
- }
- outpoint := wire.NewOutPoint(ch, in.OutpointIndex)
- input := wire.NewTxIn(outpoint, []byte{}, [][]byte{})
- tx.TxIn = append(tx.TxIn, input)
- }
- for _, out := range outs {
- scriptPubkey, err := bchutil.PayToAddrScript(out.Address)
- if err != nil {
- return nil, err
- }
- output := wire.NewTxOut(out.Value, scriptPubkey)
- tx.TxOut = append(tx.TxOut, output)
- }
-
- // Subtract fee
- txType := P2SH_2of3_Multisig
- _, err := LockTimeFromRedeemScript(redeemScript)
- if err == nil {
- txType = P2SH_Multisig_Timelock_2Sigs
- }
- estimatedSize := EstimateSerializeSize(len(ins), tx.TxOut, false, txType)
- fee := estimatedSize * int(feePerByte)
- if len(tx.TxOut) > 0 {
- feePerOutput := fee / len(tx.TxOut)
- for _, output := range tx.TxOut {
- output.Value -= int64(feePerOutput)
- }
- }
-
- // BIP 69 sorting
- txsort.InPlaceSort(tx)
-
- // Check if time locked
- var timeLocked bool
- if redeemScript[0] == txscript.OP_IF {
- timeLocked = true
- }
-
- for i, input := range tx.TxIn {
- var sig1 []byte
- var sig2 []byte
- for _, sig := range sigs1 {
- if int(sig.InputIndex) == i {
- sig1 = sig.Signature
- }
- }
- for _, sig := range sigs2 {
- if int(sig.InputIndex) == i {
- sig2 = sig.Signature
- }
- }
- builder := txscript.NewScriptBuilder()
- builder.AddOp(txscript.OP_0)
- builder.AddData(sig1)
- builder.AddData(sig2)
-
- if timeLocked {
- builder.AddOp(txscript.OP_1)
- }
-
- builder.AddData(redeemScript)
- scriptSig, err := builder.Script()
- if err != nil {
- return nil, err
- }
- input.SignatureScript = scriptSig
- }
- // broadcast
- if broadcast {
- w.Broadcast(tx)
- }
- var buf bytes.Buffer
- tx.BtcEncode(&buf, 1, wire.BaseEncoding)
- return buf.Bytes(), nil
-}
-
-func (w *SPVWallet) SweepAddress(ins []wallet.TransactionInput, address *btc.Address, key *hd.ExtendedKey, redeemScript *[]byte, feeLevel wallet.FeeLevel) (*chainhash.Hash, error) {
- var internalAddr btc.Address
- if address != nil {
- internalAddr = *address
- } else {
- internalAddr = w.CurrentAddress(wallet.INTERNAL)
- }
- script, err := bchutil.PayToAddrScript(internalAddr)
- if err != nil {
- return nil, err
- }
-
- var val int64
- var inputs []*wire.TxIn
- additionalPrevScripts := make(map[wire.OutPoint][]byte)
- for _, in := range ins {
- val += in.Value
- ch, err := chainhash.NewHashFromStr(hex.EncodeToString(in.OutpointHash))
- if err != nil {
- return nil, err
- }
- script, err := bchutil.PayToAddrScript(in.LinkedAddress)
- if err != nil {
- return nil, err
- }
- outpoint := wire.NewOutPoint(ch, in.OutpointIndex)
- input := wire.NewTxIn(outpoint, []byte{}, [][]byte{})
- inputs = append(inputs, input)
- additionalPrevScripts[*outpoint] = script
- }
- out := wire.NewTxOut(val, script)
-
- txType := P2PKH
- if redeemScript != nil {
- txType = P2SH_1of2_Multisig
- _, err := LockTimeFromRedeemScript(*redeemScript)
- if err == nil {
- txType = P2SH_Multisig_Timelock_1Sig
- }
- }
- estimatedSize := EstimateSerializeSize(len(ins), []*wire.TxOut{out}, false, txType)
-
- // Calculate the fee
- feePerByte := int(w.GetFeePerByte(feeLevel))
- fee := estimatedSize * feePerByte
-
- outVal := val - int64(fee)
- if outVal < 0 {
- outVal = 0
- }
- out.Value = outVal
-
- tx := &wire.MsgTx{
- Version: wire.TxVersion,
- TxIn: inputs,
- TxOut: []*wire.TxOut{out},
- LockTime: 0,
- }
-
- // BIP 69 sorting
- txsort.InPlaceSort(tx)
-
- // Sign tx
- privKey, err := key.ECPrivKey()
- if err != nil {
- return nil, err
- }
- pk := privKey.PubKey().SerializeCompressed()
- addressPub, err := btc.NewAddressPubKey(pk, w.params)
-
- getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) {
- if addressPub.EncodeAddress() == addr.EncodeAddress() {
- wif, err := btc.NewWIF(privKey, w.params, true)
- if err != nil {
- return nil, false, err
- }
- return wif.PrivKey, wif.CompressPubKey, nil
- }
- return nil, false, errors.New("Not found")
- })
- getScript := txscript.ScriptClosure(func(addr btc.Address) ([]byte, error) {
- if redeemScript == nil {
- return []byte{}, nil
- }
- return *redeemScript, nil
- })
-
- // Check if time locked
- var timeLocked bool
- if redeemScript != nil {
- rs := *redeemScript
- if rs[0] == txscript.OP_IF {
- timeLocked = true
- tx.Version = 2
- for _, txIn := range tx.TxIn {
- locktime, err := LockTimeFromRedeemScript(*redeemScript)
- if err != nil {
- return nil, err
- }
- txIn.Sequence = locktime
- }
- }
- }
-
- for i, txIn := range tx.TxIn {
- if !timeLocked {
- prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint]
- script, err := bchutil.SignTxOutput(w.params,
- tx, i, prevOutScript, txscript.SigHashAll, getKey,
- getScript, txIn.SignatureScript, ins[i].Value)
- if err != nil {
- return nil, errors.New("Failed to sign transaction")
- }
- txIn.SignatureScript = script
- } else {
- priv, err := key.ECPrivKey()
- if err != nil {
- return nil, err
- }
- script, err := bchutil.RawTxInSignature(tx, i, *redeemScript, txscript.SigHashAll, priv, ins[i].Value)
- if err != nil {
- return nil, err
- }
- builder := txscript.NewScriptBuilder().
- AddData(script).
- AddOp(txscript.OP_0).
- AddData(*redeemScript)
- scriptSig, _ := builder.Script()
- txIn.SignatureScript = scriptSig
- }
- }
-
- // broadcast
- w.Broadcast(tx)
- txid := tx.TxHash()
- return &txid, nil
-}
-
-func (w *SPVWallet) buildTx(amount int64, addr btc.Address, feeLevel wallet.FeeLevel, optionalOutput *wire.TxOut) (*wire.MsgTx, error) {
- // Check for dust
- script, _ := bchutil.PayToAddrScript(addr)
- if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) {
- return nil, errors.New("Amount is below dust threshold")
- }
-
- var additionalPrevScripts map[wire.OutPoint][]byte
- var additionalKeysByAddress map[string]*btc.WIF
- var inVals map[wire.OutPoint]int64
-
- // Create input source
- coinMap := w.gatherCoins()
- coins := make([]coinset.Coin, 0, len(coinMap))
- for k := range coinMap {
- coins = append(coins, k)
- }
- inputSource := func(target btc.Amount) (total btc.Amount, inputs []*wire.TxIn, amounts []btc.Amount, scripts [][]byte, err error) {
- coinSelector := coinset.MaxValueAgeCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(0)}
- coins, err := coinSelector.CoinSelect(target, coins)
- if err != nil {
- return total, inputs, []btc.Amount{}, scripts, errors.New("insuffient funds")
- }
- additionalPrevScripts = make(map[wire.OutPoint][]byte)
- inVals = make(map[wire.OutPoint]int64)
- additionalKeysByAddress = make(map[string]*btc.WIF)
- for _, c := range coins.Coins() {
- total += c.Value()
- outpoint := wire.NewOutPoint(c.Hash(), c.Index())
- in := wire.NewTxIn(outpoint, []byte{}, [][]byte{})
- inputs = append(inputs, in)
- additionalPrevScripts[*outpoint] = c.PkScript()
- key := coinMap[c]
- addr, err := key.Address(w.params)
- if err != nil {
- continue
- }
- privKey, err := key.ECPrivKey()
- if err != nil {
- continue
- }
- wif, _ := btc.NewWIF(privKey, w.params, true)
- additionalKeysByAddress[addr.EncodeAddress()] = wif
- val := c.Value()
- sat := val.ToUnit(btc.AmountSatoshi)
- inVals[*outpoint] = int64(sat)
- }
- return total, inputs, []btc.Amount{}, scripts, nil
- }
-
- // Get the fee per kilobyte
- feePerKB := int64(w.GetFeePerByte(feeLevel)) * 1000
-
- // outputs
- out := wire.NewTxOut(amount, script)
-
- // Create change source
- changeSource := func() ([]byte, error) {
- addr := w.CurrentAddress(wallet.INTERNAL)
- script, err := bchutil.PayToAddrScript(addr)
- if err != nil {
- return []byte{}, err
- }
- return script, nil
- }
-
- outputs := []*wire.TxOut{out}
- if optionalOutput != nil {
- outputs = append(outputs, optionalOutput)
- }
- authoredTx, err := NewUnsignedTransaction(outputs, btc.Amount(feePerKB), inputSource, changeSource)
- if err != nil {
- return nil, err
- }
-
- // BIP 69 sorting
- txsort.InPlaceSort(authoredTx.Tx)
-
- // Sign tx
- getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) {
- addrStr := addr.EncodeAddress()
- wif := additionalKeysByAddress[addrStr]
- return wif.PrivKey, wif.CompressPubKey, nil
- })
- getScript := txscript.ScriptClosure(func(
- addr btc.Address) ([]byte, error) {
- return []byte{}, nil
- })
- for i, txIn := range authoredTx.Tx.TxIn {
- prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint]
- script, err := bchutil.SignTxOutput(w.params,
- authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, getKey,
- getScript, txIn.SignatureScript, inVals[txIn.PreviousOutPoint])
- if err != nil {
- return nil, errors.New("Failed to sign transaction")
- }
- txIn.SignatureScript = script
- }
- return authoredTx.Tx, nil
-}
-
-func (w *SPVWallet) buildSpendAllTx(addr btc.Address, feeLevel wallet.FeeLevel) (*wire.MsgTx, error) {
- tx := wire.NewMsgTx(1)
-
- coinMap := w.gatherCoins()
-
- inVals := make(map[wire.OutPoint]int64)
- totalIn := int64(0)
- additionalPrevScripts := make(map[wire.OutPoint][]byte)
- additionalKeysByAddress := make(map[string]*btc.WIF)
-
- for coin, key := range coinMap {
- outpoint := wire.NewOutPoint(coin.Hash(), coin.Index())
- in := wire.NewTxIn(outpoint, nil, nil)
- additionalPrevScripts[*outpoint] = coin.PkScript()
- tx.TxIn = append(tx.TxIn, in)
- val := int64(coin.Value().ToUnit(btc.AmountSatoshi))
- totalIn += val
- inVals[*outpoint] = val
-
- addr, err := key.Address(w.params)
- if err != nil {
- continue
- }
- privKey, err := key.ECPrivKey()
- if err != nil {
- continue
- }
- wif, _ := btc.NewWIF(privKey, w.params, true)
- additionalKeysByAddress[addr.EncodeAddress()] = wif
- }
-
- // outputs
- script, err := bchutil.PayToAddrScript(addr)
- if err != nil {
- return nil, err
- }
-
- // Get the fee
- feePerByte := int64(w.GetFeePerByte(feeLevel))
- estimatedSize := EstimateSerializeSize(1, []*wire.TxOut{wire.NewTxOut(0, script)}, false, P2PKH)
- fee := int64(estimatedSize) * feePerByte
-
- // Check for dust output
- if txrules.IsDustAmount(btc.Amount(totalIn-fee), len(script), txrules.DefaultRelayFeePerKb) {
- return nil, wallet.ErrorDustAmount
- }
-
- // Build the output
- out := wire.NewTxOut(totalIn-fee, script)
- tx.TxOut = append(tx.TxOut, out)
-
- // BIP 69 sorting
- txsort.InPlaceSort(tx)
-
- // Sign
- getKey := txscript.KeyClosure(func(addr btc.Address) (*btcec.PrivateKey, bool, error) {
- addrStr := addr.EncodeAddress()
- wif, ok := additionalKeysByAddress[addrStr]
- if !ok {
- return nil, false, errors.New("key not found")
- }
- return wif.PrivKey, wif.CompressPubKey, nil
- })
- getScript := txscript.ScriptClosure(func(
- addr btc.Address) ([]byte, error) {
- return []byte{}, nil
- })
- for i, txIn := range tx.TxIn {
- prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint]
- script, err := bchutil.SignTxOutput(w.params,
- tx, i, prevOutScript, txscript.SigHashAll, getKey,
- getScript, txIn.SignatureScript, inVals[txIn.PreviousOutPoint])
- if err != nil {
- return nil, errors.New("failed to sign transaction")
- }
- txIn.SignatureScript = script
- }
- return tx, nil
-}
-
-func NewUnsignedTransaction(outputs []*wire.TxOut, feePerKb btc.Amount, fetchInputs txauthor.InputSource, fetchChange txauthor.ChangeSource) (*txauthor.AuthoredTx, error) {
-
- var targetAmount btc.Amount
- for _, txOut := range outputs {
- targetAmount += btc.Amount(txOut.Value)
- }
-
- estimatedSize := EstimateSerializeSize(1, outputs, true, P2PKH)
- targetFee := txrules.FeeForSerializeSize(feePerKb, estimatedSize)
-
- for {
- inputAmount, inputs, _, scripts, err := fetchInputs(targetAmount + targetFee)
- if err != nil {
- return nil, err
- }
- if inputAmount < targetAmount+targetFee {
- return nil, errors.New("insufficient funds available to construct transaction")
- }
-
- maxSignedSize := EstimateSerializeSize(len(inputs), outputs, true, P2PKH)
- maxRequiredFee := txrules.FeeForSerializeSize(feePerKb, maxSignedSize)
- remainingAmount := inputAmount - targetAmount
- if remainingAmount < maxRequiredFee {
- targetFee = maxRequiredFee
- continue
- }
-
- unsignedTransaction := &wire.MsgTx{
- Version: wire.TxVersion,
- TxIn: inputs,
- TxOut: outputs,
- LockTime: 0,
- }
- changeIndex := -1
- changeAmount := inputAmount - targetAmount - maxRequiredFee
- if changeAmount != 0 && !txrules.IsDustAmount(changeAmount,
- P2PKHOutputSize, txrules.DefaultRelayFeePerKb) {
- changeScript, err := fetchChange()
- if err != nil {
- return nil, err
- }
- if len(changeScript) > P2PKHPkScriptSize {
- return nil, errors.New("fee estimation requires change " +
- "scripts no larger than P2PKH output scripts")
- }
- change := wire.NewTxOut(int64(changeAmount), changeScript)
- l := len(outputs)
- unsignedTransaction.TxOut = append(outputs[:l:l], change)
- changeIndex = l
- }
-
- return &txauthor.AuthoredTx{
- Tx: unsignedTransaction,
- PrevScripts: scripts,
- TotalInput: inputAmount,
- ChangeIndex: changeIndex,
- }, nil
- }
-}
-
-func (w *SPVWallet) GetFeePerByte(feeLevel wallet.FeeLevel) uint64 {
- return w.feeProvider.GetFeePerByte(feeLevel)
-}
-
-func LockTimeFromRedeemScript(redeemScript []byte) (uint32, error) {
- if len(redeemScript) < 113 {
- return 0, errors.New("Redeem script invalid length")
- }
- if redeemScript[106] != 103 {
- return 0, errors.New("Invalid redeem script")
- }
- if redeemScript[107] == 0 {
- return 0, nil
- }
- if 81 <= redeemScript[107] && redeemScript[107] <= 96 {
- return uint32((redeemScript[107] - 81) + 1), nil
- }
- var v []byte
- op := redeemScript[107]
- if 1 <= op && op <= 75 {
- for i := 0; i < int(op); i++ {
- v = append(v, []byte{redeemScript[108+i]}...)
- }
- } else {
- return 0, errors.New("Too many bytes pushed for sequence")
- }
- var result int64
- for i, val := range v {
- result |= int64(val) << uint8(8*i)
- }
-
- return uint32(result), nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh b/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh
deleted file mode 100755
index 878211bd62..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/test_compile.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-set -e
-pwd
-go get github.com/cpacia/BitcoinCash-Wallet
-go get github.com/mattn/go-sqlite3
-go test -coverprofile=bitcoincash.cover.out ./
-echo "mode: set" > coverage.out && cat *.cover.out | grep -v mode: | sort -r | \
-awk '{if($1 != last) {print $0;last=$1}}' >> coverage.out
-rm -rf *.cover.out
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go
deleted file mode 100644
index f3139ec0fe..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/timesorter.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2013-2017 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-package bitcoincash
-
-// timeSorter implements sort.Interface to allow a slice of timestamps to
-// be sorted.
-type timeSorter []int64
-
-// Len returns the number of timestamps in the slice. It is part of the
-// sort.Interface implementation.
-func (s timeSorter) Len() int {
- return len(s)
-}
-
-// Swap swaps the timestamps at the passed indices. It is part of the
-// sort.Interface implementation.
-func (s timeSorter) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-
-// Less returns whether the timstamp with index i should sort before the
-// timestamp with index j. It is part of the sort.Interface implementation.
-func (s timeSorter) Less(i, j int) bool {
- return s[i] < s[j]
-}
-
-// timeSorter implements sort.Interface to allow a slice of block headers to
-// be sorted by timestamp.
-type blockSorter []StoredHeader
-
-// Len returns the number of timestamps in the slice. It is part of the
-// sort.Interface implementation.
-func (s blockSorter) Len() int {
- return len(s)
-}
-
-// Swap swaps the timestamps at the passed indices. It is part of the
-// sort.Interface implementation.
-func (s blockSorter) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-
-// Less returns whether the timstamp with index i should sort before the
-// timestamp with index j. It is part of the sort.Interface implementation.
-func (s blockSorter) Less(i, j int) bool {
- if s[i].header.Timestamp.Before(s[j].header.Timestamp) || s[i].header.Timestamp.Equal(s[j].header.Timestamp) {
- return true
- }
- return false
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go
deleted file mode 100644
index 189bd3c86f..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/tor.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package bitcoincash
-
-// Copyright (c) 2013-2016 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-import (
- "encoding/binary"
- "errors"
- "net"
-)
-
-const (
- torSucceeded = 0x00
- torGeneralError = 0x01
- torNotAllowed = 0x02
- torNetUnreachable = 0x03
- torHostUnreachable = 0x04
- torConnectionRefused = 0x05
- torTTLExpired = 0x06
- torCmdNotSupported = 0x07
- torAddrNotSupported = 0x08
-)
-
-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")
-
- torStatusErrors = map[byte]error{
- torSucceeded: errors.New("tor succeeded"),
- torGeneralError: errors.New("tor general error"),
- torNotAllowed: errors.New("tor not allowed"),
- torNetUnreachable: errors.New("tor network is unreachable"),
- torHostUnreachable: errors.New("tor host is unreachable"),
- torConnectionRefused: errors.New("tor connection refused"),
- torTTLExpired: errors.New("tor TTL expired"),
- torCmdNotSupported: errors.New("tor command not supported"),
- torAddrNotSupported: errors.New("tor address type not supported"),
- }
-)
-
-// 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.
-func TorLookupIP(host string) ([]net.IP, error) {
- conn, err := net.Dial("tcp", "127.0.0.1:9150")
- if err != nil {
- conn, err = net.Dial("tcp", "127.0.0.1:9050")
- if err != nil {
- return nil, err
- }
- }
- defer conn.Close()
-
- buf := []byte{'\x05', '\x01', '\x00'}
- _, err = conn.Write(buf)
- if err != nil {
- return nil, err
- }
-
- buf = make([]byte, 2)
- _, err = conn.Read(buf)
- if err != nil {
- return nil, err
- }
- if buf[0] != '\x05' {
- return nil, ErrTorInvalidProxyResponse
- }
- if buf[1] != '\x00' {
- return nil, ErrTorUnrecognizedAuthMethod
- }
-
- buf = make([]byte, 7+len(host))
- buf[0] = 5 // protocol version
- buf[1] = '\xF0' // Tor Resolve
- buf[2] = 0 // reserved
- buf[3] = 3 // Tor Resolve
- buf[4] = byte(len(host))
- copy(buf[5:], host)
- buf[5+len(host)] = 0 // Port 0
-
- _, err = conn.Write(buf)
- if err != nil {
- return nil, err
- }
-
- buf = make([]byte, 4)
- _, err = conn.Read(buf)
- if err != nil {
- return nil, err
- }
- if buf[0] != 5 {
- return nil, ErrTorInvalidProxyResponse
- }
- if buf[1] != 0 {
- if int(buf[1]) > len(torStatusErrors) {
- err = ErrTorInvalidProxyResponse
- } else {
- err = torStatusErrors[buf[1]]
- if err == nil {
- err = ErrTorInvalidProxyResponse
- }
- }
- return nil, err
- }
- if buf[3] != 1 {
- err := torStatusErrors[torGeneralError]
- return nil, err
- }
-
- buf = make([]byte, 4)
- bytes, err := conn.Read(buf)
- if err != nil {
- return nil, err
- }
- if bytes != 4 {
- return nil, ErrTorInvalidAddressResponse
- }
-
- r := binary.BigEndian.Uint32(buf)
-
- addr := make([]net.IP, 1)
- addr[0] = net.IPv4(byte(r>>24), byte(r>>16), byte(r>>8), byte(r))
-
- return addr, nil
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go
deleted file mode 100644
index 0db2af0eb2..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/txsizes.go
+++ /dev/null
@@ -1,249 +0,0 @@
-package bitcoincash
-
-// Copyright (c) 2016 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-/* Copied here from a btcd internal package*/
-
-import (
- "github.com/btcsuite/btcd/wire"
-)
-
-// Worst case script and input/output size estimates.
-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
-)
-
-type InputType int
-
-const (
- P2PKH InputType = iota
- P2SH_1of2_Multisig
- P2SH_2of3_Multisig
- P2SH_Multisig_Timelock_1Sig
- P2SH_Multisig_Timelock_2Sigs
-)
-
-// 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 EstimateSerializeSize(inputCount int, txOuts []*wire.TxOut, addChangeOutput bool, inputType InputType) int {
- changeSize := 0
- outputCount := len(txOuts)
- if addChangeOutput {
- changeSize = P2PKHOutputSize
- outputCount++
- }
-
- var redeemScriptSize int
- switch inputType {
- case P2PKH:
- redeemScriptSize = RedeemP2PKHInputSize
- case P2SH_1of2_Multisig:
- redeemScriptSize = RedeemP2SH1of2MultisigInputSize
- case P2SH_2of3_Multisig:
- redeemScriptSize = RedeemP2SH2of3MultisigInputSize
- case P2SH_Multisig_Timelock_1Sig:
- redeemScriptSize = RedeemP2SHMultisigTimelock1InputSize
- case P2SH_Multisig_Timelock_2Sigs:
- redeemScriptSize = RedeemP2SHMultisigTimelock2InputSize
- }
-
- // 10 additional bytes are for version, locktime, and segwit flags
- return 10 + wire.VarIntSerializeSize(uint64(inputCount)) +
- wire.VarIntSerializeSize(uint64(outputCount)) +
- inputCount*redeemScriptSize +
- SumOutputSerializeSizes(txOuts) +
- changeSize
-}
-
-// SumOutputSerializeSizes sums up the serialized size of the supplied outputs.
-func SumOutputSerializeSizes(outputs []*wire.TxOut) (serializeSize int) {
- for _, txOut := range outputs {
- serializeSize += txOut.SerializeSize()
- }
- return serializeSize
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go
deleted file mode 100644
index 46fe6bc79d..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/txstore.go
+++ /dev/null
@@ -1,498 +0,0 @@
-// Copyright (C) 2015-2016 The Lightning Network Developers
-// Copyright (c) 2016-2017 The OpenBazaar Developers
-
-package bitcoincash
-
-import (
- "bytes"
- "errors"
- "github.com/OpenBazaar/wallet-interface"
- "github.com/btcsuite/btcd/blockchain"
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/txscript"
- "github.com/btcsuite/btcd/wire"
- "github.com/btcsuite/btcutil"
- "github.com/btcsuite/btcutil/bloom"
- "sync"
- "time"
-)
-
-type TxStore struct {
- adrs []btcutil.Address
- watchedScripts [][]byte
- txids map[string]int32
- addrMutex *sync.Mutex
- txidsMutex *sync.RWMutex
- cbMutex *sync.Mutex
-
- keyManager *KeyManager
-
- params *chaincfg.Params
-
- listeners []func(wallet.TransactionCallback)
-
- additionalFilters [][]byte
-
- wallet.Datastore
-}
-
-func NewTxStore(p *chaincfg.Params, db wallet.Datastore, keyManager *KeyManager, additionalFilters ...[]byte) (*TxStore, error) {
- txs := &TxStore{
- params: p,
- keyManager: keyManager,
- addrMutex: new(sync.Mutex),
- cbMutex: new(sync.Mutex),
- txidsMutex: new(sync.RWMutex),
- txids: make(map[string]int32),
- Datastore: db,
- additionalFilters: additionalFilters,
- }
- err := txs.PopulateAdrs()
- if err != nil {
- return nil, err
- }
- return txs, nil
-}
-
-// ... or I'm gonna fade away
-func (ts *TxStore) GimmeFilter() (*bloom.Filter, error) {
- ts.PopulateAdrs()
-
- // get all utxos to add outpoints to filter
- allUtxos, err := ts.Utxos().GetAll()
- if err != nil {
- return nil, err
- }
-
- allStxos, err := ts.Stxos().GetAll()
- if err != nil {
- return nil, err
- }
- ts.addrMutex.Lock()
- elem := uint32(len(ts.adrs)+len(allUtxos)+len(allStxos)) + uint32(len(ts.watchedScripts))
- f := bloom.NewFilter(elem, 0, 0.00003, wire.BloomUpdateAll)
-
- // note there could be false positives since we're just looking
- // for the 20 byte PKH without the opcodes.
- for _, a := range ts.adrs { // add 20-byte pubkeyhash
- f.Add(a.ScriptAddress())
- }
- ts.addrMutex.Unlock()
- for _, u := range allUtxos {
- f.AddOutPoint(&u.Op)
- }
-
- for _, s := range allStxos {
- f.AddOutPoint(&s.Utxo.Op)
- }
- for _, w := range ts.watchedScripts {
- _, addrs, _, err := txscript.ExtractPkScriptAddrs(w, ts.params)
- if err != nil {
- continue
- }
- f.Add(addrs[0].ScriptAddress())
- }
- for _, toAdd := range ts.additionalFilters {
- f.Add(toAdd)
- }
- return f, nil
-}
-
-// 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 (ts *TxStore) CheckDoubleSpends(argTx *wire.MsgTx) ([]*chainhash.Hash, error) {
- var dubs []*chainhash.Hash // slice of all double-spent txs
- argTxid := argTx.TxHash()
- txs, err := ts.Txns().GetAll(true)
- if err != nil {
- return dubs, err
- }
- for _, compTx := range txs {
- if compTx.Height < 0 {
- continue
- }
- r := bytes.NewReader(compTx.Bytes)
- msgTx := wire.NewMsgTx(1)
- msgTx.BtcDecode(r, 1, wire.WitnessEncoding)
- compTxid := msgTx.TxHash()
- for _, argIn := range argTx.TxIn {
- // iterate through inputs of compTx
- for _, compIn := range msgTx.TxIn {
- if outPointsEqual(argIn.PreviousOutPoint, compIn.PreviousOutPoint) && !compTxid.IsEqual(&argTxid) {
- // found double spend
- dubs = append(dubs, &compTxid)
- break // back to argIn loop
- }
- }
- }
- }
- return dubs, nil
-}
-
-// 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 (ts *TxStore) GetPendingInv() (*wire.MsgInv, error) {
- // use a map (really a set) do avoid dupes
- txidMap := make(map[chainhash.Hash]struct{})
-
- utxos, err := ts.Utxos().GetAll() // get utxos from db
- if err != nil {
- return nil, err
- }
- stxos, err := ts.Stxos().GetAll() // get stxos from db
- if err != nil {
- return nil, err
- }
-
- // iterate through utxos, adding txids of anything with height 0
- for _, utxo := range utxos {
- if utxo.AtHeight == 0 {
- txidMap[utxo.Op.Hash] = struct{}{} // adds to map
- }
- }
- // do the same with stxos based on height at which spent
- for _, stxo := range stxos {
- if stxo.SpendHeight == 0 {
- txidMap[stxo.SpendTxid] = struct{}{}
- }
- }
-
- invMsg := wire.NewMsgInv()
- for txid := range txidMap {
- item := wire.NewInvVect(wire.InvTypeTx, &txid)
- err = invMsg.AddInvVect(item)
- if err != nil {
- return nil, err
- }
- }
-
- // return inv message with all txids (maybe none)
- return invMsg, nil
-}
-
-// PopulateAdrs just puts a bunch of adrs in ram; it doesn't touch the DB
-func (ts *TxStore) PopulateAdrs() error {
- keys := ts.keyManager.GetKeys()
- ts.addrMutex.Lock()
- ts.adrs = []btcutil.Address{}
- for _, k := range keys {
- addr, err := k.Address(ts.params)
- if err != nil {
- continue
- }
- ts.adrs = append(ts.adrs, addr)
- }
- ts.addrMutex.Unlock()
- ts.watchedScripts, _ = ts.WatchedScripts().GetAll()
- txns, _ := ts.Txns().GetAll(true)
- ts.txidsMutex.Lock()
- for _, t := range txns {
- ts.txids[t.Txid] = t.Height
- }
- ts.txidsMutex.Unlock()
- return nil
-}
-
-// 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 (ts *TxStore) Ingest(tx *wire.MsgTx, height int32, timestamp time.Time) (uint32, error) {
- var hits uint32
- var err error
- // Tx has been OK'd by SPV; check tx sanity
- utilTx := btcutil.NewTx(tx) // convert for validation
- // Checks basic stuff like there are inputs and ouputs
- err = blockchain.CheckTransactionSanity(utilTx)
- if err != nil {
- return hits, err
- }
-
- // Check to see if we've already processed this tx. If so, return.
-
- ts.txidsMutex.RLock()
- sh, ok := ts.txids[tx.TxHash().String()]
- ts.txidsMutex.RUnlock()
- if ok && (sh > 0 || (sh == 0 && height == 0)) {
- return 1, nil
- }
-
- // Check to see if this is a double spend
- doubleSpends, err := ts.CheckDoubleSpends(tx)
- if err != nil {
- return hits, err
- }
- if len(doubleSpends) > 0 {
- // First seen rule
- if height == 0 {
- return 0, nil
- } else {
- // Mark any unconfirmed doubles as dead
- for _, double := range doubleSpends {
- ts.markAsDead(*double)
- }
- }
- }
-
- // Generate PKscripts for all addresses
- ts.addrMutex.Lock()
- PKscripts := make([][]byte, len(ts.adrs))
- for i := range ts.adrs {
- // Iterate through all our addresses
- // TODO: This will need to test both segwit and legacy once segwit activates
- PKscripts[i], err = txscript.PayToAddrScript(ts.adrs[i])
- if err != nil {
- ts.addrMutex.Unlock()
- return hits, err
- }
- }
- ts.addrMutex.Unlock()
-
- // Iterate through all outputs of this tx, see if we gain
- cachedSha := tx.TxHash()
- cb := wallet.TransactionCallback{Txid: cachedSha.String(), Height: height}
- value := int64(0)
- matchesWatchOnly := false
- for i, txout := range tx.TxOut {
- // Ignore the error here because the sender could have used and exotic script
- // for his change and we don't want to fail in that case.
- addr, _ := scriptToAddress(txout.PkScript, ts.params)
- out := wallet.TransactionOutput{Address: addr, Value: txout.Value, Index: uint32(i)}
- for _, script := range PKscripts {
- if bytes.Equal(txout.PkScript, script) { // new utxo found
- scriptAddress, _ := ts.extractScriptAddress(txout.PkScript)
- ts.keyManager.MarkKeyAsUsed(scriptAddress)
- newop := wire.OutPoint{
- Hash: cachedSha,
- Index: uint32(i),
- }
- newu := wallet.Utxo{
- AtHeight: height,
- Value: txout.Value,
- ScriptPubkey: txout.PkScript,
- Op: newop,
- WatchOnly: false,
- }
- value += newu.Value
- ts.Utxos().Put(newu)
- hits++
- break
- }
- }
- // Now check watched scripts
- for _, script := range ts.watchedScripts {
- if bytes.Equal(txout.PkScript, script) {
- newop := wire.OutPoint{
- Hash: cachedSha,
- Index: uint32(i),
- }
- newu := wallet.Utxo{
- AtHeight: height,
- Value: txout.Value,
- ScriptPubkey: txout.PkScript,
- Op: newop,
- WatchOnly: true,
- }
- ts.Utxos().Put(newu)
- matchesWatchOnly = true
- }
- }
- for _, f := range ts.additionalFilters {
- if bytes.Contains(txout.PkScript, f) {
- matchesWatchOnly = true
- break
- }
- }
- cb.Outputs = append(cb.Outputs, out)
- }
- utxos, err := ts.Utxos().GetAll()
- if err != nil {
- return 0, err
- }
- for _, txin := range tx.TxIn {
- for i, u := range utxos {
- if outPointsEqual(txin.PreviousOutPoint, u.Op) {
- st := wallet.Stxo{
- Utxo: u,
- SpendHeight: height,
- SpendTxid: cachedSha,
- }
- ts.Stxos().Put(st)
- ts.Utxos().Delete(u)
- utxos = append(utxos[:i], utxos[i+1:]...)
- if !u.WatchOnly {
- value -= u.Value
- hits++
- } else {
- matchesWatchOnly = true
- }
-
- // Ignore the error here because the sender could have used and exotic script
- // for his change and we don't want to fail in that case.
- addr, _ := scriptToAddress(u.ScriptPubkey, ts.params)
-
- in := wallet.TransactionInput{
- OutpointHash: u.Op.Hash.CloneBytes(),
- OutpointIndex: u.Op.Index,
- LinkedAddress: addr,
- Value: u.Value,
- }
- cb.Inputs = append(cb.Inputs, in)
- break
- }
- }
- }
-
- // Update height of any stxos
- if height > 0 {
- stxos, err := ts.Stxos().GetAll()
- if err != nil {
- return 0, err
- }
- for _, stxo := range stxos {
- if stxo.SpendTxid.IsEqual(&cachedSha) {
- stxo.SpendHeight = height
- ts.Stxos().Put(stxo)
- if !stxo.Utxo.WatchOnly {
- hits++
- } else {
- matchesWatchOnly = true
- }
- break
- }
- }
- }
-
- // If hits is nonzero it's a relevant tx and we should store it
- if hits > 0 || matchesWatchOnly {
- ts.cbMutex.Lock()
- ts.txidsMutex.Lock()
- txn, err := ts.Txns().Get(tx.TxHash())
- shouldCallback := false
- if err != nil {
- cb.Value = value
- txn.Timestamp = timestamp
- shouldCallback = true
- var buf bytes.Buffer
- tx.BtcEncode(&buf, 1, wire.BaseEncoding)
- ts.Txns().Put(buf.Bytes(), tx.TxHash().String(), int(value), int(height), txn.Timestamp, hits == 0)
- ts.txids[tx.TxHash().String()] = height
- }
- // Let's check the height before committing so we don't allow rogue peers to send us a lose
- // tx that resets our height to zero.
- if txn.Height <= 0 {
- ts.Txns().UpdateHeight(tx.TxHash(), int(height), timestamp)
- ts.txids[tx.TxHash().String()] = height
- if height > 0 {
- cb.Value = txn.Value
- shouldCallback = true
- }
- }
- cb.BlockTime = timestamp
- ts.txidsMutex.Unlock()
- if shouldCallback {
- // Callback on listeners
- for _, listener := range ts.listeners {
- listener(cb)
- }
- }
- ts.cbMutex.Unlock()
- ts.PopulateAdrs()
- hits++
- }
- return hits, err
-}
-
-func (ts *TxStore) markAsDead(txid chainhash.Hash) error {
- stxos, err := ts.Stxos().GetAll()
- if err != nil {
- return err
- }
- markStxoAsDead := func(s wallet.Stxo) error {
- err := ts.Stxos().Delete(s)
- if err != nil {
- return err
- }
- err = ts.Txns().UpdateHeight(s.SpendTxid, -1, time.Now())
- if err != nil {
- return err
- }
- return nil
- }
- for _, s := range stxos {
- // If an stxo is marked dead, move it back into the utxo table
- if txid.IsEqual(&s.SpendTxid) {
- if err := markStxoAsDead(s); err != nil {
- return err
- }
- if err := ts.Utxos().Put(s.Utxo); err != nil {
- return err
- }
- }
- // If a dependency of the spend is dead then mark the spend as dead
- if txid.IsEqual(&s.Utxo.Op.Hash) {
- if err := markStxoAsDead(s); err != nil {
- return err
- }
- if err := ts.markAsDead(s.SpendTxid); err != nil {
- return err
- }
- }
- }
- utxos, err := ts.Utxos().GetAll()
- if err != nil {
- return err
- }
- // Dead utxos should just be deleted
- for _, u := range utxos {
- if txid.IsEqual(&u.Op.Hash) {
- err := ts.Utxos().Delete(u)
- if err != nil {
- return err
- }
- }
- }
- ts.Txns().UpdateHeight(txid, -1, time.Now())
- return nil
-}
-
-func (ts *TxStore) processReorg(lastGoodHeight uint32) error {
- txns, err := ts.Txns().GetAll(true)
- if err != nil {
- return err
- }
- for i := len(txns) - 1; i >= 0; i-- {
- if txns[i].Height > int32(lastGoodHeight) {
- txid, err := chainhash.NewHashFromStr(txns[i].Txid)
- if err != nil {
- log.Error(err)
- continue
- }
- err = ts.markAsDead(*txid)
- if err != nil {
- log.Error(err)
- continue
- }
- }
- }
- return nil
-}
-
-func (ts *TxStore) extractScriptAddress(script []byte) ([]byte, error) {
- _, addrs, _, err := txscript.ExtractPkScriptAddrs(script, ts.params)
- if err != nil {
- return nil, err
- }
- if len(addrs) == 0 {
- return nil, errors.New("unknown script")
- }
- return addrs[0].ScriptAddress(), nil
-}
-
-func outPointsEqual(a, b wire.OutPoint) bool {
- if !a.Hash.IsEqual(&b.Hash) {
- return false
- }
- return a.Index == b.Index
-}
diff --git a/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go b/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go
deleted file mode 100644
index c3cc353ef9..0000000000
--- a/vendor/github.com/cpacia/BitcoinCash-Wallet/wallet.go
+++ /dev/null
@@ -1,539 +0,0 @@
-package bitcoincash
-
-import (
- "bytes"
- "errors"
- "io"
- "sync"
- "time"
-
- "github.com/OpenBazaar/wallet-interface"
- "github.com/btcsuite/btcd/btcec"
- "github.com/btcsuite/btcd/chaincfg"
- "github.com/btcsuite/btcd/chaincfg/chainhash"
- "github.com/btcsuite/btcd/peer"
- "github.com/btcsuite/btcd/txscript"
- "github.com/btcsuite/btcd/wire"
- btc "github.com/btcsuite/btcutil"
- hd "github.com/btcsuite/btcutil/hdkeychain"
- "github.com/btcsuite/btcwallet/wallet/txrules"
- "github.com/cpacia/BitcoinCash-Wallet/exchangerates"
- "github.com/cpacia/bchutil"
- "github.com/op/go-logging"
- b39 "github.com/tyler-smith/go-bip39"
-)
-
-func setupNetworkParams(params *chaincfg.Params) {
- switch params.Name {
- case chaincfg.MainNetParams.Name:
- params.Net = bchutil.MainnetMagic
- case chaincfg.TestNet3Params.Name:
- params.Net = bchutil.TestnetMagic
- case chaincfg.RegressionNetParams.Name:
- params.Net = bchutil.Regtestmagic
- }
-}
-
-type SPVWallet struct {
- params *chaincfg.Params
-
- masterPrivateKey *hd.ExtendedKey
- masterPublicKey *hd.ExtendedKey
-
- mnemonic string
-
- feeProvider *FeeProvider
-
- repoPath string
-
- blockchain *Blockchain
- txstore *TxStore
- peerManager *PeerManager
- keyManager *KeyManager
- wireService *WireService
-
- fPositives chan *peer.Peer
- stopChan chan int
- fpAccumulator map[int32]int32
- mutex *sync.RWMutex
-
- creationDate time.Time
-
- running bool
-
- config *PeerManagerConfig
-
- exchangeRates wallet.ExchangeRates
-}
-
-var log = logging.MustGetLogger("bitcoin")
-
-const WALLET_VERSION = "0.1.0"
-
-func NewSPVWallet(config *Config) (*SPVWallet, error) {
- setupNetworkParams(config.Params)
-
- log.SetBackend(logging.AddModuleLevel(config.Logger))
-
- if config.Mnemonic == "" {
- ent, err := b39.NewEntropy(128)
- if err != nil {
- return nil, err
- }
- mnemonic, err := b39.NewMnemonic(ent)
- if err != nil {
- return nil, err
- }
- config.Mnemonic = mnemonic
- config.CreationDate = time.Now()
- }
- seed := b39.NewSeed(config.Mnemonic, "")
-
- mPrivKey, err := hd.NewMaster(seed, config.Params)
- if err != nil {
- return nil, err
- }
- mPubKey, err := mPrivKey.Neuter()
- if err != nil {
- return nil, err
- }
- w := &SPVWallet{
- repoPath: config.RepoPath,
- masterPrivateKey: mPrivKey,
- masterPublicKey: mPubKey,
- mnemonic: config.Mnemonic,
- params: config.Params,
- creationDate: config.CreationDate,
- feeProvider: NewFeeProvider(
- config.MaxFee,
- config.HighFee,
- config.MediumFee,
- config.LowFee,
- nil,
- ),
- fPositives: make(chan *peer.Peer),
- stopChan: make(chan int),
- fpAccumulator: make(map[int32]int32),
- mutex: new(sync.RWMutex),
- }
-
- er := exchangerates.NewBitcoinCashPriceFetcher(config.Proxy)
- w.exchangeRates = er
- if !config.DisableExchangeRates {
- go er.Run()
- w.feeProvider.exchangeRates = er
- }
-
- w.keyManager, err = NewKeyManager(config.DB.Keys(), w.params, w.masterPrivateKey)
-
- w.txstore, err = NewTxStore(w.params, config.DB, w.keyManager, config.AdditionalFilters...)
- if err != nil {
- return nil, err
- }
-
- w.blockchain, err = NewBlockchain(w.repoPath, w.creationDate, w.params)
- if err != nil {
- return nil, err
- }
-
- minSync := 5
- if config.TrustedPeer != nil {
- minSync = 1
- }
- wireConfig := &WireServiceConfig{
- txStore: w.txstore,
- chain: w.blockchain,
- walletCreationDate: w.creationDate,
- minPeersForSync: minSync,
- params: w.params,
- }
-
- ws := NewWireService(wireConfig)
- w.wireService = ws
-
- getNewestBlock := func() (*chainhash.Hash, int32, error) {
- sh, err := w.blockchain.BestBlock()
- if err != nil {
- return nil, 0, err
- }
- h := sh.header.BlockHash()
- return &h, int32(sh.height), nil
- }
-
- w.config = &PeerManagerConfig{
- UserAgentName: config.UserAgent,
- UserAgentVersion: WALLET_VERSION,
- Params: w.params,
- AddressCacheDir: config.RepoPath,
- Proxy: config.Proxy,
- GetNewestBlock: getNewestBlock,
- MsgChan: ws.MsgChan(),
- }
-
- if config.TrustedPeer != nil {
- w.config.TrustedPeer = config.TrustedPeer
- }
-
- w.peerManager, err = NewPeerManager(w.config)
- if err != nil {
- return nil, err
- }
-
- return w, nil
-}
-
-func (w *SPVWallet) Start() {
- w.running = true
- go w.wireService.Start()
- go w.peerManager.Start()
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// API
-//
-//////////////
-
-func (w *SPVWallet) CurrencyCode() string {
- if w.params.Name == chaincfg.MainNetParams.Name {
- return "bch"
- } else {
- return "tbch"
- }
-}
-
-func (w *SPVWallet) CreationDate() time.Time {
- return w.creationDate
-}
-
-func (w *SPVWallet) IsDust(amount int64) bool {
- return txrules.IsDustAmount(btc.Amount(amount), 25, txrules.DefaultRelayFeePerKb)
-}
-
-func (w *SPVWallet) MasterPrivateKey() *hd.ExtendedKey {
- return w.masterPrivateKey
-}
-
-func (w *SPVWallet) MasterPublicKey() *hd.ExtendedKey {
- return w.masterPublicKey
-}
-
-func (w *SPVWallet) ChildKey(keyBytes []byte, chaincode []byte, isPrivateKey bool) (*hd.ExtendedKey, error) {
- parentFP := []byte{0x00, 0x00, 0x00, 0x00}
- var id []byte
- if isPrivateKey {
- id = w.params.HDPrivateKeyID[:]
- } else {
- id = w.params.HDPublicKeyID[:]
- }
- hdKey := hd.NewExtendedKey(
- id,
- keyBytes,
- chaincode,
- parentFP,
- 0,
- 0,
- isPrivateKey)
- return hdKey.Child(0)
-}
-
-func (w *SPVWallet) Mnemonic() string {
- return w.mnemonic
-}
-
-func (w *SPVWallet) ConnectedPeers() []*peer.Peer {
- return w.peerManager.ConnectedPeers()
-}
-
-func (w *SPVWallet) CurrentAddress(purpose wallet.KeyPurpose) btc.Address {
- key, _ := w.keyManager.GetCurrentKey(purpose)
- addr, _ := key.Address(w.params)
- cashaddr, _ := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params)
- return btc.Address(cashaddr)
-}
-
-func (w *SPVWallet) NewAddress(purpose wallet.KeyPurpose) btc.Address {
- i, _ := w.txstore.Keys().GetUnused(purpose)
- key, _ := w.keyManager.generateChildKey(purpose, uint32(i[1]))
- addr, _ := key.Address(w.params)
- w.txstore.Keys().MarkKeyAsUsed(addr.ScriptAddress())
- w.txstore.PopulateAdrs()
- cashaddr, _ := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params)
- return btc.Address(cashaddr)
-}
-
-func (w *SPVWallet) DecodeAddress(addr string) (btc.Address, error) {
- // Legacy
- decoded, err := btc.DecodeAddress(addr, w.params)
- if err == nil {
- return decoded, nil
- }
- // Cashaddr
- decoded, err = bchutil.DecodeAddress(addr, w.params)
- if err == nil {
- return decoded, nil
- }
- // Bitpay
- decoded, err = bchutil.DecodeBitpay(addr, w.params)
- if err == nil {
- return decoded, nil
- }
- return nil, errors.New("Unrecognized address format")
-}
-
-func (w *SPVWallet) ScriptToAddress(script []byte) (btc.Address, error) {
- return scriptToAddress(script, w.params)
-}
-
-func scriptToAddress(script []byte, params *chaincfg.Params) (btc.Address, error) {
- addr, err := bchutil.ExtractPkScriptAddrs(script, params)
- if err != nil {
- return nil, err
- }
- return btc.Address(addr), nil
-}
-
-func (w *SPVWallet) AddressToScript(addr btc.Address) ([]byte, error) {
- return bchutil.PayToAddrScript(addr)
-}
-
-func (w *SPVWallet) HasKey(addr btc.Address) bool {
- _, err := w.keyManager.GetKeyForScript(addr.ScriptAddress())
- if err != nil {
- return false
- }
- return true
-}
-
-func (w *SPVWallet) GetKey(addr btc.Address) (*btcec.PrivateKey, error) {
- key, err := w.keyManager.GetKeyForScript(addr.ScriptAddress())
- if err != nil {
- return nil, err
- }
- return key.ECPrivKey()
-}
-
-func (w *SPVWallet) ListAddresses() []btc.Address {
- keys := w.keyManager.GetKeys()
- addrs := []btc.Address{}
- for _, k := range keys {
- addr, err := k.Address(w.params)
- if err != nil {
- continue
- }
- cashaddr, err := bchutil.NewCashAddressPubKeyHash(addr.ScriptAddress(), w.params)
- if err != nil {
- continue
- }
- addrs = append(addrs, cashaddr)
- }
- return addrs
-}
-
-func (w *SPVWallet) ListKeys() []btcec.PrivateKey {
- keys := w.keyManager.GetKeys()
- list := []btcec.PrivateKey{}
- for _, k := range keys {
- priv, err := k.ECPrivKey()
- if err != nil {
- continue
- }
- list = append(list, *priv)
- }
- return list
-}
-
-func (w *SPVWallet) ImportKey(privKey *btcec.PrivateKey, compress bool) error {
- pub := privKey.PubKey()
- var pubKeyBytes []byte
- if compress {
- pubKeyBytes = pub.SerializeCompressed()
- } else {
- pubKeyBytes = pub.SerializeUncompressed()
- }
- pkHash := btc.Hash160(pubKeyBytes)
- addr, err := btc.NewAddressPubKeyHash(pkHash, w.params)
- if err != nil {
- return err
- }
- return w.keyManager.datastore.ImportKey(addr.ScriptAddress(), privKey)
-}
-
-func (w *SPVWallet) Balance() (confirmed, unconfirmed int64) {
- utxos, _ := w.txstore.Utxos().GetAll()
- stxos, _ := w.txstore.Stxos().GetAll()
- for _, utxo := range utxos {
- if !utxo.WatchOnly {
- if utxo.AtHeight > 0 {
- confirmed += utxo.Value
- } else {
- if w.checkIfStxoIsConfirmed(utxo, stxos) {
- confirmed += utxo.Value
- } else {
- unconfirmed += utxo.Value
- }
- }
- }
- }
- return confirmed, unconfirmed
-}
-
-func (w *SPVWallet) Transactions() ([]wallet.Txn, error) {
- height, _ := w.ChainTip()
- txns, err := w.txstore.Txns().GetAll(false)
- if err != nil {
- return txns, err
- }
- for i, tx := range txns {
- var confirmations int32
- var status wallet.StatusCode
- confs := int32(height) - tx.Height + 1
- if tx.Height <= 0 {
- confs = tx.Height
- }
- switch {
- case confs < 0:
- status = wallet.StatusDead
- case confs == 0 && time.Since(tx.Timestamp) <= time.Hour*6:
- status = wallet.StatusUnconfirmed
- case confs == 0 && time.Since(tx.Timestamp) > time.Hour*6:
- status = wallet.StatusStuck
- case confs > 0 && confs < 6:
- status = wallet.StatusPending
- confirmations = confs
- case confs > 5:
- status = wallet.StatusConfirmed
- confirmations = confs
- }
- tx.Confirmations = int64(confirmations)
- tx.Status = status
- txns[i] = tx
- }
- return txns, nil
-}
-
-func (w *SPVWallet) GetTransaction(txid chainhash.Hash) (wallet.Txn, error) {
- txn, err := w.txstore.Txns().Get(txid)
- if err == nil {
- tx := wire.NewMsgTx(1)
- rbuf := bytes.NewReader(txn.Bytes)
- err := tx.BtcDecode(rbuf, wire.ProtocolVersion, wire.WitnessEncoding)
- if err != nil {
- return txn, err
- }
- outs := []wallet.TransactionOutput{}
- for i, out := range tx.TxOut {
- var addr btc.Address
- _, addrs, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, w.params)
- if err != nil {
- log.Warningf("error extracting address from txn pkscript: %v\n", err)
- }
- if len(addrs) == 0 {
- addr = nil
- } else {
- addr = addrs[0]
- }
- tout := wallet.TransactionOutput{
- Address: addr,
- Value: out.Value,
- Index: uint32(i),
- }
- outs = append(outs, tout)
- }
- txn.Outputs = outs
- }
- return txn, err
-}
-
-func (w *SPVWallet) GetConfirmations(txid chainhash.Hash) (uint32, uint32, error) {
- txn, err := w.txstore.Txns().Get(txid)
- if err != nil {
- return 0, 0, err
- }
- if txn.Height == 0 {
- return 0, 0, nil
- }
- chainTip, _ := w.ChainTip()
- return chainTip - uint32(txn.Height) + 1, uint32(txn.Height), nil
-}
-
-func (w *SPVWallet) checkIfStxoIsConfirmed(utxo wallet.Utxo, stxos []wallet.Stxo) bool {
- for _, stxo := range stxos {
- if !stxo.Utxo.WatchOnly {
- if stxo.SpendTxid.IsEqual(&utxo.Op.Hash) {
- if stxo.SpendHeight > 0 {
- return true
- } else {
- return w.checkIfStxoIsConfirmed(stxo.Utxo, stxos)
- }
- } else if stxo.Utxo.IsEqual(&utxo) {
- if stxo.Utxo.AtHeight > 0 {
- return true
- } else {
- return false
- }
- }
- }
- }
- return false
-}
-
-func (w *SPVWallet) Params() *chaincfg.Params {
- return w.params
-}
-
-func (w *SPVWallet) AddTransactionListener(callback func(wallet.TransactionCallback)) {
- w.txstore.listeners = append(w.txstore.listeners, callback)
-}
-
-func (w *SPVWallet) ChainTip() (uint32, chainhash.Hash) {
- var ch chainhash.Hash
- sh, err := w.blockchain.db.GetBestHeader()
- if err != nil {
- return 0, ch
- }
- return sh.height, sh.header.BlockHash()
-}
-
-func (w *SPVWallet) AddWatchedAddress(addr btc.Address) error {
- script, err := w.AddressToScript(addr)
- if err != nil {
- return err
- }
- err = w.txstore.WatchedScripts().Put(script)
- w.txstore.PopulateAdrs()
-
- w.wireService.MsgChan() <- updateFiltersMsg{}
- return err
-}
-
-func (w *SPVWallet) DumpHeaders(writer io.Writer) {
- w.blockchain.db.Print(writer)
-}
-
-func (w *SPVWallet) ExchangeRates() wallet.ExchangeRates {
- return w.exchangeRates
-}
-
-func (w *SPVWallet) Close() {
- if w.running {
- log.Info("Disconnecting from peers and shutting down")
- w.peerManager.Stop()
- w.blockchain.Close()
- w.wireService.Stop()
- w.running = false
- }
-}
-
-func (w *SPVWallet) ReSyncBlockchain(fromDate time.Time) {
- w.blockchain.Rollback(fromDate)
- w.txstore.PopulateAdrs()
- w.wireService.Resync()
-}
-
-// AssociateTransactionWithOrder used for ORDER_PAYMENT message
-func (w *SPVWallet) AssociateTransactionWithOrder(cb wallet.TransactionCallback) {
- for _, l := range w.txstore.listeners {
- go l(cb)
- }
-}
diff --git a/wallet/builder.go b/wallet/builder.go
index 91568d6a85..5f9b957bae 100644
--- a/wallet/builder.go
+++ b/wallet/builder.go
@@ -24,7 +24,6 @@ import (
"github.com/OpenBazaar/spvwallet"
"github.com/OpenBazaar/wallet-interface"
"github.com/btcsuite/btcd/chaincfg"
- bchspv "github.com/cpacia/BitcoinCash-Wallet"
"github.com/op/go-logging"
"golang.org/x/net/proxy"
)
@@ -248,49 +247,6 @@ func createSPVWallet(coin wallet.CoinType, coinConfigOverrides *schema.CoinConfi
actualCoin = wallet.Bitcoin
}
return actualCoin, newSPVWallet, nil
- case wallet.BitcoinCash:
- defaultConfig := defaultConfigSet.BCH
- preparedConfig := &bchspv.Config{
- Mnemonic: cfg.Mnemonic,
- Params: cfg.Params,
- MaxFee: coinConfigOverrides.MaxFee,
- LowFee: coinConfigOverrides.LowFeeDefault,
- MediumFee: coinConfigOverrides.MediumFeeDefault,
- HighFee: coinConfigOverrides.HighFeeDefault,
- FeeAPI: *feeAPI,
- RepoPath: walletRepoPath,
- CreationDate: cfg.WalletCreationDate,
- DB: CreateWalletDB(cfg.DB, coin),
- UserAgent: "OpenBazaar",
- TrustedPeer: trustedPeer,
- Proxy: cfg.Proxy,
- Logger: cfg.Logger,
- DisableExchangeRates: cfg.DisableExchangeRates,
- }
- if preparedConfig.HighFee == 0 {
- preparedConfig.HighFee = defaultConfig.HighFeeDefault
- }
- if preparedConfig.MediumFee == 0 {
- preparedConfig.MediumFee = defaultConfig.MediumFeeDefault
- }
- if preparedConfig.LowFee == 0 {
- preparedConfig.LowFee = defaultConfig.LowFeeDefault
- }
- if preparedConfig.MaxFee == 0 {
- preparedConfig.MaxFee = defaultConfig.MaxFee
- }
-
- newSPVWallet, err := bchspv.NewSPVWallet(preparedConfig)
- if err != nil {
- return InvalidCoinType, nil, err
- }
-
- if notMainnet {
- actualCoin = wallet.TestnetBitcoinCash
- } else {
- actualCoin = wallet.BitcoinCash
- }
- return actualCoin, newSPVWallet, nil
}
return InvalidCoinType, nil, fmt.Errorf("unable to create wallet for unknown coin %s", coin.String())
}