From 29dd25ef89c5f1aae15af9e01c971662a9601f96 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 6 Jan 2024 22:58:53 +0000 Subject: [PATCH 01/75] Mempool transaction notification --- blockmanager.go | 67 ++++++++++++++++++- go.mod | 13 ++++ go.sum | 166 ++++++++++-------------------------------------- mempool.go | 74 +++++++++++++++++++++ neutrino.go | 59 ++++++++++++++--- 5 files changed, 237 insertions(+), 142 deletions(-) create mode 100644 mempool.go diff --git a/blockmanager.go b/blockmanager.go index 92001d1bd..d45f3aa14 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -72,6 +72,13 @@ type donePeerMsg struct { peer *ServerPeer } +// txMsg packages a bitcoin tx message and the peer it came from together +// so the block handler has access to that information. +type txMsg struct { + tx *ltcutil.Tx + peer *ServerPeer +} + // blockManagerCfg holds options and dependencies needed by the blockManager // during operation. type blockManagerCfg struct { @@ -109,6 +116,8 @@ type blockManagerCfg struct { checkResponse func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}, peerQuit chan<- struct{}), options ...QueryOption) + + mempool *Mempool } // blockManager provides a concurrency safe block manager for handling all @@ -206,6 +215,8 @@ type blockManager struct { // nolint:maligned minRetargetTimespan int64 // target timespan / adjustment factor maxRetargetTimespan int64 // target timespan * adjustment factor blocksPerRetarget int32 // target timespan / target time per block + + requestedTxns map[chainhash.Hash]struct{} } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -235,6 +246,7 @@ func newBlockManager(cfg *blockManagerCfg) (*blockManager, error) { blocksPerRetarget: int32(targetTimespan / targetTimePerBlock), minRetargetTimespan: targetTimespan / adjustmentFactor, maxRetargetTimespan: targetTimespan * adjustmentFactor, + requestedTxns: make(map[chainhash.Hash]struct{}), } // Next we'll create the two signals that goroutines will use to wait @@ -1994,6 +2006,9 @@ out: case *invMsg: b.handleInvMsg(msg) + case *txMsg: + b.handleTxMsg(msg) + case *headersMsg: b.handleHeadersMsg(msg) @@ -2260,13 +2275,48 @@ func (b *blockManager) QueueInv(inv *wire.MsgInv, sp *ServerPeer) { } } +// QueueTx adds the passed transaction message and peer to the block handling +// queue. Responds to the done channel argument after the tx message is +// processed. +func (b *blockManager) QueueTx(tx *ltcutil.Tx, sp *ServerPeer) { + // No channel handling here because peers do not need to block on inv + // messages. + if atomic.LoadInt32(&b.shutdown) != 0 { + return + } + + select { + case b.peerChan <- &txMsg{tx: tx, peer: sp}: + case <-b.quit: + return + } +} + // handleInvMsg handles inv messages from all peers. // We examine the inventory advertised by the remote peer and act accordingly. func (b *blockManager) handleInvMsg(imsg *invMsg) { + invVects := imsg.inv.InvList + if b.BlockHeadersSynced() { + gdmsg := wire.NewMsgGetData() + for _, iv := range invVects { + if iv.Type == wire.InvTypeTx { + if b.cfg.mempool.HaveTransaction(&iv.Hash) { + continue + } + if _, exists := b.requestedTxns[iv.Hash]; !exists { + b.requestedTxns[iv.Hash] = struct{}{} + gdmsg.AddInvVect(iv) + } + } + } + if len(gdmsg.InvList) > 0 { + imsg.peer.QueueMessage(gdmsg, nil) + } + } + // 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 @@ -2344,6 +2394,17 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { } } +// handleTxMsg handles transaction messages from all peers. +func (b *blockManager) handleTxMsg(tmsg *txMsg) { + txHash := tmsg.tx.Hash() + if _, exists := b.requestedTxns[*txHash]; !exists { + log.Warnf("Peer %s sent us a transaction we didn't request", tmsg.peer.Addr()) + return + } + b.cfg.mempool.AddTransaction(tmsg.tx) + delete(b.requestedTxns, *txHash) +} + // QueueHeaders adds the passed headers message and peer to the block handling // queue. func (b *blockManager) QueueHeaders(headers *wire.MsgHeaders, sp *ServerPeer) { @@ -2729,6 +2790,10 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { b.headerTipHash = *finalHash b.newHeadersMtx.Unlock() b.newHeadersSignal.Broadcast() + + // Clear the mempool to free up memory. This may mean we might receive + // transactions we've previously downloaded but this is rather unlikely. + b.cfg.mempool.Clear() } // areHeadersConnected returns true if the passed block headers are connected to diff --git a/go.mod b/go.mod index 644eba892..30ec3861b 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/ltcsuite/lnd/clock v1.1.0 // indirect github.com/ltcsuite/lnd/ticker v1.1.0 // indirect + github.com/ltcsuite/ltcwallet v0.13.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/crypto v0.7.0 // indirect @@ -40,6 +41,18 @@ go 1.18 replace github.com/ltcsuite/neutrino/cache => ./cache +replace github.com/ltcsuite/ltcd => ../ltcd + +replace github.com/ltcsuite/ltcd/btcec/v2 => ../ltcd/btcec + +replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhash + +replace github.com/ltcsuite/ltcd/ltcutil => ../ltcd/ltcutil + +replace github.com/ltcsuite/ltcwallet/walletdb => ../ltcwallet/walletdb + +replace github.com/ltcsuite/ltcwallet/wtxmgr => ../ltcwallet/wtxmgr + replace github.com/ltcsuite/ltcwallet/wallet/txauthor => ../ltcwallet/wallet/txauthor replace github.com/ltcsuite/ltcwallet/wallet/txsizes => ../ltcwallet/wallet/txsizes diff --git a/go.sum b/go.sum index 10e10e26a..64b162868 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= @@ -9,10 +10,7 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -26,9 +24,9 @@ github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -43,89 +41,51 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= github.com/ltcsuite/lnd/clock v1.1.0 h1:am2L2QTKgotbUSILSLLdZNe1ziSacXfR34Ry0f8npCs= github.com/ltcsuite/lnd/clock v1.1.0/go.mod h1:Nn3X2+B0/70MnytJPHvOf3SPTPno09v90J/KJf5/dA8= +github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2PEq7IexlTWQ= github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4= github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof1yXM= github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8= -github.com/ltcsuite/ltcd v0.22.0-beta/go.mod h1:/BXtm50r591uMfXf8XgSpL5er32HCvheJtBSPYK5bFM= -github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI= -github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g= -github.com/ltcsuite/ltcd/btcec/v2 v2.1.0/go.mod h1:Vc9ZYXMcl5D6bA0VwMvGRDJYggO3YZ7/BuIri02Lq0E= -github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 h1:HVArUNQGqGaSSoyYkk9qGht74U0/uNhS0n7jV9rkmno= -github.com/ltcsuite/ltcd/btcec/v2 v2.3.2/go.mod h1:T1t5TjbjPnryvlGQ+RpSKGuU8KhjNN7rS5+IznPj1VM= -github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 h1:xuWxvRKxLvOKuS7/Q/7I3tpc3cWAB0+hZpU8YdVqkzg= -github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2/go.mod h1:nkLkAFGhursWf2U68gt61hPieK1I+0m78e+2aevNyD8= -github.com/ltcsuite/ltcd/ltcutil v1.1.0/go.mod h1:VbZlcopVgQteiCC5KRjIuxXH5wi1CtzhsvoYZ3K7FaE= -github.com/ltcsuite/ltcd/ltcutil v1.1.3 h1:8AapjCPLIt/wtYe6Odfk1EC2y9mcbpgjyxyCoNjAkFI= -github.com/ltcsuite/ltcd/ltcutil v1.1.3/go.mod h1:z8txd/ohBFrOMBUT70K8iZvHJD/Vc3gzx+6BP6cBxQw= +github.com/ltcsuite/ltcd/ltcutil/psbt v1.1.0-1/go.mod h1:jpDQOdehihA+lu9OW26YgHSJ+6lReEb8HNcQL5grC4k= +github.com/ltcsuite/ltcwallet v0.13.1 h1:XMyrDHn0BmgUgkNbR/Lzg36vjRsup3xdiPLSD471UMg= +github.com/ltcsuite/ltcwallet v0.13.1/go.mod h1:e6pIWRM9gsd5JnMsI9SgCJM0wi7awWdr20F1C1KUPiw= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks= -github.com/ltcsuite/ltcwallet/walletdb v1.3.5 h1:WymVw0FBQ8KJgH7B88ujRqBOJ9R0en9K9urpJW4atAE= -github.com/ltcsuite/ltcwallet/walletdb v1.3.5/go.mod h1:29SBzxA55wNxY3ctFw6t5PgsULwf3NMwg2MiGQgtrJE= -github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0 h1:5pM7L26/OzJMcwQqGwGKIZvPIBt1Er4Ve9Ymc9KK6gc= -github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0/go.mod h1:jAnztxV6d2JykUlGLCO5yNvtosmFaGMshBx0kps+K+M= +github.com/ltcsuite/neutrino v0.13.2/go.mod h1:eTkaETZBeu3es/FisfjY8Cp3M2fC4s+2V2VUeS8O1Ic= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -133,118 +93,63 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -253,23 +158,20 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/mempool.go b/mempool.go new file mode 100644 index 000000000..1537c38d0 --- /dev/null +++ b/mempool.go @@ -0,0 +1,74 @@ +package neutrino + +import ( + "sync" + + "github.com/ltcsuite/ltcd/btcjson" + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/ltcutil" +) + +// Mempool is used when we are downloading unconfirmed transactions. +// We will use this object to track which transactions we've already +// downloaded so that we don't download them more than once. +type Mempool struct { + downloadedTxs map[chainhash.Hash]bool + mtx sync.RWMutex + callbacks []func(tx *ltcutil.Tx, block *btcjson.BlockDetails) + watchedAddrs []ltcutil.Address +} + +// NewMempool returns an initialized mempool +func NewMempool() *Mempool { + return &Mempool{ + downloadedTxs: make(map[chainhash.Hash]bool), + mtx: sync.RWMutex{}, + } +} + +// RegisterCallback will register a callback that will fire when a transaction +// matching a watched address enters the mempool. +func (mp *Mempool) RegisterCallback(onRecvTx func(tx *ltcutil.Tx, block *btcjson.BlockDetails)) { + mp.mtx.Lock() + defer mp.mtx.Unlock() + mp.callbacks = append(mp.callbacks, onRecvTx) +} + +// HaveTransaction returns whether or not the passed transaction already exists +// in the mempool. +func (mp *Mempool) HaveTransaction(hash *chainhash.Hash) bool { + mp.mtx.RLock() + defer mp.mtx.RUnlock() + return mp.downloadedTxs[*hash] +} + +// AddTransaction adds a new transaction to the mempool and +// maybe calls back if it matches any watched addresses. +func (mp *Mempool) AddTransaction(tx *ltcutil.Tx) { + mp.mtx.Lock() + defer mp.mtx.Unlock() + mp.downloadedTxs[*tx.Hash()] = true + + ro := defaultRescanOptions() + WatchAddrs(mp.watchedAddrs...)(ro) + if ok, err := ro.paysWatchedAddr(tx); ok && err == nil { + for _, cb := range mp.callbacks { + cb(tx, nil) + } + } +} + +// Clear will remove all transactions from the mempool. This +// should be done whenever a new block is accepted. +func (mp *Mempool) Clear() { + mp.mtx.Lock() + defer mp.mtx.Unlock() + mp.downloadedTxs = make(map[chainhash.Hash]bool) +} + +// NotifyReceived stores addresses to watch +func (mp *Mempool) NotifyReceived(addrs []ltcutil.Address) { + mp.mtx.Lock() + defer mp.mtx.Unlock() + mp.watchedAddrs = append(mp.watchedAddrs, addrs...) +} diff --git a/neutrino.go b/neutrino.go index 8a0792598..551390456 100644 --- a/neutrino.go +++ b/neutrino.go @@ -15,6 +15,7 @@ import ( "github.com/ltcsuite/ltcd/addrmgr" "github.com/ltcsuite/ltcd/blockchain" + "github.com/ltcsuite/ltcd/btcjson" "github.com/ltcsuite/ltcd/chaincfg" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/connmgr" @@ -275,15 +276,17 @@ func (sp *ServerPeer) OnInv(p *peer.Peer, msg *wire.MsgInv) { newInv := wire.NewMsgInvSizeHint(uint(len(msg.InvList))) for _, invVect := range msg.InvList { if invVect.Type == wire.InvTypeTx { - log.Tracef("Ignoring tx %s in inv from %v -- "+ - "SPV mode", invVect.Hash, sp) - if sp.ProtocolVersion() >= wire.BIP0037Version { - log.Infof("Peer %v is announcing "+ - "transactions -- disconnecting", sp) - sp.Disconnect() - return + if sp.server.blocksOnly { + log.Tracef("Ignoring tx %s in inv from %v -- "+ + "SPV mode", invVect.Hash, sp) + if sp.ProtocolVersion() >= wire.BIP0037Version { + log.Infof("Peer %v is announcing "+ + "transactions -- disconnecting", sp) + sp.Disconnect() + return + } + continue } - continue } err := newInv.AddInvVect(invVect) if err != nil { @@ -297,6 +300,17 @@ func (sp *ServerPeer) OnInv(p *peer.Peer, msg *wire.MsgInv) { } } +// OnTx is invoked when a peer sends us a new transaction. We will pass it +// into the blockmanager for further processing. +func (sp *ServerPeer) OnTx(p *peer.Peer, msg *wire.MsgTx) { + if sp.server.blocksOnly { + log.Tracef("Ignoring tx %v from %v - blocksonly enabled", + msg.TxHash(), sp) + return + } + sp.server.blockManager.QueueTx(ltcutil.NewTx(msg), sp) +} + // OnHeaders is invoked when a peer receives a headers bitcoin // message. The message is passed down to the block manager. func (sp *ServerPeer) OnHeaders(p *peer.Peer, msg *wire.MsgHeaders) { @@ -618,6 +632,13 @@ type Config struct { // not, replies with a getdata message. // 3. Neutrino sends the raw transaction. BroadcastTimeout time.Duration + + // BlocksOnly sets whether or not to download unconfirmed transactions + // off the wire. If false the ChainService will send notifications when an + // unconfirmed transaction matches a watching address. The trade-off here is + // you're going to use a lot more bandwidth but it may be acceptable for apps + // which only run for brief periods of time. + BlocksOnly bool } // peerSubscription holds a peer subscription which we'll notify about any @@ -678,6 +699,10 @@ type ChainService struct { // nolint:maligned dialer func(net.Addr) (net.Conn, error) broadcastTimeout time.Duration + + blocksOnly bool + + mempool *Mempool } // NewChainService returns a new chain service configured to connect to the @@ -737,6 +762,8 @@ func NewChainService(cfg Config) (*ChainService, error) { dialer: dialer, persistToDisk: cfg.PersistToDisk, broadcastTimeout: cfg.BroadcastTimeout, + blocksOnly: cfg.BlocksOnly, + mempool: NewMempool(), } s.workManager = query.NewWorkManager(&query.Config{ ConnectedPeers: s.ConnectedPeers, @@ -809,6 +836,7 @@ func NewChainService(cfg Config) (*ChainService, error) { GetBlock: s.GetBlock, firstPeerSignal: s.firstPeerConnect, queryAllPeers: s.queryAllPeers, + mempool: s.mempool, }) if err != nil { return nil, err @@ -1133,6 +1161,18 @@ func (s *ChainService) NetTotals() (uint64, uint64) { atomic.LoadUint64(&s.bytesSent) } +// RegisterMempoolCallback registers a callback to be fired whenever a new transaction is +// received into the mempool +func (s *ChainService) RegisterMempoolCallback(onRecvTx func(tx *ltcutil.Tx, block *btcjson.BlockDetails)) { + s.mempool.RegisterCallback(onRecvTx) +} + +// NotifyMempoolReceived registers addresses to receive a callback on when a transaction +// paying to them enters the mempool. +func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { + s.mempool.NotifyReceived(addrs) +} + // peerHandler is used to handle peer operations such as adding and removing // peers to and from the server, banning peers, and broadcasting messages to // peers. It must be run in a goroutine. @@ -1489,6 +1529,7 @@ func NewPeerConfig(sp *ServerPeer) *peer.Config { OnAddrV2: sp.OnAddrV2, OnRead: sp.OnRead, OnWrite: sp.OnWrite, + OnTx: sp.OnTx, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but @@ -1503,7 +1544,7 @@ func NewPeerConfig(sp *ServerPeer) *peer.Config { ChainParams: &sp.server.chainParams, Services: sp.server.services, ProtocolVersion: wire.AddrV2Version, - DisableRelayTx: true, + DisableRelayTx: sp.server.blocksOnly, } } From 5e46c246c3774c69dee46aa46a673a22a1b86218 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 9 Jan 2024 13:14:39 +0000 Subject: [PATCH 02/75] Get mweb header and leafset --- blockmanager.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++- neutrino.go | 3 +- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index d45f3aa14..f1ecc6c33 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -117,6 +117,12 @@ type blockManagerCfg struct { quit chan<- struct{}, peerQuit chan<- struct{}), options ...QueryOption) + queryPeers func( + queryMsg wire.Message, + checkResponse func(sp *ServerPeer, resp wire.Message, + quit chan<- struct{}), + options ...QueryOption) + mempool *Mempool } @@ -302,7 +308,7 @@ func (b *blockManager) Start() { } log.Trace("Starting block manager") - b.wg.Add(2) + b.wg.Add(3) go b.blockHandler() go func() { defer b.wg.Done() @@ -314,10 +320,12 @@ func (b *blockManager) Start() { select { case <-b.cfg.firstPeerSignal: case <-b.quit: + b.wg.Done() return } log.Debug("Peer connected, starting cfHandler.") + go b.mwebHandler() b.cfHandler() }() } @@ -463,6 +471,78 @@ func (b *blockManager) handleDonePeerMsg(peers *list.List, sp *ServerPeer) { } } +// mwebHandler is the mweb download handler for the block manager. It must be +// run as a goroutine. It requests and processes mweb messages in a +// separate goroutine from the peer handlers. +func (b *blockManager) mwebHandler() { + defer b.wg.Done() + defer log.Trace("Mweb handler done") + + b.newHeadersSignal.L.Lock() + for !b.BlockHeadersSynced() { + b.newHeadersSignal.Wait() + + // While we're awake, we'll quickly check to see if we need to + // quit early. + select { + case <-b.quit: + b.newHeadersSignal.L.Unlock() + return + default: + } + } + b.newHeadersSignal.L.Unlock() + + for { + // Now that the block headers are finished, we'll grab the current + // chain tip so we can base our mweb header sync off of that. + lastHeader, lastHeight, err := b.cfg.BlockHeaders.ChainTip() + if err != nil { + log.Critical(err) + return + } + lastHash := lastHeader.BlockHash() + + log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", + lastHeight, lastHeader.BlockHash()) + + gdmsg := wire.NewMsgGetData() + gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &lastHash)) + gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebLeafset, &lastHash)) + + var ( + mwebHeader *wire.MsgMwebHeader + mwebLeafset *wire.MsgMwebLeafset + ) + b.cfg.queryPeers( + gdmsg, + func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}) { + + switch m := resp.(type) { + case *wire.MsgMwebHeader: + mwebHeader = m + case *wire.MsgMwebLeafset: + mwebLeafset = m + } + if mwebHeader != nil && mwebLeafset != nil { + close(quit) + } + }, + ) + select { + case <-b.quit: + return + default: + if mwebHeader == nil || mwebLeafset == nil { + continue + } + } + + log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", + lastHeight, lastHeader.BlockHash()) + } +} + // cfHandler is the cfheader download handler for the block manager. It must be // run as a goroutine. It requests and processes cfheaders messages in a // separate goroutine from the peer handlers. diff --git a/neutrino.go b/neutrino.go index 551390456..87a1e9eae 100644 --- a/neutrino.go +++ b/neutrino.go @@ -836,6 +836,7 @@ func NewChainService(cfg Config) (*ChainService, error) { GetBlock: s.GetBlock, firstPeerSignal: s.firstPeerConnect, queryAllPeers: s.queryAllPeers, + queryPeers: s.queryPeers, mempool: s.mempool, }) if err != nil { @@ -1543,7 +1544,7 @@ func NewPeerConfig(sp *ServerPeer) *peer.Config { UserAgentVersion: sp.server.userAgentVersion, ChainParams: &sp.server.chainParams, Services: sp.server.services, - ProtocolVersion: wire.AddrV2Version, + ProtocolVersion: wire.MwebLightClientVersion, DisableRelayTx: sp.server.blocksOnly, } } From 4e18a4ae10a717bef89c0d847c120f35bd55d8fd Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 10 Jan 2024 02:24:29 +0000 Subject: [PATCH 03/75] Verify mweb header and leafset --- blockmanager.go | 95 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index f1ecc6c33..ba27f3868 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -18,6 +18,7 @@ import ( "github.com/ltcsuite/ltcd/ltcutil" "github.com/ltcsuite/ltcd/ltcutil/gcs" "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" + "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" @@ -25,6 +26,7 @@ import ( "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/neutrino/headerlist" "github.com/ltcsuite/neutrino/query" + "lukechampine.com/blake3" ) const ( @@ -478,22 +480,22 @@ func (b *blockManager) mwebHandler() { defer b.wg.Done() defer log.Trace("Mweb handler done") - b.newHeadersSignal.L.Lock() - for !b.BlockHeadersSynced() { - b.newHeadersSignal.Wait() + for { + b.newHeadersSignal.L.Lock() + for !b.BlockHeadersSynced() { + b.newHeadersSignal.Wait() - // While we're awake, we'll quickly check to see if we need to - // quit early. - select { - case <-b.quit: - b.newHeadersSignal.L.Unlock() - return - default: + // While we're awake, we'll quickly check to see if we need to + // quit early. + select { + case <-b.quit: + b.newHeadersSignal.L.Unlock() + return + default: + } } - } - b.newHeadersSignal.L.Unlock() + b.newHeadersSignal.L.Unlock() - for { // Now that the block headers are finished, we'll grab the current // chain tip so we can base our mweb header sync off of that. lastHeader, lastHeight, err := b.cfg.BlockHeaders.ChainTip() @@ -504,7 +506,7 @@ func (b *blockManager) mwebHandler() { lastHash := lastHeader.BlockHash() log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", - lastHeight, lastHeader.BlockHash()) + lastHeight, lastHash) gdmsg := wire.NewMsgGetData() gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &lastHash)) @@ -513,6 +515,7 @@ func (b *blockManager) mwebHandler() { var ( mwebHeader *wire.MsgMwebHeader mwebLeafset *wire.MsgMwebLeafset + verified bool ) b.cfg.queryPeers( gdmsg, @@ -524,7 +527,8 @@ func (b *blockManager) mwebHandler() { case *wire.MsgMwebLeafset: mwebLeafset = m } - if mwebHeader != nil && mwebLeafset != nil { + verified = b.verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) + if verified { close(quit) } }, @@ -533,16 +537,71 @@ func (b *blockManager) mwebHandler() { case <-b.quit: return default: - if mwebHeader == nil || mwebLeafset == nil { + if !verified { continue } } - log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", - lastHeight, lastHeader.BlockHash()) + break } } +func (b *blockManager) verifyMwebHeader( + mwebHeader *wire.MsgMwebHeader, mwebLeafset *wire.MsgMwebLeafset, + lastHeight uint32, lastHash *chainhash.Hash) bool { + + if mwebHeader == nil || mwebLeafset == nil { + return false + } + log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", + lastHeight, *lastHash) + + if mwebHeader.Merkle.Header.BlockHash() != *lastHash { + log.Infof("Block hash mismatch, merkle header hash=%v, block hash=%v", + mwebHeader.Merkle.Header.BlockHash(), *lastHash) + return false + } + + if !mwebHeader.Hogex.IsHogEx { + log.Info("mwebheader hogex not hogex") + return false + } + + // Validate that the hash of the HogEx transaction in the tx message + // matches the hash in the merkleblock message, and that it’s the last + // transaction committed to by the merkle root of the block. + hashes := mwebHeader.Merkle.Hashes + if mwebHeader.Hogex.TxHash() != *hashes[len(hashes)-1] { + log.Infof("Tx hash mismatch, hogex=%v, last merkle tx=%v", + mwebHeader.Hogex.TxHash(), *hashes[len(hashes)-1]) + return false + } + + // Validate that the pubkey script of the first output contains the HogAddr, + // which shall consist of <0x20> followed by the 32-byte hash of the + // MWEB header. + mwebHeaderHash := mwebHeader.MwebHeader.Hash() + script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) + if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { + log.Infof("HogAddr mismatch, hogex=%v, expected=%v", + mwebHeader.Hogex.TxOut[0].PkScript, script) + return false + } + + // Verify that the hash of the leafset bitmap matches the + // leafset_root value in the MWEB header. + leafsetRoot := blake3.Sum256(mwebLeafset.Leafset) + if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { + log.Infof("Leafset root mismatch, leafset=%v, in header=%v", + leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) + return false + } + + log.Infof("Verified mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", + lastHeight, *lastHash) + return true +} + // cfHandler is the cfheader download handler for the block manager. It must be // run as a goroutine. It requests and processes cfheaders messages in a // separate goroutine from the peer handlers. From 27ec42e03a051351136a94c08dd4b9b5981f4542 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 10 Jan 2024 18:12:40 +0000 Subject: [PATCH 04/75] Verify mwebheader merkle block --- blockmanager.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/blockmanager.go b/blockmanager.go index ba27f3868..16a94507f 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -16,6 +16,7 @@ import ( "github.com/ltcsuite/ltcd/chaincfg" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/ltcutil" + "github.com/ltcsuite/ltcd/ltcutil/bloom" "github.com/ltcsuite/ltcd/ltcutil/gcs" "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" "github.com/ltcsuite/ltcd/txscript" @@ -562,6 +563,11 @@ func (b *blockManager) verifyMwebHeader( return false } + if !bloom.VerifyMerkleBlock(&mwebHeader.Merkle) { + log.Info("mwebheader merkle block is bad") + return false + } + if !mwebHeader.Hogex.IsHogEx { log.Info("mwebheader hogex not hogex") return false From 0c4882ccc22f0c30548ec2db72779b84f3187f6a Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 10 Jan 2024 19:33:29 +0000 Subject: [PATCH 05/75] Verify that the hogex is the final transaction --- blockmanager.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 16a94507f..790ca3df0 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -563,23 +563,30 @@ func (b *blockManager) verifyMwebHeader( return false } - if !bloom.VerifyMerkleBlock(&mwebHeader.Merkle) { + extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) + if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { log.Info("mwebheader merkle block is bad") return false } if !mwebHeader.Hogex.IsHogEx { - log.Info("mwebheader hogex not hogex") + log.Info("mwebheader hogex is not hogex") return false } // Validate that the hash of the HogEx transaction in the tx message // matches the hash in the merkleblock message, and that it’s the last // transaction committed to by the merkle root of the block. - hashes := mwebHeader.Merkle.Hashes - if mwebHeader.Hogex.TxHash() != *hashes[len(hashes)-1] { + finalTx := extractResult.Match[len(extractResult.Match)-1] + if mwebHeader.Hogex.TxHash() != *finalTx { log.Infof("Tx hash mismatch, hogex=%v, last merkle tx=%v", - mwebHeader.Hogex.TxHash(), *hashes[len(hashes)-1]) + mwebHeader.Hogex.TxHash(), *finalTx) + return false + } + finalTxPos := extractResult.Index[len(extractResult.Index)-1] + if finalTxPos != mwebHeader.Merkle.Transactions-1 { + log.Infof("Tx index mismatch, got=%v, expected=%v", + finalTxPos, mwebHeader.Merkle.Transactions-1) return false } From 51770041cc6a2712d03e30e47f393c538384f877 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 10 Jan 2024 22:41:37 +0000 Subject: [PATCH 06/75] Restart with new tip if we detect the empty leafset message --- blockmanager.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/blockmanager.go b/blockmanager.go index 790ca3df0..56630f455 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -526,6 +526,11 @@ func (b *blockManager) mwebHandler() { case *wire.MsgMwebHeader: mwebHeader = m case *wire.MsgMwebLeafset: + if m.BlockHash.IsEqual(&chainhash.Hash{}) && len(m.Leafset) == 0 { + // Empty leafset; we are too far behind and need to catch-up first + close(quit) + return + } mwebLeafset = m } verified = b.verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) @@ -603,7 +608,7 @@ func (b *blockManager) verifyMwebHeader( // Verify that the hash of the leafset bitmap matches the // leafset_root value in the MWEB header. - leafsetRoot := blake3.Sum256(mwebLeafset.Leafset) + leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { log.Infof("Leafset root mismatch, leafset=%v, in header=%v", leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) From 24d02f84abb5ea6aa745fbee2b9ef3e0934caaed Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 12 Jan 2024 15:35:20 +0000 Subject: [PATCH 07/75] First cut of code to verify mweb utxos --- blockmanager.go | 73 +----------- go.mod | 2 +- mweb.go | 294 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+), 73 deletions(-) create mode 100644 mweb.go diff --git a/blockmanager.go b/blockmanager.go index 56630f455..2008912d1 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -16,10 +16,8 @@ import ( "github.com/ltcsuite/ltcd/chaincfg" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/bloom" "github.com/ltcsuite/ltcd/ltcutil/gcs" "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" @@ -27,7 +25,6 @@ import ( "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/neutrino/headerlist" "github.com/ltcsuite/neutrino/query" - "lukechampine.com/blake3" ) const ( @@ -533,7 +530,7 @@ func (b *blockManager) mwebHandler() { } mwebLeafset = m } - verified = b.verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) + verified = verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) if verified { close(quit) } @@ -552,74 +549,6 @@ func (b *blockManager) mwebHandler() { } } -func (b *blockManager) verifyMwebHeader( - mwebHeader *wire.MsgMwebHeader, mwebLeafset *wire.MsgMwebLeafset, - lastHeight uint32, lastHash *chainhash.Hash) bool { - - if mwebHeader == nil || mwebLeafset == nil { - return false - } - log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", - lastHeight, *lastHash) - - if mwebHeader.Merkle.Header.BlockHash() != *lastHash { - log.Infof("Block hash mismatch, merkle header hash=%v, block hash=%v", - mwebHeader.Merkle.Header.BlockHash(), *lastHash) - return false - } - - extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) - if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { - log.Info("mwebheader merkle block is bad") - return false - } - - if !mwebHeader.Hogex.IsHogEx { - log.Info("mwebheader hogex is not hogex") - return false - } - - // Validate that the hash of the HogEx transaction in the tx message - // matches the hash in the merkleblock message, and that it’s the last - // transaction committed to by the merkle root of the block. - finalTx := extractResult.Match[len(extractResult.Match)-1] - if mwebHeader.Hogex.TxHash() != *finalTx { - log.Infof("Tx hash mismatch, hogex=%v, last merkle tx=%v", - mwebHeader.Hogex.TxHash(), *finalTx) - return false - } - finalTxPos := extractResult.Index[len(extractResult.Index)-1] - if finalTxPos != mwebHeader.Merkle.Transactions-1 { - log.Infof("Tx index mismatch, got=%v, expected=%v", - finalTxPos, mwebHeader.Merkle.Transactions-1) - return false - } - - // Validate that the pubkey script of the first output contains the HogAddr, - // which shall consist of <0x20> followed by the 32-byte hash of the - // MWEB header. - mwebHeaderHash := mwebHeader.MwebHeader.Hash() - script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) - if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { - log.Infof("HogAddr mismatch, hogex=%v, expected=%v", - mwebHeader.Hogex.TxOut[0].PkScript, script) - return false - } - - // Verify that the hash of the leafset bitmap matches the - // leafset_root value in the MWEB header. - leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) - if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { - log.Infof("Leafset root mismatch, leafset=%v, in header=%v", - leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) - return false - } - - log.Infof("Verified mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", - lastHeight, *lastHash) - return true -} - // cfHandler is the cfheader download handler for the block manager. It must be // run as a goroutine. It requests and processes cfheaders messages in a // separate goroutine from the peer handlers. diff --git a/go.mod b/go.mod index 30ec3861b..26f98b47b 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0 github.com/ltcsuite/neutrino/cache v1.1.0 github.com/stretchr/testify v1.8.2 + lukechampine.com/blake3 v1.2.1 ) require ( @@ -34,7 +35,6 @@ require ( golang.org/x/crypto v0.7.0 // indirect golang.org/x/sys v0.8.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.2.1 // indirect ) go 1.18 diff --git a/mweb.go b/mweb.go new file mode 100644 index 000000000..9dcc81828 --- /dev/null +++ b/mweb.go @@ -0,0 +1,294 @@ +package neutrino + +import ( + "bytes" + "encoding/binary" + "math/bits" + + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/ltcutil/bloom" + "github.com/ltcsuite/ltcd/txscript" + "github.com/ltcsuite/ltcd/wire" + "lukechampine.com/blake3" +) + +func verifyMwebHeader( + mwebHeader *wire.MsgMwebHeader, mwebLeafset *wire.MsgMwebLeafset, + lastHeight uint32, lastHash *chainhash.Hash) bool { + + if mwebHeader == nil || mwebLeafset == nil { + return false + } + log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", + lastHeight, *lastHash) + + if mwebHeader.Merkle.Header.BlockHash() != *lastHash { + log.Infof("Block hash mismatch, merkle header hash=%v, block hash=%v", + mwebHeader.Merkle.Header.BlockHash(), *lastHash) + return false + } + + extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) + if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { + log.Info("mwebheader merkle block is bad") + return false + } + + if !mwebHeader.Hogex.IsHogEx { + log.Info("mwebheader hogex is not hogex") + return false + } + + // Validate that the hash of the HogEx transaction in the tx message + // matches the hash in the merkleblock message, and that it’s the last + // transaction committed to by the merkle root of the block. + finalTx := extractResult.Match[len(extractResult.Match)-1] + if mwebHeader.Hogex.TxHash() != *finalTx { + log.Infof("Tx hash mismatch, hogex=%v, last merkle tx=%v", + mwebHeader.Hogex.TxHash(), *finalTx) + return false + } + finalTxPos := extractResult.Index[len(extractResult.Index)-1] + if finalTxPos != mwebHeader.Merkle.Transactions-1 { + log.Infof("Tx index mismatch, got=%v, expected=%v", + finalTxPos, mwebHeader.Merkle.Transactions-1) + return false + } + + // Validate that the pubkey script of the first output contains the HogAddr, + // which shall consist of <0x20> followed by the 32-byte hash of the + // MWEB header. + mwebHeaderHash := mwebHeader.MwebHeader.Hash() + script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) + if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { + log.Infof("HogAddr mismatch, hogex=%v, expected=%v", + mwebHeader.Hogex.TxOut[0].PkScript, script) + return false + } + + // Verify that the hash of the leafset bitmap matches the + // leafset_root value in the MWEB header. + leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) + if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { + log.Infof("Leafset root mismatch, leafset=%v, in header=%v", + leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) + return false + } + + log.Infof("Verified mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", + lastHeight, *lastHash) + return true +} + +type ( + leafset []byte + leafIdx uint64 + nodeIdx uint64 +) + +func (l leafset) contains(i leafIdx) bool { + if int(i/8) >= len(l) { + return false + } + return l[i/8]&(0x80>>(i%8)) > 0 +} + +func (i leafIdx) nodeIdx() nodeIdx { + return nodeIdx(2*i) - nodeIdx(bits.OnesCount64(uint64(i))) +} + +func (i nodeIdx) height() uint64 { + height := uint64(i) + h := 64 - bits.LeadingZeros64(uint64(i)) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if height >= peakSize { + height -= peakSize + } + } + return height +} + +func (i nodeIdx) leafIdx() leafIdx { + leafIndex := uint64(0) + numLeft := uint64(i) + h := 64 - bits.LeadingZeros64(uint64(i)) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if numLeft >= peakSize { + leafIndex += (peakSize + 1) / 2 + numLeft -= peakSize + } + } + return leafIdx(leafIndex) +} + +func (i nodeIdx) left(height uint64) nodeIdx { + return i - (1 << height) +} + +func (i nodeIdx) right() nodeIdx { + return i - 1 +} + +func (i nodeIdx) hash(data []byte) *chainhash.Hash { + h := blake3.New(32, nil) + binary.Write(h, binary.LittleEndian, uint64(i)) + h.Write(data) + hash := &chainhash.Hash{} + h.Sum(hash[:0]) + return hash +} + +func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { + h := blake3.New(32, nil) + binary.Write(h, binary.LittleEndian, uint64(i)) + h.Write(left) + h.Write(right) + hash := &chainhash.Hash{} + h.Sum(hash[:0]) + return hash +} + +func calcPeaks(nodes uint64) (peaks []nodeIdx) { + sumPrevPeaks := uint64(0) + h := 64 - bits.LeadingZeros64(nodes) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if nodes >= peakSize { + peaks = append(peaks, nodeIdx(sumPrevPeaks+peakSize-1)) + sumPrevPeaks += peakSize + nodes -= peakSize + } + } + return +} + +type verifyMwebUtxosVars struct { + mwebUtxos *wire.MsgMwebUtxos + leafset leafset + firstLeafIdx, lastLeafIdx leafIdx + leavesUsed, hashesUsed int +} + +func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Hash) { + if v.leavesUsed == len(v.mwebUtxos.Utxos) { + return + } + utxo := v.mwebUtxos.Utxos[v.leavesUsed] + leafIndex = leafIdx(utxo.LeafIndex) + hash = &utxo.OutputId + v.leavesUsed++ + return +} + +func (v *verifyMwebUtxosVars) nextHash() (hash *chainhash.Hash) { + if v.hashesUsed == len(v.mwebUtxos.ProofHashes) { + return + } + hash = v.mwebUtxos.ProofHashes[v.hashesUsed] + v.hashesUsed++ + return +} + +func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chainhash.Hash { + if nodeIdx < v.firstLeafIdx.nodeIdx() { + return v.nextHash() + } + if height == 0 { + leafIdx := nodeIdx.leafIdx() + if !v.leafset.contains(leafIdx) { + return nil + } + leafIdx2, outputId := v.nextLeaf() + if leafIdx != leafIdx2 || outputId == nil { + return nil + } + return nodeIdx.hash(outputId[:]) + } + left := v.calcNodeHash(nodeIdx.left(height), height-1) + if left == nil { + return nil + } + var right *chainhash.Hash + if v.lastLeafIdx.nodeIdx() <= nodeIdx.left(height) { + right = v.nextHash() + } else { + right = v.calcNodeHash(nodeIdx.right(), height-1) + } + if right == nil { + return nil + } + return nodeIdx.parentHash(left[:], right[:]) +} + +func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, + mwebLeafset *wire.MsgMwebLeafset, mwebUtxos *wire.MsgMwebUtxos) bool { + + if mwebUtxos.StartIndex == 0 && + len(mwebUtxos.Utxos) == 0 && + len(mwebUtxos.ProofHashes) == 0 && + mwebHeader.MwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && + mwebHeader.MwebHeader.OutputMMRSize == 0 { + return true + } else if len(mwebUtxos.Utxos) == 0 || + mwebHeader.MwebHeader.OutputMMRSize == 0 { + return false + } + + v := &verifyMwebUtxosVars{ + mwebUtxos: mwebUtxos, + leafset: leafset(mwebLeafset.Leafset), + firstLeafIdx: leafIdx(mwebUtxos.StartIndex), + lastLeafIdx: leafIdx(mwebUtxos.StartIndex), + } + nextLeafIdx := leafIdx(mwebHeader.MwebHeader.OutputMMRSize) + + for i := 0; ; i++ { + if !v.leafset.contains(v.lastLeafIdx) { + return false + } + if leafIdx(mwebUtxos.Utxos[i].LeafIndex) != v.lastLeafIdx { + return false + } + if i == len(mwebUtxos.Utxos)-1 { + break + } + for { + v.lastLeafIdx++ + if v.lastLeafIdx == nextLeafIdx { + return false + } + if v.leafset.contains(v.lastLeafIdx) { + break + } + } + } + + peaks := calcPeaks(uint64(nextLeafIdx.nodeIdx())) + var peakHashes []*chainhash.Hash + for _, peakNodeIdx := range peaks { + peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) + if peakHash == nil { + return false + } + peakHashes = append(peakHashes, peakHash) + if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { + if peakNodeIdx != peaks[len(peaks)-1] { + baggedPeak := v.nextHash() + if baggedPeak == nil { + return false + } + peakHashes = append(peakHashes, baggedPeak) + } + break + } + } + + if v.leavesUsed != len(v.mwebUtxos.Utxos) || + v.hashesUsed != len(v.mwebUtxos.ProofHashes) { + return false + } + baggedPeak := peakHashes[len(peakHashes)-1] + for i := len(peakHashes) - 2; i >= 0; i-- { + baggedPeak = nextLeafIdx.nodeIdx().parentHash(peakHashes[i][:], baggedPeak[:]) + } + return baggedPeak.IsEqual(&mwebHeader.MwebHeader.OutputRoot) +} From 66d1725489e8502eca51ffb8f7092e7d35d388c4 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 13 Jan 2024 00:55:43 +0000 Subject: [PATCH 08/75] Switch to queryAllPeers --- blockmanager.go | 17 ++++------------- neutrino.go | 1 - 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 2008912d1..a8b7be62f 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -117,12 +117,6 @@ type blockManagerCfg struct { quit chan<- struct{}, peerQuit chan<- struct{}), options ...QueryOption) - queryPeers func( - queryMsg wire.Message, - checkResponse func(sp *ServerPeer, resp wire.Message, - quit chan<- struct{}), - options ...QueryOption) - mempool *Mempool } @@ -515,24 +509,21 @@ func (b *blockManager) mwebHandler() { mwebLeafset *wire.MsgMwebLeafset verified bool ) - b.cfg.queryPeers( + b.cfg.queryAllPeers( gdmsg, - func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}) { + func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}, + peerQuit chan<- struct{}) { switch m := resp.(type) { case *wire.MsgMwebHeader: mwebHeader = m case *wire.MsgMwebLeafset: - if m.BlockHash.IsEqual(&chainhash.Hash{}) && len(m.Leafset) == 0 { - // Empty leafset; we are too far behind and need to catch-up first - close(quit) - return - } mwebLeafset = m } verified = verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) if verified { close(quit) + close(peerQuit) } }, ) diff --git a/neutrino.go b/neutrino.go index 87a1e9eae..c009a7239 100644 --- a/neutrino.go +++ b/neutrino.go @@ -836,7 +836,6 @@ func NewChainService(cfg Config) (*ChainService, error) { GetBlock: s.GetBlock, firstPeerSignal: s.firstPeerConnect, queryAllPeers: s.queryAllPeers, - queryPeers: s.queryPeers, mempool: s.mempool, }) if err != nil { From 490ea90f7465462bb85343310996aff48e72d53e Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 14 Jan 2024 03:50:26 +0000 Subject: [PATCH 09/75] Fixed bugs --- mweb.go | 67 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/mweb.go b/mweb.go index 9dcc81828..1a368b569 100644 --- a/mweb.go +++ b/mweb.go @@ -132,7 +132,7 @@ func (i nodeIdx) right() nodeIdx { func (i nodeIdx) hash(data []byte) *chainhash.Hash { h := blake3.New(32, nil) binary.Write(h, binary.LittleEndian, uint64(i)) - h.Write(data) + wire.WriteVarBytes(h, 0, data) hash := &chainhash.Hash{} h.Sum(hash[:0]) return hash @@ -166,6 +166,7 @@ type verifyMwebUtxosVars struct { leafset leafset firstLeafIdx, lastLeafIdx leafIdx leavesUsed, hashesUsed int + isProofHash map[nodeIdx]bool } func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Hash) { @@ -179,18 +180,19 @@ func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Has return } -func (v *verifyMwebUtxosVars) nextHash() (hash *chainhash.Hash) { +func (v *verifyMwebUtxosVars) nextHash(nodeIdx nodeIdx) (hash *chainhash.Hash) { if v.hashesUsed == len(v.mwebUtxos.ProofHashes) { return } hash = v.mwebUtxos.ProofHashes[v.hashesUsed] v.hashesUsed++ + v.isProofHash[nodeIdx] = true return } func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chainhash.Hash { - if nodeIdx < v.firstLeafIdx.nodeIdx() { - return v.nextHash() + if nodeIdx < v.firstLeafIdx.nodeIdx() || v.isProofHash[nodeIdx] { + return v.nextHash(nodeIdx) } if height == 0 { leafIdx := nodeIdx.leafIdx() @@ -204,17 +206,23 @@ func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chai return nodeIdx.hash(outputId[:]) } left := v.calcNodeHash(nodeIdx.left(height), height-1) - if left == nil { - return nil - } var right *chainhash.Hash if v.lastLeafIdx.nodeIdx() <= nodeIdx.left(height) { - right = v.nextHash() + right = v.nextHash(nodeIdx.right()) } else { right = v.calcNodeHash(nodeIdx.right(), height-1) } - if right == nil { + switch { + case left == nil && right == nil: return nil + case left == nil: + if left = v.nextHash(nodeIdx.left(height)); left == nil { + return nil + } + case right == nil: + if right = v.nextHash(nodeIdx.right()); right == nil { + return nil + } } return nodeIdx.parentHash(left[:], right[:]) } @@ -238,6 +246,7 @@ func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, leafset: leafset(mwebLeafset.Leafset), firstLeafIdx: leafIdx(mwebUtxos.StartIndex), lastLeafIdx: leafIdx(mwebUtxos.StartIndex), + isProofHash: make(map[nodeIdx]bool), } nextLeafIdx := leafIdx(mwebHeader.MwebHeader.OutputMMRSize) @@ -264,28 +273,34 @@ func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, peaks := calcPeaks(uint64(nextLeafIdx.nodeIdx())) var peakHashes []*chainhash.Hash - for _, peakNodeIdx := range peaks { - peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) - if peakHash == nil { - return false - } - peakHashes = append(peakHashes, peakHash) - if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { - if peakNodeIdx != peaks[len(peaks)-1] { - baggedPeak := v.nextHash() - if baggedPeak == nil { - return false + for i := 0; i < 2; i++ { + peakHashes = nil + v.leavesUsed = 0 + v.hashesUsed = 0 + + for _, peakNodeIdx := range peaks { + peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) + if peakHash == nil { + return false + } + peakHashes = append(peakHashes, peakHash) + if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { + if peakNodeIdx != peaks[len(peaks)-1] { + baggedPeak := v.nextHash(nextLeafIdx.nodeIdx()) + if baggedPeak == nil { + return false + } + peakHashes = append(peakHashes, baggedPeak) } - peakHashes = append(peakHashes, baggedPeak) + break } - break + } + if v.leavesUsed != len(v.mwebUtxos.Utxos) || + v.hashesUsed != len(v.mwebUtxos.ProofHashes) { + return false } } - if v.leavesUsed != len(v.mwebUtxos.Utxos) || - v.hashesUsed != len(v.mwebUtxos.ProofHashes) { - return false - } baggedPeak := peakHashes[len(peakHashes)-1] for i := len(peakHashes) - 2; i >= 0; i-- { baggedPeak = nextLeafIdx.nodeIdx().parentHash(peakHashes[i][:], baggedPeak[:]) From 032d4437dda2a524a8667e81ddbf7c1cba375b3d Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 14 Jan 2024 23:43:53 +0000 Subject: [PATCH 10/75] Added code to download all mweb utxos --- banman/reason.go | 7 ++ blockmanager.go | 8 ++ mweb.go | 290 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 286 insertions(+), 19 deletions(-) diff --git a/banman/reason.go b/banman/reason.go index 7e544ecb1..ba2fec015 100644 --- a/banman/reason.go +++ b/banman/reason.go @@ -23,6 +23,10 @@ const ( // InvalidBlock signals that a peer served us a bad block. InvalidBlock Reason = 5 + + // InvalidMwebUtxos signals that a peer served us an invalid + // mweb utxos message. + InvalidMwebUtxos Reason = 20 ) // String returns a human-readable description for the reason a peer was banned. @@ -43,6 +47,9 @@ func (r Reason) String() string { case InvalidBlock: return "peer served an invalid block" + case InvalidMwebUtxos: + return "peer served invalid mweb utxos message" + default: return "unknown reason" } diff --git a/blockmanager.go b/blockmanager.go index a8b7be62f..ec797b15e 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -536,6 +536,14 @@ func (b *blockManager) mwebHandler() { } } + // Get all the mweb utxos at this height. + b.getMwebUtxos(&mwebHeader.MwebHeader, mwebLeafset.Leafset, lastHeight, &lastHash) + + // Now we check the headers again. If the block headers are not yet + // current, then we go back to the loop waiting for them to finish. + if !b.BlockHeadersSynced() { + continue + } break } } diff --git a/mweb.go b/mweb.go index 1a368b569..594f141df 100644 --- a/mweb.go +++ b/mweb.go @@ -9,6 +9,8 @@ import ( "github.com/ltcsuite/ltcd/ltcutil/bloom" "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/neutrino/banman" + "github.com/ltcsuite/neutrino/query" "lukechampine.com/blake3" ) @@ -93,6 +95,15 @@ func (l leafset) contains(i leafIdx) bool { return l[i/8]&(0x80>>(i%8)) > 0 } +func (l leafset) nextUnspent(i leafIdx) leafIdx { + for { + i++ + if l.contains(i) || int(i/8) >= len(l) { + return i + } + } +} + func (i leafIdx) nodeIdx() nodeIdx { return nodeIdx(2*i) - nodeIdx(bits.OnesCount64(uint64(i))) } @@ -227,28 +238,27 @@ func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chai return nodeIdx.parentHash(left[:], right[:]) } -func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, - mwebLeafset *wire.MsgMwebLeafset, mwebUtxos *wire.MsgMwebUtxos) bool { +func verifyMwebUtxos(mwebHeader *wire.MwebHeader, + mwebLeafset leafset, mwebUtxos *wire.MsgMwebUtxos) bool { if mwebUtxos.StartIndex == 0 && len(mwebUtxos.Utxos) == 0 && len(mwebUtxos.ProofHashes) == 0 && - mwebHeader.MwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && - mwebHeader.MwebHeader.OutputMMRSize == 0 { + mwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && + mwebHeader.OutputMMRSize == 0 { return true } else if len(mwebUtxos.Utxos) == 0 || - mwebHeader.MwebHeader.OutputMMRSize == 0 { + mwebHeader.OutputMMRSize == 0 { return false } v := &verifyMwebUtxosVars{ mwebUtxos: mwebUtxos, - leafset: leafset(mwebLeafset.Leafset), + leafset: mwebLeafset, firstLeafIdx: leafIdx(mwebUtxos.StartIndex), lastLeafIdx: leafIdx(mwebUtxos.StartIndex), isProofHash: make(map[nodeIdx]bool), } - nextLeafIdx := leafIdx(mwebHeader.MwebHeader.OutputMMRSize) for i := 0; ; i++ { if !v.leafset.contains(v.lastLeafIdx) { @@ -260,19 +270,14 @@ func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, if i == len(mwebUtxos.Utxos)-1 { break } - for { - v.lastLeafIdx++ - if v.lastLeafIdx == nextLeafIdx { - return false - } - if v.leafset.contains(v.lastLeafIdx) { - break - } - } + v.lastLeafIdx = v.leafset.nextUnspent(v.lastLeafIdx) } - peaks := calcPeaks(uint64(nextLeafIdx.nodeIdx())) - var peakHashes []*chainhash.Hash + var ( + nextLeafIdx = leafIdx(mwebHeader.OutputMMRSize) + peaks = calcPeaks(uint64(nextLeafIdx.nodeIdx())) + peakHashes []*chainhash.Hash + ) for i := 0; i < 2; i++ { peakHashes = nil v.leavesUsed = 0 @@ -305,5 +310,252 @@ func verifyMwebUtxos(mwebHeader *wire.MsgMwebHeader, for i := len(peakHashes) - 2; i >= 0; i-- { baggedPeak = nextLeafIdx.nodeIdx().parentHash(peakHashes[i][:], baggedPeak[:]) } - return baggedPeak.IsEqual(&mwebHeader.MwebHeader.OutputRoot) + return baggedPeak.IsEqual(&mwebHeader.OutputRoot) +} + +// mwebUtxosQuery holds all information necessary to perform and +// handle a query for mweb utxos. +type mwebUtxosQuery struct { + blockMgr *blockManager + mwebHeader *wire.MwebHeader + leafset leafset + msgs []wire.Message + utxosChan chan *wire.MsgMwebUtxos +} + +const maxMwebUtxosPerQuery = 4096 + +func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, + leafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { + + log.Infof("Fetching set of mweb utxos from "+ + "height=%v, hash=%v", lastHeight, *lastHash) + + var curIndex leafIdx + if !leafset.contains(curIndex) { + curIndex = leafset.nextUnspent(curIndex) + } + startIndex := curIndex + + log.Infof("Starting to query for mweb utxos from "+ + "index=%v", startIndex) + + var queryMsgs []wire.Message + for leafset.contains(startIndex) { + var numLeaves uint16 + nextIndex := startIndex + for ; numLeaves < maxMwebUtxosPerQuery; numLeaves++ { + if !leafset.contains(nextIndex) { + break + } + nextIndex = leafset.nextUnspent(nextIndex) + } + queryMsgs = append(queryMsgs, + wire.NewMsgGetMwebUtxos(lastHash, uint64(startIndex), + numLeaves, wire.MwebNetUtxoCompact)) + startIndex = nextIndex + } + + // We'll also create an additional map that we'll use to + // re-order the responses as we get them in. + queryResponses := make(map[leafIdx]*wire.MsgMwebUtxos, len(queryMsgs)) + + batchesCount := len(queryMsgs) + if batchesCount == 0 { + return + } + + log.Infof("Attempting to query for %v mwebutxos batches", batchesCount) + + // With the set of messages constructed, we'll now request the batch + // all at once. This message will distribute the mwebutxos requests + // amongst all active peers, effectively sharding each query + // dynamically. + utxosChan := make(chan *wire.MsgMwebUtxos, len(queryMsgs)) + q := mwebUtxosQuery{ + blockMgr: b, + mwebHeader: mwebHeader, + leafset: leafset, + msgs: queryMsgs, + utxosChan: utxosChan, + } + + // Hand the queries to the work manager, and consume the verified + // responses as they come back. + errChan := b.cfg.QueryDispatcher.Query( + q.requests(), query.Cancel(b.quit), + ) + + // Keep waiting for more mwebutxos as long as we haven't received an + // answer for our last getmwebutxos, and no error is encountered. + totalUtxos := 0 + for { + var r *wire.MsgMwebUtxos + select { + case r = <-utxosChan: + case err := <-errChan: + switch { + case err == query.ErrWorkManagerShuttingDown: + return + case err != nil: + log.Errorf("Query finished with error before "+ + "all responses received: %v", err) + return + } + + // The query did finish successfully, but continue to + // allow picking up the last mwebutxos sent on the + // utxosChan. + continue + + case <-b.quit: + return + } + + // Find the first and last indices for the mweb utxos + // represented by this message. + startIndex = leafIdx(r.Utxos[0].LeafIndex) + lastIndex := leafIdx(r.Utxos[len(r.Utxos)-1].LeafIndex) + + log.Debugf("Got mwebutxos from index=%v to "+ + "index=%v, block hash=%v", startIndex, + lastIndex, r.BlockHash) + + // If this is out of order but not yet written, we can + // store them for later. + if startIndex > curIndex { + log.Debugf("Got response for mwebutxos at "+ + "index=%v, only at index=%v, stashing", + startIndex, curIndex) + } + + // If this is out of order stuff that's already been + // written, we can ignore it. + if lastIndex < curIndex { + log.Debugf("Received out of order reply "+ + "lastIndex=%v, already written", lastIndex) + continue + } + + // Add the verified response to our cache. + queryResponses[startIndex] = r + + // Then, we cycle through any cached messages, adding + // them to the batch and deleting them from the cache. + for { + // If we don't yet have the next response, then + // we'll break out so we can wait for the peers + // to respond with this message. + r, ok := queryResponses[curIndex] + if !ok { + break + } + + // We have another response to write, so delete + // it from the cache and write it. + delete(queryResponses, curIndex) + + log.Debugf("Writing mwebutxos at index=%v", curIndex) + + totalUtxos += len(r.Utxos) + + // Update the next index to write. + lastIndex := leafIdx(r.Utxos[len(r.Utxos)-1].LeafIndex) + curIndex = leafset.nextUnspent(lastIndex) + } + + // If the current index is beyond the end of the leafset, + // we are done. + if !leafset.contains(curIndex) { + log.Infof("Successfully got %v mweb utxos", totalUtxos) + break + } + } +} + +// requests creates the query.Requests for this mwebutxos query. +func (m *mwebUtxosQuery) requests() []*query.Request { + reqs := make([]*query.Request, len(m.msgs)) + for idx, msg := range m.msgs { + reqs[idx] = &query.Request{ + Req: msg, + HandleResp: m.handleResponse, + } + } + return reqs +} + +// handleResponse is the internal response handler used for requests for this +// mwebutxos query. +func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, + peerAddr string) query.Progress { + + r, ok := resp.(*wire.MsgMwebUtxos) + if !ok { + // We are only looking for mwebutxos messages. + return query.Progress{ + Finished: false, + Progressed: false, + } + } + + q, ok := req.(*wire.MsgGetMwebUtxos) + if !ok { + // We sent a getmwebutxos message, so that's what we should be + // comparing against. + return query.Progress{ + Finished: false, + Progressed: false, + } + } + + // The response doesn't match the query. + if !q.BlockHash.IsEqual(&r.BlockHash) || + q.StartIndex != r.StartIndex || + q.OutputFormat != r.OutputFormat || + q.NumRequested != uint16(len(r.Utxos)) { + return query.Progress{ + Finished: false, + Progressed: false, + } + } + + if !verifyMwebUtxos(m.mwebHeader, m.leafset, r) { + log.Warnf("Failed to verify mweb utxos at index %v!!!", + r.StartIndex) + + // If the peer gives us a bad mwebutxos message, + // then we'll ban the peer so we can re-allocate + // the query elsewhere. + err := m.blockMgr.cfg.BanPeer( + peerAddr, banman.InvalidMwebUtxos, + ) + if err != nil { + log.Errorf("Unable to ban peer %v: %v", peerAddr, err) + } + + return query.Progress{ + Finished: false, + Progressed: false, + } + } + + // At this point, the response matches the query, + // so we'll deliver the verified utxos on the utxosChan. + // We'll also return a Progress indicating the query + // finished, that the peer looking for the answer to this + // query can move on to the next query. + select { + case m.utxosChan <- r: + case <-m.blockMgr.quit: + return query.Progress{ + Finished: false, + Progressed: false, + } + } + + return query.Progress{ + Finished: true, + Progressed: true, + } } From 123e038e62db51d213a9b2419eacc1847ca2997f Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 15 Jan 2024 13:19:17 +0000 Subject: [PATCH 11/75] Save mweb utxos in database --- blockmanager.go | 4 + mweb.go | 17 ++++- mwebdb/mwebcoindb.go | 177 +++++++++++++++++++++++++++++++++++++++++++ neutrino.go | 8 ++ 4 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 mwebdb/mwebcoindb.go diff --git a/blockmanager.go b/blockmanager.go index ec797b15e..1fa7405bd 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -24,6 +24,7 @@ import ( "github.com/ltcsuite/neutrino/chainsync" "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/neutrino/headerlist" + "github.com/ltcsuite/neutrino/mwebdb" "github.com/ltcsuite/neutrino/query" ) @@ -93,6 +94,9 @@ type blockManagerCfg struct { // compact filters are persistently stored. RegFilterHeaders *headerfs.FilterHeaderStore + // MwebCoins is the store where mweb coins are persistently stored. + MwebCoins mwebdb.CoinDatabase + // TimeSource is used to access a time estimate based on the clocks of // the connected peers. TimeSource blockchain.MedianTimeSource diff --git a/mweb.go b/mweb.go index 594f141df..ba5b8dcc5 100644 --- a/mweb.go +++ b/mweb.go @@ -3,6 +3,7 @@ package neutrino import ( "bytes" "encoding/binary" + "fmt" "math/bits" "github.com/ltcsuite/ltcd/chaincfg/chainhash" @@ -274,8 +275,8 @@ func verifyMwebUtxos(mwebHeader *wire.MwebHeader, } var ( - nextLeafIdx = leafIdx(mwebHeader.OutputMMRSize) - peaks = calcPeaks(uint64(nextLeafIdx.nodeIdx())) + nextNodeIdx = leafIdx(mwebHeader.OutputMMRSize).nodeIdx() + peaks = calcPeaks(uint64(nextNodeIdx)) peakHashes []*chainhash.Hash ) for i := 0; i < 2; i++ { @@ -291,7 +292,7 @@ func verifyMwebUtxos(mwebHeader *wire.MwebHeader, peakHashes = append(peakHashes, peakHash) if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { if peakNodeIdx != peaks[len(peaks)-1] { - baggedPeak := v.nextHash(nextLeafIdx.nodeIdx()) + baggedPeak := v.nextHash(nextNodeIdx) if baggedPeak == nil { return false } @@ -308,7 +309,7 @@ func verifyMwebUtxos(mwebHeader *wire.MwebHeader, baggedPeak := peakHashes[len(peakHashes)-1] for i := len(peakHashes) - 2; i >= 0; i-- { - baggedPeak = nextLeafIdx.nodeIdx().parentHash(peakHashes[i][:], baggedPeak[:]) + baggedPeak = nextNodeIdx.parentHash(peakHashes[i][:], baggedPeak[:]) } return baggedPeak.IsEqual(&mwebHeader.OutputRoot) } @@ -457,6 +458,14 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Debugf("Writing mwebutxos at index=%v", curIndex) + var coins []*wire.MwebOutput + for _, utxo := range r.Utxos { + coins = append(coins, utxo.Output) + } + err := b.cfg.MwebCoins.PutCoins(coins) + if err != nil { + panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) + } totalUtxos += len(r.Utxos) // Update the next index to write. diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go new file mode 100644 index 000000000..2592ccc76 --- /dev/null +++ b/mwebdb/mwebcoindb.go @@ -0,0 +1,177 @@ +package mwebdb + +import ( + "bytes" + "fmt" + + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/ltcwallet/walletdb" +) + +var ( + // rootBucket is the name of the root bucket for this package. Within + // this bucket, sub-buckets are stored which themselves store the + // actual coins. + rootBucket = []byte("mweb-coindb") + + // coinBucket is the bucket that stores the coins. + coinBucket = []byte("coins") +) + +var ( + // ErrCoinNotFound is returned when a coin for an output ID is + // unable to be located. + ErrCoinNotFound = fmt.Errorf("unable to find coin") +) + +// CoinDatabase is an interface which represents an object that is capable of +// storing and retrieving coins according to their corresponding output ID. +type CoinDatabase interface { + // PutCoin stores a coin with the given output ID to persistent + // storage. + PutCoin(*chainhash.Hash, *wire.MwebOutput) error + + // PutCoins stores coins to persistent storage. + PutCoins([]*wire.MwebOutput) error + + // FetchCoin attempts to fetch a coin with the given output ID + // from persistent storage. In the case that a coin matching the + // target output ID cannot be found, then ErrCoinNotFound is to be + // returned. + FetchCoin(*chainhash.Hash) (*wire.MwebOutput, error) + + // PurgeCoins purges all coins from persistent storage. + PurgeCoins() error +} + +// CoinStore is an implementation of the CoinDatabase interface which is +// backed by boltdb. +type CoinStore struct { + db walletdb.DB +} + +// A compile-time check to ensure the CoinStore adheres to the CoinDatabase +// interface. +var _ CoinDatabase = (*CoinStore)(nil) + +// New creates a new instance of the CoinStore given an already open +// database. +func New(db walletdb.DB) (*CoinStore, error) { + err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { + // As part of our initial setup, we'll try to create the top + // level root bucket. If this already exists, then we can + // exit early. + rootBucket, err := tx.CreateTopLevelBucket(rootBucket) + if err != nil { + return err + } + + // If the main bucket doesn't already exist, then we'll need to + // create the sub-buckets. + _, err = rootBucket.CreateBucketIfNotExists(coinBucket) + return err + }) + if err != nil && err != walletdb.ErrBucketExists { + return nil, err + } + + return &CoinStore{db: db}, nil +} + +// PutCoin stores a coin with the given output ID to persistent +// storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PutCoin(outputId *chainhash.Hash, + coin *wire.MwebOutput) error { + + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + + if coin == nil { + return coinBucket.Put(outputId[:], nil) + } + + var buf bytes.Buffer + if err := coin.Serialize(&buf); err != nil { + return err + } + + return coinBucket.Put(outputId[:], buf.Bytes()) + }) +} + +// PutCoins stores coins to persistent storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PutCoins(coins []*wire.MwebOutput) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + + var buf bytes.Buffer + for _, coin := range coins { + if err := coin.Serialize(&buf); err != nil { + return err + } + + outputId := coin.Hash() + err := coinBucket.Put(outputId[:], buf.Bytes()) + if err != nil { + return err + } + buf.Reset() + } + + return nil + }) +} + +// FetchCoin attempts to fetch a coin with the given output ID from +// persistent storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error) { + var coin *wire.MwebOutput + + err := walletdb.View(c.db, func(tx walletdb.ReadTx) error { + rootBucket := tx.ReadBucket(rootBucket) + coinBucket := rootBucket.NestedReadBucket(coinBucket) + + coinBytes := coinBucket.Get(outputId[:]) + if coinBytes == nil { + return ErrCoinNotFound + } + if len(coinBytes) == 0 { + return nil + } + + coin = new(wire.MwebOutput) + return coin.Deserialize(bytes.NewBuffer(coinBytes)) + }) + if err != nil { + return nil, err + } + + return coin, nil +} + +// PurgeCoins purges all coins from persistent storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PurgeCoins() error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + + if err := rootBucket.DeleteNestedBucket(coinBucket); err != nil { + return err + } + if _, err := rootBucket.CreateBucket(coinBucket); err != nil { + return err + } + + return nil + }) +} diff --git a/neutrino.go b/neutrino.go index c009a7239..9ca8d97cd 100644 --- a/neutrino.go +++ b/neutrino.go @@ -29,6 +29,7 @@ import ( "github.com/ltcsuite/neutrino/chanutils" "github.com/ltcsuite/neutrino/filterdb" "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcsuite/neutrino/mwebdb" "github.com/ltcsuite/neutrino/pushtx" "github.com/ltcsuite/neutrino/query" ) @@ -660,6 +661,7 @@ type ChainService struct { // nolint:maligned FilterDB filterdb.FilterDatabase BlockHeaders headerfs.BlockHeaderStore RegFilterHeaders *headerfs.FilterHeaderStore + MwebCoinDB mwebdb.CoinDatabase persistToDisk bool FilterCache *lru.Cache[FilterCacheKey, *CacheableFilter] @@ -826,10 +828,16 @@ func NewChainService(cfg Config) (*ChainService, error) { return nil, err } + s.MwebCoinDB, err = mwebdb.New(cfg.Database) + if err != nil { + return nil, err + } + bm, err := newBlockManager(&blockManagerCfg{ ChainParams: s.chainParams, BlockHeaders: s.BlockHeaders, RegFilterHeaders: s.RegFilterHeaders, + MwebCoins: s.MwebCoinDB, TimeSource: s.timeSource, QueryDispatcher: s.workManager, BanPeer: s.BanPeer, From 9bb868ded4a20bc98cfb8ddfc6d6129915e2665c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 17 Jan 2024 03:03:36 +0000 Subject: [PATCH 12/75] Fix build --- mweb.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mweb.go b/mweb.go index ba5b8dcc5..5cb01146a 100644 --- a/mweb.go +++ b/mweb.go @@ -145,9 +145,7 @@ func (i nodeIdx) hash(data []byte) *chainhash.Hash { h := blake3.New(32, nil) binary.Write(h, binary.LittleEndian, uint64(i)) wire.WriteVarBytes(h, 0, data) - hash := &chainhash.Hash{} - h.Sum(hash[:0]) - return hash + return (*chainhash.Hash)(h.Sum(nil)) } func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { @@ -155,9 +153,7 @@ func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { binary.Write(h, binary.LittleEndian, uint64(i)) h.Write(left) h.Write(right) - hash := &chainhash.Hash{} - h.Sum(hash[:0]) - return hash + return (*chainhash.Hash)(h.Sum(nil)) } func calcPeaks(nodes uint64) (peaks []nodeIdx) { @@ -187,7 +183,7 @@ func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Has } utxo := v.mwebUtxos.Utxos[v.leavesUsed] leafIndex = leafIdx(utxo.LeafIndex) - hash = &utxo.OutputId + hash = utxo.OutputId v.leavesUsed++ return } From 00369326adcc9c68401b86d7a4132825ef35d982 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 21 Jan 2024 14:46:38 +0000 Subject: [PATCH 13/75] Add mweb utxos notification --- blockmanager.go | 13 +++++++++++++ mweb.go | 6 ++++++ neutrino.go | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/blockmanager.go b/blockmanager.go index 1fa7405bd..aea91c8bd 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -221,6 +221,9 @@ type blockManager struct { // nolint:maligned blocksPerRetarget int32 // target timespan / target time per block requestedTxns map[chainhash.Hash]struct{} + + mwebUtxosCallbacksMtx sync.RWMutex + mwebUtxosCallbacks []func(utxos []*wire.MwebOutput) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -3198,3 +3201,13 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( ancestorHeight, ancestor, l.store, l.headerList, ) } + +// RegisterMwebUtxosCallback will register a callback that will fire when +// new mweb utxos are received. +func (b *blockManager) RegisterMwebUtxosCallback( + onMwebUtxos func(utxos []*wire.MwebOutput)) { + + b.mwebUtxosCallbacksMtx.Lock() + defer b.mwebUtxosCallbacksMtx.Unlock() + b.mwebUtxosCallbacks = append(b.mwebUtxosCallbacks, onMwebUtxos) +} diff --git a/mweb.go b/mweb.go index 5cb01146a..abc9a6317 100644 --- a/mweb.go +++ b/mweb.go @@ -383,6 +383,9 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, q.requests(), query.Cancel(b.quit), ) + b.mwebUtxosCallbacksMtx.Lock() + defer b.mwebUtxosCallbacksMtx.Unlock() + // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 @@ -462,6 +465,9 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, if err != nil { panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) } + for _, cb := range b.mwebUtxosCallbacks { + cb(coins) + } totalUtxos += len(r.Utxos) // Update the next index to write. diff --git a/neutrino.go b/neutrino.go index 9ca8d97cd..087e955dd 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1181,6 +1181,12 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { s.mempool.NotifyReceived(addrs) } +// RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos +// are received +func (s *ChainService) RegisterMwebUtxosCallback(onMwebUtxos func(utxos []*wire.MwebOutput)) { + s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) +} + // peerHandler is used to handle peer operations such as adding and removing // peers to and from the server, banning peers, and broadcasting messages to // peers. It must be run in a goroutine. From b51ea1959959fa7a6e4f278874be5918c20b1495 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 21 Jan 2024 19:21:55 +0000 Subject: [PATCH 14/75] Continually fetch mweb utxos --- blockmanager.go | 36 +++++++++++++++++++++++++++++++++++- mweb.go | 13 ++++++++++++- mwebdb/mwebcoindb.go | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index aea91c8bd..842ac844b 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -551,7 +551,41 @@ func (b *blockManager) mwebHandler() { if !b.BlockHeadersSynced() { continue } - break + + // If block headers are current, but the mweb sync was for an + // earlier block, we also go back to the loop. + b.newHeadersMtx.RLock() + if lastHeight < b.headerTip { + b.newHeadersMtx.RUnlock() + continue + } + b.newHeadersMtx.RUnlock() + + log.Infof("Fully caught up with mweb at height "+ + "%v, waiting at tip for new blocks", lastHeight) + + // Now that we've been fully caught up to the tip of the current header + // chain, we'll wait here for a signal that more blocks have been + // connected. If this happens then we'll do another round to fetch the + // new set of mweb utxos. + + // We'll wait until the header tip has advanced. + b.newHeadersSignal.L.Lock() + for lastHeight == b.headerTip { + // We'll wait here until we're woken up by the + // broadcast signal. + b.newHeadersSignal.Wait() + + // Before we proceed, we'll check if we need to exit at + // all. + select { + case <-b.quit: + b.newHeadersSignal.L.Unlock() + return + default: + } + } + b.newHeadersSignal.L.Unlock() } } diff --git a/mweb.go b/mweb.go index abc9a6317..fc6c13f07 100644 --- a/mweb.go +++ b/mweb.go @@ -328,7 +328,11 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Infof("Fetching set of mweb utxos from "+ "height=%v, hash=%v", lastHeight, *lastHash) - var curIndex leafIdx + dbIndex, err := b.cfg.MwebCoins.GetLastIndex() + if err != nil { + panic(fmt.Sprintf("couldn't read mweb coins db: %v", err)) + } + curIndex := leafIdx(dbIndex) if !leafset.contains(curIndex) { curIndex = leafset.nextUnspent(curIndex) } @@ -473,6 +477,13 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // Update the next index to write. lastIndex := leafIdx(r.Utxos[len(r.Utxos)-1].LeafIndex) curIndex = leafset.nextUnspent(lastIndex) + if curIndex > leafIdx(mwebHeader.OutputMMRSize) { + curIndex = leafIdx(mwebHeader.OutputMMRSize) + } + + if err := b.cfg.MwebCoins.PutLastIndex(uint64(curIndex)); err != nil { + panic(fmt.Sprintf("couldn't write mweb coins index: %v", err)) + } } // If the current index is beyond the end of the leafset, diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 2592ccc76..8c90e6a26 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -2,6 +2,7 @@ package mwebdb import ( "bytes" + "encoding/binary" "fmt" "github.com/ltcsuite/ltcd/chaincfg/chainhash" @@ -23,11 +24,19 @@ var ( // ErrCoinNotFound is returned when a coin for an output ID is // unable to be located. ErrCoinNotFound = fmt.Errorf("unable to find coin") + + // ErrUnexpectedValueLen is returned when the bytes value is + // of an unexpected length. + ErrUnexpectedValueLen = fmt.Errorf("unexpected value length") ) // CoinDatabase is an interface which represents an object that is capable of // storing and retrieving coins according to their corresponding output ID. type CoinDatabase interface { + // Get and set the last coin index we have synced up to. + GetLastIndex() (uint64, error) + PutLastIndex(index uint64) error + // PutCoin stores a coin with the given output ID to persistent // storage. PutCoin(*chainhash.Hash, *wire.MwebOutput) error @@ -79,6 +88,33 @@ func New(db walletdb.DB) (*CoinStore, error) { return &CoinStore{db: db}, nil } +func (c *CoinStore) GetLastIndex() (index uint64, err error) { + err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { + rootBucket := tx.ReadBucket(rootBucket) + + b := rootBucket.Get([]byte("lastIndex")) + if b == nil { + return nil + } + if len(b) != 8 { + return ErrUnexpectedValueLen + } + + index = binary.LittleEndian.Uint64(b) + return nil + }) + return +} + +func (c *CoinStore) PutLastIndex(index uint64) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + + b := binary.LittleEndian.AppendUint64(nil, index) + return rootBucket.Put([]byte("lastIndex"), b) + }) +} + // PutCoin stores a coin with the given output ID to persistent // storage. // From ac9bec8ee3f62dc8c5cbedfd7833551cdae2187d Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 02:22:25 +0000 Subject: [PATCH 15/75] Rewrote the leaf span selection logic --- mweb.go | 107 ++++++++++++++++++++++++++----------------- mwebdb/mwebcoindb.go | 30 ++++++++---- 2 files changed, 86 insertions(+), 51 deletions(-) diff --git a/mweb.go b/mweb.go index fc6c13f07..3ee277909 100644 --- a/mweb.go +++ b/mweb.go @@ -323,49 +323,81 @@ type mwebUtxosQuery struct { const maxMwebUtxosPerQuery = 4096 func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - leafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { + newLeafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { log.Infof("Fetching set of mweb utxos from "+ "height=%v, hash=%v", lastHeight, *lastHash) - dbIndex, err := b.cfg.MwebCoins.GetLastIndex() + newNumLeaves := mwebHeader.OutputMMRSize + dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() if err != nil { panic(fmt.Sprintf("couldn't read mweb coins db: %v", err)) } - curIndex := leafIdx(dbIndex) - if !leafset.contains(curIndex) { - curIndex = leafset.nextUnspent(curIndex) - } - startIndex := curIndex + oldLeafset := leafset(dbLeafset) - log.Infof("Starting to query for mweb utxos from "+ - "index=%v", startIndex) + // Skip over common prefix + var index uint64 + for index < uint64(len(oldLeafset)) && + index < uint64(len(newLeafset)) && + oldLeafset[index] == newLeafset[index] { + index++ + } + index *= 8 + if index > oldNumLeaves { + index = oldNumLeaves + } + if index > newNumLeaves { + index = newNumLeaves + } - var queryMsgs []wire.Message - for leafset.contains(startIndex) { - var numLeaves uint16 - nextIndex := startIndex - for ; numLeaves < maxMwebUtxosPerQuery; numLeaves++ { - if !leafset.contains(nextIndex) { - break + type span struct { + start uint64 + count uint16 + } + var addLeaf span + var addedLeaves []span + var removedLeaves []uint64 + addLeafSpan := func() { + if addLeaf.count > 0 { + addedLeaves = append(addedLeaves, addLeaf) + addLeaf = span{} + } + } + for ; index < oldNumLeaves || index < newNumLeaves; index++ { + if oldLeafset.contains(leafIdx(index)) { + addLeafSpan() + if !newLeafset.contains(leafIdx(index)) { + removedLeaves = append(removedLeaves, index) + } + } else if newLeafset.contains(leafIdx(index)) { + if addLeaf.count == 0 { + addLeaf.start = index + } + addLeaf.count++ + if addLeaf.count == maxMwebUtxosPerQuery { + addLeafSpan() } - nextIndex = leafset.nextUnspent(nextIndex) } + } + addLeafSpan() + + var queryMsgs []wire.Message + for _, addLeaf := range addedLeaves { queryMsgs = append(queryMsgs, - wire.NewMsgGetMwebUtxos(lastHash, uint64(startIndex), - numLeaves, wire.MwebNetUtxoCompact)) - startIndex = nextIndex + wire.NewMsgGetMwebUtxos(lastHash, addLeaf.start, + addLeaf.count, wire.MwebNetUtxoCompact)) } // We'll also create an additional map that we'll use to // re-order the responses as we get them in. - queryResponses := make(map[leafIdx]*wire.MsgMwebUtxos, len(queryMsgs)) + queryResponses := make(map[uint64]*wire.MsgMwebUtxos, len(queryMsgs)) batchesCount := len(queryMsgs) if batchesCount == 0 { return } + log.Infof("Starting to query for mweb utxos from index=%v", addedLeaves[0].start) log.Infof("Attempting to query for %v mwebutxos batches", batchesCount) // With the set of messages constructed, we'll now request the batch @@ -376,7 +408,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, q := mwebUtxosQuery{ blockMgr: b, mwebHeader: mwebHeader, - leafset: leafset, + leafset: newLeafset, msgs: queryMsgs, utxosChan: utxosChan, } @@ -393,7 +425,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 - for { + for i := 0; i < len(addedLeaves); { var r *wire.MsgMwebUtxos select { case r = <-utxosChan: @@ -418,8 +450,9 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // Find the first and last indices for the mweb utxos // represented by this message. - startIndex = leafIdx(r.Utxos[0].LeafIndex) - lastIndex := leafIdx(r.Utxos[len(r.Utxos)-1].LeafIndex) + startIndex := r.Utxos[0].LeafIndex + lastIndex := r.Utxos[len(r.Utxos)-1].LeafIndex + curIndex := addedLeaves[i].start log.Debugf("Got mwebutxos from index=%v to "+ "index=%v, block hash=%v", startIndex, @@ -446,10 +479,11 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // Then, we cycle through any cached messages, adding // them to the batch and deleting them from the cache. - for { + for i < len(addedLeaves) { // If we don't yet have the next response, then // we'll break out so we can wait for the peers // to respond with this message. + curIndex = addedLeaves[i].start r, ok := queryResponses[curIndex] if !ok { break @@ -475,23 +509,14 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, totalUtxos += len(r.Utxos) // Update the next index to write. - lastIndex := leafIdx(r.Utxos[len(r.Utxos)-1].LeafIndex) - curIndex = leafset.nextUnspent(lastIndex) - if curIndex > leafIdx(mwebHeader.OutputMMRSize) { - curIndex = leafIdx(mwebHeader.OutputMMRSize) - } - - if err := b.cfg.MwebCoins.PutLastIndex(uint64(curIndex)); err != nil { - panic(fmt.Sprintf("couldn't write mweb coins index: %v", err)) - } + i++ } + } - // If the current index is beyond the end of the leafset, - // we are done. - if !leafset.contains(curIndex) { - log.Infof("Successfully got %v mweb utxos", totalUtxos) - break - } + log.Infof("Successfully got %v mweb utxos", totalUtxos) + + if err := b.cfg.MwebCoins.PutLeafSet(newLeafset, newNumLeaves); err != nil { + panic(fmt.Sprintf("couldn't write mweb leafset: %v", err)) } } diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 8c90e6a26..40a56bb19 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -33,9 +33,9 @@ var ( // CoinDatabase is an interface which represents an object that is capable of // storing and retrieving coins according to their corresponding output ID. type CoinDatabase interface { - // Get and set the last coin index we have synced up to. - GetLastIndex() (uint64, error) - PutLastIndex(index uint64) error + // Get and set the leafset marking the unspent indices. + GetLeafSet() (leafset []byte, numLeaves uint64, err error) + PutLeafSet(leafset []byte, numLeaves uint64) error // PutCoin stores a coin with the given output ID to persistent // storage. @@ -88,30 +88,40 @@ func New(db walletdb.DB) (*CoinStore, error) { return &CoinStore{db: db}, nil } -func (c *CoinStore) GetLastIndex() (index uint64, err error) { +func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) - b := rootBucket.Get([]byte("lastIndex")) + leafset = rootBucket.Get([]byte("leafset")) + if leafset == nil { + return nil + } + + b := rootBucket.Get([]byte("numLeaves")) if b == nil { + leafset = nil return nil } if len(b) != 8 { return ErrUnexpectedValueLen } - - index = binary.LittleEndian.Uint64(b) + numLeaves = binary.LittleEndian.Uint64(b) return nil }) return } -func (c *CoinStore) PutLastIndex(index uint64) error { +func (c *CoinStore) PutLeafSet(leafset []byte, numLeaves uint64) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) - b := binary.LittleEndian.AppendUint64(nil, index) - return rootBucket.Put([]byte("lastIndex"), b) + err := rootBucket.Put([]byte("leafset"), leafset) + if err != nil { + return err + } + + b := binary.LittleEndian.AppendUint64(nil, numLeaves) + return rootBucket.Put([]byte("numLeaves"), b) }) } From c05e78b228d39a0c124b9a39aec81085a31888c9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 12:53:41 +0000 Subject: [PATCH 16/75] Store leaf to utxo mapping --- blockmanager.go | 4 ++-- mweb.go | 8 ++------ mwebdb/mwebcoindb.go | 46 +++++++++++++++++++++++++++++++++++--------- neutrino.go | 2 +- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 842ac844b..d777701c1 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -223,7 +223,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} mwebUtxosCallbacksMtx sync.RWMutex - mwebUtxosCallbacks []func(utxos []*wire.MwebOutput) + mwebUtxosCallbacks []func(utxos []*wire.MwebNetUtxo) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -3239,7 +3239,7 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( // RegisterMwebUtxosCallback will register a callback that will fire when // new mweb utxos are received. func (b *blockManager) RegisterMwebUtxosCallback( - onMwebUtxos func(utxos []*wire.MwebOutput)) { + onMwebUtxos func(utxos []*wire.MwebNetUtxo)) { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() diff --git a/mweb.go b/mweb.go index 3ee277909..b1f027224 100644 --- a/mweb.go +++ b/mweb.go @@ -495,16 +495,12 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Debugf("Writing mwebutxos at index=%v", curIndex) - var coins []*wire.MwebOutput - for _, utxo := range r.Utxos { - coins = append(coins, utxo.Output) - } - err := b.cfg.MwebCoins.PutCoins(coins) + err := b.cfg.MwebCoins.PutCoins(r.Utxos) if err != nil { panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) } for _, cb := range b.mwebUtxosCallbacks { - cb(coins) + cb(r.Utxos) } totalUtxos += len(r.Utxos) diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 40a56bb19..e82148c27 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -18,6 +18,10 @@ var ( // coinBucket is the bucket that stores the coins. coinBucket = []byte("coins") + + // leafBucket is the bucket that stores the mapping between + // leaf indices and output IDs. + leafBucket = []byte("leaves") ) var ( @@ -39,10 +43,10 @@ type CoinDatabase interface { // PutCoin stores a coin with the given output ID to persistent // storage. - PutCoin(*chainhash.Hash, *wire.MwebOutput) error + PutCoin(*chainhash.Hash, *wire.MwebNetUtxo) error // PutCoins stores coins to persistent storage. - PutCoins([]*wire.MwebOutput) error + PutCoins([]*wire.MwebNetUtxo) error // FetchCoin attempts to fetch a coin with the given output ID // from persistent storage. In the case that a coin matching the @@ -79,6 +83,10 @@ func New(db walletdb.DB) (*CoinStore, error) { // If the main bucket doesn't already exist, then we'll need to // create the sub-buckets. _, err = rootBucket.CreateBucketIfNotExists(coinBucket) + if err != nil { + return err + } + _, err = rootBucket.CreateBucketIfNotExists(leafBucket) return err }) if err != nil && err != walletdb.ErrBucketExists { @@ -130,41 +138,54 @@ func (c *CoinStore) PutLeafSet(leafset []byte, numLeaves uint64) error { // // NOTE: This method is a part of the CoinDatabase interface. func (c *CoinStore) PutCoin(outputId *chainhash.Hash, - coin *wire.MwebOutput) error { + coin *wire.MwebNetUtxo) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) if coin == nil { return coinBucket.Put(outputId[:], nil) } var buf bytes.Buffer - if err := coin.Serialize(&buf); err != nil { + if err := coin.Output.Serialize(&buf); err != nil { return err } - return coinBucket.Put(outputId[:], buf.Bytes()) + err := coinBucket.Put(coin.OutputId[:], buf.Bytes()) + if err != nil { + return err + } + + leafIndex := binary.LittleEndian.AppendUint64(nil, coin.LeafIndex) + return leafBucket.Put(leafIndex, coin.OutputId[:]) }) } // PutCoins stores coins to persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) PutCoins(coins []*wire.MwebOutput) error { +func (c *CoinStore) PutCoins(coins []*wire.MwebNetUtxo) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) var buf bytes.Buffer for _, coin := range coins { - if err := coin.Serialize(&buf); err != nil { + if err := coin.Output.Serialize(&buf); err != nil { return err } - outputId := coin.Hash() - err := coinBucket.Put(outputId[:], buf.Bytes()) + err := coinBucket.Put(coin.OutputId[:], buf.Bytes()) + if err != nil { + return err + } + + leafIndex := binary.LittleEndian.AppendUint64(nil, coin.LeafIndex) + err = leafBucket.Put(leafIndex, coin.OutputId[:]) if err != nil { return err } @@ -214,9 +235,16 @@ func (c *CoinStore) PurgeCoins() error { if err := rootBucket.DeleteNestedBucket(coinBucket); err != nil { return err } + if err := rootBucket.DeleteNestedBucket(leafBucket); err != nil { + return err + } + if _, err := rootBucket.CreateBucket(coinBucket); err != nil { return err } + if _, err := rootBucket.CreateBucket(leafBucket); err != nil { + return err + } return nil }) diff --git a/neutrino.go b/neutrino.go index 087e955dd..f8aca5a6e 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1183,7 +1183,7 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { // RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos // are received -func (s *ChainService) RegisterMwebUtxosCallback(onMwebUtxos func(utxos []*wire.MwebOutput)) { +func (s *ChainService) RegisterMwebUtxosCallback(onMwebUtxos func(utxos []*wire.MwebNetUtxo)) { s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) } From 1fb18a32d6edc6c9e11ca83aa567a761866d7d6c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 15:31:05 +0000 Subject: [PATCH 17/75] Fix bug when mmr peak has no unspent leaves --- mweb.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mweb.go b/mweb.go index b1f027224..885b7fd22 100644 --- a/mweb.go +++ b/mweb.go @@ -282,6 +282,9 @@ func verifyMwebUtxos(mwebHeader *wire.MwebHeader, for _, peakNodeIdx := range peaks { peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) + if peakHash == nil { + peakHash = v.nextHash(peakNodeIdx) + } if peakHash == nil { return false } From 246a4bb4e44efca9555aba61b4cc73071d35881d Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 16:38:05 +0000 Subject: [PATCH 18/75] Purge spent coins from db --- mweb.go | 12 +++++++++--- mwebdb/mwebcoindb.go | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/mweb.go b/mweb.go index 885b7fd22..b1a854cbd 100644 --- a/mweb.go +++ b/mweb.go @@ -284,9 +284,9 @@ func verifyMwebUtxos(mwebHeader *wire.MwebHeader, peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) if peakHash == nil { peakHash = v.nextHash(peakNodeIdx) - } - if peakHash == nil { - return false + if peakHash == nil { + return false + } } peakHashes = append(peakHashes, peakHash) if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { @@ -517,6 +517,12 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, if err := b.cfg.MwebCoins.PutLeafSet(newLeafset, newNumLeaves); err != nil { panic(fmt.Sprintf("couldn't write mweb leafset: %v", err)) } + + log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) + + if err := b.cfg.MwebCoins.PurgeLeaves(removedLeaves); err != nil { + panic(fmt.Sprintf("couldn't purge mweb txos: %v", err)) + } } // requests creates the query.Requests for this mwebutxos query. diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index e82148c27..1d7f851d0 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -29,6 +29,9 @@ var ( // unable to be located. ErrCoinNotFound = fmt.Errorf("unable to find coin") + // ErrLeafNotFound is returned when a leaf is unable to be located. + ErrLeafNotFound = fmt.Errorf("unable to find leaf") + // ErrUnexpectedValueLen is returned when the bytes value is // of an unexpected length. ErrUnexpectedValueLen = fmt.Errorf("unexpected value length") @@ -54,6 +57,10 @@ type CoinDatabase interface { // returned. FetchCoin(*chainhash.Hash) (*wire.MwebOutput, error) + // PurgeLeaves purges the specified leaves and their associated + // coins from persistent storage. + PurgeLeaves([]uint64) error + // PurgeCoins purges all coins from persistent storage. PurgeCoins() error } @@ -146,7 +153,7 @@ func (c *CoinStore) PutCoin(outputId *chainhash.Hash, leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) if coin == nil { - return coinBucket.Put(outputId[:], nil) + return coinBucket.Delete(outputId[:]) } var buf bytes.Buffer @@ -225,6 +232,34 @@ func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error return coin, nil } +// PurgeLeaves purges the specified leaves and their associated +// coins from persistent storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PurgeLeaves(leaves []uint64) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) + + for _, leafIndex := range leaves { + leafIndex := binary.LittleEndian.AppendUint64(nil, leafIndex) + outputId := leafBucket.Get(leafIndex) + if outputId == nil { + return ErrLeafNotFound + } + if err := coinBucket.Delete(outputId); err != nil { + return err + } + if err := leafBucket.Delete(leafIndex); err != nil { + return err + } + } + + return nil + }) +} + // PurgeCoins purges all coins from persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. From 0a3a3a58facc2107cf0732999d3b0eddfa16f6b4 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 22:51:32 +0000 Subject: [PATCH 19/75] Notify new utxos at startup --- blockmanager.go | 4 ++-- mweb.go | 48 +++++++++++++++++++++++++++++++++++--------- mwebdb/mwebcoindb.go | 48 +++++++++++++++++++++++++++++++++++++++++--- neutrino.go | 9 ++++++++- 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index d777701c1..17f26c038 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -223,7 +223,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} mwebUtxosCallbacksMtx sync.RWMutex - mwebUtxosCallbacks []func(utxos []*wire.MwebNetUtxo) + mwebUtxosCallbacks []func(leafset []byte, utxos []*wire.MwebNetUtxo) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -3239,7 +3239,7 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( // RegisterMwebUtxosCallback will register a callback that will fire when // new mweb utxos are received. func (b *blockManager) RegisterMwebUtxosCallback( - onMwebUtxos func(utxos []*wire.MwebNetUtxo)) { + onMwebUtxos func(leafset []byte, utxos []*wire.MwebNetUtxo)) { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() diff --git a/mweb.go b/mweb.go index b1a854cbd..6d396465a 100644 --- a/mweb.go +++ b/mweb.go @@ -345,13 +345,6 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, oldLeafset[index] == newLeafset[index] { index++ } - index *= 8 - if index > oldNumLeaves { - index = oldNumLeaves - } - if index > newNumLeaves { - index = newNumLeaves - } type span struct { start uint64 @@ -366,7 +359,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, addLeaf = span{} } } - for ; index < oldNumLeaves || index < newNumLeaves; index++ { + for index *= 8; index < oldNumLeaves || index < newNumLeaves; index++ { if oldLeafset.contains(leafIdx(index)) { addLeafSpan() if !newLeafset.contains(leafIdx(index)) { @@ -503,7 +496,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) } for _, cb := range b.mwebUtxosCallbacks { - cb(r.Utxos) + cb(newLeafset, r.Utxos) } totalUtxos += len(r.Utxos) @@ -611,3 +604,40 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, Progressed: true, } } + +func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { + b.mwebUtxosCallbacksMtx.Lock() + defer b.mwebUtxosCallbacksMtx.Unlock() + + dbLeafset, newNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() + if err != nil { + return err + } + oldLeafset := leafset(leafSet) + newLeafset := leafset(dbLeafset) + + // Skip over common prefix + var index uint64 + for index < uint64(len(oldLeafset)) && + index < uint64(len(newLeafset)) && + oldLeafset[index] == newLeafset[index] { + index++ + } + + var addedLeaves []uint64 + for index *= 8; index < newNumLeaves; index++ { + if !oldLeafset.contains(leafIdx(index)) && + newLeafset.contains(leafIdx(index)) { + addedLeaves = append(addedLeaves, index) + } + } + + utxos, err := b.cfg.MwebCoins.FetchLeaves(addedLeaves) + if err != nil { + return err + } + for _, cb := range b.mwebUtxosCallbacks { + cb(newLeafset, utxos) + } + return nil +} diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 1d7f851d0..a62caa185 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -57,6 +57,9 @@ type CoinDatabase interface { // returned. FetchCoin(*chainhash.Hash) (*wire.MwebOutput, error) + // FetchLeaves fetches the coins corresponding to the leaves specified. + FetchLeaves([]uint64) ([]*wire.MwebNetUtxo, error) + // PurgeLeaves purges the specified leaves and their associated // coins from persistent storage. PurgeLeaves([]uint64) error @@ -218,9 +221,6 @@ func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error if coinBytes == nil { return ErrCoinNotFound } - if len(coinBytes) == 0 { - return nil - } coin = new(wire.MwebOutput) return coin.Deserialize(bytes.NewBuffer(coinBytes)) @@ -232,6 +232,48 @@ func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error return coin, nil } +// FetchLeaves fetches the coins corresponding to the leaves specified. +func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { + var coins []*wire.MwebNetUtxo + + err := walletdb.View(c.db, func(tx walletdb.ReadTx) error { + rootBucket := tx.ReadBucket(rootBucket) + coinBucket := rootBucket.NestedReadBucket(coinBucket) + leafBucket := rootBucket.NestedReadBucket(leafBucket) + + for _, leaf := range leaves { + leafIndex := binary.LittleEndian.AppendUint64(nil, leaf) + outputId := leafBucket.Get(leafIndex) + if outputId == nil { + return ErrLeafNotFound + } + + coinBytes := coinBucket.Get(outputId) + if coinBytes == nil { + return ErrCoinNotFound + } + + coin := new(wire.MwebOutput) + err := coin.Deserialize(bytes.NewBuffer(coinBytes)) + if err != nil { + return err + } + coins = append(coins, &wire.MwebNetUtxo{ + LeafIndex: leaf, + Output: coin, + OutputId: (*chainhash.Hash)(outputId), + }) + } + + return nil + }) + if err != nil { + return nil, err + } + + return coins, nil +} + // PurgeLeaves purges the specified leaves and their associated // coins from persistent storage. // diff --git a/neutrino.go b/neutrino.go index f8aca5a6e..c9f1b3cd3 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1183,10 +1183,17 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { // RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos // are received -func (s *ChainService) RegisterMwebUtxosCallback(onMwebUtxos func(utxos []*wire.MwebNetUtxo)) { +func (s *ChainService) RegisterMwebUtxosCallback( + onMwebUtxos func(leafset []byte, utxos []*wire.MwebNetUtxo)) { + s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) } +// Notify of any added mweb utxos since the last snapshot indicated by the leafset. +func (s *ChainService) NotifyAddedMwebUtxos(leafset []byte) error { + return s.blockManager.notifyAddedMwebUtxos(leafset) +} + // peerHandler is used to handle peer operations such as adding and removing // peers to and from the server, banning peers, and broadcasting messages to // peers. It must be run in a goroutine. From 49a10bd98286833cc73ffc86f0fd33b6cf17876c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 22 Jan 2024 23:22:12 +0000 Subject: [PATCH 20/75] Fix bug - bytes.Buffer cannot be reused --- mwebdb/mwebcoindb.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index a62caa185..a58813706 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -183,8 +183,8 @@ func (c *CoinStore) PutCoins(coins []*wire.MwebNetUtxo) error { coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) - var buf bytes.Buffer for _, coin := range coins { + var buf bytes.Buffer if err := coin.Output.Serialize(&buf); err != nil { return err } @@ -199,7 +199,6 @@ func (c *CoinStore) PutCoins(coins []*wire.MwebNetUtxo) error { if err != nil { return err } - buf.Reset() } return nil From 9aa29b7a377115dc3baf83238ccef2cf4daa8e6e Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 23 Jan 2024 18:27:31 +0000 Subject: [PATCH 21/75] Fill in BlockMeta at source --- blockmanager.go | 13 +++++++++---- mweb.go | 36 ++++++++++++++++++++++++++++++------ neutrino.go | 3 ++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 17f26c038..aaf7d9e4d 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -19,6 +19,7 @@ import ( "github.com/ltcsuite/ltcd/ltcutil/gcs" "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" "github.com/ltcsuite/neutrino/chainsync" @@ -223,7 +224,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} mwebUtxosCallbacksMtx sync.RWMutex - mwebUtxosCallbacks []func(leafset []byte, utxos []*wire.MwebNetUtxo) + mwebUtxosCallbacks []func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -527,7 +528,10 @@ func (b *blockManager) mwebHandler() { case *wire.MsgMwebLeafset: mwebLeafset = m } - verified = verifyMwebHeader(mwebHeader, mwebLeafset, lastHeight, &lastHash) + + verified = verifyMwebHeader(mwebHeader, + mwebLeafset, lastHeight, &lastHash) + if verified { close(quit) close(peerQuit) @@ -544,7 +548,8 @@ func (b *blockManager) mwebHandler() { } // Get all the mweb utxos at this height. - b.getMwebUtxos(&mwebHeader.MwebHeader, mwebLeafset.Leafset, lastHeight, &lastHash) + b.getMwebUtxos(&mwebHeader.MwebHeader, + mwebLeafset.Leafset, lastHeight, lastHeader) // Now we check the headers again. If the block headers are not yet // current, then we go back to the loop waiting for them to finish. @@ -3239,7 +3244,7 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( // RegisterMwebUtxosCallback will register a callback that will fire when // new mweb utxos are received. func (b *blockManager) RegisterMwebUtxosCallback( - onMwebUtxos func(leafset []byte, utxos []*wire.MwebNetUtxo)) { + onMwebUtxos func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta)) { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() diff --git a/mweb.go b/mweb.go index 6d396465a..120bd7f9a 100644 --- a/mweb.go +++ b/mweb.go @@ -10,6 +10,7 @@ import ( "github.com/ltcsuite/ltcd/ltcutil/bloom" "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/query" "lukechampine.com/blake3" @@ -326,10 +327,10 @@ type mwebUtxosQuery struct { const maxMwebUtxosPerQuery = 4096 func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - newLeafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { + newLeafset leafset, lastHeight uint32, lastHeader *wire.BlockHeader) { log.Infof("Fetching set of mweb utxos from "+ - "height=%v, hash=%v", lastHeight, *lastHash) + "height=%v, hash=%v", lastHeight, lastHeader.BlockHash()) newNumLeaves := mwebHeader.OutputMMRSize dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() @@ -380,8 +381,8 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, var queryMsgs []wire.Message for _, addLeaf := range addedLeaves { queryMsgs = append(queryMsgs, - wire.NewMsgGetMwebUtxos(lastHash, addLeaf.start, - addLeaf.count, wire.MwebNetUtxoCompact)) + wire.NewMsgGetMwebUtxos(lastHeader.BlockHash(), + addLeaf.start, addLeaf.count, wire.MwebNetUtxoCompact)) } // We'll also create an additional map that we'll use to @@ -495,9 +496,18 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, if err != nil { panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) } + + block := &wtxmgr.BlockMeta{ + Block: wtxmgr.Block{ + Hash: lastHeader.BlockHash(), + Height: int32(lastHeight), + }, + Time: lastHeader.Timestamp, + } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, r.Utxos) + cb(newLeafset, r.Utxos, block) } + totalUtxos += len(r.Utxos) // Update the next index to write. @@ -636,8 +646,22 @@ func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { if err != nil { return err } + + header, height, err := b.cfg.BlockHeaders.ChainTip() + if err != nil { + return err + } + + block := &wtxmgr.BlockMeta{ + Block: wtxmgr.Block{ + Hash: header.BlockHash(), + Height: int32(height), + }, + Time: header.Timestamp, + } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, utxos) + cb(newLeafset, utxos, block) } + return nil } diff --git a/neutrino.go b/neutrino.go index c9f1b3cd3..501cef426 100644 --- a/neutrino.go +++ b/neutrino.go @@ -23,6 +23,7 @@ import ( "github.com/ltcsuite/ltcd/peer" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" + "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" "github.com/ltcsuite/neutrino/cache/lru" @@ -1184,7 +1185,7 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { // RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos // are received func (s *ChainService) RegisterMwebUtxosCallback( - onMwebUtxos func(leafset []byte, utxos []*wire.MwebNetUtxo)) { + onMwebUtxos func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta)) { s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) } From 8aee05a917008ad06e51dc5f9683a50b5b05317c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 27 Jan 2024 14:08:41 +0000 Subject: [PATCH 22/75] Moved const to wire package --- mweb.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mweb.go b/mweb.go index 120bd7f9a..7c82dc972 100644 --- a/mweb.go +++ b/mweb.go @@ -324,8 +324,6 @@ type mwebUtxosQuery struct { utxosChan chan *wire.MsgMwebUtxos } -const maxMwebUtxosPerQuery = 4096 - func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, newLeafset leafset, lastHeight uint32, lastHeader *wire.BlockHeader) { @@ -371,7 +369,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, addLeaf.start = index } addLeaf.count++ - if addLeaf.count == maxMwebUtxosPerQuery { + if addLeaf.count == wire.MaxMwebUtxosPerQuery { addLeafSpan() } } From dc6700e2ae5a9636525b093442580d6e6774c5a9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 28 Jan 2024 14:27:00 +0000 Subject: [PATCH 23/75] Encodings --- query.go | 2 +- query/interface.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/query.go b/query.go index ad86bec4e..30e4e0ec5 100644 --- a/query.go +++ b/query.go @@ -58,7 +58,7 @@ var ( // QueryEncoding specifies the default encoding (witness or not) for // `getdata` and other similar messages. - QueryEncoding = wire.WitnessEncoding + QueryEncoding = wire.LatestEncoding // ErrFilterFetchFailed is returned in case fetching a compact filter // fails. diff --git a/query/interface.go b/query/interface.go index 443a66d3d..19a09b481 100644 --- a/query/interface.go +++ b/query/interface.go @@ -13,7 +13,7 @@ const ( // defaultQueryEncoding specifies the default encoding (witness or not) // for `getdata` and other similar messages. - defaultQueryEncoding = wire.WitnessEncoding + defaultQueryEncoding = wire.LatestEncoding // defaultNumRetries is the default number of times that a query job // will be retried. From 12283d0ff522e4b827c0bb791c2e6416199918bd Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 28 Jan 2024 20:41:44 +0000 Subject: [PATCH 24/75] Purge spent coins even if no new coins are added --- mweb.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mweb.go b/mweb.go index 7c82dc972..b4bfb57e8 100644 --- a/mweb.go +++ b/mweb.go @@ -389,6 +389,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, batchesCount := len(queryMsgs) if batchesCount == 0 { + b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) return } @@ -515,6 +516,12 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Infof("Successfully got %v mweb utxos", totalUtxos) + b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) +} + +func (b *blockManager) purgeSpentMwebTxos(newLeafset leafset, + newNumLeaves uint64, removedLeaves []uint64) { + if err := b.cfg.MwebCoins.PutLeafSet(newLeafset, newNumLeaves); err != nil { panic(fmt.Sprintf("couldn't write mweb leafset: %v", err)) } From fe8ae472fd7a8613b4c354837352660132fb5d3b Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 28 Jan 2024 21:49:19 +0000 Subject: [PATCH 25/75] Atomically update leafset and purge spents --- mweb.go | 10 +++--- mwebdb/mwebcoindb.go | 74 +++++++++++++++++++++++--------------------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/mweb.go b/mweb.go index b4bfb57e8..487c178e3 100644 --- a/mweb.go +++ b/mweb.go @@ -522,13 +522,13 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, func (b *blockManager) purgeSpentMwebTxos(newLeafset leafset, newNumLeaves uint64, removedLeaves []uint64) { - if err := b.cfg.MwebCoins.PutLeafSet(newLeafset, newNumLeaves); err != nil { - panic(fmt.Sprintf("couldn't write mweb leafset: %v", err)) + if len(removedLeaves) > 0 { + log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) } - log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) - - if err := b.cfg.MwebCoins.PurgeLeaves(removedLeaves); err != nil { + err := b.cfg.MwebCoins.PutLeafSetAndPurge( + newLeafset, newNumLeaves, removedLeaves) + if err != nil { panic(fmt.Sprintf("couldn't purge mweb txos: %v", err)) } } diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index a58813706..5b640aa76 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -40,9 +40,13 @@ var ( // CoinDatabase is an interface which represents an object that is capable of // storing and retrieving coins according to their corresponding output ID. type CoinDatabase interface { - // Get and set the leafset marking the unspent indices. + // Get the leafset marking the unspent indices. GetLeafSet() (leafset []byte, numLeaves uint64, err error) - PutLeafSet(leafset []byte, numLeaves uint64) error + + // Set the leafset and purge the specified leaves and their associated + // coins from persistent storage. + PutLeafSetAndPurge(leafset []byte, numLeaves uint64, + removedLeaves []uint64) error // PutCoin stores a coin with the given output ID to persistent // storage. @@ -60,10 +64,6 @@ type CoinDatabase interface { // FetchLeaves fetches the coins corresponding to the leaves specified. FetchLeaves([]uint64) ([]*wire.MwebNetUtxo, error) - // PurgeLeaves purges the specified leaves and their associated - // coins from persistent storage. - PurgeLeaves([]uint64) error - // PurgeCoins purges all coins from persistent storage. PurgeCoins() error } @@ -106,6 +106,9 @@ func New(db walletdb.DB) (*CoinStore, error) { return &CoinStore{db: db}, nil } +// Get the leafset marking the unspent indices. +// +// NOTE: This method is a part of the CoinDatabase interface. func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) @@ -129,9 +132,17 @@ func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { return } -func (c *CoinStore) PutLeafSet(leafset []byte, numLeaves uint64) error { +// Set the leafset and purge the specified leaves and their associated +// coins from persistent storage. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PutLeafSetAndPurge(leafset []byte, + numLeaves uint64, removedLeaves []uint64) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) + coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) + leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) err := rootBucket.Put([]byte("leafset"), leafset) if err != nil { @@ -139,7 +150,26 @@ func (c *CoinStore) PutLeafSet(leafset []byte, numLeaves uint64) error { } b := binary.LittleEndian.AppendUint64(nil, numLeaves) - return rootBucket.Put([]byte("numLeaves"), b) + err = rootBucket.Put([]byte("numLeaves"), b) + if err != nil { + return err + } + + for _, leafIndex := range removedLeaves { + leafIndex := binary.LittleEndian.AppendUint64(nil, leafIndex) + outputId := leafBucket.Get(leafIndex) + if outputId == nil { + return ErrLeafNotFound + } + if err := coinBucket.Delete(outputId); err != nil { + return err + } + if err := leafBucket.Delete(leafIndex); err != nil { + return err + } + } + + return nil }) } @@ -273,34 +303,6 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { return coins, nil } -// PurgeLeaves purges the specified leaves and their associated -// coins from persistent storage. -// -// NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) PurgeLeaves(leaves []uint64) error { - return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { - rootBucket := tx.ReadWriteBucket(rootBucket) - coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) - leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) - - for _, leafIndex := range leaves { - leafIndex := binary.LittleEndian.AppendUint64(nil, leafIndex) - outputId := leafBucket.Get(leafIndex) - if outputId == nil { - return ErrLeafNotFound - } - if err := coinBucket.Delete(outputId); err != nil { - return err - } - if err := leafBucket.Delete(leafIndex); err != nil { - return err - } - } - - return nil - }) -} - // PurgeCoins purges all coins from persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. From 0a9debd0c1ee608f2af1a344b926ca4092013e67 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 29 Jan 2024 00:46:47 +0000 Subject: [PATCH 26/75] Block meta comes from utxo height --- blockmanager.go | 7 ++-- mweb.go | 32 ++++------------- mwebdb/mwebcoindb.go | 85 +++++++++++++++++--------------------------- neutrino.go | 3 +- 4 files changed, 43 insertions(+), 84 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index aaf7d9e4d..700116f68 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -19,7 +19,6 @@ import ( "github.com/ltcsuite/ltcd/ltcutil/gcs" "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" "github.com/ltcsuite/neutrino/chainsync" @@ -224,7 +223,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} mwebUtxosCallbacksMtx sync.RWMutex - mwebUtxosCallbacks []func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta) + mwebUtxosCallbacks []func([]byte, []*wire.MwebNetUtxo) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -549,7 +548,7 @@ func (b *blockManager) mwebHandler() { // Get all the mweb utxos at this height. b.getMwebUtxos(&mwebHeader.MwebHeader, - mwebLeafset.Leafset, lastHeight, lastHeader) + mwebLeafset.Leafset, lastHeight, &lastHash) // Now we check the headers again. If the block headers are not yet // current, then we go back to the loop waiting for them to finish. @@ -3244,7 +3243,7 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( // RegisterMwebUtxosCallback will register a callback that will fire when // new mweb utxos are received. func (b *blockManager) RegisterMwebUtxosCallback( - onMwebUtxos func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta)) { + onMwebUtxos func([]byte, []*wire.MwebNetUtxo)) { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() diff --git a/mweb.go b/mweb.go index 487c178e3..9c02cbcd4 100644 --- a/mweb.go +++ b/mweb.go @@ -10,7 +10,6 @@ import ( "github.com/ltcsuite/ltcd/ltcutil/bloom" "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/query" "lukechampine.com/blake3" @@ -325,10 +324,10 @@ type mwebUtxosQuery struct { } func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - newLeafset leafset, lastHeight uint32, lastHeader *wire.BlockHeader) { + newLeafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { log.Infof("Fetching set of mweb utxos from "+ - "height=%v, hash=%v", lastHeight, lastHeader.BlockHash()) + "height=%v, hash=%v", lastHeight, *lastHash) newNumLeaves := mwebHeader.OutputMMRSize dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() @@ -379,8 +378,8 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, var queryMsgs []wire.Message for _, addLeaf := range addedLeaves { queryMsgs = append(queryMsgs, - wire.NewMsgGetMwebUtxos(lastHeader.BlockHash(), - addLeaf.start, addLeaf.count, wire.MwebNetUtxoCompact)) + wire.NewMsgGetMwebUtxos(*lastHash, addLeaf.start, + addLeaf.count, wire.MwebNetUtxoCompact)) } // We'll also create an additional map that we'll use to @@ -496,15 +495,8 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) } - block := &wtxmgr.BlockMeta{ - Block: wtxmgr.Block{ - Hash: lastHeader.BlockHash(), - Height: int32(lastHeight), - }, - Time: lastHeader.Timestamp, - } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, r.Utxos, block) + cb(newLeafset, r.Utxos) } totalUtxos += len(r.Utxos) @@ -652,20 +644,8 @@ func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { return err } - header, height, err := b.cfg.BlockHeaders.ChainTip() - if err != nil { - return err - } - - block := &wtxmgr.BlockMeta{ - Block: wtxmgr.Block{ - Hash: header.BlockHash(), - Height: int32(height), - }, - Time: header.Timestamp, - } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, utxos, block) + cb(newLeafset, utxos) } return nil diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 5b640aa76..8c6cd639a 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -43,15 +43,11 @@ type CoinDatabase interface { // Get the leafset marking the unspent indices. GetLeafSet() (leafset []byte, numLeaves uint64, err error) - // Set the leafset and purge the specified leaves and their associated - // coins from persistent storage. + // Set the leafset and purge the specified leaves and their + // associated coins from persistent storage. PutLeafSetAndPurge(leafset []byte, numLeaves uint64, removedLeaves []uint64) error - // PutCoin stores a coin with the given output ID to persistent - // storage. - PutCoin(*chainhash.Hash, *wire.MwebNetUtxo) error - // PutCoins stores coins to persistent storage. PutCoins([]*wire.MwebNetUtxo) error @@ -161,10 +157,10 @@ func (c *CoinStore) PutLeafSetAndPurge(leafset []byte, if outputId == nil { return ErrLeafNotFound } - if err := coinBucket.Delete(outputId); err != nil { + if err = coinBucket.Delete(outputId); err != nil { return err } - if err := leafBucket.Delete(leafIndex); err != nil { + if err = leafBucket.Delete(leafIndex); err != nil { return err } } @@ -173,37 +169,6 @@ func (c *CoinStore) PutLeafSetAndPurge(leafset []byte, }) } -// PutCoin stores a coin with the given output ID to persistent -// storage. -// -// NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) PutCoin(outputId *chainhash.Hash, - coin *wire.MwebNetUtxo) error { - - return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { - rootBucket := tx.ReadWriteBucket(rootBucket) - coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) - leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) - - if coin == nil { - return coinBucket.Delete(outputId[:]) - } - - var buf bytes.Buffer - if err := coin.Output.Serialize(&buf); err != nil { - return err - } - - err := coinBucket.Put(coin.OutputId[:], buf.Bytes()) - if err != nil { - return err - } - - leafIndex := binary.LittleEndian.AppendUint64(nil, coin.LeafIndex) - return leafBucket.Put(leafIndex, coin.OutputId[:]) - }) -} - // PutCoins stores coins to persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. @@ -215,11 +180,15 @@ func (c *CoinStore) PutCoins(coins []*wire.MwebNetUtxo) error { for _, coin := range coins { var buf bytes.Buffer - if err := coin.Output.Serialize(&buf); err != nil { + err := binary.Write(&buf, binary.LittleEndian, coin.Height) + if err != nil { + return err + } + if err = coin.Output.Serialize(&buf); err != nil { return err } - err := coinBucket.Put(coin.OutputId[:], buf.Bytes()) + err = coinBucket.Put(coin.OutputId[:], buf.Bytes()) if err != nil { return err } @@ -240,7 +209,7 @@ func (c *CoinStore) PutCoins(coins []*wire.MwebNetUtxo) error { // // NOTE: This method is a part of the CoinDatabase interface. func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error) { - var coin *wire.MwebOutput + var coin wire.MwebOutput err := walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) @@ -250,18 +219,25 @@ func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error if coinBytes == nil { return ErrCoinNotFound } + buf := bytes.NewBuffer(coinBytes) - coin = new(wire.MwebOutput) - return coin.Deserialize(bytes.NewBuffer(coinBytes)) + var height int32 + err := binary.Read(buf, binary.LittleEndian, &height) + if err != nil { + return err + } + return coin.Deserialize(buf) }) if err != nil { return nil, err } - return coin, nil + return &coin, nil } // FetchLeaves fetches the coins corresponding to the leaves specified. +// +// NOTE: This method is a part of the CoinDatabase interface. func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { var coins []*wire.MwebNetUtxo @@ -281,17 +257,22 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { if coinBytes == nil { return ErrCoinNotFound } + buf := bytes.NewBuffer(coinBytes) + + coin := &wire.MwebNetUtxo{ + LeafIndex: leaf, + Output: &wire.MwebOutput{}, + OutputId: (*chainhash.Hash)(outputId), + } + coins = append(coins, coin) - coin := new(wire.MwebOutput) - err := coin.Deserialize(bytes.NewBuffer(coinBytes)) + err := binary.Read(buf, binary.LittleEndian, &coin.Height) if err != nil { return err } - coins = append(coins, &wire.MwebNetUtxo{ - LeafIndex: leaf, - Output: coin, - OutputId: (*chainhash.Hash)(outputId), - }) + if err = coin.Output.Deserialize(buf); err != nil { + return err + } } return nil diff --git a/neutrino.go b/neutrino.go index 501cef426..19a018140 100644 --- a/neutrino.go +++ b/neutrino.go @@ -23,7 +23,6 @@ import ( "github.com/ltcsuite/ltcd/peer" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/ltcwallet/wtxmgr" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" "github.com/ltcsuite/neutrino/cache/lru" @@ -1185,7 +1184,7 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { // RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos // are received func (s *ChainService) RegisterMwebUtxosCallback( - onMwebUtxos func([]byte, []*wire.MwebNetUtxo, *wtxmgr.BlockMeta)) { + onMwebUtxos func([]byte, []*wire.MwebNetUtxo)) { s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) } From 4dae5aea6e5592da6accb877e01df85eb3a76b8d Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 30 Jan 2024 19:07:18 +0000 Subject: [PATCH 27/75] Fix looping bug? --- blockmanager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockmanager.go b/blockmanager.go index 700116f68..a47c6ecf5 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -575,7 +575,7 @@ func (b *blockManager) mwebHandler() { // We'll wait until the header tip has advanced. b.newHeadersSignal.L.Lock() - for lastHeight == b.headerTip { + for lastHeight >= b.headerTip { // We'll wait here until we're woken up by the // broadcast signal. b.newHeadersSignal.Wait() From f89fe7cc37981c0fba5414ded620d505f9a37c4b Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 31 Jan 2024 01:46:15 +0000 Subject: [PATCH 28/75] Notify new leafset after purge --- mweb.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mweb.go b/mweb.go index 9c02cbcd4..e49f0bddf 100644 --- a/mweb.go +++ b/mweb.go @@ -386,6 +386,9 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // re-order the responses as we get them in. queryResponses := make(map[uint64]*wire.MsgMwebUtxos, len(queryMsgs)) + b.mwebUtxosCallbacksMtx.Lock() + defer b.mwebUtxosCallbacksMtx.Unlock() + batchesCount := len(queryMsgs) if batchesCount == 0 { b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) @@ -414,9 +417,6 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, q.requests(), query.Cancel(b.quit), ) - b.mwebUtxosCallbacksMtx.Lock() - defer b.mwebUtxosCallbacksMtx.Unlock() - // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 @@ -496,7 +496,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, r.Utxos) + cb(nil, r.Utxos) } totalUtxos += len(r.Utxos) @@ -523,6 +523,10 @@ func (b *blockManager) purgeSpentMwebTxos(newLeafset leafset, if err != nil { panic(fmt.Sprintf("couldn't purge mweb txos: %v", err)) } + + for _, cb := range b.mwebUtxosCallbacks { + cb(newLeafset, nil) + } } // requests creates the query.Requests for this mwebutxos query. From 8b38d14222a8012c660c56780d553de1c312045f Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 3 Feb 2024 13:57:47 +0000 Subject: [PATCH 29/75] Fix test --- go.mod | 6 +++++- go.sum | 32 -------------------------------- sync_test.go | 18 ++++++++++++------ 3 files changed, 17 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 26f98b47b..5946c0c04 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( 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/ltcwallet v0.13.1 github.com/ltcsuite/ltcwallet/wallet/txauthor v1.2.3 github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 // indirect github.com/ltcsuite/ltcwallet/wallet/txsizes v1.2.3 // indirect @@ -29,7 +30,6 @@ require ( github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/ltcsuite/lnd/clock v1.1.0 // indirect github.com/ltcsuite/lnd/ticker v1.1.0 // indirect - github.com/ltcsuite/ltcwallet v0.13.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/crypto v0.7.0 // indirect @@ -49,8 +49,12 @@ replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhas replace github.com/ltcsuite/ltcd/ltcutil => ../ltcd/ltcutil +replace github.com/ltcsuite/ltcwallet => ../ltcwallet + replace github.com/ltcsuite/ltcwallet/walletdb => ../ltcwallet/walletdb +replace github.com/ltcsuite/ltcwallet/waddrmgr => ../ltcwallet/waddrmgr + replace github.com/ltcsuite/ltcwallet/wtxmgr => ../ltcwallet/wtxmgr replace github.com/ltcsuite/ltcwallet/wallet/txauthor => ../ltcwallet/wallet/txauthor diff --git a/go.sum b/go.sum index 64b162868..97b1c7eb0 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= @@ -10,7 +9,6 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -24,9 +22,6 @@ github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -46,7 +41,6 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -56,22 +50,15 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= github.com/ltcsuite/lnd/clock v1.1.0 h1:am2L2QTKgotbUSILSLLdZNe1ziSacXfR34Ry0f8npCs= github.com/ltcsuite/lnd/clock v1.1.0/go.mod h1:Nn3X2+B0/70MnytJPHvOf3SPTPno09v90J/KJf5/dA8= -github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2PEq7IexlTWQ= github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4= github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof1yXM= github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8= -github.com/ltcsuite/ltcd/ltcutil/psbt v1.1.0-1/go.mod h1:jpDQOdehihA+lu9OW26YgHSJ+6lReEb8HNcQL5grC4k= -github.com/ltcsuite/ltcwallet v0.13.1 h1:XMyrDHn0BmgUgkNbR/Lzg36vjRsup3xdiPLSD471UMg= -github.com/ltcsuite/ltcwallet v0.13.1/go.mod h1:e6pIWRM9gsd5JnMsI9SgCJM0wi7awWdr20F1C1KUPiw= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks= -github.com/ltcsuite/neutrino v0.13.2/go.mod h1:eTkaETZBeu3es/FisfjY8Cp3M2fC4s+2V2VUeS8O1Ic= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -99,25 +86,16 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -130,8 +108,6 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -140,16 +116,9 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -172,6 +141,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/sync_test.go b/sync_test.go index c14bfc6b5..2fdad8035 100644 --- a/sync_test.go +++ b/sync_test.go @@ -25,6 +25,7 @@ import ( "github.com/ltcsuite/ltcd/rpcclient" "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/ltcwallet/waddrmgr" "github.com/ltcsuite/ltcwallet/wallet/txauthor" "github.com/ltcsuite/ltcwallet/walletdb" _ "github.com/ltcsuite/ltcwallet/walletdb/bdb" @@ -240,6 +241,10 @@ func (s *secSource) GetScript(addr ltcutil.Address) ([]byte, error) { return *script, nil } +func (s *secSource) GetScanKey(ltcutil.Address) (*btcec.PrivateKey, error) { + return nil, nil +} + // ChainParams is required by the SecretsSource interface. func (s *secSource) ChainParams() *chaincfg.Params { return s.params @@ -443,7 +448,8 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { // Spend the outputs we sent ourselves over two blocks. inSrc := func(tx wire.MsgTx) func(target ltcutil.Amount) ( total ltcutil.Amount, inputs []*wire.TxIn, - inputValues []ltcutil.Amount, scripts [][]byte, err error) { + inputValues []ltcutil.Amount, scripts [][]byte, + mwebOutputs []*wire.MwebOutput, err error) { ourIndex := 1 << 30 // Should work on 32-bit systems for i, txo := range tx.TxOut { @@ -455,12 +461,12 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { } return func(target ltcutil.Amount) (ltcutil.Amount, []*wire.TxIn, []ltcutil.Amount, - [][]byte, error) { + [][]byte, []*wire.MwebOutput, error) { if ourIndex == 1<<30 { err = fmt.Errorf("Couldn't find our address " + "in the passed transaction's outputs.") - return 0, nil, nil, nil, err + return 0, nil, nil, nil, nil, err } total := target inputs := []*wire.TxIn{ @@ -476,7 +482,7 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { } scripts := [][]byte{tx.TxOut[ourIndex].PkScript} - return total, inputs, inputValues, scripts, nil + return total, inputs, inputValues, scripts, nil, nil } } @@ -531,7 +537,7 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { 1024000, inSrc(*tx1), &txauthor.ChangeSource{ - NewScript: func() ([]byte, error) { + NewScript: func(*waddrmgr.KeyScope) ([]byte, error) { return script3, nil }, ScriptSize: len(script3), @@ -579,7 +585,7 @@ func testStartRescan(harness *neutrinoHarness, t *testing.T) { 1024000, inSrc(*tx2), &txauthor.ChangeSource{ - NewScript: func() ([]byte, error) { + NewScript: func(*waddrmgr.KeyScope) ([]byte, error) { return script3, nil }, ScriptSize: len(script3), From d4eb1c37488402656bddc709357ad6240bf905a9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 3 Feb 2024 17:20:05 +0000 Subject: [PATCH 30/75] Fixed closing a closed channel in queryAllPeers --- neutrino.go | 8 +++----- query.go | 3 +++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/neutrino.go b/neutrino.go index 19a018140..56f2be8e6 100644 --- a/neutrino.go +++ b/neutrino.go @@ -57,7 +57,8 @@ var ( // RequiredServices describes the services that are required to be // supported by outbound peers. - RequiredServices = wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeCF + RequiredServices = wire.SFNodeNetwork | wire.SFNodeWitness | + wire.SFNodeCF | wire.SFNodeMWEB | wire.SFNodeMWEBLightClient // BanThreshold is the maximum ban score before a peer is banned. BanThreshold = uint32(100) @@ -238,10 +239,7 @@ func (sp *ServerPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // Check to see if the peer supports the latest protocol version and // service bits required to service us. If not, then we'll disconnect // so we can find compatible peers. - peerServices := sp.Services() - if peerServices&wire.SFNodeWitness != wire.SFNodeWitness || - peerServices&wire.SFNodeCF != wire.SFNodeCF { - + if sp.Services()&RequiredServices != RequiredServices { peerAddr := sp.Addr() err := sp.server.BanPeer(peerAddr, banman.NoCompactFilters) if err != nil { diff --git a/query.go b/query.go index 30e4e0ec5..24432a9c3 100644 --- a/query.go +++ b/query.go @@ -365,7 +365,10 @@ checkResponses: select { case <-queryQuit: break checkResponses + default: + } + select { case <-s.quit: break checkResponses From f5e6f590512bd9f4a37c53438b08801cffff7740 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 6 Feb 2024 15:55:51 +0000 Subject: [PATCH 31/75] Stop rebroadcasting confirmed transactions --- neutrino.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/neutrino.go b/neutrino.go index 56f2be8e6..c3161b8ac 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1534,6 +1534,12 @@ func (s *ChainService) SendTransaction(tx *wire.MsgTx) error { return s.broadcaster.Broadcast(tx) } +// MarkAsConfirmed is used to tell the broadcaster that a transaction has been +// confirmed and that it is no longer necessary to rebroadcast this transaction. +func (s *ChainService) MarkAsConfirmed(txHash chainhash.Hash) { + s.broadcaster.MarkAsConfirmed(txHash) +} + // NewPeerConfig returns the configuration for the given ServerPeer. func NewPeerConfig(sp *ServerPeer) *peer.Config { return &peer.Config{ From 83263bfdcea66f47050601ea4b29a559f4745619 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 14 Feb 2024 23:52:37 +0000 Subject: [PATCH 32/75] Fix crash --- mwebdb/mwebcoindb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 8c6cd639a..332a43b56 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -109,7 +109,7 @@ func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) - leafset = rootBucket.Get([]byte("leafset")) + leafset = bytes.Clone(rootBucket.Get([]byte("leafset"))) if leafset == nil { return nil } @@ -248,7 +248,7 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { for _, leaf := range leaves { leafIndex := binary.LittleEndian.AppendUint64(nil, leaf) - outputId := leafBucket.Get(leafIndex) + outputId := bytes.Clone(leafBucket.Get(leafIndex)) if outputId == nil { return ErrLeafNotFound } From 0e9156ec32cd3a5c55822aea95d996172b204e6a Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 15 Feb 2024 11:27:08 +0000 Subject: [PATCH 33/75] Use bytes.Reader --- mwebdb/mwebcoindb.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mwebdb/mwebcoindb.go b/mwebdb/mwebcoindb.go index 332a43b56..bf9bd36f1 100644 --- a/mwebdb/mwebcoindb.go +++ b/mwebdb/mwebcoindb.go @@ -219,7 +219,7 @@ func (c *CoinStore) FetchCoin(outputId *chainhash.Hash) (*wire.MwebOutput, error if coinBytes == nil { return ErrCoinNotFound } - buf := bytes.NewBuffer(coinBytes) + buf := bytes.NewReader(coinBytes) var height int32 err := binary.Read(buf, binary.LittleEndian, &height) @@ -257,7 +257,7 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { if coinBytes == nil { return ErrCoinNotFound } - buf := bytes.NewBuffer(coinBytes) + buf := bytes.NewReader(coinBytes) coin := &wire.MwebNetUtxo{ LeafIndex: leaf, From 0d6113386a644ad187d6fbb3bc8427491545a67c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 17 Feb 2024 10:47:08 +0000 Subject: [PATCH 34/75] Add ConnectPeer method --- neutrino.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/neutrino.go b/neutrino.go index c3161b8ac..3e4e0b688 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1026,6 +1026,20 @@ func NewChainService(cfg Config) (*ChainService, error) { return &s, nil } +func (s *ChainService) ConnectPeer(addr string) error { + tcpAddr, err := s.addrStringToNetAddr(addr) + if err != nil { + return fmt.Errorf("unable to lookup IP for "+ + "%v: %v", addr, err) + } + + s.connManager.Connect(&connmgr.ConnReq{ + Addr: tcpAddr, + Permanent: true, + }) + return nil +} + // BestBlock retrieves the most recent block's height and hash where we // have both the header and filter header ready. func (s *ChainService) BestBlock() (*headerfs.BlockStamp, error) { From d0a394ce06dd531fbad69b9a87d66bee6cd8df76 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 18 Feb 2024 15:11:04 +0000 Subject: [PATCH 35/75] Fix build --- neutrino.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/neutrino.go b/neutrino.go index 3e4e0b688..bcd413ec4 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1206,6 +1206,17 @@ func (s *ChainService) NotifyAddedMwebUtxos(leafset []byte) error { return s.blockManager.notifyAddedMwebUtxos(leafset) } +// MwebUtxoExists checks if a mweb utxo with the given output ID exists in the db. +func (s *ChainService) MwebUtxoExists(outputId *chainhash.Hash) bool { + if _, err := s.MwebCoinDB.FetchCoin(outputId); err != nil { + if err == mwebdb.ErrCoinNotFound { + return false + } + panic(err) + } + return true +} + // peerHandler is used to handle peer operations such as adding and removing // peers to and from the server, banning peers, and broadcasting messages to // peers. It must be run in a goroutine. From 7dcf1659c08868c74b701f87799d87cbc351dac9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 18 Feb 2024 18:15:15 +0000 Subject: [PATCH 36/75] Fix test --- blockmanager.go | 4 +- go.mod | 15 +++-- go.sum | 148 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 144 insertions(+), 23 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index a47c6ecf5..8b7442e4c 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -2923,7 +2923,9 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // Clear the mempool to free up memory. This may mean we might receive // transactions we've previously downloaded but this is rather unlikely. - b.cfg.mempool.Clear() + if b.cfg.mempool != nil { + b.cfg.mempool.Clear() + } } // areHeadersConnected returns true if the passed block headers are connected to diff --git a/go.mod b/go.mod index 5946c0c04..19d007c66 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,12 @@ require ( github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 github.com/ltcsuite/ltcd/ltcutil v1.1.3 github.com/ltcsuite/ltcwallet v0.13.1 - github.com/ltcsuite/ltcwallet/wallet/txauthor v1.2.3 + github.com/ltcsuite/ltcwallet/wallet/txauthor v1.3.2 github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 // indirect github.com/ltcsuite/ltcwallet/wallet/txsizes v1.2.3 // indirect - github.com/ltcsuite/ltcwallet/walletdb v1.3.5 + github.com/ltcsuite/ltcwallet/walletdb v1.4.0 github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0 - github.com/ltcsuite/neutrino/cache v1.1.0 + github.com/ltcsuite/neutrino/cache v1.1.1 github.com/stretchr/testify v1.8.2 lukechampine.com/blake3 v1.2.1 ) @@ -30,10 +30,11 @@ require ( github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/ltcsuite/lnd/clock v1.1.0 // indirect github.com/ltcsuite/lnd/ticker v1.1.0 // indirect + github.com/ltcsuite/lnd/tlv v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.etcd.io/bbolt v1.3.6 // indirect + go.etcd.io/bbolt v1.3.7 // indirect golang.org/x/crypto v0.7.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -49,6 +50,8 @@ replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhas replace github.com/ltcsuite/ltcd/ltcutil => ../ltcd/ltcutil +replace github.com/ltcsuite/ltcd/ltcutil/psbt => ../ltcd/ltcutil/psbt + replace github.com/ltcsuite/ltcwallet => ../ltcwallet replace github.com/ltcsuite/ltcwallet/walletdb => ../ltcwallet/walletdb @@ -60,3 +63,5 @@ replace github.com/ltcsuite/ltcwallet/wtxmgr => ../ltcwallet/wtxmgr replace github.com/ltcsuite/ltcwallet/wallet/txauthor => ../ltcwallet/wallet/txauthor replace github.com/ltcsuite/ltcwallet/wallet/txsizes => ../ltcwallet/wallet/txsizes + +replace github.com/ltcsuite/lnd/tlv => ../lnd/tlv diff --git a/go.sum b/go.sum index 97b1c7eb0..fd176e943 100644 --- a/go.sum +++ b/go.sum @@ -4,11 +4,13 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -22,6 +24,10 @@ github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -36,20 +42,30 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= +github.com/ltcsuite/lnd v0.14.2-beta.rc3 h1:FSvwVonmzMqq4biW1LXeFY8LkZSOe8s9YUPZB096ufU= github.com/ltcsuite/lnd/clock v1.1.0 h1:am2L2QTKgotbUSILSLLdZNe1ziSacXfR34Ry0f8npCs= github.com/ltcsuite/lnd/clock v1.1.0/go.mod h1:Nn3X2+B0/70MnytJPHvOf3SPTPno09v90J/KJf5/dA8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= @@ -59,64 +75,159 @@ github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI= github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= +github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -127,15 +238,18 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From e9357a65edb31d2e35484b4ffd117dcd451940f1 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 20 Feb 2024 12:56:25 +0000 Subject: [PATCH 37/75] Remove unused param --- mempool.go | 7 +++---- neutrino.go | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mempool.go b/mempool.go index 1537c38d0..7dc2d8415 100644 --- a/mempool.go +++ b/mempool.go @@ -3,7 +3,6 @@ package neutrino import ( "sync" - "github.com/ltcsuite/ltcd/btcjson" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/ltcutil" ) @@ -14,7 +13,7 @@ import ( type Mempool struct { downloadedTxs map[chainhash.Hash]bool mtx sync.RWMutex - callbacks []func(tx *ltcutil.Tx, block *btcjson.BlockDetails) + callbacks []func(*ltcutil.Tx) watchedAddrs []ltcutil.Address } @@ -28,7 +27,7 @@ func NewMempool() *Mempool { // RegisterCallback will register a callback that will fire when a transaction // matching a watched address enters the mempool. -func (mp *Mempool) RegisterCallback(onRecvTx func(tx *ltcutil.Tx, block *btcjson.BlockDetails)) { +func (mp *Mempool) RegisterCallback(onRecvTx func(*ltcutil.Tx)) { mp.mtx.Lock() defer mp.mtx.Unlock() mp.callbacks = append(mp.callbacks, onRecvTx) @@ -53,7 +52,7 @@ func (mp *Mempool) AddTransaction(tx *ltcutil.Tx) { WatchAddrs(mp.watchedAddrs...)(ro) if ok, err := ro.paysWatchedAddr(tx); ok && err == nil { for _, cb := range mp.callbacks { - cb(tx, nil) + cb(tx) } } } diff --git a/neutrino.go b/neutrino.go index bcd413ec4..abe8c0454 100644 --- a/neutrino.go +++ b/neutrino.go @@ -15,7 +15,6 @@ import ( "github.com/ltcsuite/ltcd/addrmgr" "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/btcjson" "github.com/ltcsuite/ltcd/chaincfg" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/connmgr" @@ -1183,7 +1182,7 @@ func (s *ChainService) NetTotals() (uint64, uint64) { // RegisterMempoolCallback registers a callback to be fired whenever a new transaction is // received into the mempool -func (s *ChainService) RegisterMempoolCallback(onRecvTx func(tx *ltcutil.Tx, block *btcjson.BlockDetails)) { +func (s *ChainService) RegisterMempoolCallback(onRecvTx func(*ltcutil.Tx)) { s.mempool.RegisterCallback(onRecvTx) } From 273ddc8fbe94c5ae5afce2573379f1fac8de7877 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 21 Feb 2024 13:25:06 +0000 Subject: [PATCH 38/75] Notify unconfirmed mweb utxos --- blockmanager.go | 5 ++++- mempool.go | 5 +++++ mweb.go | 16 ++++++++++++++++ neutrino.go | 3 ++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 8b7442e4c..2ac49fe6a 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -2435,7 +2435,10 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { } if _, exists := b.requestedTxns[iv.Hash]; !exists { b.requestedTxns[iv.Hash] = struct{}{} - gdmsg.AddInvVect(iv) + gdmsg.AddInvVect(&wire.InvVect{ + Type: wire.InvTypeMwebTx, + Hash: iv.Hash, + }) } } } diff --git a/mempool.go b/mempool.go index 7dc2d8415..4016e329e 100644 --- a/mempool.go +++ b/mempool.go @@ -11,6 +11,7 @@ import ( // We will use this object to track which transactions we've already // downloaded so that we don't download them more than once. type Mempool struct { + blockManager *blockManager downloadedTxs map[chainhash.Hash]bool mtx sync.RWMutex callbacks []func(*ltcutil.Tx) @@ -55,6 +56,10 @@ func (mp *Mempool) AddTransaction(tx *ltcutil.Tx) { cb(tx) } } + + if tx.MsgTx().Mweb != nil { + mp.blockManager.notifyMwebUtxos(tx.MsgTx().Mweb.TxBody.Outputs) + } } // Clear will remove all transactions from the mempool. This diff --git a/mweb.go b/mweb.go index e49f0bddf..f6c2b5788 100644 --- a/mweb.go +++ b/mweb.go @@ -654,3 +654,19 @@ func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { return nil } + +func (b *blockManager) notifyMwebUtxos(outputs []*wire.MwebOutput) { + b.mwebUtxosCallbacksMtx.Lock() + defer b.mwebUtxosCallbacksMtx.Unlock() + + var utxos []*wire.MwebNetUtxo + for _, output := range outputs { + utxos = append(utxos, &wire.MwebNetUtxo{ + Output: output, + OutputId: output.Hash(), + }) + } + for _, cb := range b.mwebUtxosCallbacks { + cb(nil, utxos) + } +} diff --git a/neutrino.go b/neutrino.go index abe8c0454..cec24ebca 100644 --- a/neutrino.go +++ b/neutrino.go @@ -52,7 +52,7 @@ var ( UserAgentVersion = "0.12.0-beta" // Services describes the services that are supported by the server. - Services = wire.SFNodeWitness | wire.SFNodeCF + Services = wire.SFNodeWitness | wire.SFNodeCF | wire.SFNodeMWEB // RequiredServices describes the services that are required to be // supported by outbound peers. @@ -848,6 +848,7 @@ func NewChainService(cfg Config) (*ChainService, error) { } s.blockManager = bm s.blockSubscriptionMgr = blockntfns.NewSubscriptionManager(s.blockManager) + s.mempool.blockManager = bm // Only setup a function to return new addresses to connect to when not // running in connect-only mode. Private development networks are always in From 7c9f6790f738c401a0557994bda5a9239e10caa5 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 22 Feb 2024 01:33:43 +0000 Subject: [PATCH 39/75] Split verifyMwebHeader function --- blockmanager.go | 6 ++++-- mweb.go | 25 ++++++++++++++----------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 2ac49fe6a..6076843c4 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -528,10 +528,12 @@ func (b *blockManager) mwebHandler() { mwebLeafset = m } - verified = verifyMwebHeader(mwebHeader, - mwebLeafset, lastHeight, &lastHash) + verified = verifyMwebHeader(mwebHeader, lastHash) + verified = verified && verifyMwebLeafset(mwebHeader, mwebLeafset) if verified { + log.Infof("Verified mwebheader and mwebleafset at "+ + "(block_height=%v, block_hash=%v)", lastHeight, lastHash) close(quit) close(peerQuit) } diff --git a/mweb.go b/mweb.go index f6c2b5788..7cf5fd804 100644 --- a/mweb.go +++ b/mweb.go @@ -15,19 +15,14 @@ import ( "lukechampine.com/blake3" ) -func verifyMwebHeader( - mwebHeader *wire.MsgMwebHeader, mwebLeafset *wire.MsgMwebLeafset, - lastHeight uint32, lastHash *chainhash.Hash) bool { - - if mwebHeader == nil || mwebLeafset == nil { +func verifyMwebHeader(mwebHeader *wire.MsgMwebHeader, lastHash chainhash.Hash) bool { + if mwebHeader == nil { return false } - log.Infof("Got mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", - lastHeight, *lastHash) - if mwebHeader.Merkle.Header.BlockHash() != *lastHash { + if mwebHeader.Merkle.Header.BlockHash() != lastHash { log.Infof("Block hash mismatch, merkle header hash=%v, block hash=%v", - mwebHeader.Merkle.Header.BlockHash(), *lastHash) + mwebHeader.Merkle.Header.BlockHash(), lastHash) return false } @@ -69,6 +64,16 @@ func verifyMwebHeader( return false } + return true +} + +func verifyMwebLeafset(mwebHeader *wire.MsgMwebHeader, + mwebLeafset *wire.MsgMwebLeafset) bool { + + if mwebLeafset == nil { + return false + } + // Verify that the hash of the leafset bitmap matches the // leafset_root value in the MWEB header. leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) @@ -78,8 +83,6 @@ func verifyMwebHeader( return false } - log.Infof("Verified mwebheader and mwebleafset at (block_height=%v, block_hash=%v)", - lastHeight, *lastHash) return true } From 34c155e30260b4fb8914325ccf3b0891cb3541f0 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 22 Feb 2024 13:46:57 +0000 Subject: [PATCH 40/75] Reorg for clarity --- blockmanager.go | 35 ++- mwebdb/mwebcoindb.go => mweb/coindb.go | 8 +- mweb/header.go | 76 ++++++ mweb/utxos.go | 244 ++++++++++++++++++ mweb.go => mwebutxos.go | 332 +------------------------ neutrino.go | 8 +- 6 files changed, 367 insertions(+), 336 deletions(-) rename mwebdb/mwebcoindb.go => mweb/coindb.go (98%) create mode 100644 mweb/header.go create mode 100644 mweb/utxos.go rename mweb.go => mwebutxos.go (51%) diff --git a/blockmanager.go b/blockmanager.go index 6076843c4..308463c39 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -24,7 +24,7 @@ import ( "github.com/ltcsuite/neutrino/chainsync" "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/neutrino/headerlist" - "github.com/ltcsuite/neutrino/mwebdb" + "github.com/ltcsuite/neutrino/mweb" "github.com/ltcsuite/neutrino/query" ) @@ -95,7 +95,7 @@ type blockManagerCfg struct { RegFilterHeaders *headerfs.FilterHeaderStore // MwebCoins is the store where mweb coins are persistently stored. - MwebCoins mwebdb.CoinDatabase + MwebCoins mweb.CoinDatabase // TimeSource is used to access a time estimate based on the clocks of // the connected peers. @@ -523,20 +523,37 @@ func (b *blockManager) mwebHandler() { switch m := resp.(type) { case *wire.MsgMwebHeader: + if err := mweb.VerifyHeader(m, lastHash); err != nil { + log.Infof("failed to verify mwebheader: %v", err) + return + } mwebHeader = m + case *wire.MsgMwebLeafset: mwebLeafset = m + + default: + log.Infof("unexpected message %v", resp) + return } - verified = verifyMwebHeader(mwebHeader, lastHash) - verified = verified && verifyMwebLeafset(mwebHeader, mwebLeafset) + if mwebHeader == nil || mwebLeafset == nil { + return + } - if verified { - log.Infof("Verified mwebheader and mwebleafset at "+ - "(block_height=%v, block_hash=%v)", lastHeight, lastHash) - close(quit) - close(peerQuit) + err := mweb.VerifyLeafset(mwebHeader, mwebLeafset) + if err != nil { + log.Infof("failed to verify mwebleafset: %v", err) + return } + + verified = true + + log.Infof("Verified mwebheader and mwebleafset at "+ + "(block_height=%v, block_hash=%v)", lastHeight, lastHash) + + close(quit) + close(peerQuit) }, ) select { diff --git a/mwebdb/mwebcoindb.go b/mweb/coindb.go similarity index 98% rename from mwebdb/mwebcoindb.go rename to mweb/coindb.go index bf9bd36f1..35d8a7458 100644 --- a/mwebdb/mwebcoindb.go +++ b/mweb/coindb.go @@ -1,4 +1,4 @@ -package mwebdb +package mweb import ( "bytes" @@ -74,9 +74,9 @@ type CoinStore struct { // interface. var _ CoinDatabase = (*CoinStore)(nil) -// New creates a new instance of the CoinStore given an already open -// database. -func New(db walletdb.DB) (*CoinStore, error) { +// NewCoinStore creates a new instance of the CoinStore given an +// already open database. +func NewCoinStore(db walletdb.DB) (*CoinStore, error) { err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error { // As part of our initial setup, we'll try to create the top // level root bucket. If this already exists, then we can diff --git a/mweb/header.go b/mweb/header.go new file mode 100644 index 000000000..6fd3f3570 --- /dev/null +++ b/mweb/header.go @@ -0,0 +1,76 @@ +package mweb + +import ( + "bytes" + "errors" + "fmt" + + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/ltcutil/bloom" + "github.com/ltcsuite/ltcd/txscript" + "github.com/ltcsuite/ltcd/wire" + "lukechampine.com/blake3" +) + +func VerifyHeader(mwebHeader *wire.MsgMwebHeader, + blockHash chainhash.Hash) error { + + if mwebHeader.Merkle.Header.BlockHash() != blockHash { + return fmt.Errorf("block hash mismatch, "+ + "merkle header hash=%v, block hash=%v", + mwebHeader.Merkle.Header.BlockHash(), blockHash) + } + + extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) + if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { + return errors.New("mwebheader merkle block is bad") + } + + if !mwebHeader.Hogex.IsHogEx { + return errors.New("mwebheader hogex is not hogex") + } + + // Validate that the hash of the HogEx transaction in the tx message + // matches the hash in the merkleblock message, and that it's the + // last transaction committed to by the merkle root of the block. + + finalTx := extractResult.Match[len(extractResult.Match)-1] + if mwebHeader.Hogex.TxHash() != *finalTx { + return fmt.Errorf("tx hash mismatch, hogex=%v, last merkle tx=%v", + mwebHeader.Hogex.TxHash(), *finalTx) + } + + finalTxPos := extractResult.Index[len(extractResult.Index)-1] + if finalTxPos != mwebHeader.Merkle.Transactions-1 { + return fmt.Errorf("tx index mismatch, got=%v, expected=%v", + finalTxPos, mwebHeader.Merkle.Transactions-1) + } + + // Validate that the pubkey script of the first output contains + // the HogAddr, which shall consist of <0x20> followed by + // the 32-byte hash of the MWEB header. + + mwebHeaderHash := mwebHeader.MwebHeader.Hash() + script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) + if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { + return fmt.Errorf("HogAddr mismatch, hogex=%v, expected=%v", + mwebHeader.Hogex.TxOut[0].PkScript, script) + } + + return nil +} + +func VerifyLeafset(mwebHeader *wire.MsgMwebHeader, + mwebLeafset *wire.MsgMwebLeafset) error { + + // Verify that the hash of the leafset bitmap matches the + // leafset_root value in the MWEB header. + + leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) + if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { + return fmt.Errorf("leafset root mismatch, leafset=%v, header=%v", + leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) + } + + return nil +} diff --git a/mweb/utxos.go b/mweb/utxos.go new file mode 100644 index 000000000..06c2b55ab --- /dev/null +++ b/mweb/utxos.go @@ -0,0 +1,244 @@ +package mweb + +import ( + "encoding/binary" + "math/bits" + + "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/wire" + "lukechampine.com/blake3" +) + +type ( + Leafset []byte + leafIdx uint64 + nodeIdx uint64 +) + +func (l Leafset) Contains(i uint64) bool { + return l.contains(leafIdx(i)) +} + +func (l Leafset) contains(i leafIdx) bool { + if int(i/8) >= len(l) { + return false + } + return l[i/8]&(0x80>>(i%8)) > 0 +} + +func (l Leafset) nextUnspent(i leafIdx) leafIdx { + for { + i++ + if l.contains(i) || int(i/8) >= len(l) { + return i + } + } +} + +func (i leafIdx) nodeIdx() nodeIdx { + return nodeIdx(2*i) - nodeIdx(bits.OnesCount64(uint64(i))) +} + +func (i nodeIdx) height() uint64 { + height := uint64(i) + h := 64 - bits.LeadingZeros64(uint64(i)) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if height >= peakSize { + height -= peakSize + } + } + return height +} + +func (i nodeIdx) leafIdx() leafIdx { + leafIndex := uint64(0) + numLeft := uint64(i) + h := 64 - bits.LeadingZeros64(uint64(i)) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if numLeft >= peakSize { + leafIndex += (peakSize + 1) / 2 + numLeft -= peakSize + } + } + return leafIdx(leafIndex) +} + +func (i nodeIdx) left(height uint64) nodeIdx { + return i - (1 << height) +} + +func (i nodeIdx) right() nodeIdx { + return i - 1 +} + +func (i nodeIdx) hash(data []byte) *chainhash.Hash { + h := blake3.New(32, nil) + binary.Write(h, binary.LittleEndian, uint64(i)) + wire.WriteVarBytes(h, 0, data) + return (*chainhash.Hash)(h.Sum(nil)) +} + +func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { + h := blake3.New(32, nil) + binary.Write(h, binary.LittleEndian, uint64(i)) + h.Write(left) + h.Write(right) + return (*chainhash.Hash)(h.Sum(nil)) +} + +func calcPeaks(nodes uint64) (peaks []nodeIdx) { + sumPrevPeaks := uint64(0) + h := 64 - bits.LeadingZeros64(nodes) + for peakSize := uint64(1< 0; peakSize >>= 1 { + if nodes >= peakSize { + peaks = append(peaks, nodeIdx(sumPrevPeaks+peakSize-1)) + sumPrevPeaks += peakSize + nodes -= peakSize + } + } + return +} + +type verifyMwebUtxosVars struct { + mwebUtxos *wire.MsgMwebUtxos + leafset Leafset + firstLeafIdx, lastLeafIdx leafIdx + leavesUsed, hashesUsed int + isProofHash map[nodeIdx]bool +} + +func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Hash) { + if v.leavesUsed == len(v.mwebUtxos.Utxos) { + return + } + utxo := v.mwebUtxos.Utxos[v.leavesUsed] + leafIndex = leafIdx(utxo.LeafIndex) + hash = utxo.OutputId + v.leavesUsed++ + return +} + +func (v *verifyMwebUtxosVars) nextHash(nodeIdx nodeIdx) (hash *chainhash.Hash) { + if v.hashesUsed == len(v.mwebUtxos.ProofHashes) { + return + } + hash = v.mwebUtxos.ProofHashes[v.hashesUsed] + v.hashesUsed++ + v.isProofHash[nodeIdx] = true + return +} + +func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chainhash.Hash { + if nodeIdx < v.firstLeafIdx.nodeIdx() || v.isProofHash[nodeIdx] { + return v.nextHash(nodeIdx) + } + if height == 0 { + leafIdx := nodeIdx.leafIdx() + if !v.leafset.contains(leafIdx) { + return nil + } + leafIdx2, outputId := v.nextLeaf() + if leafIdx != leafIdx2 || outputId == nil { + return nil + } + return nodeIdx.hash(outputId[:]) + } + left := v.calcNodeHash(nodeIdx.left(height), height-1) + var right *chainhash.Hash + if v.lastLeafIdx.nodeIdx() <= nodeIdx.left(height) { + right = v.nextHash(nodeIdx.right()) + } else { + right = v.calcNodeHash(nodeIdx.right(), height-1) + } + switch { + case left == nil && right == nil: + return nil + case left == nil: + if left = v.nextHash(nodeIdx.left(height)); left == nil { + return nil + } + case right == nil: + if right = v.nextHash(nodeIdx.right()); right == nil { + return nil + } + } + return nodeIdx.parentHash(left[:], right[:]) +} + +func VerifyUtxos(mwebHeader *wire.MwebHeader, + mwebLeafset Leafset, mwebUtxos *wire.MsgMwebUtxos) bool { + + if mwebUtxos.StartIndex == 0 && + len(mwebUtxos.Utxos) == 0 && + len(mwebUtxos.ProofHashes) == 0 && + mwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && + mwebHeader.OutputMMRSize == 0 { + return true + } else if len(mwebUtxos.Utxos) == 0 || + mwebHeader.OutputMMRSize == 0 { + return false + } + + v := &verifyMwebUtxosVars{ + mwebUtxos: mwebUtxos, + leafset: mwebLeafset, + firstLeafIdx: leafIdx(mwebUtxos.StartIndex), + lastLeafIdx: leafIdx(mwebUtxos.StartIndex), + isProofHash: make(map[nodeIdx]bool), + } + + for i := 0; ; i++ { + if !v.leafset.contains(v.lastLeafIdx) { + return false + } + if leafIdx(mwebUtxos.Utxos[i].LeafIndex) != v.lastLeafIdx { + return false + } + if i == len(mwebUtxos.Utxos)-1 { + break + } + v.lastLeafIdx = v.leafset.nextUnspent(v.lastLeafIdx) + } + + var ( + nextNodeIdx = leafIdx(mwebHeader.OutputMMRSize).nodeIdx() + peaks = calcPeaks(uint64(nextNodeIdx)) + peakHashes []*chainhash.Hash + ) + for i := 0; i < 2; i++ { + peakHashes = nil + v.leavesUsed = 0 + v.hashesUsed = 0 + + for _, peakNodeIdx := range peaks { + peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) + if peakHash == nil { + peakHash = v.nextHash(peakNodeIdx) + if peakHash == nil { + return false + } + } + peakHashes = append(peakHashes, peakHash) + if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { + if peakNodeIdx != peaks[len(peaks)-1] { + baggedPeak := v.nextHash(nextNodeIdx) + if baggedPeak == nil { + return false + } + peakHashes = append(peakHashes, baggedPeak) + } + break + } + } + if v.leavesUsed != len(v.mwebUtxos.Utxos) || + v.hashesUsed != len(v.mwebUtxos.ProofHashes) { + return false + } + } + + baggedPeak := peakHashes[len(peakHashes)-1] + for i := len(peakHashes) - 2; i >= 0; i-- { + baggedPeak = nextNodeIdx.parentHash(peakHashes[i][:], baggedPeak[:]) + } + return baggedPeak.IsEqual(&mwebHeader.OutputRoot) +} diff --git a/mweb.go b/mwebutxos.go similarity index 51% rename from mweb.go rename to mwebutxos.go index 7cf5fd804..361233f61 100644 --- a/mweb.go +++ b/mwebutxos.go @@ -1,333 +1,27 @@ package neutrino import ( - "bytes" - "encoding/binary" "fmt" - "math/bits" "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/bloom" - "github.com/ltcsuite/ltcd/txscript" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/neutrino/banman" + "github.com/ltcsuite/neutrino/mweb" "github.com/ltcsuite/neutrino/query" - "lukechampine.com/blake3" ) -func verifyMwebHeader(mwebHeader *wire.MsgMwebHeader, lastHash chainhash.Hash) bool { - if mwebHeader == nil { - return false - } - - if mwebHeader.Merkle.Header.BlockHash() != lastHash { - log.Infof("Block hash mismatch, merkle header hash=%v, block hash=%v", - mwebHeader.Merkle.Header.BlockHash(), lastHash) - return false - } - - extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) - if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { - log.Info("mwebheader merkle block is bad") - return false - } - - if !mwebHeader.Hogex.IsHogEx { - log.Info("mwebheader hogex is not hogex") - return false - } - - // Validate that the hash of the HogEx transaction in the tx message - // matches the hash in the merkleblock message, and that it’s the last - // transaction committed to by the merkle root of the block. - finalTx := extractResult.Match[len(extractResult.Match)-1] - if mwebHeader.Hogex.TxHash() != *finalTx { - log.Infof("Tx hash mismatch, hogex=%v, last merkle tx=%v", - mwebHeader.Hogex.TxHash(), *finalTx) - return false - } - finalTxPos := extractResult.Index[len(extractResult.Index)-1] - if finalTxPos != mwebHeader.Merkle.Transactions-1 { - log.Infof("Tx index mismatch, got=%v, expected=%v", - finalTxPos, mwebHeader.Merkle.Transactions-1) - return false - } - - // Validate that the pubkey script of the first output contains the HogAddr, - // which shall consist of <0x20> followed by the 32-byte hash of the - // MWEB header. - mwebHeaderHash := mwebHeader.MwebHeader.Hash() - script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) - if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { - log.Infof("HogAddr mismatch, hogex=%v, expected=%v", - mwebHeader.Hogex.TxOut[0].PkScript, script) - return false - } - - return true -} - -func verifyMwebLeafset(mwebHeader *wire.MsgMwebHeader, - mwebLeafset *wire.MsgMwebLeafset) bool { - - if mwebLeafset == nil { - return false - } - - // Verify that the hash of the leafset bitmap matches the - // leafset_root value in the MWEB header. - leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) - if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { - log.Infof("Leafset root mismatch, leafset=%v, in header=%v", - leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) - return false - } - - return true -} - -type ( - leafset []byte - leafIdx uint64 - nodeIdx uint64 -) - -func (l leafset) contains(i leafIdx) bool { - if int(i/8) >= len(l) { - return false - } - return l[i/8]&(0x80>>(i%8)) > 0 -} - -func (l leafset) nextUnspent(i leafIdx) leafIdx { - for { - i++ - if l.contains(i) || int(i/8) >= len(l) { - return i - } - } -} - -func (i leafIdx) nodeIdx() nodeIdx { - return nodeIdx(2*i) - nodeIdx(bits.OnesCount64(uint64(i))) -} - -func (i nodeIdx) height() uint64 { - height := uint64(i) - h := 64 - bits.LeadingZeros64(uint64(i)) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if height >= peakSize { - height -= peakSize - } - } - return height -} - -func (i nodeIdx) leafIdx() leafIdx { - leafIndex := uint64(0) - numLeft := uint64(i) - h := 64 - bits.LeadingZeros64(uint64(i)) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if numLeft >= peakSize { - leafIndex += (peakSize + 1) / 2 - numLeft -= peakSize - } - } - return leafIdx(leafIndex) -} - -func (i nodeIdx) left(height uint64) nodeIdx { - return i - (1 << height) -} - -func (i nodeIdx) right() nodeIdx { - return i - 1 -} - -func (i nodeIdx) hash(data []byte) *chainhash.Hash { - h := blake3.New(32, nil) - binary.Write(h, binary.LittleEndian, uint64(i)) - wire.WriteVarBytes(h, 0, data) - return (*chainhash.Hash)(h.Sum(nil)) -} - -func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { - h := blake3.New(32, nil) - binary.Write(h, binary.LittleEndian, uint64(i)) - h.Write(left) - h.Write(right) - return (*chainhash.Hash)(h.Sum(nil)) -} - -func calcPeaks(nodes uint64) (peaks []nodeIdx) { - sumPrevPeaks := uint64(0) - h := 64 - bits.LeadingZeros64(nodes) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if nodes >= peakSize { - peaks = append(peaks, nodeIdx(sumPrevPeaks+peakSize-1)) - sumPrevPeaks += peakSize - nodes -= peakSize - } - } - return -} - -type verifyMwebUtxosVars struct { - mwebUtxos *wire.MsgMwebUtxos - leafset leafset - firstLeafIdx, lastLeafIdx leafIdx - leavesUsed, hashesUsed int - isProofHash map[nodeIdx]bool -} - -func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Hash) { - if v.leavesUsed == len(v.mwebUtxos.Utxos) { - return - } - utxo := v.mwebUtxos.Utxos[v.leavesUsed] - leafIndex = leafIdx(utxo.LeafIndex) - hash = utxo.OutputId - v.leavesUsed++ - return -} - -func (v *verifyMwebUtxosVars) nextHash(nodeIdx nodeIdx) (hash *chainhash.Hash) { - if v.hashesUsed == len(v.mwebUtxos.ProofHashes) { - return - } - hash = v.mwebUtxos.ProofHashes[v.hashesUsed] - v.hashesUsed++ - v.isProofHash[nodeIdx] = true - return -} - -func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chainhash.Hash { - if nodeIdx < v.firstLeafIdx.nodeIdx() || v.isProofHash[nodeIdx] { - return v.nextHash(nodeIdx) - } - if height == 0 { - leafIdx := nodeIdx.leafIdx() - if !v.leafset.contains(leafIdx) { - return nil - } - leafIdx2, outputId := v.nextLeaf() - if leafIdx != leafIdx2 || outputId == nil { - return nil - } - return nodeIdx.hash(outputId[:]) - } - left := v.calcNodeHash(nodeIdx.left(height), height-1) - var right *chainhash.Hash - if v.lastLeafIdx.nodeIdx() <= nodeIdx.left(height) { - right = v.nextHash(nodeIdx.right()) - } else { - right = v.calcNodeHash(nodeIdx.right(), height-1) - } - switch { - case left == nil && right == nil: - return nil - case left == nil: - if left = v.nextHash(nodeIdx.left(height)); left == nil { - return nil - } - case right == nil: - if right = v.nextHash(nodeIdx.right()); right == nil { - return nil - } - } - return nodeIdx.parentHash(left[:], right[:]) -} - -func verifyMwebUtxos(mwebHeader *wire.MwebHeader, - mwebLeafset leafset, mwebUtxos *wire.MsgMwebUtxos) bool { - - if mwebUtxos.StartIndex == 0 && - len(mwebUtxos.Utxos) == 0 && - len(mwebUtxos.ProofHashes) == 0 && - mwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && - mwebHeader.OutputMMRSize == 0 { - return true - } else if len(mwebUtxos.Utxos) == 0 || - mwebHeader.OutputMMRSize == 0 { - return false - } - - v := &verifyMwebUtxosVars{ - mwebUtxos: mwebUtxos, - leafset: mwebLeafset, - firstLeafIdx: leafIdx(mwebUtxos.StartIndex), - lastLeafIdx: leafIdx(mwebUtxos.StartIndex), - isProofHash: make(map[nodeIdx]bool), - } - - for i := 0; ; i++ { - if !v.leafset.contains(v.lastLeafIdx) { - return false - } - if leafIdx(mwebUtxos.Utxos[i].LeafIndex) != v.lastLeafIdx { - return false - } - if i == len(mwebUtxos.Utxos)-1 { - break - } - v.lastLeafIdx = v.leafset.nextUnspent(v.lastLeafIdx) - } - - var ( - nextNodeIdx = leafIdx(mwebHeader.OutputMMRSize).nodeIdx() - peaks = calcPeaks(uint64(nextNodeIdx)) - peakHashes []*chainhash.Hash - ) - for i := 0; i < 2; i++ { - peakHashes = nil - v.leavesUsed = 0 - v.hashesUsed = 0 - - for _, peakNodeIdx := range peaks { - peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) - if peakHash == nil { - peakHash = v.nextHash(peakNodeIdx) - if peakHash == nil { - return false - } - } - peakHashes = append(peakHashes, peakHash) - if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { - if peakNodeIdx != peaks[len(peaks)-1] { - baggedPeak := v.nextHash(nextNodeIdx) - if baggedPeak == nil { - return false - } - peakHashes = append(peakHashes, baggedPeak) - } - break - } - } - if v.leavesUsed != len(v.mwebUtxos.Utxos) || - v.hashesUsed != len(v.mwebUtxos.ProofHashes) { - return false - } - } - - baggedPeak := peakHashes[len(peakHashes)-1] - for i := len(peakHashes) - 2; i >= 0; i-- { - baggedPeak = nextNodeIdx.parentHash(peakHashes[i][:], baggedPeak[:]) - } - return baggedPeak.IsEqual(&mwebHeader.OutputRoot) -} - // mwebUtxosQuery holds all information necessary to perform and // handle a query for mweb utxos. type mwebUtxosQuery struct { blockMgr *blockManager mwebHeader *wire.MwebHeader - leafset leafset + leafset mweb.Leafset msgs []wire.Message utxosChan chan *wire.MsgMwebUtxos } func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - newLeafset leafset, lastHeight uint32, lastHash *chainhash.Hash) { + newLeafset mweb.Leafset, lastHeight uint32, lastHash *chainhash.Hash) { log.Infof("Fetching set of mweb utxos from "+ "height=%v, hash=%v", lastHeight, *lastHash) @@ -337,7 +31,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, if err != nil { panic(fmt.Sprintf("couldn't read mweb coins db: %v", err)) } - oldLeafset := leafset(dbLeafset) + oldLeafset := mweb.Leafset(dbLeafset) // Skip over common prefix var index uint64 @@ -361,12 +55,12 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, } } for index *= 8; index < oldNumLeaves || index < newNumLeaves; index++ { - if oldLeafset.contains(leafIdx(index)) { + if oldLeafset.Contains(index) { addLeafSpan() - if !newLeafset.contains(leafIdx(index)) { + if !newLeafset.Contains(index) { removedLeaves = append(removedLeaves, index) } - } else if newLeafset.contains(leafIdx(index)) { + } else if newLeafset.Contains(index) { if addLeaf.count == 0 { addLeaf.start = index } @@ -514,7 +208,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) } -func (b *blockManager) purgeSpentMwebTxos(newLeafset leafset, +func (b *blockManager) purgeSpentMwebTxos(newLeafset mweb.Leafset, newNumLeaves uint64, removedLeaves []uint64) { if len(removedLeaves) > 0 { @@ -579,7 +273,7 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, } } - if !verifyMwebUtxos(m.mwebHeader, m.leafset, r) { + if !mweb.VerifyUtxos(m.mwebHeader, m.leafset, r) { log.Warnf("Failed to verify mweb utxos at index %v!!!", r.StartIndex) @@ -627,8 +321,8 @@ func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { if err != nil { return err } - oldLeafset := leafset(leafSet) - newLeafset := leafset(dbLeafset) + oldLeafset := mweb.Leafset(leafSet) + newLeafset := mweb.Leafset(dbLeafset) // Skip over common prefix var index uint64 @@ -640,8 +334,8 @@ func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { var addedLeaves []uint64 for index *= 8; index < newNumLeaves; index++ { - if !oldLeafset.contains(leafIdx(index)) && - newLeafset.contains(leafIdx(index)) { + if !oldLeafset.Contains(index) && + newLeafset.Contains(index) { addedLeaves = append(addedLeaves, index) } } diff --git a/neutrino.go b/neutrino.go index cec24ebca..f85b125f4 100644 --- a/neutrino.go +++ b/neutrino.go @@ -28,7 +28,7 @@ import ( "github.com/ltcsuite/neutrino/chanutils" "github.com/ltcsuite/neutrino/filterdb" "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/mwebdb" + "github.com/ltcsuite/neutrino/mweb" "github.com/ltcsuite/neutrino/pushtx" "github.com/ltcsuite/neutrino/query" ) @@ -658,7 +658,7 @@ type ChainService struct { // nolint:maligned FilterDB filterdb.FilterDatabase BlockHeaders headerfs.BlockHeaderStore RegFilterHeaders *headerfs.FilterHeaderStore - MwebCoinDB mwebdb.CoinDatabase + MwebCoinDB mweb.CoinDatabase persistToDisk bool FilterCache *lru.Cache[FilterCacheKey, *CacheableFilter] @@ -825,7 +825,7 @@ func NewChainService(cfg Config) (*ChainService, error) { return nil, err } - s.MwebCoinDB, err = mwebdb.New(cfg.Database) + s.MwebCoinDB, err = mweb.NewCoinStore(cfg.Database) if err != nil { return nil, err } @@ -1209,7 +1209,7 @@ func (s *ChainService) NotifyAddedMwebUtxos(leafset []byte) error { // MwebUtxoExists checks if a mweb utxo with the given output ID exists in the db. func (s *ChainService) MwebUtxoExists(outputId *chainhash.Hash) bool { if _, err := s.MwebCoinDB.FetchCoin(outputId); err != nil { - if err == mwebdb.ErrCoinNotFound { + if err == mweb.ErrCoinNotFound { return false } panic(err) From 4a76f15601fdce6b86db028d7eb0673c0f592973 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 23 Feb 2024 01:34:26 +0000 Subject: [PATCH 41/75] Fetch mweb headers --- banman/reason.go | 9 +- blockmanager.go | 12 ++- go.mod | 2 + mweb/header.go | 10 +- mwebheaders.go | 261 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 282 insertions(+), 12 deletions(-) create mode 100644 mwebheaders.go diff --git a/banman/reason.go b/banman/reason.go index ba2fec015..73fb25186 100644 --- a/banman/reason.go +++ b/banman/reason.go @@ -24,9 +24,13 @@ const ( // InvalidBlock signals that a peer served us a bad block. InvalidBlock Reason = 5 + // InvalidMwebHeader signals that a peer served us an invalid + // mweb header message. + InvalidMwebHeader Reason = 20 + // InvalidMwebUtxos signals that a peer served us an invalid // mweb utxos message. - InvalidMwebUtxos Reason = 20 + InvalidMwebUtxos Reason = 21 ) // String returns a human-readable description for the reason a peer was banned. @@ -47,6 +51,9 @@ func (r Reason) String() string { case InvalidBlock: return "peer served an invalid block" + case InvalidMwebHeader: + return "peer served invalid mweb header message" + case InvalidMwebUtxos: return "peer served invalid mweb utxos message" diff --git a/blockmanager.go b/blockmanager.go index 308463c39..dc779d877 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -507,6 +507,12 @@ func (b *blockManager) mwebHandler() { log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", lastHeight, lastHash) + // Get a representative set of mweb headers up to this height. + if err := b.getMwebHeaders(lastHeight); err != nil { + log.Error(err) + continue + } + gdmsg := wire.NewMsgGetData() gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &lastHash)) gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebLeafset, &lastHash)) @@ -523,7 +529,10 @@ func (b *blockManager) mwebHandler() { switch m := resp.(type) { case *wire.MsgMwebHeader: - if err := mweb.VerifyHeader(m, lastHash); err != nil { + if m.Merkle.Header.BlockHash() != lastHash { + return + } + if err := mweb.VerifyHeader(m); err != nil { log.Infof("failed to verify mwebheader: %v", err) return } @@ -533,7 +542,6 @@ func (b *blockManager) mwebHandler() { mwebLeafset = m default: - log.Infof("unexpected message %v", resp) return } diff --git a/go.mod b/go.mod index 19d007c66..4fc9fcd86 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,8 @@ replace github.com/ltcsuite/ltcd => ../ltcd replace github.com/ltcsuite/ltcd/btcec/v2 => ../ltcd/btcec +replace github.com/ltcsuite/ltcd/chaincfg => ../ltcd/chaincfg + replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhash replace github.com/ltcsuite/ltcd/ltcutil => ../ltcd/ltcutil diff --git a/mweb/header.go b/mweb/header.go index 6fd3f3570..a7d59eb60 100644 --- a/mweb/header.go +++ b/mweb/header.go @@ -12,15 +12,7 @@ import ( "lukechampine.com/blake3" ) -func VerifyHeader(mwebHeader *wire.MsgMwebHeader, - blockHash chainhash.Hash) error { - - if mwebHeader.Merkle.Header.BlockHash() != blockHash { - return fmt.Errorf("block hash mismatch, "+ - "merkle header hash=%v, block hash=%v", - mwebHeader.Merkle.Header.BlockHash(), blockHash) - } - +func VerifyHeader(mwebHeader *wire.MsgMwebHeader) error { extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { return errors.New("mwebheader merkle block is bad") diff --git a/mwebheaders.go b/mwebheaders.go new file mode 100644 index 000000000..5e594c92c --- /dev/null +++ b/mwebheaders.go @@ -0,0 +1,261 @@ +package neutrino + +import ( + "slices" + + "github.com/ltcsuite/ltcd/wire" + "github.com/ltcsuite/neutrino/banman" + "github.com/ltcsuite/neutrino/mweb" + "github.com/ltcsuite/neutrino/query" +) + +// mwebHeadersQuery holds all information necessary to perform and +// handle a query for mweb headers. +type mwebHeadersQuery struct { + blockMgr *blockManager + msgs []wire.Message + headersChan chan *wire.MsgMwebHeader +} + +func (b *blockManager) getMwebHeaders(lastHeight uint32) error { + var height uint32 + switch b.cfg.ChainParams.Net { + case wire.MainNet: + height = 2265984 + case wire.TestNet4: + height = 2215584 + case wire.TestNet: + height = 432 + } + + fetch := func(height, stride uint32) error { + for height < lastHeight { + toHeight := height + 1000*stride + if toHeight > lastHeight { + toHeight = lastHeight + } + err := b.getMwebHeaderBatch(height, toHeight, stride) + if err != nil { + return err + } + height = toHeight + } + return nil + } + + if err := fetch(height, 100); err != nil { + return err + } + if err := fetch(lastHeight-4000, 1); err != nil { + return err + } + + return nil +} + +func (b *blockManager) getMwebHeaderBatch( + fromHeight, toHeight, stride uint32) error { + + log.Infof("Fetching mweb headers from height %v to %v", + fromHeight, toHeight) + + var queryMsgs []wire.Message + var heights []uint32 + for height := fromHeight; height < toHeight; height += stride { + header, err := b.cfg.BlockHeaders.FetchHeaderByHeight(height) + if err != nil { + return err + } + hash := header.BlockHash() + + var gdmsg *wire.MsgGetData + if len(queryMsgs) > 0 { + gdmsg = queryMsgs[len(queryMsgs)-1].(*wire.MsgGetData) + if len(gdmsg.InvList) == 100 { + gdmsg = nil + } + } + if gdmsg == nil { + gdmsg = wire.NewMsgGetData() + queryMsgs = append(queryMsgs, gdmsg) + } + gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &hash)) + heights = append(heights, height) + } + + // We'll also create an additional map that we'll use to + // re-order the responses as we get them in. + queryResponses := make(map[uint32]*wire.MsgMwebHeader, len(heights)) + + batchesCount := len(queryMsgs) + if batchesCount == 0 { + return nil + } + + log.Infof("Starting to query for mweb headers from height=%v", heights[0]) + + // With the set of messages constructed, we'll now request the batch + // all at once. This message will distribute the mwebheader requests + // amongst all active peers, effectively sharding each query + // dynamically. + headersChan := make(chan *wire.MsgMwebHeader, len(heights)) + q := mwebHeadersQuery{ + blockMgr: b, + msgs: queryMsgs, + headersChan: headersChan, + } + + // Hand the queries to the work manager, and consume the verified + // responses as they come back. + errChan := b.cfg.QueryDispatcher.Query( + q.requests(), query.Cancel(b.quit), + ) + + // Keep waiting for more mweb headers as long as we haven't received an + // answer for our last getdata message, and no error is encountered. + for i := 0; i < len(heights); { + var r *wire.MsgMwebHeader + select { + case r = <-headersChan: + case err := <-errChan: + switch { + case err == query.ErrWorkManagerShuttingDown: + return nil + case err != nil: + log.Errorf("Query finished with error before "+ + "all responses received: %v", err) + return err + } + + // The query did finish successfully, but continue to + // allow picking up the last mwebheader sent on the + // headersChan. + continue + + case <-b.quit: + return nil + } + + height := uint32(r.MwebHeader.Height) + blockHash := r.Merkle.Header.BlockHash() + + log.Debugf("Got mwebheader at height=%v, block hash=%v", + height, blockHash) + + // If this is out of order but not yet written, we can + // store them for later. + if height > heights[i] { + log.Debugf("Got response for mwebheader at "+ + "height=%v, only at height=%v, stashing", + height, heights[i]) + } + + // If this is out of order stuff that's already been + // written, we can ignore it. + if height < heights[i] { + log.Debugf("Received out of order reply "+ + "height=%v, already written", height) + continue + } + + // Add the verified response to our cache. + queryResponses[height] = r + + // Then, we cycle through any cached messages, adding + // them to the batch and deleting them from the cache. + for i < len(heights) { + // If we don't yet have the next response, then + // we'll break out so we can wait for the peers + // to respond with this message. + r, ok := queryResponses[heights[i]] + if !ok { + break + } + + // We have another response to write, so delete + // it from the cache and write it. + delete(queryResponses, heights[i]) + + log.Debugf("Writing mwebheader at height=%v", heights[i]) + + log.Infof("Height = %v, OutputMMRSize = %v", heights[i], r.MwebHeader.OutputMMRSize) + + // Update the next index to write. + i++ + } + } + + return nil +} + +// requests creates the query.Requests for this mwebheader query. +func (m *mwebHeadersQuery) requests() []*query.Request { + reqs := make([]*query.Request, len(m.msgs)) + for idx, msg := range m.msgs { + reqs[idx] = &query.Request{ + Req: msg, + HandleResp: m.handleResponse, + } + } + return reqs +} + +// handleResponse is the internal response handler used for requests +// for this mwebheader query. +func (m *mwebHeadersQuery) handleResponse(req, resp wire.Message, + peerAddr string) query.Progress { + + r, ok := resp.(*wire.MsgMwebHeader) + if !ok { + // We are only looking for mwebheader messages. + return query.Progress{} + } + + q, ok := req.(*wire.MsgGetData) + if !ok { + // We sent a getdata message, so that's what we should be + // comparing against. + return query.Progress{} + } + + // The response doesn't match the query. + blockHash := r.Merkle.Header.BlockHash() + matchBlockHash := func(iv *wire.InvVect) bool { + return iv.Hash.IsEqual(&blockHash) + } + if !slices.ContainsFunc(q.InvList, matchBlockHash) { + return query.Progress{} + } + + if err := mweb.VerifyHeader(r); err != nil { + log.Warnf("Failed to verify mwebheader at block hash %v!!!", + blockHash) + + // If the peer gives us a bad mwebheader message, + // then we'll ban the peer so we can re-allocate + // the query elsewhere. + err := m.blockMgr.cfg.BanPeer( + peerAddr, banman.InvalidMwebHeader, + ) + if err != nil { + log.Errorf("Unable to ban peer %v: %v", peerAddr, err) + } + + return query.Progress{} + } + + // At this point, the response matches the query, + // so we'll deliver the verified header on the headersChan. + select { + case m.headersChan <- r: + case <-m.blockMgr.quit: + return query.Progress{} + } + + q.InvList = slices.DeleteFunc(q.InvList, matchBlockHash) + + return query.Progress{ + Finished: len(q.InvList) == 0, + Progressed: true, + } +} From 1be256b63edb72e144c8971e84d6c9a4604889a5 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 23 Feb 2024 04:01:43 +0000 Subject: [PATCH 42/75] Store height to leaf count mapping in db --- mweb/coindb.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++ mwebheaders.go | 64 +++++++++++++------------------------------------- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/mweb/coindb.go b/mweb/coindb.go index 35d8a7458..8b4b197b2 100644 --- a/mweb/coindb.go +++ b/mweb/coindb.go @@ -16,6 +16,10 @@ var ( // actual coins. rootBucket = []byte("mweb-coindb") + // heightBucket is the bucket that stores the mapping between + // block heights and number of leaves. + heightBucket = []byte("heights") + // coinBucket is the bucket that stores the coins. coinBucket = []byte("coins") @@ -40,6 +44,12 @@ var ( // CoinDatabase is an interface which represents an object that is capable of // storing and retrieving coins according to their corresponding output ID. type CoinDatabase interface { + // Get the block height to number of leaves mapping. + GetLeavesAtHeight() (map[uint32]uint64, error) + + // Set the block height to number of leaves mapping. + PutLeavesAtHeight(map[uint32]uint64) error + // Get the leafset marking the unspent indices. GetLeafSet() (leafset []byte, numLeaves uint64, err error) @@ -88,6 +98,10 @@ func NewCoinStore(db walletdb.DB) (*CoinStore, error) { // If the main bucket doesn't already exist, then we'll need to // create the sub-buckets. + _, err = rootBucket.CreateBucketIfNotExists(heightBucket) + if err != nil { + return err + } _, err = rootBucket.CreateBucketIfNotExists(coinBucket) if err != nil { return err @@ -102,6 +116,45 @@ func NewCoinStore(db walletdb.DB) (*CoinStore, error) { return &CoinStore{db: db}, nil } +// Get the block height to number of leaves mapping. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) GetLeavesAtHeight() (map[uint32]uint64, error) { + m := make(map[uint32]uint64) + err := walletdb.View(c.db, func(tx walletdb.ReadTx) error { + rootBucket := tx.ReadBucket(rootBucket) + heightBucket := rootBucket.NestedReadBucket(heightBucket) + + return heightBucket.ForEach(func(k, v []byte) error { + height := binary.LittleEndian.Uint32(k) + m[height] = binary.LittleEndian.Uint64(v) + return nil + }) + }) + return m, err +} + +// Set the block height to number of leaves mapping. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PutLeavesAtHeight(m map[uint32]uint64) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + heightBucket := rootBucket.NestedReadWriteBucket(heightBucket) + + for height, numLeaves := range m { + err := heightBucket.Put( + binary.LittleEndian.AppendUint32(nil, height), + binary.LittleEndian.AppendUint64(nil, numLeaves), + ) + if err != nil { + return err + } + } + return nil + }) +} + // Get the leafset marking the unspent indices. // // NOTE: This method is a part of the CoinDatabase interface. @@ -291,6 +344,9 @@ func (c *CoinStore) PurgeCoins() error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) + if err := rootBucket.DeleteNestedBucket(heightBucket); err != nil { + return err + } if err := rootBucket.DeleteNestedBucket(coinBucket); err != nil { return err } @@ -298,6 +354,9 @@ func (c *CoinStore) PurgeCoins() error { return err } + if _, err := rootBucket.CreateBucket(heightBucket); err != nil { + return err + } if _, err := rootBucket.CreateBucket(coinBucket); err != nil { return err } diff --git a/mwebheaders.go b/mwebheaders.go index 5e594c92c..3ff76ebdd 100644 --- a/mwebheaders.go +++ b/mwebheaders.go @@ -28,13 +28,18 @@ func (b *blockManager) getMwebHeaders(lastHeight uint32) error { height = 432 } + heightMap, err := b.cfg.MwebCoins.GetLeavesAtHeight() + if err != nil { + return err + } + fetch := func(height, stride uint32) error { for height < lastHeight { toHeight := height + 1000*stride if toHeight > lastHeight { toHeight = lastHeight } - err := b.getMwebHeaderBatch(height, toHeight, stride) + err := b.getMwebHeaderBatch(height, toHeight, stride, heightMap) if err != nil { return err } @@ -53,15 +58,18 @@ func (b *blockManager) getMwebHeaders(lastHeight uint32) error { return nil } -func (b *blockManager) getMwebHeaderBatch( - fromHeight, toHeight, stride uint32) error { +func (b *blockManager) getMwebHeaderBatch(fromHeight, toHeight, + stride uint32, heightMap map[uint32]uint64) error { - log.Infof("Fetching mweb headers from height %v to %v", + log.Debugf("Fetching mweb headers from height %v to %v", fromHeight, toHeight) var queryMsgs []wire.Message var heights []uint32 for height := fromHeight; height < toHeight; height += stride { + if _, ok := heightMap[height]; ok { + continue + } header, err := b.cfg.BlockHeaders.FetchHeaderByHeight(height) if err != nil { return err @@ -85,7 +93,7 @@ func (b *blockManager) getMwebHeaderBatch( // We'll also create an additional map that we'll use to // re-order the responses as we get them in. - queryResponses := make(map[uint32]*wire.MsgMwebHeader, len(heights)) + queryResponses := make(map[uint32]uint64, len(heights)) batchesCount := len(queryMsgs) if batchesCount == 0 { @@ -113,7 +121,7 @@ func (b *blockManager) getMwebHeaderBatch( // Keep waiting for more mweb headers as long as we haven't received an // answer for our last getdata message, and no error is encountered. - for i := 0; i < len(heights); { + for len(queryResponses) < len(heights) { var r *wire.MsgMwebHeader select { case r = <-headersChan: @@ -142,50 +150,10 @@ func (b *blockManager) getMwebHeaderBatch( log.Debugf("Got mwebheader at height=%v, block hash=%v", height, blockHash) - // If this is out of order but not yet written, we can - // store them for later. - if height > heights[i] { - log.Debugf("Got response for mwebheader at "+ - "height=%v, only at height=%v, stashing", - height, heights[i]) - } - - // If this is out of order stuff that's already been - // written, we can ignore it. - if height < heights[i] { - log.Debugf("Received out of order reply "+ - "height=%v, already written", height) - continue - } - - // Add the verified response to our cache. - queryResponses[height] = r - - // Then, we cycle through any cached messages, adding - // them to the batch and deleting them from the cache. - for i < len(heights) { - // If we don't yet have the next response, then - // we'll break out so we can wait for the peers - // to respond with this message. - r, ok := queryResponses[heights[i]] - if !ok { - break - } - - // We have another response to write, so delete - // it from the cache and write it. - delete(queryResponses, heights[i]) - - log.Debugf("Writing mwebheader at height=%v", heights[i]) - - log.Infof("Height = %v, OutputMMRSize = %v", heights[i], r.MwebHeader.OutputMMRSize) - - // Update the next index to write. - i++ - } + queryResponses[height] = r.MwebHeader.OutputMMRSize } - return nil + return b.cfg.MwebCoins.PutLeavesAtHeight(queryResponses) } // requests creates the query.Requests for this mwebheader query. From 0eb808ac11f5e44a9c876f079f645b25df60ff77 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 23 Feb 2024 11:59:15 +0000 Subject: [PATCH 43/75] Calculate utxo heights from headers --- blockmanager.go | 16 +++++++++++++--- mwebheaders.go | 4 ++-- mwebutxos.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index dc779d877..b683bb51c 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -509,6 +509,9 @@ func (b *blockManager) mwebHandler() { // Get a representative set of mweb headers up to this height. if err := b.getMwebHeaders(lastHeight); err != nil { + if err == ErrShuttingDown { + return + } log.Error(err) continue } @@ -557,9 +560,6 @@ func (b *blockManager) mwebHandler() { verified = true - log.Infof("Verified mwebheader and mwebleafset at "+ - "(block_height=%v, block_hash=%v)", lastHeight, lastHash) - close(quit) close(peerQuit) }, @@ -573,6 +573,16 @@ func (b *blockManager) mwebHandler() { } } + log.Infof("Verified mwebheader and mwebleafset at "+ + "(block_height=%v, block_hash=%v)", lastHeight, lastHash) + + // Store the leaf count at this height. + err = b.cfg.MwebCoins.PutLeavesAtHeight(map[uint32]uint64{ + lastHeight: mwebHeader.MwebHeader.OutputMMRSize}) + if err != nil { + log.Errorf("failed to write mwebheader to db: %v", err) + } + // Get all the mweb utxos at this height. b.getMwebUtxos(&mwebHeader.MwebHeader, mwebLeafset.Leafset, lastHeight, &lastHash) diff --git a/mwebheaders.go b/mwebheaders.go index 3ff76ebdd..adab9d424 100644 --- a/mwebheaders.go +++ b/mwebheaders.go @@ -128,7 +128,7 @@ func (b *blockManager) getMwebHeaderBatch(fromHeight, toHeight, case err := <-errChan: switch { case err == query.ErrWorkManagerShuttingDown: - return nil + return ErrShuttingDown case err != nil: log.Errorf("Query finished with error before "+ "all responses received: %v", err) @@ -141,7 +141,7 @@ func (b *blockManager) getMwebHeaderBatch(fromHeight, toHeight, continue case <-b.quit: - return nil + return ErrShuttingDown } height := uint32(r.MwebHeader.Height) diff --git a/mwebutxos.go b/mwebutxos.go index 361233f61..9aca62246 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -1,7 +1,9 @@ package neutrino import ( + "cmp" "fmt" + "slices" "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/wire" @@ -114,6 +116,19 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, q.requests(), query.Cancel(b.quit), ) + // Load the block height to leaf count mapping so that we can + // work out roughly when a utxo was included in a block. + heightMap, err := b.cfg.MwebCoins.GetLeavesAtHeight() + if err != nil { + log.Errorf("could not get leaves at height from db: %v", err) + return + } + heights := make([]uint32, 0, len(heightMap)) + for height := range heightMap { + heights = append(heights, height) + } + slices.Sort(heights) + // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 @@ -187,6 +202,19 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Debugf("Writing mwebutxos at index=%v", curIndex) + // Calculate rough heights for each utxo. + for _, utxo := range r.Utxos { + index, _ := slices.BinarySearchFunc(heights, utxo.LeafIndex, + func(height uint32, leafIndex uint64) int { + return cmp.Compare(heightMap[height]-1, leafIndex) + }) + if index < len(heights) { + utxo.Height = int32(heights[index]) + } else { + utxo.Height = int32(lastHeight) + } + } + err := b.cfg.MwebCoins.PutCoins(r.Utxos) if err != nil { panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) From 2034e8a875937de5606886f99ede45c74acbdade Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 23 Feb 2024 17:37:30 +0000 Subject: [PATCH 44/75] Fix query timing out for large batches --- blockmanager.go | 5 +- mwebutxos.go | 241 ++++++++++++++++++++---------------------------- 2 files changed, 103 insertions(+), 143 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index b683bb51c..9375458b8 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -584,8 +584,11 @@ func (b *blockManager) mwebHandler() { } // Get all the mweb utxos at this height. - b.getMwebUtxos(&mwebHeader.MwebHeader, + err = b.getMwebUtxos(&mwebHeader.MwebHeader, mwebLeafset.Leafset, lastHeight, &lastHash) + if err != nil { + continue + } // Now we check the headers again. If the block headers are not yet // current, then we go back to the loop waiting for them to finish. diff --git a/mwebutxos.go b/mwebutxos.go index 9aca62246..e9abea1ca 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -2,7 +2,6 @@ package neutrino import ( "cmp" - "fmt" "slices" "github.com/ltcsuite/ltcd/chaincfg/chainhash" @@ -18,12 +17,14 @@ type mwebUtxosQuery struct { blockMgr *blockManager mwebHeader *wire.MwebHeader leafset mweb.Leafset - msgs []wire.Message + lastHeight uint32 + msgs []*wire.MsgGetMwebUtxos utxosChan chan *wire.MsgMwebUtxos } func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - newLeafset mweb.Leafset, lastHeight uint32, lastHash *chainhash.Hash) { + newLeafset mweb.Leafset, lastHeight uint32, + lastHash *chainhash.Hash) error { log.Infof("Fetching set of mweb utxos from "+ "height=%v, hash=%v", lastHeight, *lastHash) @@ -31,7 +32,8 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, newNumLeaves := mwebHeader.OutputMMRSize dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() if err != nil { - panic(fmt.Sprintf("couldn't read mweb coins db: %v", err)) + log.Errorf("Couldn't read mweb coins db: %v", err) + return err } oldLeafset := mweb.Leafset(dbLeafset) @@ -74,54 +76,64 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, } addLeafSpan() - var queryMsgs []wire.Message - for _, addLeaf := range addedLeaves { - queryMsgs = append(queryMsgs, - wire.NewMsgGetMwebUtxos(*lastHash, addLeaf.start, - addLeaf.count, wire.MwebNetUtxoCompact)) - } - - // We'll also create an additional map that we'll use to - // re-order the responses as we get them in. - queryResponses := make(map[uint64]*wire.MsgMwebUtxos, len(queryMsgs)) - b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() - batchesCount := len(queryMsgs) + batchesCount := len(addedLeaves) if batchesCount == 0 { - b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) - return + return b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) } log.Infof("Starting to query for mweb utxos from index=%v", addedLeaves[0].start) log.Infof("Attempting to query for %v mwebutxos batches", batchesCount) - // With the set of messages constructed, we'll now request the batch - // all at once. This message will distribute the mwebutxos requests - // amongst all active peers, effectively sharding each query - // dynamically. - utxosChan := make(chan *wire.MsgMwebUtxos, len(queryMsgs)) - q := mwebUtxosQuery{ + // With the set of messages constructed, we'll now request the + // batch all at once. This message will distribute the mwebutxos + // requests amongst all active peers, effectively sharding each + // query dynamically. + q := &mwebUtxosQuery{ blockMgr: b, mwebHeader: mwebHeader, leafset: newLeafset, - msgs: queryMsgs, - utxosChan: utxosChan, + lastHeight: lastHeight, + utxosChan: make(chan *wire.MsgMwebUtxos), + } + + totalUtxos := 0 + for len(addedLeaves) > 0 { + for _, addLeaf := range addedLeaves { + q.msgs = append(q.msgs, wire.NewMsgGetMwebUtxos(*lastHash, + addLeaf.start, addLeaf.count, wire.MwebNetUtxoCompact)) + if len(q.msgs) == 10 { + break + } + } + addedLeaves = addedLeaves[len(q.msgs):] + + count, err := b.getMwebUtxosBatch(q) + if err != nil { + return err + } + totalUtxos += count } - // Hand the queries to the work manager, and consume the verified - // responses as they come back. + log.Infof("Successfully got %v mweb utxos", totalUtxos) + + return b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) +} + +func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { + // Hand the queries to the work manager, and consume the + // verified responses as they come back. errChan := b.cfg.QueryDispatcher.Query( - q.requests(), query.Cancel(b.quit), - ) + q.requests(), query.Cancel(b.quit)) // Load the block height to leaf count mapping so that we can // work out roughly when a utxo was included in a block. heightMap, err := b.cfg.MwebCoins.GetLeavesAtHeight() if err != nil { - log.Errorf("could not get leaves at height from db: %v", err) - return + log.Errorf("Couldn't get leaves at height from db: %v", err) + return 0, err } heights := make([]uint32, 0, len(heightMap)) for height := range heightMap { @@ -132,112 +144,75 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 - for i := 0; i < len(addedLeaves); { + for len(q.msgs) > 0 { var r *wire.MsgMwebUtxos select { - case r = <-utxosChan: + case r = <-q.utxosChan: case err := <-errChan: switch { case err == query.ErrWorkManagerShuttingDown: - return + return totalUtxos, ErrShuttingDown case err != nil: log.Errorf("Query finished with error before "+ "all responses received: %v", err) - return + return totalUtxos, err } - // The query did finish successfully, but continue to - // allow picking up the last mwebutxos sent on the - // utxosChan. + // The query did finish successfully, but continue to allow + // picking up the last mwebutxos sent on the utxosChan. continue case <-b.quit: - return + return totalUtxos, ErrShuttingDown } // Find the first and last indices for the mweb utxos // represented by this message. startIndex := r.Utxos[0].LeafIndex lastIndex := r.Utxos[len(r.Utxos)-1].LeafIndex - curIndex := addedLeaves[i].start - - log.Debugf("Got mwebutxos from index=%v to "+ - "index=%v, block hash=%v", startIndex, - lastIndex, r.BlockHash) - - // If this is out of order but not yet written, we can - // store them for later. - if startIndex > curIndex { - log.Debugf("Got response for mwebutxos at "+ - "index=%v, only at index=%v, stashing", - startIndex, curIndex) - } - // If this is out of order stuff that's already been - // written, we can ignore it. - if lastIndex < curIndex { - log.Debugf("Received out of order reply "+ - "lastIndex=%v, already written", lastIndex) + index, ok := slices.BinarySearchFunc(q.msgs, startIndex, + func(msg *wire.MsgGetMwebUtxos, target uint64) int { + return cmp.Compare(msg.StartIndex, target) + }) + if !ok { continue } - - // Add the verified response to our cache. - queryResponses[startIndex] = r - - // Then, we cycle through any cached messages, adding - // them to the batch and deleting them from the cache. - for i < len(addedLeaves) { - // If we don't yet have the next response, then - // we'll break out so we can wait for the peers - // to respond with this message. - curIndex = addedLeaves[i].start - r, ok := queryResponses[curIndex] - if !ok { - break - } - - // We have another response to write, so delete - // it from the cache and write it. - delete(queryResponses, curIndex) - - log.Debugf("Writing mwebutxos at index=%v", curIndex) - - // Calculate rough heights for each utxo. - for _, utxo := range r.Utxos { - index, _ := slices.BinarySearchFunc(heights, utxo.LeafIndex, - func(height uint32, leafIndex uint64) int { - return cmp.Compare(heightMap[height]-1, leafIndex) - }) - if index < len(heights) { - utxo.Height = int32(heights[index]) - } else { - utxo.Height = int32(lastHeight) - } - } - - err := b.cfg.MwebCoins.PutCoins(r.Utxos) - if err != nil { - panic(fmt.Sprintf("couldn't write mweb coins: %v", err)) - } - - for _, cb := range b.mwebUtxosCallbacks { - cb(nil, r.Utxos) + q.msgs = append(q.msgs[:index], q.msgs[index+1:]...) + + log.Debugf("Got mwebutxos from index=%v to index=%v, "+ + "block hash=%v", startIndex, lastIndex, r.BlockHash) + + // Calculate rough heights for each utxo. + for _, utxo := range r.Utxos { + index, _ := slices.BinarySearchFunc(heights, utxo.LeafIndex, + func(height uint32, target uint64) int { + return cmp.Compare(heightMap[height]-1, target) + }) + if index < len(heights) { + utxo.Height = int32(heights[index]) + } else { + utxo.Height = int32(q.lastHeight) } + } - totalUtxos += len(r.Utxos) + if err := b.cfg.MwebCoins.PutCoins(r.Utxos); err != nil { + log.Errorf("Couldn't write mweb coins: %v", err) + return totalUtxos, err + } - // Update the next index to write. - i++ + for _, cb := range b.mwebUtxosCallbacks { + cb(nil, r.Utxos) } - } - log.Infof("Successfully got %v mweb utxos", totalUtxos) + totalUtxos += len(r.Utxos) + } - b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) + return totalUtxos, nil } func (b *blockManager) purgeSpentMwebTxos(newLeafset mweb.Leafset, - newNumLeaves uint64, removedLeaves []uint64) { + newNumLeaves uint64, removedLeaves []uint64) error { if len(removedLeaves) > 0 { log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) @@ -246,12 +221,15 @@ func (b *blockManager) purgeSpentMwebTxos(newLeafset mweb.Leafset, err := b.cfg.MwebCoins.PutLeafSetAndPurge( newLeafset, newNumLeaves, removedLeaves) if err != nil { - panic(fmt.Sprintf("couldn't purge mweb txos: %v", err)) + log.Errorf("Couldn't purge mweb txos: %v", err) + return err } for _, cb := range b.mwebUtxosCallbacks { cb(newLeafset, nil) } + + return nil } // requests creates the query.Requests for this mwebutxos query. @@ -266,28 +244,22 @@ func (m *mwebUtxosQuery) requests() []*query.Request { return reqs } -// handleResponse is the internal response handler used for requests for this -// mwebutxos query. +// handleResponse is the internal response handler used for requests +// for this mwebutxos query. func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, peerAddr string) query.Progress { r, ok := resp.(*wire.MsgMwebUtxos) if !ok { // We are only looking for mwebutxos messages. - return query.Progress{ - Finished: false, - Progressed: false, - } + return query.Progress{} } q, ok := req.(*wire.MsgGetMwebUtxos) if !ok { - // We sent a getmwebutxos message, so that's what we should be - // comparing against. - return query.Progress{ - Finished: false, - Progressed: false, - } + // We sent a getmwebutxos message, so that's what + // we should be comparing against. + return query.Progress{} } // The response doesn't match the query. @@ -295,30 +267,21 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, q.StartIndex != r.StartIndex || q.OutputFormat != r.OutputFormat || q.NumRequested != uint16(len(r.Utxos)) { - return query.Progress{ - Finished: false, - Progressed: false, - } + return query.Progress{} } if !mweb.VerifyUtxos(m.mwebHeader, m.leafset, r) { log.Warnf("Failed to verify mweb utxos at index %v!!!", r.StartIndex) - // If the peer gives us a bad mwebutxos message, - // then we'll ban the peer so we can re-allocate - // the query elsewhere. - err := m.blockMgr.cfg.BanPeer( - peerAddr, banman.InvalidMwebUtxos, - ) + // If the peer gives us a bad mwebutxos message, then we'll + // ban the peer so we can reallocate the query elsewhere. + err := m.blockMgr.cfg.BanPeer(peerAddr, banman.InvalidMwebUtxos) if err != nil { log.Errorf("Unable to ban peer %v: %v", peerAddr, err) } - return query.Progress{ - Finished: false, - Progressed: false, - } + return query.Progress{} } // At this point, the response matches the query, @@ -329,16 +292,10 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, select { case m.utxosChan <- r: case <-m.blockMgr.quit: - return query.Progress{ - Finished: false, - Progressed: false, - } + return query.Progress{} } - return query.Progress{ - Finished: true, - Progressed: true, - } + return query.Progress{Finished: true, Progressed: true} } func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { From de809509fa0321d992ddfb2a878ee0800d7a15a3 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 23 Feb 2024 19:20:50 +0000 Subject: [PATCH 45/75] Small cosmetic change --- mweb/coindb.go | 8 ++++---- mwebutxos.go | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mweb/coindb.go b/mweb/coindb.go index 8b4b197b2..d2335668d 100644 --- a/mweb/coindb.go +++ b/mweb/coindb.go @@ -51,11 +51,11 @@ type CoinDatabase interface { PutLeavesAtHeight(map[uint32]uint64) error // Get the leafset marking the unspent indices. - GetLeafSet() (leafset []byte, numLeaves uint64, err error) + GetLeafset() (leafset []byte, numLeaves uint64, err error) // Set the leafset and purge the specified leaves and their // associated coins from persistent storage. - PutLeafSetAndPurge(leafset []byte, numLeaves uint64, + PutLeafsetAndPurge(leafset []byte, numLeaves uint64, removedLeaves []uint64) error // PutCoins stores coins to persistent storage. @@ -158,7 +158,7 @@ func (c *CoinStore) PutLeavesAtHeight(m map[uint32]uint64) error { // Get the leafset marking the unspent indices. // // NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { +func (c *CoinStore) GetLeafset() (leafset []byte, numLeaves uint64, err error) { err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) @@ -185,7 +185,7 @@ func (c *CoinStore) GetLeafSet() (leafset []byte, numLeaves uint64, err error) { // coins from persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) PutLeafSetAndPurge(leafset []byte, +func (c *CoinStore) PutLeafsetAndPurge(leafset []byte, numLeaves uint64, removedLeaves []uint64) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { diff --git a/mwebutxos.go b/mwebutxos.go index e9abea1ca..8ecc28662 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -30,7 +30,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, "height=%v, hash=%v", lastHeight, *lastHash) newNumLeaves := mwebHeader.OutputMMRSize - dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() + dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafset() if err != nil { log.Errorf("Couldn't read mweb coins db: %v", err) return err @@ -218,7 +218,7 @@ func (b *blockManager) purgeSpentMwebTxos(newLeafset mweb.Leafset, log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) } - err := b.cfg.MwebCoins.PutLeafSetAndPurge( + err := b.cfg.MwebCoins.PutLeafsetAndPurge( newLeafset, newNumLeaves, removedLeaves) if err != nil { log.Errorf("Couldn't purge mweb txos: %v", err) @@ -298,15 +298,15 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, return query.Progress{Finished: true, Progressed: true} } -func (b *blockManager) notifyAddedMwebUtxos(leafSet []byte) error { +func (b *blockManager) notifyAddedMwebUtxos(leafset []byte) error { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() - dbLeafset, newNumLeaves, err := b.cfg.MwebCoins.GetLeafSet() + dbLeafset, newNumLeaves, err := b.cfg.MwebCoins.GetLeafset() if err != nil { return err } - oldLeafset := mweb.Leafset(leafSet) + oldLeafset := mweb.Leafset(leafset) newLeafset := mweb.Leafset(dbLeafset) // Skip over common prefix From 32779288aff406dd0bf9a44df5bb0f831fa03e87 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 24 Feb 2024 12:10:43 +0000 Subject: [PATCH 46/75] Only load the leaves at height mapping once --- mwebutxos.go | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/mwebutxos.go b/mwebutxos.go index 8ecc28662..cee89d44a 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -18,6 +18,8 @@ type mwebUtxosQuery struct { mwebHeader *wire.MwebHeader leafset mweb.Leafset lastHeight uint32 + heights []uint32 + heightMap map[uint32]uint64 msgs []*wire.MsgGetMwebUtxos utxosChan chan *wire.MsgMwebUtxos } @@ -87,6 +89,19 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Infof("Starting to query for mweb utxos from index=%v", addedLeaves[0].start) log.Infof("Attempting to query for %v mwebutxos batches", batchesCount) + // Load the block height to leaf count mapping so that we can + // work out roughly when a utxo was included in a block. + heightMap, err := b.cfg.MwebCoins.GetLeavesAtHeight() + if err != nil { + log.Errorf("Couldn't get leaves at height from db: %v", err) + return err + } + heights := make([]uint32, 0, len(heightMap)) + for height := range heightMap { + heights = append(heights, height) + } + slices.Sort(heights) + // With the set of messages constructed, we'll now request the // batch all at once. This message will distribute the mwebutxos // requests amongst all active peers, effectively sharding each @@ -96,6 +111,8 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, mwebHeader: mwebHeader, leafset: newLeafset, lastHeight: lastHeight, + heights: heights, + heightMap: heightMap, utxosChan: make(chan *wire.MsgMwebUtxos), } @@ -128,19 +145,6 @@ func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { errChan := b.cfg.QueryDispatcher.Query( q.requests(), query.Cancel(b.quit)) - // Load the block height to leaf count mapping so that we can - // work out roughly when a utxo was included in a block. - heightMap, err := b.cfg.MwebCoins.GetLeavesAtHeight() - if err != nil { - log.Errorf("Couldn't get leaves at height from db: %v", err) - return 0, err - } - heights := make([]uint32, 0, len(heightMap)) - for height := range heightMap { - heights = append(heights, height) - } - slices.Sort(heights) - // Keep waiting for more mwebutxos as long as we haven't received an // answer for our last getmwebutxos, and no error is encountered. totalUtxos := 0 @@ -185,12 +189,12 @@ func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { // Calculate rough heights for each utxo. for _, utxo := range r.Utxos { - index, _ := slices.BinarySearchFunc(heights, utxo.LeafIndex, + index, _ := slices.BinarySearchFunc(q.heights, utxo.LeafIndex, func(height uint32, target uint64) int { - return cmp.Compare(heightMap[height]-1, target) + return cmp.Compare(q.heightMap[height]-1, target) }) - if index < len(heights) { - utxo.Height = int32(heights[index]) + if index < len(q.heights) { + utxo.Height = int32(q.heights[index]) } else { utxo.Height = int32(q.lastHeight) } From 9138ec48c24b0c51799d589bbfe0e50d94e2d853 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 25 Feb 2024 16:23:55 +0000 Subject: [PATCH 47/75] Handle reorgs --- blockmanager.go | 48 ++++++++++++++++++++++++++++++++++++++-------- mweb/coindb.go | 51 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 9375458b8..09f1d0210 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -222,7 +222,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} - mwebUtxosCallbacksMtx sync.RWMutex + mwebUtxosCallbacksMtx sync.Mutex mwebUtxosCallbacks []func([]byte, []*wire.MwebNetUtxo) } @@ -502,16 +502,36 @@ func (b *blockManager) mwebHandler() { log.Critical(err) return } + + rollbackHeight, err := b.cfg.MwebCoins.GetRollbackHeight() + if err != nil { + log.Critical(err) + return + } + if rollbackHeight > 0 { + if lastHeight-rollbackHeight > 10 { + err = b.cfg.MwebCoins.PurgeCoins() + } else { + lastHeight = rollbackHeight + lastHeader, err = b.cfg.BlockHeaders. + FetchHeaderByHeight(lastHeight) + } + if err != nil { + log.Critical(err) + return + } + } + lastHash := lastHeader.BlockHash() log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", lastHeight, lastHash) // Get a representative set of mweb headers up to this height. - if err := b.getMwebHeaders(lastHeight); err != nil { - if err == ErrShuttingDown { - return - } + err = b.getMwebHeaders(lastHeight) + if err == ErrShuttingDown { + return + } else if err != nil { log.Error(err) continue } @@ -536,7 +556,7 @@ func (b *blockManager) mwebHandler() { return } if err := mweb.VerifyHeader(m); err != nil { - log.Infof("failed to verify mwebheader: %v", err) + log.Infof("Failed to verify mwebheader: %v", err) return } mwebHeader = m @@ -554,7 +574,7 @@ func (b *blockManager) mwebHandler() { err := mweb.VerifyLeafset(mwebHeader, mwebLeafset) if err != nil { - log.Infof("failed to verify mwebleafset: %v", err) + log.Infof("Failed to verify mwebleafset: %v", err) return } @@ -580,7 +600,8 @@ func (b *blockManager) mwebHandler() { err = b.cfg.MwebCoins.PutLeavesAtHeight(map[uint32]uint64{ lastHeight: mwebHeader.MwebHeader.OutputMMRSize}) if err != nil { - log.Errorf("failed to write mwebheader to db: %v", err) + log.Critical(err) + return } // Get all the mweb utxos at this height. @@ -590,6 +611,12 @@ func (b *blockManager) mwebHandler() { continue } + err = b.cfg.MwebCoins.PutRollbackHeight(0) + if err != nil { + log.Critical(err) + return + } + // Now we check the headers again. If the block headers are not yet // current, then we go back to the loop waiting for them to finish. if !b.BlockHeadersSynced() { @@ -1464,6 +1491,11 @@ func (b *blockManager) rollBackToHeight(height uint32) error { return err } + err = b.cfg.MwebCoins.PutRollbackHeight(height) + if err != nil { + return err + } + for uint32(bs.Height) > height { header, headerHeight, err := b.cfg.BlockHeaders.FetchHeader(&bs.Hash) if err != nil { diff --git a/mweb/coindb.go b/mweb/coindb.go index d2335668d..53c7935ad 100644 --- a/mweb/coindb.go +++ b/mweb/coindb.go @@ -44,6 +44,12 @@ var ( // CoinDatabase is an interface which represents an object that is capable of // storing and retrieving coins according to their corresponding output ID. type CoinDatabase interface { + // Get rollback height. + GetRollbackHeight() (uint32, error) + + // Set rollback height. + PutRollbackHeight(uint32) error + // Get the block height to number of leaves mapping. GetLeavesAtHeight() (map[uint32]uint64, error) @@ -116,6 +122,41 @@ func NewCoinStore(db walletdb.DB) (*CoinStore, error) { return &CoinStore{db: db}, nil } +// Get rollback height. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) GetRollbackHeight() (height uint32, err error) { + err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { + rootBucket := tx.ReadBucket(rootBucket) + + b := rootBucket.Get([]byte("rollbackHeight")) + if b != nil { + if len(b) != 4 { + return ErrUnexpectedValueLen + } + height = binary.LittleEndian.Uint32(b) + } + return nil + }) + return +} + +// Set rollback height. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) PutRollbackHeight(height uint32) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + + k := []byte("rollbackHeight") + if height == 0 { + return rootBucket.Delete(k) + } + b := binary.LittleEndian.AppendUint32(nil, height) + return rootBucket.Put(k, b) + }) +} + // Get the block height to number of leaves mapping. // // NOTE: This method is a part of the CoinDatabase interface. @@ -342,15 +383,11 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { // NOTE: This method is a part of the CoinDatabase interface. func (c *CoinStore) PurgeCoins() error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { - rootBucket := tx.ReadWriteBucket(rootBucket) - - if err := rootBucket.DeleteNestedBucket(heightBucket); err != nil { + if err := tx.DeleteTopLevelBucket(rootBucket); err != nil { return err } - if err := rootBucket.DeleteNestedBucket(coinBucket); err != nil { - return err - } - if err := rootBucket.DeleteNestedBucket(leafBucket); err != nil { + rootBucket, err := tx.CreateTopLevelBucket(rootBucket) + if err != nil { return err } From 800859fd3fd4ff8406a63e69245ef4d3f0948204 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 25 Feb 2024 17:12:42 +0000 Subject: [PATCH 48/75] Make sure rollback height is earlier --- blockmanager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockmanager.go b/blockmanager.go index 09f1d0210..5b1faf914 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -511,7 +511,7 @@ func (b *blockManager) mwebHandler() { if rollbackHeight > 0 { if lastHeight-rollbackHeight > 10 { err = b.cfg.MwebCoins.PurgeCoins() - } else { + } else if rollbackHeight < lastHeight { lastHeight = rollbackHeight lastHeader, err = b.cfg.BlockHeaders. FetchHeaderByHeight(lastHeight) From f54c93c1affe74b0e596de3c8df7b5a0a285b4c3 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sun, 25 Feb 2024 18:01:41 +0000 Subject: [PATCH 49/75] Fix small oversight --- blockmanager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index 5b1faf914..0b94a0748 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -508,10 +508,10 @@ func (b *blockManager) mwebHandler() { log.Critical(err) return } - if rollbackHeight > 0 { + if rollbackHeight > 0 && rollbackHeight < lastHeight { if lastHeight-rollbackHeight > 10 { err = b.cfg.MwebCoins.PurgeCoins() - } else if rollbackHeight < lastHeight { + } else { lastHeight = rollbackHeight lastHeader, err = b.cfg.BlockHeaders. FetchHeaderByHeight(lastHeight) From efcfe3d3e159cb6db24cc9c64a0168302611e9af Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 26 Feb 2024 14:06:38 +0000 Subject: [PATCH 50/75] Combine leafset with height --- blockmanager.go | 20 +-- mweb/header.go | 68 ----------- mweb/utxos.go | 244 ------------------------------------- {mweb => mwebdb}/coindb.go | 36 ++---- mwebheaders.go | 2 +- mwebutxos.go | 58 ++++----- neutrino.go | 31 ++--- 7 files changed, 69 insertions(+), 390 deletions(-) delete mode 100644 mweb/header.go delete mode 100644 mweb/utxos.go rename {mweb => mwebdb}/coindb.go (93%) diff --git a/blockmanager.go b/blockmanager.go index 0b94a0748..5be328906 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -18,13 +18,14 @@ import ( "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/wire" "github.com/ltcsuite/neutrino/banman" "github.com/ltcsuite/neutrino/blockntfns" "github.com/ltcsuite/neutrino/chainsync" "github.com/ltcsuite/neutrino/headerfs" "github.com/ltcsuite/neutrino/headerlist" - "github.com/ltcsuite/neutrino/mweb" + "github.com/ltcsuite/neutrino/mwebdb" "github.com/ltcsuite/neutrino/query" ) @@ -95,7 +96,7 @@ type blockManagerCfg struct { RegFilterHeaders *headerfs.FilterHeaderStore // MwebCoins is the store where mweb coins are persistently stored. - MwebCoins mweb.CoinDatabase + MwebCoins mwebdb.CoinDatabase // TimeSource is used to access a time estimate based on the clocks of // the connected peers. @@ -223,7 +224,7 @@ type blockManager struct { // nolint:maligned requestedTxns map[chainhash.Hash]struct{} mwebUtxosCallbacksMtx sync.Mutex - mwebUtxosCallbacks []func([]byte, []*wire.MwebNetUtxo) + mwebUtxosCallbacks []func(*mweb.Leafset, []*wire.MwebNetUtxo) } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -596,17 +597,22 @@ func (b *blockManager) mwebHandler() { log.Infof("Verified mwebheader and mwebleafset at "+ "(block_height=%v, block_hash=%v)", lastHeight, lastHash) + leafset := &mweb.Leafset{ + Bits: mwebLeafset.Leafset, + Size: mwebHeader.MwebHeader.OutputMMRSize, + Height: lastHeight, + } + // Store the leaf count at this height. err = b.cfg.MwebCoins.PutLeavesAtHeight(map[uint32]uint64{ - lastHeight: mwebHeader.MwebHeader.OutputMMRSize}) + leafset.Height: leafset.Size}) if err != nil { log.Critical(err) return } // Get all the mweb utxos at this height. - err = b.getMwebUtxos(&mwebHeader.MwebHeader, - mwebLeafset.Leafset, lastHeight, &lastHash) + err = b.getMwebUtxos(&mwebHeader.MwebHeader, leafset, &lastHash) if err != nil { continue } @@ -3320,7 +3326,7 @@ func (l *lightHeaderCtx) RelativeAncestorCtx( // RegisterMwebUtxosCallback will register a callback that will fire when // new mweb utxos are received. func (b *blockManager) RegisterMwebUtxosCallback( - onMwebUtxos func([]byte, []*wire.MwebNetUtxo)) { + onMwebUtxos func(*mweb.Leafset, []*wire.MwebNetUtxo)) { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() diff --git a/mweb/header.go b/mweb/header.go deleted file mode 100644 index a7d59eb60..000000000 --- a/mweb/header.go +++ /dev/null @@ -1,68 +0,0 @@ -package mweb - -import ( - "bytes" - "errors" - "fmt" - - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/bloom" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" - "lukechampine.com/blake3" -) - -func VerifyHeader(mwebHeader *wire.MsgMwebHeader) error { - extractResult := bloom.VerifyMerkleBlock(&mwebHeader.Merkle) - if !extractResult.Root.IsEqual(&mwebHeader.Merkle.Header.MerkleRoot) { - return errors.New("mwebheader merkle block is bad") - } - - if !mwebHeader.Hogex.IsHogEx { - return errors.New("mwebheader hogex is not hogex") - } - - // Validate that the hash of the HogEx transaction in the tx message - // matches the hash in the merkleblock message, and that it's the - // last transaction committed to by the merkle root of the block. - - finalTx := extractResult.Match[len(extractResult.Match)-1] - if mwebHeader.Hogex.TxHash() != *finalTx { - return fmt.Errorf("tx hash mismatch, hogex=%v, last merkle tx=%v", - mwebHeader.Hogex.TxHash(), *finalTx) - } - - finalTxPos := extractResult.Index[len(extractResult.Index)-1] - if finalTxPos != mwebHeader.Merkle.Transactions-1 { - return fmt.Errorf("tx index mismatch, got=%v, expected=%v", - finalTxPos, mwebHeader.Merkle.Transactions-1) - } - - // Validate that the pubkey script of the first output contains - // the HogAddr, which shall consist of <0x20> followed by - // the 32-byte hash of the MWEB header. - - mwebHeaderHash := mwebHeader.MwebHeader.Hash() - script := append([]byte{txscript.OP_8, 0x20}, mwebHeaderHash[:]...) - if !bytes.Equal(mwebHeader.Hogex.TxOut[0].PkScript, script) { - return fmt.Errorf("HogAddr mismatch, hogex=%v, expected=%v", - mwebHeader.Hogex.TxOut[0].PkScript, script) - } - - return nil -} - -func VerifyLeafset(mwebHeader *wire.MsgMwebHeader, - mwebLeafset *wire.MsgMwebLeafset) error { - - // Verify that the hash of the leafset bitmap matches the - // leafset_root value in the MWEB header. - - leafsetRoot := chainhash.Hash(blake3.Sum256(mwebLeafset.Leafset)) - if leafsetRoot != mwebHeader.MwebHeader.LeafsetRoot { - return fmt.Errorf("leafset root mismatch, leafset=%v, header=%v", - leafsetRoot, mwebHeader.MwebHeader.LeafsetRoot) - } - - return nil -} diff --git a/mweb/utxos.go b/mweb/utxos.go deleted file mode 100644 index 06c2b55ab..000000000 --- a/mweb/utxos.go +++ /dev/null @@ -1,244 +0,0 @@ -package mweb - -import ( - "encoding/binary" - "math/bits" - - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" - "lukechampine.com/blake3" -) - -type ( - Leafset []byte - leafIdx uint64 - nodeIdx uint64 -) - -func (l Leafset) Contains(i uint64) bool { - return l.contains(leafIdx(i)) -} - -func (l Leafset) contains(i leafIdx) bool { - if int(i/8) >= len(l) { - return false - } - return l[i/8]&(0x80>>(i%8)) > 0 -} - -func (l Leafset) nextUnspent(i leafIdx) leafIdx { - for { - i++ - if l.contains(i) || int(i/8) >= len(l) { - return i - } - } -} - -func (i leafIdx) nodeIdx() nodeIdx { - return nodeIdx(2*i) - nodeIdx(bits.OnesCount64(uint64(i))) -} - -func (i nodeIdx) height() uint64 { - height := uint64(i) - h := 64 - bits.LeadingZeros64(uint64(i)) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if height >= peakSize { - height -= peakSize - } - } - return height -} - -func (i nodeIdx) leafIdx() leafIdx { - leafIndex := uint64(0) - numLeft := uint64(i) - h := 64 - bits.LeadingZeros64(uint64(i)) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if numLeft >= peakSize { - leafIndex += (peakSize + 1) / 2 - numLeft -= peakSize - } - } - return leafIdx(leafIndex) -} - -func (i nodeIdx) left(height uint64) nodeIdx { - return i - (1 << height) -} - -func (i nodeIdx) right() nodeIdx { - return i - 1 -} - -func (i nodeIdx) hash(data []byte) *chainhash.Hash { - h := blake3.New(32, nil) - binary.Write(h, binary.LittleEndian, uint64(i)) - wire.WriteVarBytes(h, 0, data) - return (*chainhash.Hash)(h.Sum(nil)) -} - -func (i nodeIdx) parentHash(left, right []byte) *chainhash.Hash { - h := blake3.New(32, nil) - binary.Write(h, binary.LittleEndian, uint64(i)) - h.Write(left) - h.Write(right) - return (*chainhash.Hash)(h.Sum(nil)) -} - -func calcPeaks(nodes uint64) (peaks []nodeIdx) { - sumPrevPeaks := uint64(0) - h := 64 - bits.LeadingZeros64(nodes) - for peakSize := uint64(1< 0; peakSize >>= 1 { - if nodes >= peakSize { - peaks = append(peaks, nodeIdx(sumPrevPeaks+peakSize-1)) - sumPrevPeaks += peakSize - nodes -= peakSize - } - } - return -} - -type verifyMwebUtxosVars struct { - mwebUtxos *wire.MsgMwebUtxos - leafset Leafset - firstLeafIdx, lastLeafIdx leafIdx - leavesUsed, hashesUsed int - isProofHash map[nodeIdx]bool -} - -func (v *verifyMwebUtxosVars) nextLeaf() (leafIndex leafIdx, hash *chainhash.Hash) { - if v.leavesUsed == len(v.mwebUtxos.Utxos) { - return - } - utxo := v.mwebUtxos.Utxos[v.leavesUsed] - leafIndex = leafIdx(utxo.LeafIndex) - hash = utxo.OutputId - v.leavesUsed++ - return -} - -func (v *verifyMwebUtxosVars) nextHash(nodeIdx nodeIdx) (hash *chainhash.Hash) { - if v.hashesUsed == len(v.mwebUtxos.ProofHashes) { - return - } - hash = v.mwebUtxos.ProofHashes[v.hashesUsed] - v.hashesUsed++ - v.isProofHash[nodeIdx] = true - return -} - -func (v *verifyMwebUtxosVars) calcNodeHash(nodeIdx nodeIdx, height uint64) *chainhash.Hash { - if nodeIdx < v.firstLeafIdx.nodeIdx() || v.isProofHash[nodeIdx] { - return v.nextHash(nodeIdx) - } - if height == 0 { - leafIdx := nodeIdx.leafIdx() - if !v.leafset.contains(leafIdx) { - return nil - } - leafIdx2, outputId := v.nextLeaf() - if leafIdx != leafIdx2 || outputId == nil { - return nil - } - return nodeIdx.hash(outputId[:]) - } - left := v.calcNodeHash(nodeIdx.left(height), height-1) - var right *chainhash.Hash - if v.lastLeafIdx.nodeIdx() <= nodeIdx.left(height) { - right = v.nextHash(nodeIdx.right()) - } else { - right = v.calcNodeHash(nodeIdx.right(), height-1) - } - switch { - case left == nil && right == nil: - return nil - case left == nil: - if left = v.nextHash(nodeIdx.left(height)); left == nil { - return nil - } - case right == nil: - if right = v.nextHash(nodeIdx.right()); right == nil { - return nil - } - } - return nodeIdx.parentHash(left[:], right[:]) -} - -func VerifyUtxos(mwebHeader *wire.MwebHeader, - mwebLeafset Leafset, mwebUtxos *wire.MsgMwebUtxos) bool { - - if mwebUtxos.StartIndex == 0 && - len(mwebUtxos.Utxos) == 0 && - len(mwebUtxos.ProofHashes) == 0 && - mwebHeader.OutputRoot.IsEqual(&chainhash.Hash{}) && - mwebHeader.OutputMMRSize == 0 { - return true - } else if len(mwebUtxos.Utxos) == 0 || - mwebHeader.OutputMMRSize == 0 { - return false - } - - v := &verifyMwebUtxosVars{ - mwebUtxos: mwebUtxos, - leafset: mwebLeafset, - firstLeafIdx: leafIdx(mwebUtxos.StartIndex), - lastLeafIdx: leafIdx(mwebUtxos.StartIndex), - isProofHash: make(map[nodeIdx]bool), - } - - for i := 0; ; i++ { - if !v.leafset.contains(v.lastLeafIdx) { - return false - } - if leafIdx(mwebUtxos.Utxos[i].LeafIndex) != v.lastLeafIdx { - return false - } - if i == len(mwebUtxos.Utxos)-1 { - break - } - v.lastLeafIdx = v.leafset.nextUnspent(v.lastLeafIdx) - } - - var ( - nextNodeIdx = leafIdx(mwebHeader.OutputMMRSize).nodeIdx() - peaks = calcPeaks(uint64(nextNodeIdx)) - peakHashes []*chainhash.Hash - ) - for i := 0; i < 2; i++ { - peakHashes = nil - v.leavesUsed = 0 - v.hashesUsed = 0 - - for _, peakNodeIdx := range peaks { - peakHash := v.calcNodeHash(peakNodeIdx, peakNodeIdx.height()) - if peakHash == nil { - peakHash = v.nextHash(peakNodeIdx) - if peakHash == nil { - return false - } - } - peakHashes = append(peakHashes, peakHash) - if v.lastLeafIdx.nodeIdx() <= peakNodeIdx { - if peakNodeIdx != peaks[len(peaks)-1] { - baggedPeak := v.nextHash(nextNodeIdx) - if baggedPeak == nil { - return false - } - peakHashes = append(peakHashes, baggedPeak) - } - break - } - } - if v.leavesUsed != len(v.mwebUtxos.Utxos) || - v.hashesUsed != len(v.mwebUtxos.ProofHashes) { - return false - } - } - - baggedPeak := peakHashes[len(peakHashes)-1] - for i := len(peakHashes) - 2; i >= 0; i-- { - baggedPeak = nextNodeIdx.parentHash(peakHashes[i][:], baggedPeak[:]) - } - return baggedPeak.IsEqual(&mwebHeader.OutputRoot) -} diff --git a/mweb/coindb.go b/mwebdb/coindb.go similarity index 93% rename from mweb/coindb.go rename to mwebdb/coindb.go index 53c7935ad..7d94eac73 100644 --- a/mweb/coindb.go +++ b/mwebdb/coindb.go @@ -1,4 +1,4 @@ -package mweb +package mwebdb import ( "bytes" @@ -6,6 +6,7 @@ import ( "fmt" "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/ltcutil/mweb" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" ) @@ -57,12 +58,11 @@ type CoinDatabase interface { PutLeavesAtHeight(map[uint32]uint64) error // Get the leafset marking the unspent indices. - GetLeafset() (leafset []byte, numLeaves uint64, err error) + GetLeafset() (leafset *mweb.Leafset, err error) // Set the leafset and purge the specified leaves and their // associated coins from persistent storage. - PutLeafsetAndPurge(leafset []byte, numLeaves uint64, - removedLeaves []uint64) error + PutLeafsetAndPurge(leafset *mweb.Leafset, removedLeaves []uint64) error // PutCoins stores coins to persistent storage. PutCoins([]*wire.MwebNetUtxo) error @@ -199,25 +199,16 @@ func (c *CoinStore) PutLeavesAtHeight(m map[uint32]uint64) error { // Get the leafset marking the unspent indices. // // NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) GetLeafset() (leafset []byte, numLeaves uint64, err error) { +func (c *CoinStore) GetLeafset() (leafset *mweb.Leafset, err error) { + leafset = &mweb.Leafset{} err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) - leafset = bytes.Clone(rootBucket.Get([]byte("leafset"))) - if leafset == nil { - return nil - } - - b := rootBucket.Get([]byte("numLeaves")) + b := rootBucket.Get([]byte("leafset")) if b == nil { - leafset = nil return nil } - if len(b) != 8 { - return ErrUnexpectedValueLen - } - numLeaves = binary.LittleEndian.Uint64(b) - return nil + return leafset.Deserialize(bytes.NewReader(b)) }) return } @@ -226,21 +217,20 @@ func (c *CoinStore) GetLeafset() (leafset []byte, numLeaves uint64, err error) { // coins from persistent storage. // // NOTE: This method is a part of the CoinDatabase interface. -func (c *CoinStore) PutLeafsetAndPurge(leafset []byte, - numLeaves uint64, removedLeaves []uint64) error { +func (c *CoinStore) PutLeafsetAndPurge(leafset *mweb.Leafset, + removedLeaves []uint64) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) coinBucket := rootBucket.NestedReadWriteBucket(coinBucket) leafBucket := rootBucket.NestedReadWriteBucket(leafBucket) - err := rootBucket.Put([]byte("leafset"), leafset) + var buf bytes.Buffer + err := leafset.Serialize(&buf) if err != nil { return err } - - b := binary.LittleEndian.AppendUint64(nil, numLeaves) - err = rootBucket.Put([]byte("numLeaves"), b) + err = rootBucket.Put([]byte("leafset"), buf.Bytes()) if err != nil { return err } diff --git a/mwebheaders.go b/mwebheaders.go index adab9d424..e08511f69 100644 --- a/mwebheaders.go +++ b/mwebheaders.go @@ -3,9 +3,9 @@ package neutrino import ( "slices" + "github.com/ltcsuite/ltcd/ltcutil/mweb" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/mweb" "github.com/ltcsuite/neutrino/query" ) diff --git a/mwebutxos.go b/mwebutxos.go index cee89d44a..71973695c 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -5,9 +5,9 @@ import ( "slices" "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcsuite/ltcd/ltcutil/mweb" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/mweb" "github.com/ltcsuite/neutrino/query" ) @@ -16,8 +16,7 @@ import ( type mwebUtxosQuery struct { blockMgr *blockManager mwebHeader *wire.MwebHeader - leafset mweb.Leafset - lastHeight uint32 + leafset *mweb.Leafset heights []uint32 heightMap map[uint32]uint64 msgs []*wire.MsgGetMwebUtxos @@ -25,27 +24,25 @@ type mwebUtxosQuery struct { } func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, - newLeafset mweb.Leafset, lastHeight uint32, - lastHash *chainhash.Hash) error { + newLeafset *mweb.Leafset, blockHash *chainhash.Hash) error { log.Infof("Fetching set of mweb utxos from "+ - "height=%v, hash=%v", lastHeight, *lastHash) + "height=%v, hash=%v", newLeafset.Height, *blockHash) - newNumLeaves := mwebHeader.OutputMMRSize - dbLeafset, oldNumLeaves, err := b.cfg.MwebCoins.GetLeafset() + oldLeafset, err := b.cfg.MwebCoins.GetLeafset() if err != nil { log.Errorf("Couldn't read mweb coins db: %v", err) return err } - oldLeafset := mweb.Leafset(dbLeafset) // Skip over common prefix var index uint64 - for index < uint64(len(oldLeafset)) && - index < uint64(len(newLeafset)) && - oldLeafset[index] == newLeafset[index] { + for index < uint64(len(oldLeafset.Bits)) && + index < uint64(len(newLeafset.Bits)) && + oldLeafset.Bits[index] == newLeafset.Bits[index] { index++ } + index *= 8 type span struct { start uint64 @@ -60,7 +57,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, addLeaf = span{} } } - for index *= 8; index < oldNumLeaves || index < newNumLeaves; index++ { + for ; index < oldLeafset.Size || index < newLeafset.Size; index++ { if oldLeafset.Contains(index) { addLeafSpan() if !newLeafset.Contains(index) { @@ -83,7 +80,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, batchesCount := len(addedLeaves) if batchesCount == 0 { - return b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) + return b.purgeSpentMwebTxos(newLeafset, removedLeaves) } log.Infof("Starting to query for mweb utxos from index=%v", addedLeaves[0].start) @@ -110,7 +107,6 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, blockMgr: b, mwebHeader: mwebHeader, leafset: newLeafset, - lastHeight: lastHeight, heights: heights, heightMap: heightMap, utxosChan: make(chan *wire.MsgMwebUtxos), @@ -119,7 +115,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, totalUtxos := 0 for len(addedLeaves) > 0 { for _, addLeaf := range addedLeaves { - q.msgs = append(q.msgs, wire.NewMsgGetMwebUtxos(*lastHash, + q.msgs = append(q.msgs, wire.NewMsgGetMwebUtxos(*blockHash, addLeaf.start, addLeaf.count, wire.MwebNetUtxoCompact)) if len(q.msgs) == 10 { break @@ -136,7 +132,7 @@ func (b *blockManager) getMwebUtxos(mwebHeader *wire.MwebHeader, log.Infof("Successfully got %v mweb utxos", totalUtxos) - return b.purgeSpentMwebTxos(newLeafset, newNumLeaves, removedLeaves) + return b.purgeSpentMwebTxos(newLeafset, removedLeaves) } func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { @@ -196,7 +192,7 @@ func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { if index < len(q.heights) { utxo.Height = int32(q.heights[index]) } else { - utxo.Height = int32(q.lastHeight) + utxo.Height = int32(q.leafset.Height) } } @@ -215,22 +211,21 @@ func (b *blockManager) getMwebUtxosBatch(q *mwebUtxosQuery) (int, error) { return totalUtxos, nil } -func (b *blockManager) purgeSpentMwebTxos(newLeafset mweb.Leafset, - newNumLeaves uint64, removedLeaves []uint64) error { +func (b *blockManager) purgeSpentMwebTxos( + leafset *mweb.Leafset, removedLeaves []uint64) error { if len(removedLeaves) > 0 { log.Infof("Purging %v spent mweb txos from db", len(removedLeaves)) } - err := b.cfg.MwebCoins.PutLeafsetAndPurge( - newLeafset, newNumLeaves, removedLeaves) + err := b.cfg.MwebCoins.PutLeafsetAndPurge(leafset, removedLeaves) if err != nil { log.Errorf("Couldn't purge mweb txos: %v", err) return err } for _, cb := range b.mwebUtxosCallbacks { - cb(newLeafset, nil) + cb(leafset, nil) } return nil @@ -302,29 +297,26 @@ func (m *mwebUtxosQuery) handleResponse(req, resp wire.Message, return query.Progress{Finished: true, Progressed: true} } -func (b *blockManager) notifyAddedMwebUtxos(leafset []byte) error { +func (b *blockManager) notifyAddedMwebUtxos(oldLeafset *mweb.Leafset) error { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() - dbLeafset, newNumLeaves, err := b.cfg.MwebCoins.GetLeafset() + newLeafset, err := b.cfg.MwebCoins.GetLeafset() if err != nil { return err } - oldLeafset := mweb.Leafset(leafset) - newLeafset := mweb.Leafset(dbLeafset) // Skip over common prefix var index uint64 - for index < uint64(len(oldLeafset)) && - index < uint64(len(newLeafset)) && - oldLeafset[index] == newLeafset[index] { + for index < uint64(len(oldLeafset.Bits)) && + index < uint64(len(newLeafset.Bits)) && + oldLeafset.Bits[index] == newLeafset.Bits[index] { index++ } var addedLeaves []uint64 - for index *= 8; index < newNumLeaves; index++ { - if !oldLeafset.Contains(index) && - newLeafset.Contains(index) { + for index *= 8; index < newLeafset.Size; index++ { + if !oldLeafset.Contains(index) && newLeafset.Contains(index) { addedLeaves = append(addedLeaves, index) } } diff --git a/neutrino.go b/neutrino.go index f85b125f4..7dcb5718e 100644 --- a/neutrino.go +++ b/neutrino.go @@ -19,6 +19,7 @@ import ( "github.com/ltcsuite/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcd/connmgr" "github.com/ltcsuite/ltcd/ltcutil" + "github.com/ltcsuite/ltcd/ltcutil/mweb" "github.com/ltcsuite/ltcd/peer" "github.com/ltcsuite/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" @@ -28,7 +29,7 @@ import ( "github.com/ltcsuite/neutrino/chanutils" "github.com/ltcsuite/neutrino/filterdb" "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/mweb" + "github.com/ltcsuite/neutrino/mwebdb" "github.com/ltcsuite/neutrino/pushtx" "github.com/ltcsuite/neutrino/query" ) @@ -658,7 +659,7 @@ type ChainService struct { // nolint:maligned FilterDB filterdb.FilterDatabase BlockHeaders headerfs.BlockHeaderStore RegFilterHeaders *headerfs.FilterHeaderStore - MwebCoinDB mweb.CoinDatabase + MwebCoinDB mwebdb.CoinDatabase persistToDisk bool FilterCache *lru.Cache[FilterCacheKey, *CacheableFilter] @@ -825,7 +826,7 @@ func NewChainService(cfg Config) (*ChainService, error) { return nil, err } - s.MwebCoinDB, err = mweb.NewCoinStore(cfg.Database) + s.MwebCoinDB, err = mwebdb.NewCoinStore(cfg.Database) if err != nil { return nil, err } @@ -1181,35 +1182,37 @@ func (s *ChainService) NetTotals() (uint64, uint64) { atomic.LoadUint64(&s.bytesSent) } -// RegisterMempoolCallback registers a callback to be fired whenever a new transaction is -// received into the mempool +// RegisterMempoolCallback registers a callback to be fired whenever a +// new transaction is received into the mempool func (s *ChainService) RegisterMempoolCallback(onRecvTx func(*ltcutil.Tx)) { s.mempool.RegisterCallback(onRecvTx) } -// NotifyMempoolReceived registers addresses to receive a callback on when a transaction -// paying to them enters the mempool. +// NotifyMempoolReceived registers addresses to receive a callback on +// when a transaction paying to them enters the mempool. func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { s.mempool.NotifyReceived(addrs) } -// RegisterMwebUtxosCallback registers a callback to be fired whenever new mweb utxos -// are received +// RegisterMwebUtxosCallback registers a callback to be fired whenever +// new mweb utxos are received func (s *ChainService) RegisterMwebUtxosCallback( - onMwebUtxos func([]byte, []*wire.MwebNetUtxo)) { + onMwebUtxos func(*mweb.Leafset, []*wire.MwebNetUtxo)) { s.blockManager.RegisterMwebUtxosCallback(onMwebUtxos) } -// Notify of any added mweb utxos since the last snapshot indicated by the leafset. -func (s *ChainService) NotifyAddedMwebUtxos(leafset []byte) error { +// Notify of any added mweb utxos since the last snapshot indicated by +// the leafset. +func (s *ChainService) NotifyAddedMwebUtxos(leafset *mweb.Leafset) error { return s.blockManager.notifyAddedMwebUtxos(leafset) } -// MwebUtxoExists checks if a mweb utxo with the given output ID exists in the db. +// MwebUtxoExists checks if a mweb utxo with the given output ID exists +// in the db. func (s *ChainService) MwebUtxoExists(outputId *chainhash.Hash) bool { if _, err := s.MwebCoinDB.FetchCoin(outputId); err != nil { - if err == mweb.ErrCoinNotFound { + if err == mwebdb.ErrCoinNotFound { return false } panic(err) From bc490e4a6afc4eabd2585293edeafc3e00a02259 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 26 Feb 2024 14:29:04 +0000 Subject: [PATCH 51/75] Minor tidy-up --- mwebdb/coindb.go | 4 ++-- neutrino.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mwebdb/coindb.go b/mwebdb/coindb.go index 7d94eac73..b468b5d06 100644 --- a/mwebdb/coindb.go +++ b/mwebdb/coindb.go @@ -58,11 +58,11 @@ type CoinDatabase interface { PutLeavesAtHeight(map[uint32]uint64) error // Get the leafset marking the unspent indices. - GetLeafset() (leafset *mweb.Leafset, err error) + GetLeafset() (*mweb.Leafset, error) // Set the leafset and purge the specified leaves and their // associated coins from persistent storage. - PutLeafsetAndPurge(leafset *mweb.Leafset, removedLeaves []uint64) error + PutLeafsetAndPurge(*mweb.Leafset, []uint64) error // PutCoins stores coins to persistent storage. PutCoins([]*wire.MwebNetUtxo) error diff --git a/neutrino.go b/neutrino.go index 7dcb5718e..739012f08 100644 --- a/neutrino.go +++ b/neutrino.go @@ -1183,7 +1183,7 @@ func (s *ChainService) NetTotals() (uint64, uint64) { } // RegisterMempoolCallback registers a callback to be fired whenever a -// new transaction is received into the mempool +// new transaction is received into the mempool. func (s *ChainService) RegisterMempoolCallback(onRecvTx func(*ltcutil.Tx)) { s.mempool.RegisterCallback(onRecvTx) } @@ -1195,7 +1195,7 @@ func (s *ChainService) NotifyMempoolReceived(addrs []ltcutil.Address) { } // RegisterMwebUtxosCallback registers a callback to be fired whenever -// new mweb utxos are received +// new mweb utxos are received. func (s *ChainService) RegisterMwebUtxosCallback( onMwebUtxos func(*mweb.Leafset, []*wire.MwebNetUtxo)) { From 6e3710f40eacfde1d57a37285755b31e2aa5f615 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 27 Feb 2024 00:48:55 +0000 Subject: [PATCH 52/75] Fill in leafset block header --- blockmanager.go | 1 + 1 file changed, 1 insertion(+) diff --git a/blockmanager.go b/blockmanager.go index 5be328906..d0bcd3164 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -601,6 +601,7 @@ func (b *blockManager) mwebHandler() { Bits: mwebLeafset.Leafset, Size: mwebHeader.MwebHeader.OutputMMRSize, Height: lastHeight, + Block: lastHeader, } // Store the leaf count at this height. From 5df21553ed7e735ac8e7017baecba592261f0916 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 27 Feb 2024 11:15:24 +0000 Subject: [PATCH 53/75] Only clear rollback height if unchanged --- blockmanager.go | 2 +- mwebdb/coindb.go | 35 +++++++++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/blockmanager.go b/blockmanager.go index d0bcd3164..3b6aa3849 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -618,7 +618,7 @@ func (b *blockManager) mwebHandler() { continue } - err = b.cfg.MwebCoins.PutRollbackHeight(0) + err = b.cfg.MwebCoins.ClearRollbackHeight(rollbackHeight) if err != nil { log.Critical(err) return diff --git a/mwebdb/coindb.go b/mwebdb/coindb.go index b468b5d06..359e7a186 100644 --- a/mwebdb/coindb.go +++ b/mwebdb/coindb.go @@ -27,6 +27,9 @@ var ( // leafBucket is the bucket that stores the mapping between // leaf indices and output IDs. leafBucket = []byte("leaves") + + // rollbackHeight is the key that stores the rollback height. + rollbackHeight = []byte("rollbackHeight") ) var ( @@ -51,6 +54,9 @@ type CoinDatabase interface { // Set rollback height. PutRollbackHeight(uint32) error + // Clear rollback height. + ClearRollbackHeight(uint32) error + // Get the block height to number of leaves mapping. GetLeavesAtHeight() (map[uint32]uint64, error) @@ -129,7 +135,7 @@ func (c *CoinStore) GetRollbackHeight() (height uint32, err error) { err = walletdb.View(c.db, func(tx walletdb.ReadTx) error { rootBucket := tx.ReadBucket(rootBucket) - b := rootBucket.Get([]byte("rollbackHeight")) + b := rootBucket.Get(rollbackHeight) if b != nil { if len(b) != 4 { return ErrUnexpectedValueLen @@ -148,12 +154,29 @@ func (c *CoinStore) PutRollbackHeight(height uint32) error { return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { rootBucket := tx.ReadWriteBucket(rootBucket) - k := []byte("rollbackHeight") - if height == 0 { - return rootBucket.Delete(k) - } b := binary.LittleEndian.AppendUint32(nil, height) - return rootBucket.Put(k, b) + return rootBucket.Put(rollbackHeight, b) + }) +} + +// Clear rollback height. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) ClearRollbackHeight(height uint32) error { + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + + b := rootBucket.Get(rollbackHeight) + if b == nil { + return nil + } + if len(b) != 4 { + return ErrUnexpectedValueLen + } + if binary.LittleEndian.Uint32(b) != height { + return nil + } + return rootBucket.Delete(rollbackHeight) }) } From f301b6e24ec848c4126569ebd3b54c19647625b9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 27 Feb 2024 13:07:29 +0000 Subject: [PATCH 54/75] Rollback leaves at height --- blockmanager.go | 6 ++++++ mwebdb/coindb.go | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/blockmanager.go b/blockmanager.go index 3b6aa3849..69f90a0c4 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -523,6 +523,12 @@ func (b *blockManager) mwebHandler() { } } + err = b.cfg.MwebCoins.RollbackLeavesAtHeight(rollbackHeight) + if err != nil { + log.Critical(err) + return + } + lastHash := lastHeader.BlockHash() log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", diff --git a/mwebdb/coindb.go b/mwebdb/coindb.go index 359e7a186..c93d7d5b9 100644 --- a/mwebdb/coindb.go +++ b/mwebdb/coindb.go @@ -63,6 +63,9 @@ type CoinDatabase interface { // Set the block height to number of leaves mapping. PutLeavesAtHeight(map[uint32]uint64) error + // Rollback the block height to number of leaves mapping. + RollbackLeavesAtHeight(uint32) error + // Get the leafset marking the unspent indices. GetLeafset() (*mweb.Leafset, error) @@ -219,6 +222,26 @@ func (c *CoinStore) PutLeavesAtHeight(m map[uint32]uint64) error { }) } +// Rollback the block height to number of leaves mapping. +// +// NOTE: This method is a part of the CoinDatabase interface. +func (c *CoinStore) RollbackLeavesAtHeight(height uint32) error { + if height == 0 { + return nil + } + return walletdb.Update(c.db, func(tx walletdb.ReadWriteTx) error { + rootBucket := tx.ReadWriteBucket(rootBucket) + heightBucket := rootBucket.NestedReadWriteBucket(heightBucket) + + return heightBucket.ForEach(func(k, v []byte) error { + if binary.LittleEndian.Uint32(k) > height { + return heightBucket.Delete(k) + } + return nil + }) + }) +} + // Get the leafset marking the unspent indices. // // NOTE: This method is a part of the CoinDatabase interface. From d7191acb43383ceebc6ea78e222d861715cd73ab Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 28 Feb 2024 13:32:16 +0000 Subject: [PATCH 55/75] Switching to go workspaces --- cache/go.mod | 7 +- cache/go.sum | 15 +-- go.mod | 60 +---------- go.sum | 238 +------------------------------------------- tools/go.mod | 158 +++++++++++++++-------------- tools/go.sum | 273 +++++++++++++++++---------------------------------- 6 files changed, 187 insertions(+), 564 deletions(-) diff --git a/cache/go.mod b/cache/go.mod index 9e5ae816b..351d7d5d5 100644 --- a/cache/go.mod +++ b/cache/go.mod @@ -2,12 +2,13 @@ module github.com/ltcsuite/neutrino/cache go 1.18 -require github.com/stretchr/testify v1.8.1 +require github.com/stretchr/testify v1.8.3 require ( github.com/davecgh/go-spew v1.1.1 // 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 + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) - -replace github.com/ltcsuite/neutrino/cache => ./cache diff --git a/cache/go.sum b/cache/go.sum index 2ec90f70f..4501d63e6 100644 --- a/cache/go.sum +++ b/cache/go.sum @@ -1,17 +1,12 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.mod b/go.mod index 4fc9fcd86..247b4f714 100644 --- a/go.mod +++ b/go.mod @@ -3,67 +3,15 @@ module github.com/ltcsuite/neutrino require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/davecgh/go-spew v1.1.1 - github.com/ltcsuite/lnd/queue v1.1.0 - 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/ltcwallet v0.13.1 - github.com/ltcsuite/ltcwallet/wallet/txauthor v1.3.2 - github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 // indirect - github.com/ltcsuite/ltcwallet/wallet/txsizes v1.2.3 // indirect - github.com/ltcsuite/ltcwallet/walletdb v1.4.0 - github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0 - github.com/ltcsuite/neutrino/cache v1.1.1 - github.com/stretchr/testify v1.8.2 - lukechampine.com/blake3 v1.2.1 + github.com/stretchr/testify v1.8.3 ) require ( - github.com/aead/siphash v1.0.1 // indirect - github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect - github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect - github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/decred/dcrd/lru v1.1.1 // indirect - github.com/kkdai/bstream v1.0.0 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect - github.com/ltcsuite/lnd/clock v1.1.0 // indirect - github.com/ltcsuite/lnd/ticker v1.1.0 // indirect - github.com/ltcsuite/lnd/tlv v1.1.1 // indirect + github.com/kr/pretty v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.etcd.io/bbolt v1.3.7 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/sys v0.13.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) go 1.18 - -replace github.com/ltcsuite/neutrino/cache => ./cache - -replace github.com/ltcsuite/ltcd => ../ltcd - -replace github.com/ltcsuite/ltcd/btcec/v2 => ../ltcd/btcec - -replace github.com/ltcsuite/ltcd/chaincfg => ../ltcd/chaincfg - -replace github.com/ltcsuite/ltcd/chaincfg/chainhash => ../ltcd/chaincfg/chainhash - -replace github.com/ltcsuite/ltcd/ltcutil => ../ltcd/ltcutil - -replace github.com/ltcsuite/ltcd/ltcutil/psbt => ../ltcd/ltcutil/psbt - -replace github.com/ltcsuite/ltcwallet => ../ltcwallet - -replace github.com/ltcsuite/ltcwallet/walletdb => ../ltcwallet/walletdb - -replace github.com/ltcsuite/ltcwallet/waddrmgr => ../ltcwallet/waddrmgr - -replace github.com/ltcsuite/ltcwallet/wtxmgr => ../ltcwallet/wtxmgr - -replace github.com/ltcsuite/ltcwallet/wallet/txauthor => ../ltcwallet/wallet/txauthor - -replace github.com/ltcsuite/ltcwallet/wallet/txsizes => ../ltcwallet/wallet/txsizes - -replace github.com/ltcsuite/lnd/tlv => ../lnd/tlv diff --git a/go.sum b/go.sum index fd176e943..1cb349576 100644 --- a/go.sum +++ b/go.sum @@ -1,61 +1,8 @@ -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y= -github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= -github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= @@ -64,196 +11,15 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf h1:HZKvJUHlcXI/f/O0Avg7t8sqkPo78HFzjmeYFl6DPnc= -github.com/ltcsuite/lnd v0.14.2-beta.rc3 h1:FSvwVonmzMqq4biW1LXeFY8LkZSOe8s9YUPZB096ufU= -github.com/ltcsuite/lnd/clock v1.1.0 h1:am2L2QTKgotbUSILSLLdZNe1ziSacXfR34Ry0f8npCs= -github.com/ltcsuite/lnd/clock v1.1.0/go.mod h1:Nn3X2+B0/70MnytJPHvOf3SPTPno09v90J/KJf5/dA8= -github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= -github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2PEq7IexlTWQ= -github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4= -github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof1yXM= -github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8= -github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI= -github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks= -github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/tools/go.mod b/tools/go.mod index dd993c6ba..6e42be734 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -3,17 +3,18 @@ module github.com/ltcsuite/neutrino/tools go 1.18 require ( - github.com/golangci/golangci-lint v1.50.1 + github.com/golangci/golangci-lint v1.52.2 github.com/ltcsuite/ltcd v0.23.5 github.com/ory/go-acc v0.2.8 github.com/rinchsan/gosimports v0.1.5 ) require ( - 4d63.com/gochecknoglobals v0.1.0 // indirect - github.com/Abirdcfly/dupword v0.0.7 // indirect - github.com/Antonboom/errname v0.1.7 // indirect - github.com/Antonboom/nilnil v0.1.1 // indirect + 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect + 4d63.com/gochecknoglobals v0.2.1 // indirect + github.com/Abirdcfly/dupword v0.0.11 // indirect + github.com/Antonboom/errname v0.1.9 // indirect + github.com/Antonboom/nilnil v0.1.3 // indirect github.com/BurntSushi/toml v1.2.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect @@ -22,50 +23,50 @@ require ( github.com/aead/siphash v1.0.1 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.3.0 // indirect + github.com/ashanbrown/forbidigo v1.5.1 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.0 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.3.0 // indirect - github.com/breml/bidichk v0.2.3 // indirect - github.com/breml/errchkjson v0.3.0 // indirect + github.com/bombsimon/wsl/v3 v3.4.0 // indirect + github.com/breml/bidichk v0.2.4 // indirect + github.com/breml/errchkjson v0.3.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect github.com/btcsuite/winsvc v1.0.0 // indirect github.com/butuzov/ireturn v0.1.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/charithe/durationcheck v0.0.9 // indirect - github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charithe/durationcheck v0.0.10 // indirect + github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.8.1 // indirect + github.com/daixiang0/gci v0.10.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/decred/dcrd/lru v1.0.0 // indirect + github.com/decred/dcrd/lru v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect github.com/dgraph-io/ristretto v0.0.2 // indirect github.com/esimonov/ifshort v1.0.4 // indirect github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.6.5 // indirect - github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.2 // indirect - github.com/go-toolsmith/astequal v1.0.3 // indirect - github.com/go-toolsmith/astfmt v1.0.0 // indirect - github.com/go-toolsmith/astp v1.0.0 // indirect - github.com/go-toolsmith/strparse v1.0.0 // indirect - github.com/go-toolsmith/typep v1.0.2 // indirect - github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect + github.com/go-critic/go-critic v0.7.0 // indirect + github.com/go-toolsmith/astcast v1.1.0 // indirect + github.com/go-toolsmith/astcopy v1.1.0 // indirect + github.com/go-toolsmith/astequal v1.1.0 // indirect + github.com/go-toolsmith/astfmt v1.1.0 // indirect + github.com/go-toolsmith/astp v1.1.0 // indirect + github.com/go-toolsmith/strparse v1.1.0 // indirect + github.com/go-toolsmith/typep v1.1.0 // indirect + github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect @@ -73,107 +74,111 @@ require ( github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.3.5 // indirect + github.com/golangci/misspell v0.4.0 // indirect github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect + github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/jessevdk/go-flags v1.4.0 // indirect + github.com/jessevdk/go-flags v1.5.0 // indirect github.com/jgautheron/goconst v1.5.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/jrick/logrotate v1.0.0 // indirect github.com/julz/importas v0.1.0 // indirect - github.com/kisielk/errcheck v1.6.2 // indirect + github.com/junk1tm/musttag v0.5.0 // indirect + github.com/kisielk/errcheck v1.6.3 // indirect github.com/kisielk/gotool v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.3 // indirect + github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.6 // indirect - github.com/kyoh86/exportloopref v0.1.8 // indirect + github.com/kyoh86/exportloopref v0.1.11 // indirect github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.3.1 // indirect - github.com/leonklingele/grouper v1.1.0 // indirect + github.com/ldez/tagliatelle v0.4.0 // indirect + github.com/leonklingele/grouper v1.1.1 // indirect github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 // indirect github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 // indirect github.com/ltcsuite/ltcd/ltcutil v1.1.3 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.0 // indirect - github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect + github.com/maratori/testpackage v1.1.1 // indirect + github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.2.4 // indirect + github.com/mgechev/revive v1.3.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/moricho/tparallel v0.2.1 // indirect + github.com/moricho/tparallel v0.3.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect - github.com/nishanths/exhaustive v0.8.3 // indirect + github.com/nishanths/exhaustive v0.9.5 // indirect github.com/nishanths/predeclared v0.2.2 // indirect + github.com/nunnatsa/ginkgolinter v0.9.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect github.com/ory/viper v1.7.5 // indirect github.com/pborman/uuid v1.2.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect - github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.0.5 // indirect + github.com/polyfloyd/go-errorlint v1.4.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.18 // indirect - github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f // indirect - github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect + github.com/quasilyte/go-ruleguard v0.3.19 // indirect + github.com/quasilyte/gogrep v0.5.0 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/ryancurrah/gomodguard v1.2.4 // indirect - github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect - github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/ryancurrah/gomodguard v1.3.0 // indirect + github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect + github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.20.0 // indirect - github.com/securego/gosec/v2 v2.13.1 // indirect + github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect + github.com/securego/gosec/v2 v2.15.0 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect - github.com/sirupsen/logrus v1.9.0 // indirect + github.com/sirupsen/logrus v1.9.2 // indirect github.com/sivchari/containedctx v1.0.2 // indirect github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.0 // indirect - github.com/sonatard/noctx v0.0.1 // indirect - github.com/sourcegraph/go-diff v0.6.1 // indirect + github.com/sivchari/tenv v1.7.1 // indirect + github.com/sonatard/noctx v0.0.2 // indirect + github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.6.0 // indirect + github.com/spf13/cobra v1.6.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.12.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.4.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/testify v1.8.3 // indirect github.com/subosito/gotenv v1.4.1 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect - github.com/tdakkota/asciicheck v0.1.1 // indirect + github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect + github.com/tdakkota/asciicheck v0.2.0 // indirect github.com/tetafro/godot v1.4.11 // indirect - github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect - github.com/timonwong/loggercheck v0.9.3 // indirect - github.com/tomarrell/wrapcheck/v2 v2.7.0 // indirect + github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e // indirect + github.com/timonwong/loggercheck v0.9.4 // indirect + github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect @@ -183,23 +188,24 @@ require ( gitlab.com/bosi/decorder v0.2.3 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.17.0 // indirect - golang.org/x/crypto v0.1.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 // indirect - golang.org/x/mod v0.6.0 // indirect - golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect - golang.org/x/sys v0.1.0 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/tools v0.2.0 // indirect - google.golang.org/protobuf v1.28.0 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect + golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/tools v0.9.1 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.3.3 // indirect + honnef.co/go/tools v0.4.3 // indirect lukechampine.com/blake3 v1.2.1 // indirect mvdan.cc/gofumpt v0.4.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 // indirect + mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect ) diff --git a/tools/go.sum b/tools/go.sum index 98aeca465..639bc0657 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,5 +1,5 @@ -4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= -4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= +4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -38,12 +38,9 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Abirdcfly/dupword v0.0.7 h1:z14n0yytA3wNO2gpCD/jVtp/acEXPGmYu0esewpBt6Q= -github.com/Abirdcfly/dupword v0.0.7/go.mod h1:K/4M1kj+Zh39d2aotRwypvasonOyAMH1c/IZJzE0dmk= -github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= -github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= -github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= -github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= +github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= +github.com/Antonboom/errname v0.1.9 h1:BZDX4r3l4TBZxZ2o2LNrlGxSHran4d1u4veZdoORTT4= +github.com/Antonboom/nilnil v0.1.3 h1:6RTbx3d2mcEu3Zwq9TowQpQMVpP75zugwOtqY1RTtcE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -70,10 +67,10 @@ github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cv github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= -github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -82,12 +79,9 @@ github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7 github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= -github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= -github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= -github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= -github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= +github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= +github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= +github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= @@ -102,12 +96,10 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 h1:E7LT642ysztPWE0dfz43cWOvMiF42DyTRC+eZIaO4yI= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375/go.mod h1:4m1Rv7xfuwWPNKXlThldNuJvutYM6J95wNuuVmn55To= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -122,12 +114,9 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/acmd v0.8.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= -github.com/daixiang0/gci v0.8.1 h1:T4xpSC+hmsi4CSyuYfIJdMZAr9o7xZmHpQVygMghGZ4= -github.com/daixiang0/gci v0.8.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -135,8 +124,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y= github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= @@ -156,8 +145,7 @@ github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStB github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= @@ -170,8 +158,7 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-critic/go-critic v0.6.5 h1:fDaR/5GWURljXwF8Eh31T2GZNz9X4jeboS912mWF8Uo= -github.com/go-critic/go-critic v0.6.5/go.mod h1:ezfP/Lh7MA6dBNn4c6ab5ALv3sKnZVLx37tr00uuaOY= +github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -181,28 +168,19 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= -github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+fH+674o= +github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= +github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -236,8 +214,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= @@ -248,14 +226,12 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.50.1 h1:C829clMcZXEORakZlwpk7M4iDw2XiwxxKaG504SZ9zY= -github.com/golangci/golangci-lint v1.50.1/go.mod h1:AQjHBopYS//oB8xs0y0M/dtxdKHkdhl0RvmjUct0/4w= +github.com/golangci/golangci-lint v1.52.2 h1:FrPElUUI5rrHXg1mQ7KxI1MXPAw5lBVskiz7U7a8a1A= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= -github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= @@ -299,15 +275,10 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 h1:PVRE9d4AQKmbelZ7emNig1+NT27DUmKZn5qXxfio54U= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -320,8 +291,8 @@ github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoIS github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -339,15 +310,14 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= @@ -363,13 +333,12 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7c= -github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= -github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= +github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -384,20 +353,15 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= -github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= -github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= -github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= -github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= +github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI= github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g= github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 h1:HVArUNQGqGaSSoyYkk9qGht74U0/uNhS0n7jV9rkmno= @@ -414,28 +378,21 @@ github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamh github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= -github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.4 h1:+2Hd/S8oO2H0Ikq2+egtNwQsVhAeELHjxjIUFX5ajLI= -github.com/mgechev/revive v1.2.4/go.mod h1:iAWlQishqCuj4yhV24FTnKSXGpbAA+0SckXB8GQMX/Q= +github.com/mgechev/revive v1.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -447,33 +404,30 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= -github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.8.3 h1:pw5O09vwg8ZaditDp/nQRqVnrMczSJDxRDJMowvhsrM= -github.com/nishanths/exhaustive v0.8.3/go.mod h1:qj+zJJUgJ76tR92+25+03oYUhzF4R7/2Wk7fGTfCHmg= +github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= +github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/ory/go-acc v0.2.8 h1:rOHHAPQjf0u7eHFGWpiXK+gIu/e0GRSJNr9pDukdNC4= github.com/ory/go-acc v0.2.8/go.mod h1:iCRZUdGb/7nqvSn8xWZkhfVrtXRZ9Wru2E5rabCjFPI= github.com/ory/viper v1.7.5 h1:+xVdq7SU3e1vNaCsk/ixsfxE4zylk1TJUiJrY647jUE= @@ -492,8 +446,6 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -501,8 +453,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/polyfloyd/go-errorlint v1.0.5 h1:AHB5JRCjlmelh9RrLxT9sgzpalIwwq4hqE8EkwIwKdY= -github.com/polyfloyd/go-errorlint v1.0.5/go.mod h1:APVvOesVSAnne5SClsPxPdfvZTVDojXh1/G3qb5wjGI= +github.com/polyfloyd/go-errorlint v1.4.0 h1:b+sQ5HibPIAjEZwtuwU8Wz/u0dMZ7YL+bk+9yWyHVJk= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -513,8 +464,8 @@ github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrb github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -530,38 +481,26 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.18 h1:sd+abO1PEI9fkYennwzHn9kl3nqP6M5vE7FiOzZ+5CE= -github.com/quasilyte/go-ruleguard v0.3.18/go.mod h1:lOIzcYlgxrQ2sGJ735EHXmf/e9MJ516j16K/Ifcttvs= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f h1:6Gtn2i04RD0gVyYf2/IUMTIs+qYleBt4zxDqkLTcu4U= -github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= +github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rinchsan/gosimports v0.1.5 h1:Z/l9lS79z0xgKC6fLJYmDdY44D0LFwo3MzaMtWvMKpY= github.com/rinchsan/gosimports v0.1.5/go.mod h1:102/jU2cwf9fpa/YM9D9o4gSen2Vg8Jl80Sxctgd9N0= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.2.4 h1:CpMSDKan0LtNGGhPrvupAoLeObRFjND8/tU1rEOtBp4= -github.com/ryancurrah/gomodguard v1.2.4/go.mod h1:+Kem4VjWwvFpUJRJSwa16s1tBJe+vbv02+naTow2f6M= -github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= -github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= -github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= -github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= +github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= +github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.20.0 h1:K6CXjqqtSYSsuyRDDC7Sjn6vTMLiSJa4ZmDkiokoqtw= -github.com/sashamelentyev/usestdlibvars v1.20.0/go.mod h1:0GaP+ecfZMXShS0A94CJn6aEuPRILv8h/VuWI9n1ygg= -github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= -github.com/securego/gosec/v2 v2.13.1/go.mod h1:EO1sImBMBWFjOTFzMWfTRrZW6M15gm60ljzrmy/wtHo= +github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= +github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -570,21 +509,17 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.0 h1:d4laZMBK6jpe5PWepxlV9S+LC0yXqvYHiq8E6ceoVVE= -github.com/sivchari/tenv v1.7.0/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= -github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= -github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= -github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= +github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -596,8 +531,7 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -613,8 +547,8 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -622,28 +556,25 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= -github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= +github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= -github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= +github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomarrell/wrapcheck/v2 v2.7.0 h1:J/F8DbSKJC83bAvC6FoZaRjZiZ/iKoueSdrEkmGeacA= -github.com/tomarrell/wrapcheck/v2 v2.7.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -678,12 +609,12 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -695,8 +626,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -707,11 +638,9 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 h1:Ic/qN6TEifvObMGQy72k0n1LlJr7DjWWEi+MOsDOiSk= -golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -739,8 +668,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -783,7 +712,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -806,8 +735,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -830,7 +758,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -862,7 +789,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -874,8 +800,8 @@ golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -886,8 +812,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -896,13 +822,10 @@ golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -913,7 +836,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -924,7 +846,6 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -937,29 +858,21 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -968,13 +881,12 @@ golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0t golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1070,14 +982,12 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1097,7 +1007,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= @@ -1109,8 +1018,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= -honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= +honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= @@ -1119,8 +1027,7 @@ mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wp mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 h1:seuXWbRB1qPrS3NQnHmFKLJLtskWyueeIzmLXghMGgk= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442/go.mod h1:F/Cxw/6mVrNKqrR2YjFf5CaW0Bw4RL8RfbEf4GRggJk= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From a89dfc4924cdd5bdac58e3088667ed1bf1e63951 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 28 Feb 2024 20:00:03 +0000 Subject: [PATCH 56/75] Fix underflow --- mwebheaders.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mwebheaders.go b/mwebheaders.go index e08511f69..e48935d81 100644 --- a/mwebheaders.go +++ b/mwebheaders.go @@ -51,7 +51,10 @@ func (b *blockManager) getMwebHeaders(lastHeight uint32) error { if err := fetch(height, 100); err != nil { return err } - if err := fetch(lastHeight-4000, 1); err != nil { + if height < lastHeight-4000 && lastHeight > 4000 { + height = lastHeight - 4000 + } + if err := fetch(height, 1); err != nil { return err } From b7a025c5877c2e442955b54d40b805d6fb74c5e6 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 29 Feb 2024 15:00:31 +0000 Subject: [PATCH 57/75] Move mweb handler to separate file --- blockmanager.go | 200 ---------------------------------------------- mwebhandler.go | 206 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 200 deletions(-) create mode 100644 mwebhandler.go diff --git a/blockmanager.go b/blockmanager.go index 69f90a0c4..f35991781 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -473,206 +473,6 @@ func (b *blockManager) handleDonePeerMsg(peers *list.List, sp *ServerPeer) { } } -// mwebHandler is the mweb download handler for the block manager. It must be -// run as a goroutine. It requests and processes mweb messages in a -// separate goroutine from the peer handlers. -func (b *blockManager) mwebHandler() { - defer b.wg.Done() - defer log.Trace("Mweb handler done") - - for { - b.newHeadersSignal.L.Lock() - for !b.BlockHeadersSynced() { - b.newHeadersSignal.Wait() - - // While we're awake, we'll quickly check to see if we need to - // quit early. - select { - case <-b.quit: - b.newHeadersSignal.L.Unlock() - return - default: - } - } - b.newHeadersSignal.L.Unlock() - - // Now that the block headers are finished, we'll grab the current - // chain tip so we can base our mweb header sync off of that. - lastHeader, lastHeight, err := b.cfg.BlockHeaders.ChainTip() - if err != nil { - log.Critical(err) - return - } - - rollbackHeight, err := b.cfg.MwebCoins.GetRollbackHeight() - if err != nil { - log.Critical(err) - return - } - if rollbackHeight > 0 && rollbackHeight < lastHeight { - if lastHeight-rollbackHeight > 10 { - err = b.cfg.MwebCoins.PurgeCoins() - } else { - lastHeight = rollbackHeight - lastHeader, err = b.cfg.BlockHeaders. - FetchHeaderByHeight(lastHeight) - } - if err != nil { - log.Critical(err) - return - } - } - - err = b.cfg.MwebCoins.RollbackLeavesAtHeight(rollbackHeight) - if err != nil { - log.Critical(err) - return - } - - lastHash := lastHeader.BlockHash() - - log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", - lastHeight, lastHash) - - // Get a representative set of mweb headers up to this height. - err = b.getMwebHeaders(lastHeight) - if err == ErrShuttingDown { - return - } else if err != nil { - log.Error(err) - continue - } - - gdmsg := wire.NewMsgGetData() - gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &lastHash)) - gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebLeafset, &lastHash)) - - var ( - mwebHeader *wire.MsgMwebHeader - mwebLeafset *wire.MsgMwebLeafset - verified bool - ) - b.cfg.queryAllPeers( - gdmsg, - func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}, - peerQuit chan<- struct{}) { - - switch m := resp.(type) { - case *wire.MsgMwebHeader: - if m.Merkle.Header.BlockHash() != lastHash { - return - } - if err := mweb.VerifyHeader(m); err != nil { - log.Infof("Failed to verify mwebheader: %v", err) - return - } - mwebHeader = m - - case *wire.MsgMwebLeafset: - mwebLeafset = m - - default: - return - } - - if mwebHeader == nil || mwebLeafset == nil { - return - } - - err := mweb.VerifyLeafset(mwebHeader, mwebLeafset) - if err != nil { - log.Infof("Failed to verify mwebleafset: %v", err) - return - } - - verified = true - - close(quit) - close(peerQuit) - }, - ) - select { - case <-b.quit: - return - default: - if !verified { - continue - } - } - - log.Infof("Verified mwebheader and mwebleafset at "+ - "(block_height=%v, block_hash=%v)", lastHeight, lastHash) - - leafset := &mweb.Leafset{ - Bits: mwebLeafset.Leafset, - Size: mwebHeader.MwebHeader.OutputMMRSize, - Height: lastHeight, - Block: lastHeader, - } - - // Store the leaf count at this height. - err = b.cfg.MwebCoins.PutLeavesAtHeight(map[uint32]uint64{ - leafset.Height: leafset.Size}) - if err != nil { - log.Critical(err) - return - } - - // Get all the mweb utxos at this height. - err = b.getMwebUtxos(&mwebHeader.MwebHeader, leafset, &lastHash) - if err != nil { - continue - } - - err = b.cfg.MwebCoins.ClearRollbackHeight(rollbackHeight) - if err != nil { - log.Critical(err) - return - } - - // Now we check the headers again. If the block headers are not yet - // current, then we go back to the loop waiting for them to finish. - if !b.BlockHeadersSynced() { - continue - } - - // If block headers are current, but the mweb sync was for an - // earlier block, we also go back to the loop. - b.newHeadersMtx.RLock() - if lastHeight < b.headerTip { - b.newHeadersMtx.RUnlock() - continue - } - b.newHeadersMtx.RUnlock() - - log.Infof("Fully caught up with mweb at height "+ - "%v, waiting at tip for new blocks", lastHeight) - - // Now that we've been fully caught up to the tip of the current header - // chain, we'll wait here for a signal that more blocks have been - // connected. If this happens then we'll do another round to fetch the - // new set of mweb utxos. - - // We'll wait until the header tip has advanced. - b.newHeadersSignal.L.Lock() - for lastHeight >= b.headerTip { - // We'll wait here until we're woken up by the - // broadcast signal. - b.newHeadersSignal.Wait() - - // Before we proceed, we'll check if we need to exit at - // all. - select { - case <-b.quit: - b.newHeadersSignal.L.Unlock() - return - default: - } - } - b.newHeadersSignal.L.Unlock() - } -} - // cfHandler is the cfheader download handler for the block manager. It must be // run as a goroutine. It requests and processes cfheaders messages in a // separate goroutine from the peer handlers. diff --git a/mwebhandler.go b/mwebhandler.go new file mode 100644 index 000000000..bb44f2e1e --- /dev/null +++ b/mwebhandler.go @@ -0,0 +1,206 @@ +package neutrino + +import ( + "github.com/ltcsuite/ltcd/ltcutil/mweb" + "github.com/ltcsuite/ltcd/wire" +) + +// mwebHandler is the mweb download handler for the block manager. It must be +// run as a goroutine. It requests and processes mweb messages in a +// separate goroutine from the peer handlers. +func (b *blockManager) mwebHandler() { + defer b.wg.Done() + defer log.Trace("Mweb handler done") + + for { + b.newHeadersSignal.L.Lock() + for !b.BlockHeadersSynced() { + b.newHeadersSignal.Wait() + + // While we're awake, we'll quickly check to see if we need to + // quit early. + select { + case <-b.quit: + b.newHeadersSignal.L.Unlock() + return + default: + } + } + b.newHeadersSignal.L.Unlock() + + // Now that the block headers are finished, we'll grab the current + // chain tip so we can base our mweb header sync off of that. + lastHeader, lastHeight, err := b.cfg.BlockHeaders.ChainTip() + if err != nil { + log.Critical(err) + return + } + + rollbackHeight, err := b.cfg.MwebCoins.GetRollbackHeight() + if err != nil { + log.Critical(err) + return + } + if rollbackHeight > 0 && rollbackHeight < lastHeight { + if lastHeight-rollbackHeight > 10 { + err = b.cfg.MwebCoins.PurgeCoins() + } else { + lastHeight = rollbackHeight + lastHeader, err = b.cfg.BlockHeaders. + FetchHeaderByHeight(lastHeight) + } + if err != nil { + log.Critical(err) + return + } + } + + err = b.cfg.MwebCoins.RollbackLeavesAtHeight(rollbackHeight) + if err != nil { + log.Critical(err) + return + } + + lastHash := lastHeader.BlockHash() + + log.Infof("Starting mweb sync at (block_height=%v, block_hash=%v)", + lastHeight, lastHash) + + // Get a representative set of mweb headers up to this height. + err = b.getMwebHeaders(lastHeight) + if err == ErrShuttingDown { + return + } else if err != nil { + log.Error(err) + continue + } + + gdmsg := wire.NewMsgGetData() + gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebHeader, &lastHash)) + gdmsg.AddInvVect(wire.NewInvVect(wire.InvTypeMwebLeafset, &lastHash)) + + var ( + mwebHeader *wire.MsgMwebHeader + mwebLeafset *wire.MsgMwebLeafset + verified bool + ) + b.cfg.queryAllPeers( + gdmsg, + func(sp *ServerPeer, resp wire.Message, quit chan<- struct{}, + peerQuit chan<- struct{}) { + + switch m := resp.(type) { + case *wire.MsgMwebHeader: + if m.Merkle.Header.BlockHash() != lastHash { + return + } + if err := mweb.VerifyHeader(m); err != nil { + log.Infof("Failed to verify mwebheader: %v", err) + return + } + mwebHeader = m + + case *wire.MsgMwebLeafset: + mwebLeafset = m + + default: + return + } + + if mwebHeader == nil || mwebLeafset == nil { + return + } + + err := mweb.VerifyLeafset(mwebHeader, mwebLeafset) + if err != nil { + log.Infof("Failed to verify mwebleafset: %v", err) + return + } + + verified = true + + close(quit) + close(peerQuit) + }, + ) + select { + case <-b.quit: + return + default: + if !verified { + continue + } + } + + log.Infof("Verified mwebheader and mwebleafset at "+ + "(block_height=%v, block_hash=%v)", lastHeight, lastHash) + + leafset := &mweb.Leafset{ + Bits: mwebLeafset.Leafset, + Size: mwebHeader.MwebHeader.OutputMMRSize, + Height: lastHeight, + Block: lastHeader, + } + + // Store the leaf count at this height. + err = b.cfg.MwebCoins.PutLeavesAtHeight(map[uint32]uint64{ + leafset.Height: leafset.Size}) + if err != nil { + log.Critical(err) + return + } + + // Get all the mweb utxos at this height. + err = b.getMwebUtxos(&mwebHeader.MwebHeader, leafset, &lastHash) + if err != nil { + continue + } + + err = b.cfg.MwebCoins.ClearRollbackHeight(rollbackHeight) + if err != nil { + log.Critical(err) + return + } + + // Now we check the headers again. If the block headers are not yet + // current, then we go back to the loop waiting for them to finish. + if !b.BlockHeadersSynced() { + continue + } + + // If block headers are current, but the mweb sync was for an + // earlier block, we also go back to the loop. + b.newHeadersMtx.RLock() + if lastHeight < b.headerTip { + b.newHeadersMtx.RUnlock() + continue + } + b.newHeadersMtx.RUnlock() + + log.Infof("Fully caught up with mweb at height "+ + "%v, waiting at tip for new blocks", lastHeight) + + // Now that we've been fully caught up to the tip of the current header + // chain, we'll wait here for a signal that more blocks have been + // connected. If this happens then we'll do another round to fetch the + // new set of mweb utxos. + + // We'll wait until the header tip has advanced. + b.newHeadersSignal.L.Lock() + for lastHeight >= b.headerTip { + // We'll wait here until we're woken up by the + // broadcast signal. + b.newHeadersSignal.Wait() + + // Before we proceed, we'll check if we need to exit at + // all. + select { + case <-b.quit: + b.newHeadersSignal.L.Unlock() + return + default: + } + } + b.newHeadersSignal.L.Unlock() + } +} From 6203880ab1c09425ef32bbf3bcfdf5f583596c2e Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 1 Mar 2024 17:04:03 +0000 Subject: [PATCH 58/75] Ensure we're not rolling back before notifying utxos --- blockmanager.go | 3 +++ mwebhandler.go | 1 + mwebutxos.go | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/blockmanager.go b/blockmanager.go index f35991781..8f48e32e2 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -225,6 +225,7 @@ type blockManager struct { // nolint:maligned mwebUtxosCallbacksMtx sync.Mutex mwebUtxosCallbacks []func(*mweb.Leafset, []*wire.MwebNetUtxo) + mwebRollbackSignal *sync.Cond } // newBlockManager returns a new bitcoin block manager. Use Start to begin @@ -262,6 +263,7 @@ func newBlockManager(cfg *blockManagerCfg) (*blockManager, error) { // duties. bm.newHeadersSignal = sync.NewCond(&bm.newHeadersMtx) bm.newFilterHeadersSignal = sync.NewCond(&bm.newFilterHeadersMtx) + bm.mwebRollbackSignal = sync.NewCond(&bm.mwebUtxosCallbacksMtx) // We fetch the genesis header to use for verifying the first received // interval. @@ -357,6 +359,7 @@ func (b *blockManager) Stop() error { b.newHeadersSignal.Broadcast() b.newFilterHeadersSignal.Broadcast() + b.mwebRollbackSignal.Broadcast() } }() diff --git a/mwebhandler.go b/mwebhandler.go index bb44f2e1e..f1801f8af 100644 --- a/mwebhandler.go +++ b/mwebhandler.go @@ -161,6 +161,7 @@ func (b *blockManager) mwebHandler() { log.Critical(err) return } + b.mwebRollbackSignal.Broadcast() // Now we check the headers again. If the block headers are not yet // current, then we go back to the loop waiting for them to finish. diff --git a/mwebutxos.go b/mwebutxos.go index 71973695c..a5e2267cf 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -301,6 +301,23 @@ func (b *blockManager) notifyAddedMwebUtxos(oldLeafset *mweb.Leafset) error { b.mwebUtxosCallbacksMtx.Lock() defer b.mwebUtxosCallbacksMtx.Unlock() + for { + rollbackHeight, err := b.cfg.MwebCoins.GetRollbackHeight() + if err != nil { + return err + } else if rollbackHeight == 0 { + break + } + + b.mwebRollbackSignal.Wait() + + select { + case <-b.quit: + return ErrShuttingDown + default: + } + } + newLeafset, err := b.cfg.MwebCoins.GetLeafset() if err != nil { return err From 8294325030cd93a09b6b88e3f68276e96eca2e19 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 1 Mar 2024 21:57:28 +0000 Subject: [PATCH 59/75] Only validate witness commitment if segwit is active --- query.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/query.go b/query.go index 24432a9c3..b3e9e6a06 100644 --- a/query.go +++ b/query.go @@ -888,9 +888,13 @@ func (s *ChainService) GetBlock(blockHash chainhash.Hash, return noProgress } + isSegwitActive := true + if s.chainParams.Net == wire.MainNet { + isSegwitActive = block.Height() >= 1201536 + } if err := blockchain.ValidateWitnessCommitment( block, - ); err != nil { + ); err != nil && isSegwitActive { log.Warnf("Invalid block for %s received from %s: %v "+ "-- disconnecting peer", blockHash, peer, err) From 681bb79f0331f2f6ff066a3f5f9da9da1af86051 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 2 Mar 2024 10:01:10 +0000 Subject: [PATCH 60/75] Fix double close --- query.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/query.go b/query.go index b3e9e6a06..a2b46e50f 100644 --- a/query.go +++ b/query.go @@ -983,13 +983,13 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // We'll gather all the peers who replied to our query, along with // the ones who rejected it and their reason for rejecting it. We'll use // this to determine whether our transaction was actually rejected. - replies := make(map[int32]struct{}) - rejections := make(map[int32]*pushtx.BroadcastError) + replies := make(map[string]struct{}) + rejections := make(map[string]*pushtx.BroadcastError) rejectCodes := make(map[pushtx.BroadcastErrorCode]int) // closers is a map that tracks the delayed closers we need to make sure // the peer quit channel is closed after a timeout. - closers := make(map[int32]*delayedCloser) + closers := make(map[string]*delayedCloser) // Send the peer query and listen for getdata. s.queryAllPeers( @@ -999,12 +999,12 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // The "closer" can be used to either close the peer // quit channel after a certain timeout or immediately. - closer, ok := closers[sp.ID()] + closer, ok := closers[sp.Addr()] if !ok { closer = newDelayedCloser( peerQuit, qo.rejectTimeout, ) - closers[sp.ID()] = closer + closers[sp.Addr()] = closer } switch response := resp.(type) { @@ -1021,7 +1021,7 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // request multiple times, we // need to de-duplicate them // using a map. - replies[sp.ID()] = struct{}{} + replies[sp.Addr()] = struct{}{} // Okay, so the peer responded // with an INV message, and we @@ -1052,7 +1052,7 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e broadcastErr := pushtx.ParseBroadcastError( response, sp.Addr(), ) - rejections[sp.ID()] = broadcastErr + rejections[sp.Addr()] = broadcastErr rejectCodes[broadcastErr.Code]++ log.Debugf("Transaction %v rejected by peer "+ From 48aa4d568fef287105083c0ee85b9b33b1de682b Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 5 Mar 2024 15:33:44 +0000 Subject: [PATCH 61/75] Work manager stability fixes --- query/interface.go | 6 ++++++ query/worker.go | 1 + query/workmanager.go | 12 +++++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/query/interface.go b/query/interface.go index 19a09b481..e6b1409f9 100644 --- a/query/interface.go +++ b/query/interface.go @@ -181,6 +181,12 @@ type Peer interface { // Addr returns the address of this peer. Addr() string + // ID returns the id of this peer. + ID() int32 + + // Disconnect disconnects the peer. + Disconnect() + // OnDisconnect returns a channel that will be closed when this peer is // disconnected. OnDisconnect() <-chan struct{} diff --git a/query/worker.go b/query/worker.go index 496d71089..858e4e4ec 100644 --- a/query/worker.go +++ b/query/worker.go @@ -193,6 +193,7 @@ func (w *worker) Run(results chan<- *jobResult, quit <-chan struct{}) { "with job index %v", peer.Addr(), job.Req, job.Index()) + peer.Disconnect() break Loop // If the peer disconnects before giving us a valid diff --git a/query/workmanager.go b/query/workmanager.go index e99f57abc..c15e4739b 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -74,6 +74,7 @@ type PeerRanking interface { // TODO(halseth): support more than one active job at a time. type activeWorker struct { w Worker + peerId int32 activeJob *queryJob onExit chan struct{} } @@ -275,6 +276,7 @@ Loop: onExit := make(chan struct{}) workers[peer.Addr()] = &activeWorker{ w: r, + peerId: peer.ID(), activeJob: nil, onExit: onExit, } @@ -298,7 +300,11 @@ Loop: // Delete the job from the worker's active job, such // that the slot gets opened for more work. r := workers[result.peer.Addr()] - r.activeJob = nil + if r != nil && r.peerId == result.peer.ID() { + r.activeJob = nil + } else { + result.peer.Disconnect() + } // Get the index of this query's batch, and delete it // from the map of current queries, since we don't have @@ -335,6 +341,10 @@ Loop: // Punish the peer for the failed query. w.cfg.Ranking.Punish(result.peer.Addr()) + if batch == nil { + break + } + if batch != nil && !batch.noRetryMax { result.job.tries++ } From 914d20bc5cf952880b2ae00546048efe4f86acba Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 5 Mar 2024 23:19:20 +0000 Subject: [PATCH 62/75] Fix test --- query/worker_test.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/query/worker_test.go b/query/worker_test.go index 23439c490..7e69ad709 100644 --- a/query/worker_test.go +++ b/query/worker_test.go @@ -41,6 +41,9 @@ func (m *mockPeer) SubscribeRecvMsg() (<-chan wire.Message, func()) { return msgChan, func() {} } +func (m *mockPeer) Disconnect() { +} + func (m *mockPeer) OnDisconnect() <-chan struct{} { return m.quit } @@ -49,6 +52,10 @@ func (m *mockPeer) Addr() string { return m.addr } +func (m *mockPeer) ID() int32 { + return 0 +} + // makeJob returns a new query job that will be done when it is given the // finalResp message. Similarly ot will progress on being given the // progressResp message, while any other message will be ignored. From 0cd9ef5c5514490917c50f1d3f19bf1708f44ee7 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 6 Mar 2024 21:46:24 +0000 Subject: [PATCH 63/75] Fix batch timeout --- query/workmanager.go | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/query/workmanager.go b/query/workmanager.go index c15e4739b..b552cd884 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -178,7 +178,6 @@ func (w *peerWorkManager) workDispatcher() { type batchProgress struct { noRetryMax bool maxRetries uint8 - timeout <-chan time.Time rem int errChan chan error } @@ -197,6 +196,9 @@ func (w *peerWorkManager) workDispatcher() { } }() + // Batch timeouts are notified on this channel. + batchTimeout := make(chan uint64) + // We set up a counter that we'll increase with each incoming query, // and will serve as the priority of each. In addition we map each // query to the batch they are part of. @@ -417,23 +419,15 @@ Loop: } } + case batchNum := <-batchTimeout: // If the total timeout for this batch has passed, // return an error. + batch := currentBatches[batchNum] if batch != nil { - select { - case <-batch.timeout: - batch.errChan <- ErrQueryTimeout - delete(currentBatches, batchNum) - - log.Warnf("Query(%d) failed with "+ - "error: %v. Timing out.", - result.job.index, result.err) + batch.errChan <- ErrQueryTimeout + delete(currentBatches, batchNum) - log.Debugf("Batch %v timed out", - batchNum) - - default: - } + log.Warnf("Batch %v timed out", batchNum) } // A new batch of queries where scheduled. @@ -459,10 +453,22 @@ Loop: currentBatches[batchIndex] = &batchProgress{ noRetryMax: batch.options.noRetryMax, maxRetries: batch.options.numRetries, - timeout: time.After(batch.options.timeout), rem: len(batch.requests), errChan: batch.errChan, } + + go func(batchNum uint64) { + select { + case <-time.After(batch.options.timeout): + case <-w.quit: + return + } + select { + case batchTimeout <- batchNum: + case <-w.quit: + } + }(batchIndex) + batchIndex++ case <-w.quit: From 92cc54f0dad609fb5038402917e007c0c7250cfd Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 7 Mar 2024 15:09:11 +0000 Subject: [PATCH 64/75] Allow multiple connections to an IP --- query.go | 24 ++++++++++++------------ query/peer_rank.go | 6 +++--- query/peer_rank_test.go | 12 ++++++------ query/workmanager.go | 18 ++++++------------ query/workmanager_test.go | 4 ++-- 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/query.go b/query.go index a2b46e50f..4f8f4fd55 100644 --- a/query.go +++ b/query.go @@ -315,11 +315,11 @@ func (s *ChainService) queryAllPeers( // Now we start a goroutine for each peer which manages the peer's // message subscription. - peerQuits := make(map[string]chan struct{}) + peerQuits := make(map[int32]chan struct{}) for _, sp := range peers { sp.subscribeRecvMsg(subscription) wg.Add(1) - peerQuits[sp.Addr()] = make(chan struct{}) + peerQuits[sp.ID()] = make(chan struct{}) go func(sp *ServerPeer, peerQuit <-chan struct{}) { defer wg.Done() @@ -339,7 +339,7 @@ func (s *ChainService) queryAllPeers( case <-timeout: } } - }(sp, peerQuits[sp.Addr()]) + }(sp, peerQuits[sp.ID()]) } // This goroutine will wait until all of the peer-query goroutines have @@ -383,10 +383,10 @@ checkResponses: // stuck. This is a caveat for callers that should be // fixed before exposing this function for public use. select { - case <-peerQuits[sm.sp.Addr()]: + case <-peerQuits[sm.sp.ID()]: default: checkResponse(sm.sp, sm.msg, queryQuit, - peerQuits[sm.sp.Addr()]) + peerQuits[sm.sp.ID()]) } } } @@ -983,13 +983,13 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // We'll gather all the peers who replied to our query, along with // the ones who rejected it and their reason for rejecting it. We'll use // this to determine whether our transaction was actually rejected. - replies := make(map[string]struct{}) - rejections := make(map[string]*pushtx.BroadcastError) + replies := make(map[int32]struct{}) + rejections := make(map[int32]*pushtx.BroadcastError) rejectCodes := make(map[pushtx.BroadcastErrorCode]int) // closers is a map that tracks the delayed closers we need to make sure // the peer quit channel is closed after a timeout. - closers := make(map[string]*delayedCloser) + closers := make(map[int32]*delayedCloser) // Send the peer query and listen for getdata. s.queryAllPeers( @@ -999,12 +999,12 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // The "closer" can be used to either close the peer // quit channel after a certain timeout or immediately. - closer, ok := closers[sp.Addr()] + closer, ok := closers[sp.ID()] if !ok { closer = newDelayedCloser( peerQuit, qo.rejectTimeout, ) - closers[sp.Addr()] = closer + closers[sp.ID()] = closer } switch response := resp.(type) { @@ -1021,7 +1021,7 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // request multiple times, we // need to de-duplicate them // using a map. - replies[sp.Addr()] = struct{}{} + replies[sp.ID()] = struct{}{} // Okay, so the peer responded // with an INV message, and we @@ -1052,7 +1052,7 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e broadcastErr := pushtx.ParseBroadcastError( response, sp.Addr(), ) - rejections[sp.Addr()] = broadcastErr + rejections[sp.ID()] = broadcastErr rejectCodes[broadcastErr.Code]++ log.Debugf("Transaction %v rejected by peer "+ diff --git a/query/peer_rank.go b/query/peer_rank.go index 77c6c8f42..972c19802 100644 --- a/query/peer_rank.go +++ b/query/peer_rank.go @@ -38,14 +38,14 @@ func NewPeerRanking() PeerRanking { // Order sorts the given slice of peers based on their current score. If a // peer has no current score given, the default will be used. -func (p *peerRanking) Order(peers []string) { +func (p *peerRanking) Order(peers []Peer) { sort.Slice(peers, func(i, j int) bool { - score1, ok := p.rank[peers[i]] + score1, ok := p.rank[peers[i].Addr()] if !ok { score1 = defaultScore } - score2, ok := p.rank[peers[j]] + score2, ok := p.rank[peers[j].Addr()] if !ok { score2 = defaultScore } diff --git a/query/peer_rank_test.go b/query/peer_rank_test.go index 17770e379..98a55ad1e 100644 --- a/query/peer_rank_test.go +++ b/query/peer_rank_test.go @@ -11,10 +11,10 @@ func TestPeerRank(t *testing.T) { const numPeers = 8 ranking := NewPeerRanking() - var peers []string + var peers []Peer for i := 0; i < numPeers; i++ { p := fmt.Sprintf("peer%d", i) - peers = append(peers, p) + peers = append(peers, &mockPeer{addr: p}) ranking.AddPeer(p) } @@ -26,7 +26,7 @@ func TestPeerRank(t *testing.T) { // should be unchanged. for i := 0; i < numPeers/2; i++ { p := fmt.Sprintf("peer%d", i) - if peers[i] != p { + if peers[i].Addr() != p { t.Fatalf("expected %v, got %v", p, peers[i]) } } @@ -34,14 +34,14 @@ func TestPeerRank(t *testing.T) { // Punish the first ones more, which should flip the order. for i := 0; i < numPeers/2; i++ { for j := 0; j <= i; j++ { - ranking.Punish(peers[j]) + ranking.Punish(peers[j].Addr()) } } ranking.Order(peers) for i := 0; i < numPeers/2; i++ { p := fmt.Sprintf("peer%d", numPeers/2-i-1) - if peers[i] != p { + if peers[i].Addr() != p { t.Fatalf("expected %v, got %v", p, peers[i]) } } @@ -53,7 +53,7 @@ func TestPeerRank(t *testing.T) { } ranking.Order(peers) - if peers[0] != "peer0" { + if peers[0].Addr() != "peer0" { t.Fatalf("peer0 was not first") } } diff --git a/query/workmanager.go b/query/workmanager.go index b552cd884..61e69096c 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -66,7 +66,7 @@ type PeerRanking interface { Punish(peer string) // Order sorst the slice of peers according to their ranking. - Order(peers []string) + Order(peers []Peer) } // activeWorker wraps a Worker that is currently running, together with the job @@ -74,7 +74,6 @@ type PeerRanking interface { // TODO(halseth): support more than one active job at a time. type activeWorker struct { w Worker - peerId int32 activeJob *queryJob onExit chan struct{} } @@ -205,7 +204,7 @@ func (w *peerWorkManager) workDispatcher() { queryIndex := uint64(0) currentQueries := make(map[uint64]uint64) - workers := make(map[string]*activeWorker) + workers := make(map[Peer]*activeWorker) Loop: for { @@ -215,7 +214,7 @@ Loop: next := work.Peek().(*queryJob) // Find the peers with free work slots available. - var freeWorkers []string + var freeWorkers []Peer for p, r := range workers { // Only one active job at a time is currently // supported. @@ -276,9 +275,8 @@ Loop: // worker's Run method returns, to know when we can // remove it from our set of active workers. onExit := make(chan struct{}) - workers[peer.Addr()] = &activeWorker{ + workers[peer] = &activeWorker{ w: r, - peerId: peer.ID(), activeJob: nil, onExit: onExit, } @@ -301,12 +299,8 @@ Loop: // Delete the job from the worker's active job, such // that the slot gets opened for more work. - r := workers[result.peer.Addr()] - if r != nil && r.peerId == result.peer.ID() { - r.activeJob = nil - } else { - result.peer.Disconnect() - } + r := workers[result.peer] + r.activeJob = nil // Get the index of this query's batch, and delete it // from the map of current queries, since we don't have diff --git a/query/workmanager_test.go b/query/workmanager_test.go index b7bec809c..e8ee7992a 100644 --- a/query/workmanager_test.go +++ b/query/workmanager_test.go @@ -47,13 +47,13 @@ var _ PeerRanking = (*mockPeerRanking)(nil) func (p *mockPeerRanking) AddPeer(peer string) { } -func (p *mockPeerRanking) Order(peers []string) { +func (p *mockPeerRanking) Order(peers []Peer) { if p.less == nil { return } sort.Slice(peers, func(i, j int) bool { - return p.less(peers[i], peers[j]) + return p.less(peers[i].Addr(), peers[j].Addr()) }) } From b6e22daaabb8b2d59397da1c6c9e2550fc3a8f47 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Thu, 7 Mar 2024 15:34:16 +0000 Subject: [PATCH 65/75] Remove unneeded method --- query/interface.go | 3 --- query/worker_test.go | 4 ---- 2 files changed, 7 deletions(-) diff --git a/query/interface.go b/query/interface.go index e6b1409f9..c02df978c 100644 --- a/query/interface.go +++ b/query/interface.go @@ -181,9 +181,6 @@ type Peer interface { // Addr returns the address of this peer. Addr() string - // ID returns the id of this peer. - ID() int32 - // Disconnect disconnects the peer. Disconnect() diff --git a/query/worker_test.go b/query/worker_test.go index 7e69ad709..d3ddd3e52 100644 --- a/query/worker_test.go +++ b/query/worker_test.go @@ -52,10 +52,6 @@ func (m *mockPeer) Addr() string { return m.addr } -func (m *mockPeer) ID() int32 { - return 0 -} - // makeJob returns a new query job that will be done when it is given the // finalResp message. Similarly ot will progress on being given the // progressResp message, while any other message will be ignored. From d53d13fc3c07afe61362b14b28328f444f25f479 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 1 Apr 2024 16:26:55 +0100 Subject: [PATCH 66/75] Fix more syncing issues --- mwebhandler.go | 3 +++ query/interface.go | 3 --- query/worker.go | 2 +- query/worker_test.go | 3 --- query/workmanager.go | 43 +++++++++++++++++++++++-------------------- rescan.go | 5 +++++ 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/mwebhandler.go b/mwebhandler.go index f1801f8af..f6982ca49 100644 --- a/mwebhandler.go +++ b/mwebhandler.go @@ -1,6 +1,8 @@ package neutrino import ( + "time" + "github.com/ltcsuite/ltcd/ltcutil/mweb" "github.com/ltcsuite/ltcd/wire" ) @@ -128,6 +130,7 @@ func (b *blockManager) mwebHandler() { return default: if !verified { + time.Sleep(time.Second) continue } } diff --git a/query/interface.go b/query/interface.go index c02df978c..19a09b481 100644 --- a/query/interface.go +++ b/query/interface.go @@ -181,9 +181,6 @@ type Peer interface { // Addr returns the address of this peer. Addr() string - // Disconnect disconnects the peer. - Disconnect() - // OnDisconnect returns a channel that will be closed when this peer is // disconnected. OnDisconnect() <-chan struct{} diff --git a/query/worker.go b/query/worker.go index 858e4e4ec..39abbec6f 100644 --- a/query/worker.go +++ b/query/worker.go @@ -26,6 +26,7 @@ var ( type queryJob struct { tries uint8 index uint64 + batch uint64 timeout time.Duration encoding wire.MessageEncoding cancelChan <-chan struct{} @@ -193,7 +194,6 @@ func (w *worker) Run(results chan<- *jobResult, quit <-chan struct{}) { "with job index %v", peer.Addr(), job.Req, job.Index()) - peer.Disconnect() break Loop // If the peer disconnects before giving us a valid diff --git a/query/worker_test.go b/query/worker_test.go index d3ddd3e52..23439c490 100644 --- a/query/worker_test.go +++ b/query/worker_test.go @@ -41,9 +41,6 @@ func (m *mockPeer) SubscribeRecvMsg() (<-chan wire.Message, func()) { return msgChan, func() {} } -func (m *mockPeer) Disconnect() { -} - func (m *mockPeer) OnDisconnect() <-chan struct{} { return m.quit } diff --git a/query/workmanager.go b/query/workmanager.go index 61e69096c..3697586b1 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -177,7 +177,7 @@ func (w *peerWorkManager) workDispatcher() { type batchProgress struct { noRetryMax bool maxRetries uint8 - rem int + jobs []*queryJob errChan chan error } @@ -199,10 +199,8 @@ func (w *peerWorkManager) workDispatcher() { batchTimeout := make(chan uint64) // We set up a counter that we'll increase with each incoming query, - // and will serve as the priority of each. In addition we map each - // query to the batch they are part of. + // and will serve as the priority of each. queryIndex := uint64(0) - currentQueries := make(map[uint64]uint64) workers := make(map[Peer]*activeWorker) @@ -302,12 +300,8 @@ Loop: r := workers[result.peer] r.activeJob = nil - // Get the index of this query's batch, and delete it - // from the map of current queries, since we don't have - // to track it anymore. We'll add it back if the result - // turns out to be an error. - batchNum := currentQueries[result.job.index] - delete(currentQueries, result.job.index) + // Get the index of this query's batch. + batchNum := result.job.batch batch := currentBatches[batchNum] switch { @@ -341,14 +335,14 @@ Loop: break } - if batch != nil && !batch.noRetryMax { + if !batch.noRetryMax { result.job.tries++ } // Check if this query has reached its maximum // number of retries. If so, remove it from the // batch and don't reschedule it. - if batch != nil && !batch.noRetryMax && + if !batch.noRetryMax && result.job.tries >= batch.maxRetries { log.Warnf("Query(%d) from peer %v "+ @@ -384,7 +378,6 @@ Loop: } heap.Push(work, result.job) - currentQueries[result.job.index] = batchNum // Otherwise, we got a successful result and update the // status of the batch this query is a part of. @@ -395,14 +388,21 @@ Loop: // Decrement the number of queries remaining in // the batch. if batch != nil { - batch.rem-- + var jobs []*queryJob + for _, job := range batch.jobs { + if job != result.job { + job.tries = 0 + jobs = append(jobs, job) + } + } + batch.jobs = jobs log.Tracef("Remaining jobs for batch "+ - "%v: %v ", batchNum, batch.rem) + "%v: %v ", batchNum, len(jobs)) // If this was the last query in flight // for this batch, we can notify that // it finished, and delete it. - if batch.rem == 0 { + if len(jobs) == 0 { batch.errChan <- nil delete(currentBatches, batchNum) @@ -432,22 +432,25 @@ Loop: log.Debugf("Adding new batch(%d) of %d queries to "+ "work queue", batchIndex, len(batch.requests)) + var jobs []*queryJob for _, q := range batch.requests { - heap.Push(work, &queryJob{ + job := &queryJob{ index: queryIndex, + batch: batchIndex, timeout: minQueryTimeout, encoding: batch.options.encoding, cancelChan: batch.options.cancelChan, Request: q, - }) - currentQueries[queryIndex] = batchIndex + } + heap.Push(work, job) + jobs = append(jobs, job) queryIndex++ } currentBatches[batchIndex] = &batchProgress{ noRetryMax: batch.options.noRetryMax, maxRetries: batch.options.numRetries, - rem: len(batch.requests), + jobs: jobs, errChan: batch.errChan, } diff --git a/rescan.go b/rescan.go index 50e22ec24..391310b03 100644 --- a/rescan.go +++ b/rescan.go @@ -688,6 +688,11 @@ rescanLoop: // until we reach the tip of the chain as we know it. At this // point, we'll be "current" again. case false: + select { + case <-ro.quit: + return ErrRescanExit + default: + } // Apply all queued filter updates. updateFilterLoop: From 2e8a94fda713cb02926ab81015048518c8aff136 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Mon, 1 Apr 2024 21:26:18 +0100 Subject: [PATCH 67/75] Also reset timeout --- query/worker.go | 1 + query/workmanager.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/query/worker.go b/query/worker.go index 39abbec6f..c9870cdd8 100644 --- a/query/worker.go +++ b/query/worker.go @@ -27,6 +27,7 @@ type queryJob struct { tries uint8 index uint64 batch uint64 + reset bool timeout time.Duration encoding wire.MessageEncoding cancelChan <-chan struct{} diff --git a/query/workmanager.go b/query/workmanager.go index 3697586b1..7f1494fba 100644 --- a/query/workmanager.go +++ b/query/workmanager.go @@ -342,7 +342,7 @@ Loop: // Check if this query has reached its maximum // number of retries. If so, remove it from the // batch and don't reschedule it. - if !batch.noRetryMax && + if !batch.noRetryMax && !result.job.reset && result.job.tries >= batch.maxRetries { log.Warnf("Query(%d) from peer %v "+ @@ -377,6 +377,12 @@ Loop: result.job.timeout = newTimeout } + if result.job.reset { + result.job.tries = 0 + result.job.reset = false + result.job.timeout = minQueryTimeout + } + heap.Push(work, result.job) // Otherwise, we got a successful result and update the @@ -391,7 +397,7 @@ Loop: var jobs []*queryJob for _, job := range batch.jobs { if job != result.job { - job.tries = 0 + job.reset = true jobs = append(jobs, job) } } From 8e37b254c2d04ee1cbc1f1e8549f26ff1d89feff Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 3 Apr 2024 12:13:58 +0100 Subject: [PATCH 68/75] Reduce lock hold time --- mempool.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mempool.go b/mempool.go index 4016e329e..1f9fa7618 100644 --- a/mempool.go +++ b/mempool.go @@ -46,19 +46,21 @@ func (mp *Mempool) HaveTransaction(hash *chainhash.Hash) bool { // maybe calls back if it matches any watched addresses. func (mp *Mempool) AddTransaction(tx *ltcutil.Tx) { mp.mtx.Lock() - defer mp.mtx.Unlock() mp.downloadedTxs[*tx.Hash()] = true ro := defaultRescanOptions() WatchAddrs(mp.watchedAddrs...)(ro) + callbacks := mp.callbacks + mp.mtx.Unlock() + if ok, err := ro.paysWatchedAddr(tx); ok && err == nil { - for _, cb := range mp.callbacks { + for _, cb := range callbacks { cb(tx) } } - if tx.MsgTx().Mweb != nil { - mp.blockManager.notifyMwebUtxos(tx.MsgTx().Mweb.TxBody.Outputs) + if mw := tx.MsgTx().Mweb; mw != nil { + mp.blockManager.notifyMwebUtxos(mw.TxBody.Outputs) } } From f732421611ace3eb1c9494b863bee67cc0c9eb7f Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Wed, 3 Apr 2024 20:51:09 +0100 Subject: [PATCH 69/75] Don't fail utxo lookup if leaf not found --- mwebdb/coindb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mwebdb/coindb.go b/mwebdb/coindb.go index c93d7d5b9..7ffec5c19 100644 --- a/mwebdb/coindb.go +++ b/mwebdb/coindb.go @@ -380,7 +380,7 @@ func (c *CoinStore) FetchLeaves(leaves []uint64) ([]*wire.MwebNetUtxo, error) { leafIndex := binary.LittleEndian.AppendUint64(nil, leaf) outputId := bytes.Clone(leafBucket.Get(leafIndex)) if outputId == nil { - return ErrLeafNotFound + continue } coinBytes := coinBucket.Get(outputId) From 9229dd0a253e0b05a2b7d8a9d90a7832eae5ef5c Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 27 Apr 2024 18:32:11 +0100 Subject: [PATCH 70/75] Error if no peers when sending --- query.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/query.go b/query.go index 4f8f4fd55..5d5e6182c 100644 --- a/query.go +++ b/query.go @@ -1076,9 +1076,8 @@ func (s *ChainService) sendTransaction(tx *wire.MsgTx, options ...QueryOption) e // error as the reliable broadcaster will take care of broadcasting this // transaction upon every block connected/disconnected. if len(replies) == 0 { - log.Debugf("No peers replied to inv message for transaction %v", + return fmt.Errorf("no peers replied to inv message for transaction %v", txHash) - return nil } // firstRejectWithCode returns the first reject error that we have for From 73f2c1a1cbfd02c2175bb3f3c32b3129f57172a3 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Fri, 10 May 2024 13:33:24 +0100 Subject: [PATCH 71/75] Update module name --- bamboozle_unit_test.go | 14 ++++++------- banman/store_test.go | 2 +- batch_spend_reporter.go | 4 ++-- blockmanager.go | 30 +++++++++++++-------------- blockmanager_test.go | 26 ++++++++++++------------ blockntfns/manager_test.go | 4 ++-- blockntfns/notification.go | 2 +- cache/go.mod | 2 +- cache/lru/lru.go | 2 +- cache/lru/lru_test.go | 2 +- cache_test.go | 14 ++++++------- cacheable_block.go | 2 +- cacheable_filter.go | 6 +++--- chainsync/filtercontrol.go | 6 +++--- chainsync/filtercontrol_test.go | 6 +++--- chanutils/queue.go | 2 +- filterdb/db.go | 8 ++++---- filterdb/db_test.go | 8 ++++---- go.mod | 2 +- headerfs/file.go | 4 ++-- headerfs/index.go | 2 +- headerfs/store.go | 10 ++++----- headerfs/store_test.go | 6 +++--- headerlist/header_list.go | 2 +- log.go | 20 +++++++++--------- mempool.go | 4 ++-- mock_store.go | 8 ++++---- mwebdb/coindb.go | 6 +++--- mwebhandler.go | 4 ++-- mwebheaders.go | 8 ++++---- mwebutxos.go | 10 ++++----- neutrino.go | 36 ++++++++++++++++----------------- notifications.go | 6 +++--- pushtx/broadcaster.go | 6 +++--- pushtx/broadcaster_test.go | 6 +++--- pushtx/error.go | 2 +- pushtx/error_test.go | 4 ++-- query.go | 22 ++++++++++---------- query/interface.go | 2 +- query/worker.go | 2 +- query/worker_test.go | 2 +- query_test.go | 22 ++++++++++---------- rescan.go | 22 ++++++++++---------- rescan_test.go | 18 ++++++++--------- sync_test.go | 26 ++++++++++++------------ tools/go.mod | 2 +- tools/tools.go | 2 +- utxoscanner.go | 6 +++--- utxoscanner_test.go | 10 ++++----- verification.go | 8 ++++---- verification_test.go | 14 ++++++------- 51 files changed, 222 insertions(+), 222 deletions(-) diff --git a/bamboozle_unit_test.go b/bamboozle_unit_test.go index 5108e9cf4..a7c0e2a95 100644 --- a/bamboozle_unit_test.go +++ b/bamboozle_unit_test.go @@ -7,14 +7,14 @@ import ( "sort" "testing" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/headerfs" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/neutrino/headerfs" ) func decodeHashNoError(str string) *chainhash.Hash { diff --git a/banman/store_test.go b/banman/store_test.go index 87ec9b002..cf53f4a1c 100644 --- a/banman/store_test.go +++ b/banman/store_test.go @@ -8,9 +8,9 @@ import ( "testing" "time" + "github.com/ltcmweb/neutrino/banman" "github.com/ltcsuite/ltcwallet/walletdb" _ "github.com/ltcsuite/ltcwallet/walletdb/bdb" - "github.com/ltcsuite/neutrino/banman" ) // createTestBanStore creates a test Store backed by a boltdb instance. diff --git a/batch_spend_reporter.go b/batch_spend_reporter.go index 31225848b..025ef9527 100644 --- a/batch_spend_reporter.go +++ b/batch_spend_reporter.go @@ -1,8 +1,8 @@ package neutrino import ( - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" ) // batchSpendReporter orchestrates the delivery of spend reports to diff --git a/blockmanager.go b/blockmanager.go index 8f48e32e2..524837cb3 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -12,21 +12,21 @@ import ( "sync/atomic" "time" - "github.com/ltcsuite/ltcd/blockchain" - "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/wire" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/chainsync" - "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/headerlist" - "github.com/ltcsuite/neutrino/mwebdb" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/chainsync" + "github.com/ltcmweb/neutrino/headerfs" + "github.com/ltcmweb/neutrino/headerlist" + "github.com/ltcmweb/neutrino/mwebdb" + "github.com/ltcmweb/neutrino/query" ) const ( diff --git a/blockmanager_test.go b/blockmanager_test.go index 3642a62e0..80cbf6b96 100644 --- a/blockmanager_test.go +++ b/blockmanager_test.go @@ -9,20 +9,20 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/integration/rpctest" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/peer" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/integration/rpctest" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/peer" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/headerfs" + "github.com/ltcmweb/neutrino/query" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/query" "github.com/stretchr/testify/require" ) diff --git a/blockntfns/manager_test.go b/blockntfns/manager_test.go index 1a0ce7ad8..32d83b533 100644 --- a/blockntfns/manager_test.go +++ b/blockntfns/manager_test.go @@ -5,8 +5,8 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/blockntfns" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/blockntfns" ) var emptyHeader wire.BlockHeader diff --git a/blockntfns/notification.go b/blockntfns/notification.go index 7fc15d4e4..01f6ee2c3 100644 --- a/blockntfns/notification.go +++ b/blockntfns/notification.go @@ -3,7 +3,7 @@ package blockntfns import ( "fmt" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/wire" ) // BlockNtfn is an interface that coalesces all the different types of block diff --git a/cache/go.mod b/cache/go.mod index 351d7d5d5..a18f5a8e5 100644 --- a/cache/go.mod +++ b/cache/go.mod @@ -1,4 +1,4 @@ -module github.com/ltcsuite/neutrino/cache +module github.com/ltcmweb/neutrino/cache go 1.18 diff --git a/cache/lru/lru.go b/cache/lru/lru.go index 87daac869..864826b0e 100644 --- a/cache/lru/lru.go +++ b/cache/lru/lru.go @@ -4,7 +4,7 @@ import ( "fmt" "sync" - "github.com/ltcsuite/neutrino/cache" + "github.com/ltcmweb/neutrino/cache" ) // entry represents a (key,value) pair entry in the Cache. The Cache's list diff --git a/cache/lru/lru_test.go b/cache/lru/lru_test.go index b8f712277..8035015be 100644 --- a/cache/lru/lru_test.go +++ b/cache/lru/lru_test.go @@ -4,7 +4,7 @@ import ( "sync" "testing" - "github.com/ltcsuite/neutrino/cache" + "github.com/ltcmweb/neutrino/cache" "github.com/stretchr/testify/require" ) diff --git a/cache_test.go b/cache_test.go index 824f51968..4cb5e44be 100644 --- a/cache_test.go +++ b/cache_test.go @@ -4,13 +4,13 @@ import ( "crypto/rand" "testing" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/cache" - "github.com/ltcsuite/neutrino/cache/lru" - "github.com/ltcsuite/neutrino/filterdb" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/cache" + "github.com/ltcmweb/neutrino/cache/lru" + "github.com/ltcmweb/neutrino/filterdb" ) // TestBlockFilterCaches tests that we can put and retrieve elements from all diff --git a/cacheable_block.go b/cacheable_block.go index 15d88aa12..ca2bd3657 100644 --- a/cacheable_block.go +++ b/cacheable_block.go @@ -1,6 +1,6 @@ package neutrino -import "github.com/ltcsuite/ltcd/ltcutil" +import "github.com/ltcmweb/ltcd/ltcutil" // CacheableBlock is a wrapper around the ltcutil.Block type which provides a // Size method used by the cache to target certain memory usage. diff --git a/cacheable_filter.go b/cacheable_filter.go index 642ebcee6..4a5a4ce85 100644 --- a/cacheable_filter.go +++ b/cacheable_filter.go @@ -1,9 +1,9 @@ package neutrino import ( - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/neutrino/filterdb" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/neutrino/filterdb" ) // FilterCacheKey represents the key used to access filters in the FilterCache. diff --git a/chainsync/filtercontrol.go b/chainsync/filtercontrol.go index 6cce098a8..5b037dda1 100644 --- a/chainsync/filtercontrol.go +++ b/chainsync/filtercontrol.go @@ -3,9 +3,9 @@ package chainsync import ( "fmt" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" ) // ErrCheckpointMismatch is returned if given filter headers don't pass our diff --git a/chainsync/filtercontrol_test.go b/chainsync/filtercontrol_test.go index 43ea4fc13..10a371c64 100644 --- a/chainsync/filtercontrol_test.go +++ b/chainsync/filtercontrol_test.go @@ -3,9 +3,9 @@ package chainsync import ( "testing" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" ) func TestControlCFHeader(t *testing.T) { diff --git a/chanutils/queue.go b/chanutils/queue.go index 481785239..b7b40b225 100644 --- a/chanutils/queue.go +++ b/chanutils/queue.go @@ -3,7 +3,7 @@ package chanutils import ( "sync" - "github.com/ltcsuite/neutrino/cache/lru" + "github.com/ltcmweb/neutrino/cache/lru" ) const ( diff --git a/filterdb/db.go b/filterdb/db.go index 8d0f450f9..2cdf8d75f 100644 --- a/filterdb/db.go +++ b/filterdb/db.go @@ -3,10 +3,10 @@ package filterdb import ( "fmt" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" "github.com/ltcsuite/ltcwallet/walletdb" ) diff --git a/filterdb/db_test.go b/filterdb/db_test.go index 5d1f8cfae..bf3440408 100644 --- a/filterdb/db_test.go +++ b/filterdb/db_test.go @@ -5,10 +5,10 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" "github.com/ltcsuite/ltcwallet/walletdb" _ "github.com/ltcsuite/ltcwallet/walletdb/bdb" "github.com/stretchr/testify/require" diff --git a/go.mod b/go.mod index 247b4f714..7ca280b53 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/ltcsuite/neutrino +module github.com/ltcmweb/neutrino require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f diff --git a/headerfs/file.go b/headerfs/file.go index 7486f61a8..aef73a941 100644 --- a/headerfs/file.go +++ b/headerfs/file.go @@ -5,8 +5,8 @@ import ( "fmt" "os" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" ) // ErrHeaderNotFound is returned when a target header on disk (flat file) can't diff --git a/headerfs/index.go b/headerfs/index.go index 45080199a..6233cb26a 100644 --- a/headerfs/index.go +++ b/headerfs/index.go @@ -6,7 +6,7 @@ import ( "fmt" "sort" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" "github.com/ltcsuite/ltcwallet/walletdb" ) diff --git a/headerfs/store.go b/headerfs/store.go index 3fdd98552..e2ea8da84 100644 --- a/headerfs/store.go +++ b/headerfs/store.go @@ -8,11 +8,11 @@ import ( "sync" "time" - "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" ) diff --git a/headerfs/store_test.go b/headerfs/store_test.go index f0b29263e..4d90925fe 100644 --- a/headerfs/store_test.go +++ b/headerfs/store_test.go @@ -12,9 +12,9 @@ import ( "time" "github.com/davecgh/go-spew/spew" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" ) diff --git a/headerlist/header_list.go b/headerlist/header_list.go index b26061e28..cdee23557 100644 --- a/headerlist/header_list.go +++ b/headerlist/header_list.go @@ -1,6 +1,6 @@ package headerlist -import "github.com/ltcsuite/ltcd/wire" +import "github.com/ltcmweb/ltcd/wire" // Chain is an interface that stores a list of Nodes. Each node represents a // header in the main chain and also includes a height along with it. This is diff --git a/log.go b/log.go index 49a4bf3f1..61bf161ac 100644 --- a/log.go +++ b/log.go @@ -2,16 +2,16 @@ package neutrino import ( "github.com/btcsuite/btclog" - "github.com/ltcsuite/ltcd/addrmgr" - "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/connmgr" - "github.com/ltcsuite/ltcd/peer" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/chanutils" - "github.com/ltcsuite/neutrino/filterdb" - "github.com/ltcsuite/neutrino/pushtx" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/addrmgr" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/connmgr" + "github.com/ltcmweb/ltcd/peer" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/chanutils" + "github.com/ltcmweb/neutrino/filterdb" + "github.com/ltcmweb/neutrino/pushtx" + "github.com/ltcmweb/neutrino/query" ) // log is a logger that is initialized with no output filters. This diff --git a/mempool.go b/mempool.go index 1f9fa7618..b85a48589 100644 --- a/mempool.go +++ b/mempool.go @@ -3,8 +3,8 @@ package neutrino import ( "sync" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" ) // Mempool is used when we are downloading unconfirmed transactions. diff --git a/mock_store.go b/mock_store.go index 5c56635cc..2249b83e0 100644 --- a/mock_store.go +++ b/mock_store.go @@ -3,10 +3,10 @@ package neutrino import ( "fmt" - "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/headerfs" ) // mockBlockHeaderStore is an implementation of the BlockHeaderStore backed by diff --git a/mwebdb/coindb.go b/mwebdb/coindb.go index 7ffec5c19..cc958edbe 100644 --- a/mwebdb/coindb.go +++ b/mwebdb/coindb.go @@ -5,9 +5,9 @@ import ( "encoding/binary" "fmt" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/mweb" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/wire" "github.com/ltcsuite/ltcwallet/walletdb" ) diff --git a/mwebhandler.go b/mwebhandler.go index f6982ca49..112b46e9e 100644 --- a/mwebhandler.go +++ b/mwebhandler.go @@ -3,8 +3,8 @@ package neutrino import ( "time" - "github.com/ltcsuite/ltcd/ltcutil/mweb" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/wire" ) // mwebHandler is the mweb download handler for the block manager. It must be diff --git a/mwebheaders.go b/mwebheaders.go index e48935d81..c4c6bae3e 100644 --- a/mwebheaders.go +++ b/mwebheaders.go @@ -3,10 +3,10 @@ package neutrino import ( "slices" - "github.com/ltcsuite/ltcd/ltcutil/mweb" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/query" ) // mwebHeadersQuery holds all information necessary to perform and diff --git a/mwebutxos.go b/mwebutxos.go index a5e2267cf..76a581831 100644 --- a/mwebutxos.go +++ b/mwebutxos.go @@ -4,11 +4,11 @@ import ( "cmp" "slices" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil/mweb" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/query" ) // mwebUtxosQuery holds all information necessary to perform and diff --git a/neutrino.go b/neutrino.go index 739012f08..6dcef9b63 100644 --- a/neutrino.go +++ b/neutrino.go @@ -13,25 +13,25 @@ import ( "sync/atomic" "time" - "github.com/ltcsuite/ltcd/addrmgr" - "github.com/ltcsuite/ltcd/blockchain" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/connmgr" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/mweb" - "github.com/ltcsuite/ltcd/peer" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/addrmgr" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/connmgr" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/mweb" + "github.com/ltcmweb/ltcd/peer" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/cache/lru" + "github.com/ltcmweb/neutrino/chanutils" + "github.com/ltcmweb/neutrino/filterdb" + "github.com/ltcmweb/neutrino/headerfs" + "github.com/ltcmweb/neutrino/mwebdb" + "github.com/ltcmweb/neutrino/pushtx" + "github.com/ltcmweb/neutrino/query" "github.com/ltcsuite/ltcwallet/walletdb" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/cache/lru" - "github.com/ltcsuite/neutrino/chanutils" - "github.com/ltcsuite/neutrino/filterdb" - "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/mwebdb" - "github.com/ltcsuite/neutrino/pushtx" - "github.com/ltcsuite/neutrino/query" ) // These are exported variables so they can be changed by users. diff --git a/notifications.go b/notifications.go index 01347bafb..c6f700209 100644 --- a/notifications.go +++ b/notifications.go @@ -9,9 +9,9 @@ package neutrino import ( "errors" - "github.com/ltcsuite/ltcd/addrmgr" - "github.com/ltcsuite/ltcd/connmgr" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/addrmgr" + "github.com/ltcmweb/ltcd/connmgr" + "github.com/ltcmweb/neutrino/query" ) type getConnCountMsg struct { diff --git a/pushtx/broadcaster.go b/pushtx/broadcaster.go index 6e7cae61f..96ef16428 100644 --- a/pushtx/broadcaster.go +++ b/pushtx/broadcaster.go @@ -6,10 +6,10 @@ import ( "sync" "time" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/blockntfns" "github.com/ltcsuite/ltcwallet/wtxmgr" - "github.com/ltcsuite/neutrino/blockntfns" ) var ( diff --git a/pushtx/broadcaster_test.go b/pushtx/broadcaster_test.go index 02ea5aaee..3e7c4a38a 100644 --- a/pushtx/broadcaster_test.go +++ b/pushtx/broadcaster_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/btcjson" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/blockntfns" + "github.com/ltcmweb/ltcd/btcjson" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/blockntfns" ) // createTx is a helper method to create random transactions that spend diff --git a/pushtx/error.go b/pushtx/error.go index 82933a3a2..7b7930754 100644 --- a/pushtx/error.go +++ b/pushtx/error.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/wire" ) // BroadcastErrorCode uniquely identifies the broadcast error. diff --git a/pushtx/error_test.go b/pushtx/error_test.go index 0052c7d66..bf501ffa7 100644 --- a/pushtx/error_test.go +++ b/pushtx/error_test.go @@ -3,8 +3,8 @@ package pushtx_test import ( "testing" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/pushtx" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/pushtx" ) // TestParseBroadcastErrorCode ensures that we properly construct a diff --git a/query.go b/query.go index 5d5e6182c..cb4d9b14a 100644 --- a/query.go +++ b/query.go @@ -7,17 +7,17 @@ import ( "sync" "time" - "github.com/ltcsuite/ltcd/blockchain" - "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/wire" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/cache" - "github.com/ltcsuite/neutrino/filterdb" - "github.com/ltcsuite/neutrino/pushtx" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/cache" + "github.com/ltcmweb/neutrino/filterdb" + "github.com/ltcmweb/neutrino/pushtx" + "github.com/ltcmweb/neutrino/query" ) var ( diff --git a/query/interface.go b/query/interface.go index 19a09b481..931507b17 100644 --- a/query/interface.go +++ b/query/interface.go @@ -3,7 +3,7 @@ package query import ( "time" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/wire" ) const ( diff --git a/query/worker.go b/query/worker.go index c9870cdd8..4fffca2df 100644 --- a/query/worker.go +++ b/query/worker.go @@ -4,7 +4,7 @@ import ( "errors" "time" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/wire" ) var ( diff --git a/query/worker_test.go b/query/worker_test.go index 23439c490..e6fbb10bc 100644 --- a/query/worker_test.go +++ b/query/worker_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/wire" ) var ( diff --git a/query_test.go b/query_test.go index b42d56e93..bda2117e0 100644 --- a/query_test.go +++ b/query_test.go @@ -12,17 +12,17 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/blockchain" - "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/wire" - "github.com/ltcsuite/neutrino/cache/lru" - "github.com/ltcsuite/neutrino/filterdb" - "github.com/ltcsuite/neutrino/headerfs" - "github.com/ltcsuite/neutrino/query" + "github.com/ltcmweb/ltcd/blockchain" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/cache/lru" + "github.com/ltcmweb/neutrino/filterdb" + "github.com/ltcmweb/neutrino/headerfs" + "github.com/ltcmweb/neutrino/query" "github.com/stretchr/testify/require" ) diff --git a/rescan.go b/rescan.go index 391310b03..4128b5ae1 100644 --- a/rescan.go +++ b/rescan.go @@ -10,17 +10,17 @@ import ( "sync/atomic" "time" - "github.com/ltcsuite/ltcd/btcjson" - "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/rpcclient" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcmweb/ltcd/btcjson" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/rpcclient" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/headerfs" ) var ( diff --git a/rescan_test.go b/rescan_test.go index 1c750650c..f1ff3a36c 100644 --- a/rescan_test.go +++ b/rescan_test.go @@ -10,15 +10,15 @@ import ( "time" "github.com/davecgh/go-spew/spew" - "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/rpcclient" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/blockntfns" - "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/rpcclient" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/blockntfns" + "github.com/ltcmweb/neutrino/headerfs" ) // mockChainSource is a mock implementation of the ChainSource interface that diff --git a/sync_test.go b/sync_test.go index 2fdad8035..18b8d9295 100644 --- a/sync_test.go +++ b/sync_test.go @@ -15,23 +15,23 @@ import ( "time" "github.com/btcsuite/btclog" - "github.com/ltcsuite/ltcd/btcec/v2" - "github.com/ltcsuite/ltcd/btcjson" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/integration/rpctest" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/rpcclient" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/btcec/v2" + "github.com/ltcmweb/ltcd/btcjson" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/integration/rpctest" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/rpcclient" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino" + "github.com/ltcmweb/neutrino/banman" + "github.com/ltcmweb/neutrino/headerfs" "github.com/ltcsuite/ltcwallet/waddrmgr" "github.com/ltcsuite/ltcwallet/wallet/txauthor" "github.com/ltcsuite/ltcwallet/walletdb" _ "github.com/ltcsuite/ltcwallet/walletdb/bdb" - "github.com/ltcsuite/neutrino" - "github.com/ltcsuite/neutrino/banman" - "github.com/ltcsuite/neutrino/headerfs" ) var ( diff --git a/tools/go.mod b/tools/go.mod index 6e42be734..b358deac9 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,4 +1,4 @@ -module github.com/ltcsuite/neutrino/tools +module github.com/ltcmweb/neutrino/tools go 1.18 diff --git a/tools/tools.go b/tools/tools.go index 45bab5863..c8064ff1a 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -9,7 +9,7 @@ package neutrino // dependencies here and pin the version in go.mod. import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint" - _ "github.com/ltcsuite/ltcd" + _ "github.com/ltcmweb/ltcd" _ "github.com/ory/go-acc" _ "github.com/rinchsan/gosimports/cmd/gosimports" ) diff --git a/utxoscanner.go b/utxoscanner.go index b6b3e0245..0be794d8d 100644 --- a/utxoscanner.go +++ b/utxoscanner.go @@ -6,9 +6,9 @@ import ( "sync/atomic" "time" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/neutrino/headerfs" ) // getUtxoResult is a simple pair type holding a spend report and error. diff --git a/utxoscanner_test.go b/utxoscanner_test.go index 30b0f225b..8f762dc5d 100644 --- a/utxoscanner_test.go +++ b/utxoscanner_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" - "github.com/ltcsuite/ltcd/chaincfg/chainhash" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/wire" - "github.com/ltcsuite/neutrino/headerfs" + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/wire" + "github.com/ltcmweb/neutrino/headerfs" ) type MockChainClient struct { diff --git a/verification.go b/verification.go index 7e6e2ed46..b758bfde2 100644 --- a/verification.go +++ b/verification.go @@ -3,10 +3,10 @@ package neutrino import ( "fmt" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/txscript" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/txscript" ) // VerifyBasicBlockFilter asserts that a given block filter was constructed diff --git a/verification_test.go b/verification_test.go index ba2bd0a70..859f2cb08 100644 --- a/verification_test.go +++ b/verification_test.go @@ -4,13 +4,13 @@ import ( "crypto/sha256" "testing" - "github.com/ltcsuite/ltcd/btcec/v2" - "github.com/ltcsuite/ltcd/chaincfg" - "github.com/ltcsuite/ltcd/ltcutil" - "github.com/ltcsuite/ltcd/ltcutil/gcs" - "github.com/ltcsuite/ltcd/ltcutil/gcs/builder" - "github.com/ltcsuite/ltcd/txscript" - "github.com/ltcsuite/ltcd/wire" + "github.com/ltcmweb/ltcd/btcec/v2" + "github.com/ltcmweb/ltcd/chaincfg" + "github.com/ltcmweb/ltcd/ltcutil" + "github.com/ltcmweb/ltcd/ltcutil/gcs" + "github.com/ltcmweb/ltcd/ltcutil/gcs/builder" + "github.com/ltcmweb/ltcd/txscript" + "github.com/ltcmweb/ltcd/wire" "github.com/stretchr/testify/require" ) From 90f5e669d36a57a393f2950819464722b0834b31 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 11 May 2024 12:23:37 +0100 Subject: [PATCH 72/75] go mod tidy --- Makefile | 4 +- cache/go.sum | 13 ++++ go.mod | 31 ++++++++- go.sum | 155 ++++++++++++++++++++++++++++++++++++++++-- pushtx/broadcaster.go | 3 +- pushtx/kahnsort.go | 117 +++++++++++++++++++++++++++++++ tools/go.mod | 12 ++-- tools/go.sum | 128 ++++++++++++++++++++++++++++++---- 8 files changed, 430 insertions(+), 33 deletions(-) create mode 100644 pushtx/kahnsort.go diff --git a/Makefile b/Makefile index bffaf34c8..c29aa3b85 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -PKG := github.com/ltcsuite/neutrino +PKG := github.com/ltcmweb/neutrino TOOLS_DIR := tools -LTCD_PKG := github.com/ltcsuite/ltcd +LTCD_PKG := github.com/ltcmweb/ltcd LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint GOACC_PKG := github.com/ory/go-acc GOIMPORTS_PKG := github.com/rinchsan/gosimports/cmd/gosimports diff --git a/cache/go.sum b/cache/go.sum index 4501d63e6..042242a06 100644 --- a/cache/go.sum +++ b/cache/go.sum @@ -1,12 +1,25 @@ +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.mod b/go.mod index 7ca280b53..eeb1b3cf7 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,40 @@ module github.com/ltcmweb/neutrino require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/davecgh/go-spew v1.1.1 + github.com/ltcmweb/ltcd v0.24.2 + github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 + github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 + github.com/ltcmweb/ltcd/ltcutil v1.2.2 + github.com/ltcmweb/neutrino/cache v1.1.0 + github.com/ltcsuite/lnd/queue v1.1.0 + github.com/ltcsuite/ltcwallet v0.13.1 + github.com/ltcsuite/ltcwallet/wallet/txauthor v1.1.0 + github.com/ltcsuite/ltcwallet/walletdb v1.3.5 github.com/stretchr/testify v1.8.3 ) require ( - github.com/kr/pretty v0.3.0 // indirect + github.com/aead/siphash v1.0.1 // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/decred/dcrd/lru v1.1.1 // indirect + github.com/kkdai/bstream v1.0.0 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/ltcsuite/lnd/ticker v1.0.1 // indirect + github.com/ltcsuite/ltcd v0.22.0-beta // indirect + github.com/ltcsuite/ltcd/btcec/v2 v2.1.0 // indirect + github.com/ltcsuite/ltcd/ltcutil v1.1.0 // indirect + github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 // indirect + github.com/ltcsuite/ltcwallet/wallet/txsizes v1.1.0 // indirect + github.com/ltcsuite/neutrino v0.13.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/sys v0.13.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.2.1 // indirect ) go 1.18 diff --git a/go.sum b/go.sum index 1cb349576..60da01016 100644 --- a/go.sum +++ b/go.sum @@ -1,25 +1,166 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y= +github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= +github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= +github.com/ltcmweb/ltcd v0.24.2 h1:ol1nZfp0YSmwY4dxEdiApRYX2mKC6Ph7W0f6bK7ahnE= +github.com/ltcmweb/ltcd v0.24.2/go.mod h1:TR9HEIp8c0B+jrNFPgAPf5e48vyoy1agEVKk8sMoaEc= +github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE= +github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI= +github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM= +github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= +github.com/ltcmweb/ltcd/ltcutil v1.2.2 h1:GQI4bdMwgrMz8ClO2cOPSNs80E6I0ixTSk9DgA3dyxU= +github.com/ltcmweb/ltcd/ltcutil v1.2.2/go.mod h1:ezd8H9vagau9j+/STipVxok78u01b7xlj2ImrFbGhkQ= +github.com/ltcmweb/neutrino/cache v0.0.0-20240510123324-73f2c1a1cbfd h1:d2q/We71MeLWqZa7S5GmWMIsHrsAhFJySGSGKNUuE+U= +github.com/ltcmweb/neutrino/cache v0.0.0-20240510123324-73f2c1a1cbfd/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME= +github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= +github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= +github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= +github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2PEq7IexlTWQ= +github.com/ltcsuite/lnd/ticker v1.0.1 h1:+0KvqE4HYO+fFPgNo+42hhyEjK0DwBp//IPmkLhCMcI= +github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4= +github.com/ltcsuite/ltcd v0.20.1-beta/go.mod h1:ZFQaYdYULIuTQiWqs7AUiHD2XhDFeeHW1IH+UYMdABU= +github.com/ltcsuite/ltcd v0.22.0-beta h1:jYVHOeg2oBDvsduV26LtCZnzwifMDWoVbkdHTjGvHTk= +github.com/ltcsuite/ltcd v0.22.0-beta/go.mod h1:/BXtm50r591uMfXf8XgSpL5er32HCvheJtBSPYK5bFM= +github.com/ltcsuite/ltcd/btcec/v2 v2.1.0 h1:0DMWBjQDb0V1+4kCLOJlNdHs7ewwYturuUfLHq8mosY= +github.com/ltcsuite/ltcd/btcec/v2 v2.1.0/go.mod h1:Vc9ZYXMcl5D6bA0VwMvGRDJYggO3YZ7/BuIri02Lq0E= +github.com/ltcsuite/ltcd/ltcutil v1.1.0 h1:btwbdHO9cEr22zW/vgCLiF6ghh+IDngJdJsyhJ6mntU= +github.com/ltcsuite/ltcd/ltcutil v1.1.0/go.mod h1:VbZlcopVgQteiCC5KRjIuxXH5wi1CtzhsvoYZ3K7FaE= +github.com/ltcsuite/ltcd/ltcutil/psbt v1.1.0-1/go.mod h1:jpDQOdehihA+lu9OW26YgHSJ+6lReEb8HNcQL5grC4k= +github.com/ltcsuite/ltcutil v0.0.0-20191227053721-6bec450ea6ad/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= +github.com/ltcsuite/ltcwallet v0.13.1 h1:XMyrDHn0BmgUgkNbR/Lzg36vjRsup3xdiPLSD471UMg= +github.com/ltcsuite/ltcwallet v0.13.1/go.mod h1:e6pIWRM9gsd5JnMsI9SgCJM0wi7awWdr20F1C1KUPiw= +github.com/ltcsuite/ltcwallet/wallet/txauthor v1.1.0 h1:MaSgMq7LCB+6dVm9oLzNCVp0lmY1WKmevmMK/t2c6To= +github.com/ltcsuite/ltcwallet/wallet/txauthor v1.1.0/go.mod h1:I53YELeELfA+dVporL+t44O8ArpuF8AjdJbbWIQaE2Q= +github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0 h1:P6H9zsMpBBuGOsp9lnil7XfPaPujDqrbcmkqvDdiSiI= +github.com/ltcsuite/ltcwallet/wallet/txrules v1.2.0/go.mod h1:lmA2Ozxvbr2M8Mqb6ugOv5/FQT6x2Qnwg3yT/NiWEks= +github.com/ltcsuite/ltcwallet/wallet/txsizes v1.1.0 h1:W884jMwG3K3Hu8FEMnV7KX1bd4HQd/4yvaevisFo9s8= +github.com/ltcsuite/ltcwallet/wallet/txsizes v1.1.0/go.mod h1:G9+XTWnE0xaXzHRzTuP+SOIXFPXFMfYF+w/wxPHb0K8= +github.com/ltcsuite/ltcwallet/walletdb v1.3.5 h1:WymVw0FBQ8KJgH7B88ujRqBOJ9R0en9K9urpJW4atAE= +github.com/ltcsuite/ltcwallet/walletdb v1.3.5/go.mod h1:29SBzxA55wNxY3ctFw6t5PgsULwf3NMwg2MiGQgtrJE= +github.com/ltcsuite/ltcwallet/wtxmgr v1.5.0/go.mod h1:jAnztxV6d2JykUlGLCO5yNvtosmFaGMshBx0kps+K+M= +github.com/ltcsuite/neutrino v0.13.2 h1:SDbRn4zt4e6z/4uVkVzVeKYpgXyoAh8ksA3m/uCIBaU= +github.com/ltcsuite/neutrino v0.13.2/go.mod h1:eTkaETZBeu3es/FisfjY8Cp3M2fC4s+2V2VUeS8O1Ic= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50 h1:ASw9n1EHMftwnP3Az4XW6e308+gNsrHzmdhd0Olz9Hs= +go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= +lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/pushtx/broadcaster.go b/pushtx/broadcaster.go index 96ef16428..9d1a93764 100644 --- a/pushtx/broadcaster.go +++ b/pushtx/broadcaster.go @@ -9,7 +9,6 @@ import ( "github.com/ltcmweb/ltcd/chaincfg/chainhash" "github.com/ltcmweb/ltcd/wire" "github.com/ltcmweb/neutrino/blockntfns" - "github.com/ltcsuite/ltcwallet/wtxmgr" ) var ( @@ -235,7 +234,7 @@ func (b *Broadcaster) rebroadcast(txs map[chainhash.Hash]*wire.MsgTx, log.Debugf("Re-broadcasting %d transactions", len(txs)) - sortedTxs := wtxmgr.DependencySort(txs) + sortedTxs := DependencySort(txs) for _, tx := range sortedTxs { // Before attempting to broadcast this transaction, we check // whether we are shutting down. diff --git a/pushtx/kahnsort.go b/pushtx/kahnsort.go new file mode 100644 index 000000000..cc6b83510 --- /dev/null +++ b/pushtx/kahnsort.go @@ -0,0 +1,117 @@ +// 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. + +package pushtx + +import ( + "github.com/ltcmweb/ltcd/chaincfg/chainhash" + "github.com/ltcmweb/ltcd/wire" +) + +type graphNode struct { + value *wire.MsgTx + outEdges []*chainhash.Hash + inDegree int +} + +type hashGraph map[chainhash.Hash]graphNode + +func makeGraph(set map[chainhash.Hash]*wire.MsgTx) hashGraph { + graph := make(hashGraph) + + for _, tx := range set { + // Add a node for every transaction. The output edges and input + // degree are set by iterating over each transaction's inputs + // below. + txHash := tx.TxHash() + if _, ok := graph[txHash]; !ok { + graph[txHash] = graphNode{value: tx} + } + + inputLoop: + for _, input := range tx.TxIn { + // Transaction inputs that reference transactions not + // included in the set do not create any (local) graph + // edges. + if _, ok := set[input.PreviousOutPoint.Hash]; !ok { + continue + } + + inputNode := graph[input.PreviousOutPoint.Hash] + + // Skip duplicate edges. + for _, outEdge := range inputNode.outEdges { + if *outEdge == input.PreviousOutPoint.Hash { + continue inputLoop + } + } + + // Mark a directed edge from the previous transaction + // hash to this transaction and increase the input + // degree for this transaction's node. + inputTx := inputNode.value + if inputTx == nil { + inputTx = set[input.PreviousOutPoint.Hash] + } + graph[input.PreviousOutPoint.Hash] = graphNode{ + value: inputTx, + outEdges: append(inputNode.outEdges, &txHash), + inDegree: inputNode.inDegree, + } + node := graph[txHash] + graph[txHash] = graphNode{ + value: tx, + outEdges: node.outEdges, + inDegree: node.inDegree + 1, + } + } + } + + return graph +} + +// graphRoots returns the roots of the graph. That is, it returns the node's +// values for all nodes which contain an input degree of 0. +func graphRoots(graph hashGraph) []*wire.MsgTx { + roots := make([]*wire.MsgTx, 0, len(graph)) + for _, node := range graph { + if node.inDegree == 0 { + roots = append(roots, node.value) + } + } + return roots +} + +// DependencySort topologically sorts a set of transactions by their dependency +// order. It is implemented using Kahn's algorithm. +func DependencySort(txs map[chainhash.Hash]*wire.MsgTx) []*wire.MsgTx { + graph := makeGraph(txs) + s := graphRoots(graph) + + // If there are no edges (no transactions from the map reference each + // other), then Kahn's algorithm is unnecessary. + if len(s) == len(txs) { + return s + } + + sorted := make([]*wire.MsgTx, 0, len(txs)) + for len(s) != 0 { + tx := s[0] + s = s[1:] + sorted = append(sorted, tx) + + n := graph[tx.TxHash()] + for _, mHash := range n.outEdges { + m := graph[*mHash] + if m.inDegree != 0 { + m.inDegree-- + graph[*mHash] = m + if m.inDegree == 0 { + s = append(s, m.value) + } + } + } + } + return sorted +} diff --git a/tools/go.mod b/tools/go.mod index b358deac9..88e38015d 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/golangci/golangci-lint v1.52.2 - github.com/ltcsuite/ltcd v0.23.5 + github.com/ltcmweb/ltcd v0.24.2 github.com/ory/go-acc v0.2.8 github.com/rinchsan/gosimports v0.1.5 ) @@ -108,9 +108,9 @@ require ( github.com/ldez/gomoddirectives v0.2.3 // indirect github.com/ldez/tagliatelle v0.4.0 // indirect github.com/leonklingele/grouper v1.1.1 // indirect - github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 // indirect - github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 // indirect - github.com/ltcsuite/ltcd/ltcutil v1.1.3 // indirect + github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 // indirect + github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 // indirect + github.com/ltcmweb/ltcd/ltcutil v1.2.2 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/maratori/testableexamples v1.0.0 // indirect @@ -130,8 +130,8 @@ require ( github.com/nishanths/exhaustive v0.9.5 // indirect github.com/nishanths/predeclared v0.2.2 // indirect github.com/nunnatsa/ginkgolinter v0.9.0 // indirect + github.com/nxadm/tail v1.4.8 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/onsi/ginkgo v1.16.4 // indirect github.com/ory/viper v1.7.5 // indirect github.com/pborman/uuid v1.2.0 // indirect github.com/pelletier/go-toml v1.9.5 // indirect @@ -147,7 +147,6 @@ require ( github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/rivo/uniseg v0.2.0 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect @@ -198,7 +197,6 @@ require ( golang.org/x/text v0.9.0 // indirect golang.org/x/tools v0.9.1 // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/tools/go.sum b/tools/go.sum index 639bc0657..5a660a320 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,5 +1,7 @@ 4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= +4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= 4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= +4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -39,8 +41,11 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= +github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= github.com/Antonboom/errname v0.1.9 h1:BZDX4r3l4TBZxZ2o2LNrlGxSHran4d1u4veZdoORTT4= +github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= github.com/Antonboom/nilnil v0.1.3 h1:6RTbx3d2mcEu3Zwq9TowQpQMVpP75zugwOtqY1RTtcE= +github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -68,6 +73,7 @@ github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQ github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= +github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -80,8 +86,11 @@ github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbz github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= +github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= +github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= +github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= @@ -98,8 +107,11 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -117,6 +129,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= +github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -124,8 +137,8 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/decred/dcrd/lru v1.1.1 h1:kWFDaW0OWx6AD6Ki342c+JPmHbiVdE6rK81pT3fuo/Y= +github.com/decred/dcrd/lru v1.1.1/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/denis-tingaikin/go-header v0.4.3 h1:tEaZKAlqql6SKCY++utLmkPLd6K8IBM20Ha7UVm+mtU= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE= @@ -146,6 +159,7 @@ github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcH github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= @@ -159,6 +173,7 @@ github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ= +github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -171,16 +186,24 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= +github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -216,6 +239,7 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= @@ -227,11 +251,13 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPSh github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= github.com/golangci/golangci-lint v1.52.2 h1:FrPElUUI5rrHXg1mQ7KxI1MXPAw5lBVskiz7U7a8a1A= +github.com/golangci/golangci-lint v1.52.2/go.mod h1:S5fhC5sHM5kE22/HcATKd1XLWQxX+y7mHj8B5H91Q/0= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= +github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= @@ -248,6 +274,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -276,6 +303,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= @@ -293,6 +321,7 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -310,8 +339,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= @@ -334,11 +363,14 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= +github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= +github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= +github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -358,18 +390,21 @@ github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dq github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= +github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= +github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= -github.com/ltcsuite/ltcd v0.23.5 h1:MFWjmx2hCwxrUu9v0wdIPOSN7PHg9BWQeh+AO4FsVLI= -github.com/ltcsuite/ltcd v0.23.5/go.mod h1:JV6swXR5m0cYFi0VYdQPp3UnMdaDQxaRUCaU1PPjb+g= -github.com/ltcsuite/ltcd/btcec/v2 v2.3.2 h1:HVArUNQGqGaSSoyYkk9qGht74U0/uNhS0n7jV9rkmno= -github.com/ltcsuite/ltcd/btcec/v2 v2.3.2/go.mod h1:T1t5TjbjPnryvlGQ+RpSKGuU8KhjNN7rS5+IznPj1VM= -github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2 h1:xuWxvRKxLvOKuS7/Q/7I3tpc3cWAB0+hZpU8YdVqkzg= -github.com/ltcsuite/ltcd/chaincfg/chainhash v1.0.2/go.mod h1:nkLkAFGhursWf2U68gt61hPieK1I+0m78e+2aevNyD8= -github.com/ltcsuite/ltcd/ltcutil v1.1.3 h1:8AapjCPLIt/wtYe6Odfk1EC2y9mcbpgjyxyCoNjAkFI= -github.com/ltcsuite/ltcd/ltcutil v1.1.3/go.mod h1:z8txd/ohBFrOMBUT70K8iZvHJD/Vc3gzx+6BP6cBxQw= +github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/ltcmweb/ltcd v0.24.2 h1:ol1nZfp0YSmwY4dxEdiApRYX2mKC6Ph7W0f6bK7ahnE= +github.com/ltcmweb/ltcd v0.24.2/go.mod h1:TR9HEIp8c0B+jrNFPgAPf5e48vyoy1agEVKk8sMoaEc= +github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE= +github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI= +github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM= +github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= +github.com/ltcmweb/ltcd/ltcutil v1.2.2 h1:GQI4bdMwgrMz8ClO2cOPSNs80E6I0ixTSk9DgA3dyxU= +github.com/ltcmweb/ltcd/ltcutil v1.2.2/go.mod h1:ezd8H9vagau9j+/STipVxok78u01b7xlj2ImrFbGhkQ= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -379,20 +414,25 @@ github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mgechev/revive v1.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= +github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -405,6 +445,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= +github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= @@ -412,11 +453,14 @@ github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4N github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= +github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= +github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -454,6 +498,7 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v1.4.0 h1:b+sQ5HibPIAjEZwtuwU8Wz/u0dMZ7YL+bk+9yWyHVJk= +github.com/polyfloyd/go-errorlint v1.4.0/go.mod h1:qJCkPeBn+0EXkdKTrUCcuFStM2xrDKfxI3MGLXPexUs= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -466,6 +511,7 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1: github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -482,25 +528,34 @@ github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= +github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rinchsan/gosimports v0.1.5 h1:Z/l9lS79z0xgKC6fLJYmDdY44D0LFwo3MzaMtWvMKpY= github.com/rinchsan/gosimports v0.1.5/go.mod h1:102/jU2cwf9fpa/YM9D9o4gSen2Vg8Jl80Sxctgd9N0= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= +github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= +github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= +github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= +github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= +github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -510,16 +565,20 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYIc1yrHI= github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= +github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= +github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -532,6 +591,7 @@ github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -549,6 +609,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -557,14 +618,18 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= +github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= @@ -572,9 +637,12 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1: github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= +github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= +github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= @@ -615,6 +683,7 @@ go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -623,11 +692,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -639,8 +708,11 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= +golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -669,7 +741,10 @@ golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -712,6 +787,11 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -735,7 +815,9 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -783,6 +865,7 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -801,9 +884,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -813,7 +906,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -886,7 +983,12 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -983,6 +1085,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1010,7 +1113,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1019,6 +1121,7 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= +honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= @@ -1028,6 +1131,7 @@ mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIa mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From a4a65ddea2457378a9c33df8f08cc711a863d9e2 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 11 May 2024 12:52:16 +0100 Subject: [PATCH 73/75] go mod tidy --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 60da01016..6d918838e 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= github.com/ltcmweb/ltcd/ltcutil v1.2.2 h1:GQI4bdMwgrMz8ClO2cOPSNs80E6I0ixTSk9DgA3dyxU= github.com/ltcmweb/ltcd/ltcutil v1.2.2/go.mod h1:ezd8H9vagau9j+/STipVxok78u01b7xlj2ImrFbGhkQ= -github.com/ltcmweb/neutrino/cache v0.0.0-20240510123324-73f2c1a1cbfd h1:d2q/We71MeLWqZa7S5GmWMIsHrsAhFJySGSGKNUuE+U= -github.com/ltcmweb/neutrino/cache v0.0.0-20240510123324-73f2c1a1cbfd/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME= +github.com/ltcmweb/neutrino/cache v1.1.0 h1:C0Qn2p8ogcskRPfrBKPUayjn3m/CUJqI7otopNScvhk= +github.com/ltcmweb/neutrino/cache v1.1.0/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME= github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= From 5bd91a43cd936a13d74876be0f30f73f1c6c43a9 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Sat, 11 May 2024 15:24:01 +0100 Subject: [PATCH 74/75] go mod tidy --- go.mod | 5 +++-- go.sum | 10 ++++++---- tools/go.mod | 5 +++-- tools/go.sum | 10 ++++++---- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index eeb1b3cf7..5708da314 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module github.com/ltcmweb/neutrino require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/davecgh/go-spew v1.1.1 - github.com/ltcmweb/ltcd v0.24.2 + github.com/ltcmweb/ltcd v0.24.3 github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 - github.com/ltcmweb/ltcd/ltcutil v1.2.2 + github.com/ltcmweb/ltcd/ltcutil v1.2.3 github.com/ltcmweb/neutrino/cache v1.1.0 github.com/ltcsuite/lnd/queue v1.1.0 github.com/ltcsuite/ltcwallet v0.13.1 @@ -24,6 +24,7 @@ require ( github.com/decred/dcrd/lru v1.1.1 // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/ltcmweb/secp256k1 v0.1.0 // indirect github.com/ltcsuite/lnd/ticker v1.0.1 // indirect github.com/ltcsuite/ltcd v0.22.0-beta // indirect github.com/ltcsuite/ltcd/btcec/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 6d918838e..b6223439f 100644 --- a/go.sum +++ b/go.sum @@ -52,16 +52,18 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/ltcmweb/ltcd v0.24.2 h1:ol1nZfp0YSmwY4dxEdiApRYX2mKC6Ph7W0f6bK7ahnE= -github.com/ltcmweb/ltcd v0.24.2/go.mod h1:TR9HEIp8c0B+jrNFPgAPf5e48vyoy1agEVKk8sMoaEc= +github.com/ltcmweb/ltcd v0.24.3 h1:6wDbXbMeFSMpQ9vTNWTKWHnV6TNuIw+j/vkc9VnSJVE= +github.com/ltcmweb/ltcd v0.24.3/go.mod h1:QThsxptQU/G1c9cJw8MjUeFw7jjcosIxkwEWcDaExFg= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= -github.com/ltcmweb/ltcd/ltcutil v1.2.2 h1:GQI4bdMwgrMz8ClO2cOPSNs80E6I0ixTSk9DgA3dyxU= -github.com/ltcmweb/ltcd/ltcutil v1.2.2/go.mod h1:ezd8H9vagau9j+/STipVxok78u01b7xlj2ImrFbGhkQ= +github.com/ltcmweb/ltcd/ltcutil v1.2.3 h1:/7tyvs2LxzUYCKmF09ZN3Nfnq9vSht/xXo/LYcY5kDQ= +github.com/ltcmweb/ltcd/ltcutil v1.2.3/go.mod h1:NZ2ZpVNkWgYbGG9DWcxXsfNK0N7ZFMVHWihEXCdvCPw= github.com/ltcmweb/neutrino/cache v1.1.0 h1:C0Qn2p8ogcskRPfrBKPUayjn3m/CUJqI7otopNScvhk= github.com/ltcmweb/neutrino/cache v1.1.0/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME= +github.com/ltcmweb/secp256k1 v0.1.0 h1:34S8JTD/LsLqenFPXQnI1rYSKstgDzsyjLhhc/harAs= +github.com/ltcmweb/secp256k1 v0.1.0/go.mod h1:Kdj2WHIAc0Y1apPtVY7nVxImRWiRTQue2vs1gt1VoEc= github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0= diff --git a/tools/go.mod b/tools/go.mod index 88e38015d..cf8aafe5d 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/golangci/golangci-lint v1.52.2 - github.com/ltcmweb/ltcd v0.24.2 + github.com/ltcmweb/ltcd v0.24.3 github.com/ory/go-acc v0.2.8 github.com/rinchsan/gosimports v0.1.5 ) @@ -110,7 +110,8 @@ require ( github.com/leonklingele/grouper v1.1.1 // indirect github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 // indirect github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 // indirect - github.com/ltcmweb/ltcd/ltcutil v1.2.2 // indirect + github.com/ltcmweb/ltcd/ltcutil v1.2.3 // indirect + github.com/ltcmweb/secp256k1 v0.1.0 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/maratori/testableexamples v1.0.0 // indirect diff --git a/tools/go.sum b/tools/go.sum index 5a660a320..8a4ae2a77 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -397,14 +397,16 @@ github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1 github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/ltcmweb/ltcd v0.24.2 h1:ol1nZfp0YSmwY4dxEdiApRYX2mKC6Ph7W0f6bK7ahnE= -github.com/ltcmweb/ltcd v0.24.2/go.mod h1:TR9HEIp8c0B+jrNFPgAPf5e48vyoy1agEVKk8sMoaEc= +github.com/ltcmweb/ltcd v0.24.3 h1:6wDbXbMeFSMpQ9vTNWTKWHnV6TNuIw+j/vkc9VnSJVE= +github.com/ltcmweb/ltcd v0.24.3/go.mod h1:QThsxptQU/G1c9cJw8MjUeFw7jjcosIxkwEWcDaExFg= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= -github.com/ltcmweb/ltcd/ltcutil v1.2.2 h1:GQI4bdMwgrMz8ClO2cOPSNs80E6I0ixTSk9DgA3dyxU= -github.com/ltcmweb/ltcd/ltcutil v1.2.2/go.mod h1:ezd8H9vagau9j+/STipVxok78u01b7xlj2ImrFbGhkQ= +github.com/ltcmweb/ltcd/ltcutil v1.2.3 h1:/7tyvs2LxzUYCKmF09ZN3Nfnq9vSht/xXo/LYcY5kDQ= +github.com/ltcmweb/ltcd/ltcutil v1.2.3/go.mod h1:NZ2ZpVNkWgYbGG9DWcxXsfNK0N7ZFMVHWihEXCdvCPw= +github.com/ltcmweb/secp256k1 v0.1.0 h1:34S8JTD/LsLqenFPXQnI1rYSKstgDzsyjLhhc/harAs= +github.com/ltcmweb/secp256k1 v0.1.0/go.mod h1:Kdj2WHIAc0Y1apPtVY7nVxImRWiRTQue2vs1gt1VoEc= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= From e76acf7d7867b843d86fca07182270aa2a343dc5 Mon Sep 17 00:00:00 2001 From: Hector Chu Date: Tue, 3 Sep 2024 19:55:52 +0100 Subject: [PATCH 75/75] go mod tidy --- go.mod | 5 ++--- go.sum | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 5708da314..125ad6223 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,9 @@ module github.com/ltcmweb/neutrino require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/davecgh/go-spew v1.1.1 - github.com/ltcmweb/ltcd v0.24.3 + github.com/ltcmweb/ltcd v0.25.0 github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 - github.com/ltcmweb/ltcd/ltcutil v1.2.3 github.com/ltcmweb/neutrino/cache v1.1.0 github.com/ltcsuite/lnd/queue v1.1.0 github.com/ltcsuite/ltcwallet v0.13.1 @@ -24,7 +23,7 @@ require ( github.com/decred/dcrd/lru v1.1.1 // indirect github.com/kkdai/bstream v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect - github.com/ltcmweb/secp256k1 v0.1.0 // indirect + github.com/ltcmweb/secp256k1 v0.1.1 // indirect github.com/ltcsuite/lnd/ticker v1.0.1 // indirect github.com/ltcsuite/ltcd v0.22.0-beta // indirect github.com/ltcsuite/ltcd/btcec/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index b6223439f..43a16ab91 100644 --- a/go.sum +++ b/go.sum @@ -52,18 +52,16 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/ltcmweb/ltcd v0.24.3 h1:6wDbXbMeFSMpQ9vTNWTKWHnV6TNuIw+j/vkc9VnSJVE= -github.com/ltcmweb/ltcd v0.24.3/go.mod h1:QThsxptQU/G1c9cJw8MjUeFw7jjcosIxkwEWcDaExFg= +github.com/ltcmweb/ltcd v0.25.0 h1:BJq9wF+PwWC1pNt3d3/ZxEmAFepYGxGm5LexxEbbdA8= +github.com/ltcmweb/ltcd v0.25.0/go.mod h1:jQbvPfnT4bBXJKRwU5SdD9ZUopwmSvhngdjeopv2cIU= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE= github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM= github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg= -github.com/ltcmweb/ltcd/ltcutil v1.2.3 h1:/7tyvs2LxzUYCKmF09ZN3Nfnq9vSht/xXo/LYcY5kDQ= -github.com/ltcmweb/ltcd/ltcutil v1.2.3/go.mod h1:NZ2ZpVNkWgYbGG9DWcxXsfNK0N7ZFMVHWihEXCdvCPw= github.com/ltcmweb/neutrino/cache v1.1.0 h1:C0Qn2p8ogcskRPfrBKPUayjn3m/CUJqI7otopNScvhk= github.com/ltcmweb/neutrino/cache v1.1.0/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME= -github.com/ltcmweb/secp256k1 v0.1.0 h1:34S8JTD/LsLqenFPXQnI1rYSKstgDzsyjLhhc/harAs= -github.com/ltcmweb/secp256k1 v0.1.0/go.mod h1:Kdj2WHIAc0Y1apPtVY7nVxImRWiRTQue2vs1gt1VoEc= +github.com/ltcmweb/secp256k1 v0.1.1 h1:hsGpnFcZ5zmjSxg7AswZp8ygo5NiY06OYWJk97hFizI= +github.com/ltcmweb/secp256k1 v0.1.1/go.mod h1:Kdj2WHIAc0Y1apPtVY7nVxImRWiRTQue2vs1gt1VoEc= github.com/ltcsuite/lnd/clock v0.0.0-20200822020009-1a001cbb895a/go.mod h1:d474AXivZyx25TMDB2tjjiQNuPrybFcgz+yl7vQgFTs= github.com/ltcsuite/lnd/queue v1.0.3/go.mod h1:L0MMGRrsJFPHhTInek8YgW2v7NyB6pXrAh6Bbg2D7u8= github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0=