Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MWEB Light Client #10

Open
wants to merge 83 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
4c329d6
Mempool transaction notification
hectorchu Jan 6, 2024
87aa530
Support LiteWallet derivation
hectorchu Jan 6, 2024
062acf9
Go mod
hectorchu Jan 6, 2024
f4c1e9d
Fix compat with new ltcd
hectorchu Jan 7, 2024
857ded8
More compat with latest ltcd
hectorchu Jan 8, 2024
9bf6da9
Add mweb to waddrmgr
hectorchu Jan 20, 2024
494b0c3
Test mweb address derivation
hectorchu Jan 21, 2024
f55e341
Fix broken test
hectorchu Jan 21, 2024
1dddb59
Add mweb utxos notification
hectorchu Jan 21, 2024
abb84e3
Change notification to use NetUtxo
hectorchu Jan 22, 2024
67101d5
Notify new utxos at startup
hectorchu Jan 22, 2024
8a3bbf3
Store mweb utxos in txdb
hectorchu Jan 23, 2024
eff5a25
BlockMeta gets filled in at source
hectorchu Jan 23, 2024
0b6c21c
Send mweb txns
hectorchu Jan 27, 2024
a96d6c2
Fees, change and coin selection
hectorchu Jan 28, 2024
ef8bbb0
Get block meta from utxo height
hectorchu Jan 29, 2024
b69bc53
Set and get mweb output from txdb
hectorchu Jan 29, 2024
764c601
Remove mweb tx from unmined bucket once mweb outputs are confirmed
hectorchu Jan 29, 2024
5b5e8e0
Delete unmined tx
hectorchu Jan 29, 2024
3e5b06e
Improved wtxmgr handling of mweb txns
hectorchu Jan 30, 2024
985cd24
Fixes
hectorchu Jan 30, 2024
4c5bbf6
One more
hectorchu Jan 30, 2024
b572257
Mweb outpoint fixes
hectorchu Jan 30, 2024
f4d173a
If any of the inputs are mweb then make change on mweb
hectorchu Jan 30, 2024
d1423c1
Check for spent credits
hectorchu Jan 31, 2024
6bfd38c
Check leafset param
hectorchu Jan 31, 2024
924cae5
Add coins that aren't ours to the txouts
hectorchu Jan 31, 2024
5538f8a
More thorough checking of incoming utxos
hectorchu Jan 31, 2024
d31dd59
Small oversight
hectorchu Jan 31, 2024
69cd28f
Notify blocks
hectorchu Jan 31, 2024
6faa047
Avoid adding duplicate credits
hectorchu Jan 31, 2024
3a01f3b
Really fix
hectorchu Jan 31, 2024
e3e0420
Some fixes for pegins/outs
hectorchu Jan 31, 2024
5935087
Oversight
hectorchu Jan 31, 2024
c78e81b
Pegout maturity
hectorchu Feb 1, 2024
bec07a6
Use the new HogEx detection method
hectorchu Feb 1, 2024
50730a5
Add pegouts to outpoints map
hectorchu Feb 1, 2024
8bf69a1
Avoid having two pegin records
hectorchu Feb 2, 2024
bb33a68
Use new pegins checker
hectorchu Feb 2, 2024
7404831
Keep the same txhash
hectorchu Feb 2, 2024
1b84bcf
Hash won't change - add outpoints immediately
hectorchu Feb 2, 2024
ecbfb72
Fix used address detection
hectorchu Feb 3, 2024
fcc8de5
Allow legacy rpc to generate bech32 and mweb addresses
hectorchu Feb 4, 2024
9335abd
Send from all key scopes
hectorchu Feb 4, 2024
6e06d4a
Stop rebroadcasting confirmed transactions
hectorchu Feb 6, 2024
cbd3dd4
Fix build
hectorchu Feb 18, 2024
395f8df
Fix test
hectorchu Feb 18, 2024
11d6079
Fix build
hectorchu Feb 18, 2024
8f0f0bf
Fix crash
hectorchu Feb 18, 2024
36faeb3
Fix test
hectorchu Feb 18, 2024
2e96450
More test fixes
hectorchu Feb 18, 2024
c603919
Revert default change key scope to bip84
hectorchu Feb 19, 2024
c888bc1
Allow recovery to be shut down
hectorchu Feb 19, 2024
aa29615
Get tx notifs for new addrs
hectorchu Feb 20, 2024
f9d50db
Forgot this
hectorchu Feb 20, 2024
9996976
Handle unconfirmed mweb utxos
hectorchu Feb 21, 2024
296dfa6
Reduce the size of the sentinel kernel slightly
hectorchu Feb 21, 2024
71fadaa
Treat hogex as coinbase during reorg
hectorchu Feb 24, 2024
85177fe
Always make change on mweb
hectorchu Feb 25, 2024
df11b15
Clear the wallet-side leafset on rollback
hectorchu Feb 25, 2024
acc12ed
Combine leafset with height
hectorchu Feb 26, 2024
acda183
Store old leafsets so we can rollback smarter
hectorchu Feb 26, 2024
06d3196
Missed an error check
hectorchu Feb 26, 2024
1f40752
Delete rolled-back leafsets
hectorchu Feb 26, 2024
2ae059e
Also rollback leafset when disconnecting blocks
hectorchu Feb 26, 2024
949218d
Use the leafset block for spent txo records
hectorchu Feb 27, 2024
eda8e9b
Switching to go workspaces
hectorchu Feb 28, 2024
42f8f3b
Use block hashes and synced to height to determine the latest valid l…
hectorchu Feb 28, 2024
5259f98
Fix restore from seed
hectorchu Feb 29, 2024
9af3453
Move wallet mweb functions to separate file
hectorchu Feb 29, 2024
08b6206
Add mweb keypool
hectorchu Mar 1, 2024
a12e91b
Use the new IsHogExTx function
hectorchu Mar 1, 2024
9957e33
Various improvements
hectorchu Mar 2, 2024
6e542c1
Some fixes
hectorchu Mar 3, 2024
993b9b3
More fixes
hectorchu Mar 3, 2024
5f5db78
Fix pegin fee calc
hectorchu Mar 4, 2024
cfcbef0
Remove cfilter polling.
hectorchu Mar 6, 2024
d4801e7
Fix recovery, 2nd attempt
hectorchu Mar 8, 2024
69d6e9a
Fix locking
hectorchu Mar 23, 2024
6570a36
Fix more locking
hectorchu Mar 23, 2024
dcd78b4
Correct coin type for scopes
hectorchu Mar 25, 2024
e77b8ab
Correctly deal with txns that can't be published
hectorchu Mar 27, 2024
625417b
More fixes for when a pegin transaction fails to send
hectorchu Mar 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions chain/chainservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/ltcsuite/ltcd/chaincfg/chainhash"
"github.com/ltcsuite/ltcd/ltcutil"
"github.com/ltcsuite/ltcd/ltcutil/gcs"
"github.com/ltcsuite/ltcd/ltcutil/mweb"
"github.com/ltcsuite/ltcd/wire"
"github.com/ltcsuite/neutrino"
"github.com/ltcsuite/neutrino/banman"
Expand All @@ -22,6 +23,7 @@ type NeutrinoChainService interface {
GetBlockHeader(*chainhash.Hash) (*wire.BlockHeader, error)
IsCurrent() bool
SendTransaction(*wire.MsgTx) error
MarkAsConfirmed(chainhash.Hash)
GetCFilter(chainhash.Hash, wire.FilterType,
...neutrino.QueryOption) (*gcs.Filter, error)
GetUtxo(...neutrino.RescanOption) (*neutrino.SpendReport, error)
Expand All @@ -31,6 +33,11 @@ type NeutrinoChainService interface {
AddBytesSent(uint64)
AddBytesReceived(uint64)
NetTotals() (uint64, uint64)
RegisterMempoolCallback(func(*ltcutil.Tx))
NotifyMempoolReceived([]ltcutil.Address)
RegisterMwebUtxosCallback(func(*mweb.Leafset, []*wire.MwebNetUtxo))
NotifyAddedMwebUtxos(*mweb.Leafset) error
MwebUtxoExists(*chainhash.Hash) bool
UpdatePeerHeights(*chainhash.Hash, int32, *neutrino.ServerPeer)
ChainParams() chaincfg.Params
Stop() error
Expand Down
7 changes: 7 additions & 0 deletions chain/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/ltcsuite/ltcd/chaincfg/chainhash"
"github.com/ltcsuite/ltcd/ltcutil"
"github.com/ltcsuite/ltcd/ltcutil/mweb"
"github.com/ltcsuite/ltcd/rpcclient"
"github.com/ltcsuite/ltcd/wire"
"github.com/ltcsuite/ltcwallet/waddrmgr"
Expand Down Expand Up @@ -108,6 +109,12 @@ type (
Block *wtxmgr.BlockMeta // nil if unmined
}

// MwebUtxos is a notification of new MWEB utxos.
MwebUtxos struct {
Leafset *mweb.Leafset
Utxos []*wire.MwebNetUtxo
}

// RescanProgress is a notification describing the current status
// of an in-progress rescan.
RescanProgress struct {
Expand Down
23 changes: 23 additions & 0 deletions chain/mocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/ltcsuite/ltcd/chaincfg/chainhash"
"github.com/ltcsuite/ltcd/ltcutil"
"github.com/ltcsuite/ltcd/ltcutil/gcs"
"github.com/ltcsuite/ltcd/ltcutil/mweb"
"github.com/ltcsuite/ltcd/rpcclient"
"github.com/ltcsuite/ltcd/wire"
"github.com/ltcsuite/neutrino"
Expand Down Expand Up @@ -104,6 +105,10 @@ func (m *mockChainService) SendTransaction(*wire.MsgTx) error {
return errNotImplemented
}

func (m *mockChainService) MarkAsConfirmed(chainhash.Hash) {
panic(errNotImplemented)
}

func (m *mockChainService) GetCFilter(chainhash.Hash,
wire.FilterType, ...neutrino.QueryOption) (*gcs.Filter, error) {

Expand Down Expand Up @@ -140,6 +145,24 @@ func (m *mockChainService) NetTotals() (uint64, uint64) {
panic(errNotImplemented)
}

func (m *mockChainService) RegisterMempoolCallback(func(*ltcutil.Tx)) {
}

func (m *mockChainService) NotifyMempoolReceived([]ltcutil.Address) {
}

func (m *mockChainService) RegisterMwebUtxosCallback(
func(*mweb.Leafset, []*wire.MwebNetUtxo)) {
}

func (m *mockChainService) NotifyAddedMwebUtxos(*mweb.Leafset) error {
return errNotImplemented
}

func (m *mockChainService) MwebUtxoExists(*chainhash.Hash) bool {
panic(errNotImplemented)
}

func (m *mockChainService) UpdatePeerHeights(*chainhash.Hash,
int32, *neutrino.ServerPeer,
) {
Expand Down
71 changes: 34 additions & 37 deletions chain/neutrino.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"github.com/ltcsuite/ltcd/chaincfg"
"github.com/ltcsuite/ltcd/chaincfg/chainhash"
"github.com/ltcsuite/ltcd/ltcutil"
"github.com/ltcsuite/ltcd/ltcutil/gcs"
"github.com/ltcsuite/ltcd/ltcutil/gcs/builder"
"github.com/ltcsuite/ltcd/ltcutil/mweb"
"github.com/ltcsuite/ltcd/rpcclient"
"github.com/ltcsuite/ltcd/txscript"
"github.com/ltcsuite/ltcd/wire"
Expand Down Expand Up @@ -241,12 +241,8 @@ func (s *NeutrinoClient) FilterBlocks(
// the filter returns a positive match, the full block is then requested
// and scanned for addresses using the block filterer.
for i, blk := range req.Blocks {
// TODO(wilmer): Investigate why polling it still necessary
// here. While testing, I ran into a few instances where the
// filter was not retrieved, leading to a panic. This should not
// happen in most cases thanks to the query logic revamp within
// Neutrino, but it seems there's still an uncovered edge case.
filter, err := s.pollCFilter(&blk.Hash)
filter, err := s.CS.GetCFilter(blk.Hash,
wire.GCSFilterRegular, neutrino.OptimisticBatch())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -343,36 +339,6 @@ func buildFilterBlocksWatchList(req *FilterBlocksRequest) ([][]byte, error) {
return watchList, nil
}

// pollCFilter attempts to fetch a CFilter from the neutrino client. This is
// used to get around the fact that the filter headers may lag behind the
// highest known block header.
func (s *NeutrinoClient) pollCFilter(hash *chainhash.Hash) (*gcs.Filter, error) {
var (
filter *gcs.Filter
err error
count int
)

const maxFilterRetries = 50
for count < maxFilterRetries {
if count > 0 {
time.Sleep(100 * time.Millisecond)
}

filter, err = s.CS.GetCFilter(
*hash, wire.GCSFilterRegular, neutrino.OptimisticBatch(),
)
if err != nil {
count++
continue
}

return filter, nil
}

return nil, err
}

// Rescan replicates the RPC client's Rescan command.
func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []ltcutil.Address,
outPoints map[wire.OutPoint]ltcutil.Address) error {
Expand All @@ -382,6 +348,9 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []ltcutil.Addre
defer s.rescanMtx.Unlock()

s.clientMtx.Lock()

s.CS.NotifyMempoolReceived(addrs)

if !s.started {
s.clientMtx.Unlock()
return fmt.Errorf("can't do a rescan when the chain client " +
Expand Down Expand Up @@ -477,6 +446,10 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []ltcutil.Addre
// NotifyBlocks replicates the RPC client's NotifyBlocks command.
func (s *NeutrinoClient) NotifyBlocks() error {
s.clientMtx.Lock()

s.CS.RegisterMempoolCallback(s.onRecvTx)
s.CS.RegisterMwebUtxosCallback(s.onMwebUtxos)

// If we're scanning, we're already notifying on blocks. Otherwise,
// start a rescan without watching any addresses.
if !s.scanning {
Expand All @@ -495,6 +468,8 @@ func (s *NeutrinoClient) NotifyReceived(addrs []ltcutil.Address) error {

s.clientMtx.Lock()

s.CS.NotifyMempoolReceived(addrs)

// If we have a rescan running, we just need to add the appropriate
// addresses to the watch list.
if s.scanning {
Expand Down Expand Up @@ -797,3 +772,25 @@ out:
close(s.dequeueNotification)
s.wg.Done()
}

func (s *NeutrinoClient) onRecvTx(tx *ltcutil.Tx) {
rec, err := wtxmgr.NewTxRecordFromMsgTx(tx.MsgTx(), time.Now())
if err != nil {
log.Errorf("Cannot create transaction record for relevant "+
"tx: %v", err)
return
}
select {
case s.enqueueNotification <- RelevantTx{rec, nil}:
case <-s.quit:
}
}

func (s *NeutrinoClient) onMwebUtxos(
leafset *mweb.Leafset, utxos []*wire.MwebNetUtxo) {

select {
case s.enqueueNotification <- MwebUtxos{leafset, utxos}:
case <-s.quit:
}
}
8 changes: 5 additions & 3 deletions cmd/sweepaccount/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/ltcsuite/ltcd/wire"
"github.com/ltcsuite/ltcwallet/internal/cfgutil"
"github.com/ltcsuite/ltcwallet/netparams"
"github.com/ltcsuite/ltcwallet/waddrmgr"
"github.com/ltcsuite/ltcwallet/wallet/txauthor"
"github.com/ltcsuite/ltcwallet/wallet/txrules"
"github.com/ltcsuite/ltcwallet/wallet/txsizes"
Expand Down Expand Up @@ -181,8 +182,9 @@ func makeInputSource(outputs []btcjson.ListUnspentResult) txauthor.InputSource {
sourceErr = noInputValue{}
}

return func(ltcutil.Amount) (ltcutil.Amount, []*wire.TxIn, []ltcutil.Amount, [][]byte, error) {
return totalInputValue, inputs, inputValues, nil, sourceErr
return func(ltcutil.Amount) (ltcutil.Amount, []*wire.TxIn,
[]ltcutil.Amount, [][]byte, []*wire.MwebOutput, error) {
return totalInputValue, inputs, inputValues, nil, nil, sourceErr
}
}

Expand All @@ -193,7 +195,7 @@ func makeDestinationScriptSource(rpcClient *rpcclient.Client, accountName string

// GetNewAddress always returns a P2PKH address since it assumes
// BIP-0044.
newChangeScript := func() ([]byte, error) {
newChangeScript := func(*waddrmgr.KeyScope) ([]byte, error) {
destinationAddress, err := rpcClient.GetNewAddress(accountName)
if err != nil {
return nil, err
Expand Down
61 changes: 11 additions & 50 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,30 @@ require (
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
github.com/jessevdk/go-flags v1.4.0
github.com/jessevdk/go-flags v1.5.0
github.com/jrick/logrotate v1.0.0
github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf
github.com/ltcsuite/lnd/ticker v1.1.0
github.com/ltcsuite/lnd/tlv v1.1.1
github.com/ltcsuite/ltcd v0.23.5
github.com/ltcsuite/ltcd/btcec/v2 v2.3.2
github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2
github.com/ltcsuite/ltcd/ltcutil v1.1.3
github.com/ltcsuite/ltcd/ltcutil/psbt v1.1.8
github.com/ltcsuite/ltcwallet/wallet/txauthor v1.3.2
github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0
github.com/ltcsuite/ltcwallet/wallet/txsizes v1.2.3
github.com/ltcsuite/ltcwallet/walletdb v1.4.0
github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0
github.com/ltcsuite/neutrino v0.16.0
github.com/ltcsuite/neutrino/cache v1.1.1
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.3
golang.org/x/crypto v0.7.0
golang.org/x/net v0.10.0
golang.org/x/term v0.8.0
google.golang.org/grpc v1.53.0
google.golang.org/protobuf v1.28.1
google.golang.org/grpc v1.56.3
google.golang.org/protobuf v1.30.0
lukechampine.com/blake3 v1.2.1
)

require (
github.com/aead/siphash v1.0.1 // indirect
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/decred/dcrd/lru v1.1.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/kkdai/bstream v1.0.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
github.com/ltcsuite/lnd/clock v1.1.0 // indirect
github.com/ltcsuite/lnd/queue v1.1.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/stretchr/objx v0.5.0 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)

go 1.18

replace github.com/ltcsuite/ltcwallet/walletdb => ./walletdb

replace github.com/ltcsuite/neutrino => ../neutrino

replace github.com/ltcsuite/neutrino/cache => ../neutrino/cache

replace github.com/ltcsuite/lnd/tlv => ../lnd/tlv

replace github.com/ltcsuite/ltcd/ltcutil/psbt => ../ltcd/ltcutil/psbt

replace github.com/ltcsuite/ltcwallet/wallet/txauthor => ./wallet/txauthor

replace github.com/ltcsuite/ltcwallet/wallet/txsizes => ./wallet/txsizes

// loshy temp:

replace github.com/ltcsuite/ltcd => ../ltcd

replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhash
Loading