mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-23 06:35:07 +01:00
Merge pull request #1896 from Roasbeef/btcwallet-unconf-txn
lnwallet+rpc: allow unconfirmed transactions to be returned over RPC, fix SubscribeTransaction unconf for neutrino
This commit is contained in:
commit
1c4bd04c55
7 changed files with 89 additions and 14 deletions
5
Gopkg.lock
generated
5
Gopkg.lock
generated
|
@ -106,7 +106,7 @@
|
||||||
revision = "ab6388e0c60ae4834a1f57511e20c17b5f78be4b"
|
revision = "ab6388e0c60ae4834a1f57511e20c17b5f78be4b"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:012039cbb6694894aa9e9890645e6ade8a5aff5a02c279714779eff3eae53bc2"
|
digest = "1:e6575f3ee773e72a38319dbd8f4cb7f1b574eccfed7cb103c3a25c254d5c250f"
|
||||||
name = "github.com/btcsuite/btcwallet"
|
name = "github.com/btcsuite/btcwallet"
|
||||||
packages = [
|
packages = [
|
||||||
"chain",
|
"chain",
|
||||||
|
@ -126,7 +126,7 @@
|
||||||
"wtxmgr",
|
"wtxmgr",
|
||||||
]
|
]
|
||||||
pruneopts = "UT"
|
pruneopts = "UT"
|
||||||
revision = "f4ae41ce5f5834eb67ab64cdeed74c74fc95638c"
|
revision = "421298df22601db0fe4adb8f4be71b7014324ba9"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -417,7 +417,6 @@
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
|
||||||
digest = "1:c9e7a4b4d47c0ed205d257648b0e5b0440880cb728506e318f8ac7cd36270bc4"
|
digest = "1:c9e7a4b4d47c0ed205d257648b0e5b0440880cb728506e318f8ac7cd36270bc4"
|
||||||
name = "golang.org/x/time"
|
name = "golang.org/x/time"
|
||||||
packages = ["rate"]
|
packages = ["rate"]
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/btcsuite/btcwallet"
|
name = "github.com/btcsuite/btcwallet"
|
||||||
revision = "f4ae41ce5f5834eb67ab64cdeed74c74fc95638c"
|
revision = "421298df22601db0fe4adb8f4be71b7014324ba9"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/tv42/zbase32"
|
name = "github.com/tv42/zbase32"
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
@ -115,7 +114,7 @@ func New(chainConn *chain.BitcoindConn, spendHintCache chainntnfs.SpendHintCache
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier.chainConn = chainConn.NewBitcoindClient(time.Unix(0, 0))
|
notifier.chainConn = chainConn.NewBitcoindClient()
|
||||||
|
|
||||||
return notifier
|
return notifier
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,7 +335,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
||||||
bitcoindConn, hintCache, hintCache,
|
bitcoindConn, hintCache, hintCache,
|
||||||
)
|
)
|
||||||
cc.chainView = chainview.NewBitcoindFilteredChainView(bitcoindConn)
|
cc.chainView = chainview.NewBitcoindFilteredChainView(bitcoindConn)
|
||||||
walletConfig.ChainSource = bitcoindConn.NewBitcoindClient(birthday)
|
walletConfig.ChainSource = bitcoindConn.NewBitcoindClient()
|
||||||
|
|
||||||
// If we're not in regtest mode, then we'll attempt to use a
|
// If we're not in regtest mode, then we'll attempt to use a
|
||||||
// proper fee estimator for testnet.
|
// proper fee estimator for testnet.
|
||||||
|
|
|
@ -559,9 +559,11 @@ func (b *BtcWallet) ListTransactionDetails() ([]*lnwallet.TransactionDetail, err
|
||||||
bestBlock := b.wallet.Manager.SyncedTo()
|
bestBlock := b.wallet.Manager.SyncedTo()
|
||||||
currentHeight := bestBlock.Height
|
currentHeight := bestBlock.Height
|
||||||
|
|
||||||
// TODO(roasbeef): can replace with start "wallet birthday"
|
// We'll attempt to find all unconfirmed transactions (height of -1),
|
||||||
|
// as well as all transactions that are known to have confirmed at this
|
||||||
|
// height.
|
||||||
start := base.NewBlockIdentifierFromHeight(0)
|
start := base.NewBlockIdentifierFromHeight(0)
|
||||||
stop := base.NewBlockIdentifierFromHeight(bestBlock.Height)
|
stop := base.NewBlockIdentifierFromHeight(-1)
|
||||||
txns, err := b.wallet.GetTransactions(start, stop, nil)
|
txns, err := b.wallet.GetTransactions(start, stop, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -1055,7 +1055,9 @@ func testListTransactionDetails(miner *rpctest.Harness,
|
||||||
delete(txids, txDetail.Hash)
|
delete(txids, txDetail.Hash)
|
||||||
}
|
}
|
||||||
if len(txids) != 0 {
|
if len(txids) != 0 {
|
||||||
t.Fatalf("all transactions not found in details!")
|
t.Fatalf("all transactions not found in details: left=%v, "+
|
||||||
|
"returned_set=%v", spew.Sdump(txids),
|
||||||
|
spew.Sdump(txDetails))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next create a transaction paying to an output which isn't under the
|
// Next create a transaction paying to an output which isn't under the
|
||||||
|
@ -1075,6 +1077,41 @@ func testListTransactionDetails(miner *rpctest.Harness,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("tx not relayed to miner: %v", err)
|
t.Fatalf("tx not relayed to miner: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Before we mine the next block, we'll ensure that the above
|
||||||
|
// transaction shows up in the set of unconfirmed transactions returned
|
||||||
|
// by ListTransactionDetails.
|
||||||
|
err = waitForWalletSync(miner, alice)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Couldn't sync Alice's wallet: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should be able to find the transaction above in the set of
|
||||||
|
// returned transactions, and it should have a confirmation of -1,
|
||||||
|
// indicating that it's not yet mined.
|
||||||
|
txDetails, err = alice.ListTransactionDetails()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to fetch tx details: %v", err)
|
||||||
|
}
|
||||||
|
var mempoolTxFound bool
|
||||||
|
for _, txDetail := range txDetails {
|
||||||
|
if !bytes.Equal(txDetail.Hash[:], burnTXID[:]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we've found the transaction, ensure that it has a
|
||||||
|
// negative number of confirmations to indicate that it's
|
||||||
|
// unconfirmed.
|
||||||
|
mempoolTxFound = true
|
||||||
|
if txDetail.NumConfirmations != 0 {
|
||||||
|
t.Fatalf("num confs incorrect, got %v expected %v",
|
||||||
|
txDetail.NumConfirmations, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !mempoolTxFound {
|
||||||
|
t.Fatalf("unable to find mempool tx in tx details!")
|
||||||
|
}
|
||||||
|
|
||||||
burnBlock, err := miner.Node.Generate(1)
|
burnBlock, err := miner.Node.Generate(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to mine block: %v", err)
|
t.Fatalf("unable to mine block: %v", err)
|
||||||
|
@ -1233,6 +1270,45 @@ func testTransactionSubscriptions(miner *rpctest.Harness,
|
||||||
t.Fatalf("transactions not received after 5 seconds")
|
t.Fatalf("transactions not received after 5 seconds")
|
||||||
case <-confirmedNtfns: // Fall through on success
|
case <-confirmedNtfns: // Fall through on success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We'll also ensure that the client is able to send our new
|
||||||
|
// notifications when we _create_ transactions ourselves that spend our
|
||||||
|
// own outputs.
|
||||||
|
b := txscript.NewScriptBuilder()
|
||||||
|
b.AddOp(txscript.OP_0)
|
||||||
|
outputScript, err := b.Script()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to make output script: %v", err)
|
||||||
|
}
|
||||||
|
burnOutput := wire.NewTxOut(outputAmt, outputScript)
|
||||||
|
txid, err := alice.SendOutputs([]*wire.TxOut{burnOutput}, 2500)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create burn tx: %v", err)
|
||||||
|
}
|
||||||
|
err = waitForMempoolTx(miner, txid)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("tx not relayed to miner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before we mine the next block, we'll ensure that the above
|
||||||
|
// transaction shows up in the set of unconfirmed transactions returned
|
||||||
|
// by ListTransactionDetails.
|
||||||
|
err = waitForWalletSync(miner, alice)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Couldn't sync Alice's wallet: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// As we just sent the transaction and it was landed in the mempool, we
|
||||||
|
// should get a notification for a new unconfirmed transactions
|
||||||
|
select {
|
||||||
|
case <-time.After(time.Second * 10):
|
||||||
|
t.Fatalf("transactions not received after 10 seconds")
|
||||||
|
case unConfTx := <-txClient.UnconfirmedTransactions():
|
||||||
|
if unConfTx.Hash != *txid {
|
||||||
|
t.Fatalf("wrong txn notified: expected %v got %v",
|
||||||
|
txid, unConfTx.Hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// testPublishTransaction checks that PublishTransaction returns the
|
// testPublishTransaction checks that PublishTransaction returns the
|
||||||
|
@ -2278,8 +2354,8 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver,
|
||||||
|
|
||||||
// Create a btcwallet bitcoind client for both Alice and
|
// Create a btcwallet bitcoind client for both Alice and
|
||||||
// Bob.
|
// Bob.
|
||||||
aliceClient = chainConn.NewBitcoindClient(time.Unix(0, 0))
|
aliceClient = chainConn.NewBitcoindClient()
|
||||||
bobClient = chainConn.NewBitcoindClient(time.Unix(0, 0))
|
bobClient = chainConn.NewBitcoindClient()
|
||||||
default:
|
default:
|
||||||
t.Fatalf("unknown chain driver: %v", backEnd)
|
t.Fatalf("unknown chain driver: %v", backEnd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
@ -71,7 +70,7 @@ func NewBitcoindFilteredChainView(
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
chainView.chainClient = chainConn.NewBitcoindClient(time.Unix(0, 0))
|
chainView.chainClient = chainConn.NewBitcoindClient()
|
||||||
chainView.blockQueue = newBlockEventQueue()
|
chainView.blockQueue = newBlockEventQueue()
|
||||||
|
|
||||||
return chainView
|
return chainView
|
||||||
|
|
Loading…
Add table
Reference in a new issue