Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Prepare v2.0.5 #2447

Merged
merged 15 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions chain/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,24 @@ func (s *Syncer) ExistsLiveTickets(ctx context.Context, tickets []*chainhash.Has
func (s *Syncer) UsedAddresses(ctx context.Context, addrs []stdaddr.Address) (bitset.Bytes, error) {
return s.rpc.UsedAddresses(ctx, addrs)
}

func (s *Syncer) Done() <-chan struct{} {
s.doneMu.Lock()
c := s.done
s.doneMu.Unlock()
return c
}

func (s *Syncer) Err() error {
s.doneMu.Lock()
c := s.done
err := s.err
s.doneMu.Unlock()

select {
case <-c:
return err
default:
return nil
}
}
15 changes: 15 additions & 0 deletions chain/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ type Syncer struct {
relevantTxs map[chainhash.Hash][]*wire.MsgTx

cb *Callbacks

done chan struct{}
err error
doneMu sync.Mutex
}

// RPCOptions specifies the network and security settings for establishing a
Expand Down Expand Up @@ -525,6 +529,17 @@ func (s *Syncer) Run(ctx context.Context) (err error) {
}
}()

s.doneMu.Lock()
s.done = make(chan struct{})
s.err = nil
s.doneMu.Unlock()
defer func() {
s.doneMu.Lock()
close(s.done)
s.err = err
s.doneMu.Unlock()
}()

params := s.wallet.ChainParams()

s.notifier = &notifier{
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module decred.org/dcrwallet/v4
go 1.20

require (
decred.org/cspp/v2 v2.2.0
decred.org/cspp/v2 v2.3.0
github.com/decred/dcrd/addrmgr/v2 v2.0.4
github.com/decred/dcrd/blockchain/stake/v5 v5.0.1
github.com/decred/dcrd/blockchain/standalone/v2 v2.2.1
Expand All @@ -12,7 +12,7 @@ require (
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
github.com/decred/dcrd/chaincfg/v3 v3.2.1
github.com/decred/dcrd/connmgr/v3 v3.1.2
github.com/decred/dcrd/crypto/blake256 v1.0.1
github.com/decred/dcrd/crypto/blake256 v1.1.0
github.com/decred/dcrd/crypto/rand v1.0.0
github.com/decred/dcrd/crypto/ripemd160 v1.0.2
github.com/decred/dcrd/dcrec v1.0.1
Expand All @@ -21,7 +21,7 @@ require (
github.com/decred/dcrd/dcrutil/v4 v4.0.2
github.com/decred/dcrd/gcs/v4 v4.1.0
github.com/decred/dcrd/hdkeychain/v3 v3.1.2
github.com/decred/dcrd/mixing v0.4.1
github.com/decred/dcrd/mixing v0.4.2
github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.3.0
github.com/decred/dcrd/rpcclient/v8 v8.0.1
github.com/decred/dcrd/txscript/v4 v4.1.1
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
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=
decred.org/cspp/v2 v2.2.0 h1:VSOUC1w0Wo+QOGS0r1XO6TLnO16X67KuvpDmRRYyr08=
decred.org/cspp/v2 v2.2.0/go.mod h1:9nO3bfvCheOPIFZw5f6sRQ42CjBFB5RKSaJ9Iq6G4MA=
decred.org/cspp/v2 v2.3.0 h1:GC8emJnLbOVAkgBTHK/1wy6o/m0AVsN1r4m1ZnZZWjo=
decred.org/cspp/v2 v2.3.0/go.mod h1:9nO3bfvCheOPIFZw5f6sRQ42CjBFB5RKSaJ9Iq6G4MA=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
Expand Down Expand Up @@ -41,8 +41,8 @@ github.com/decred/dcrd/connmgr/v3 v3.1.2 h1:+xNopie2L3YYwwkz51k0h/pASATOBzHtl2O8
github.com/decred/dcrd/connmgr/v3 v3.1.2/go.mod h1:tdbErFiNOuy/sHrX2mwaOk+r1HLs3EBz2EGxsocMPe4=
github.com/decred/dcrd/container/lru v1.0.0 h1:7foQymtbu18aQWYiY9RnNIeE+kvpiN+fiBQ3+viyJjI=
github.com/decred/dcrd/container/lru v1.0.0/go.mod h1:vlPwj0l+IzAHhQSsbgQnJgO5Cte78+yI065V+Mc5PRQ=
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/blake256 v1.1.0 h1:zPMNGQCm0g4QTY27fOCorQW7EryeQ/U0x++OzVrdms8=
github.com/decred/dcrd/crypto/blake256 v1.1.0/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
github.com/decred/dcrd/crypto/rand v1.0.0 h1:Ah9Asl36OZt09sGSMbJZuL1HfwGdlC38q/ZUeLDVKRg=
github.com/decred/dcrd/crypto/rand v1.0.0/go.mod h1:coa7BbxSTiKH6esi257plGfMFYuGL4MTbQlLYnOdzpE=
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 h1:TvGTmUBHDU75OHro9ojPLK+Yv7gDl2hnUvRocRCjsys=
Expand All @@ -63,8 +63,8 @@ github.com/decred/dcrd/gcs/v4 v4.1.0 h1:tpW7JW53yJZlgNwl/n2NL1b8NxHaIPRUyNuLMkB/
github.com/decred/dcrd/gcs/v4 v4.1.0/go.mod h1:nPTbGM/I3Ihe5KFvUmxZEqQP/jDZQjQ63+WEi/f4lqU=
github.com/decred/dcrd/hdkeychain/v3 v3.1.2 h1:x25WuuE7zM/20EynuVMyOhL0K8BwGBBsexGq8xTiHFA=
github.com/decred/dcrd/hdkeychain/v3 v3.1.2/go.mod h1:FnNJmZ7jqUDeAo6/c/xkQi5cuxh3EWtJeMmW6/Z8lcc=
github.com/decred/dcrd/mixing v0.4.1 h1:W8ZCzhmNyzG1xjJMA3L6FOElmp98Ttnk3dDUxD6irAE=
github.com/decred/dcrd/mixing v0.4.1/go.mod h1:ySvVwTZyVz5YvevA6YjPrB6pJEwTm7IkHohTfaiHh2c=
github.com/decred/dcrd/mixing v0.4.2 h1:mpt2pNIFTI6L1hXrieAWJTQJv5t9WzHcNnhI+tnAG90=
github.com/decred/dcrd/mixing v0.4.2/go.mod h1:VF87lOn41kitgWVOwmXoB4qMYF7+bxItZXyw4JfW3EQ=
github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.3.0 h1:l0DnCcILTNrpy8APF3FLN312ChpkQaAuW30aC/RgBaw=
github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.3.0/go.mod h1:j+kkRPXPJB5S9VFOsx8SQLcU7PTFkPKRc1aCHN4ENzA=
github.com/decred/dcrd/rpcclient/v8 v8.0.1 h1:hd81e4w1KSqvPcozJlnz6XJfWKDNuahgooH/N5E8vOU=
Expand Down
18 changes: 16 additions & 2 deletions internal/rpc/jsonrpc/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -3353,6 +3353,8 @@ func (s *Server) purchaseTicket(ctx context.Context, icmd any) (any, error) {
var mixedAccount uint32
var mixedAccountBranch uint32
var mixedSplitAccount uint32
// Use purchasing account as change account by default (overridden below if
// mixing is enabled).
var changeAccount = account

if s.cfg.Mixing {
Expand All @@ -3372,7 +3374,7 @@ func (s *Server) purchaseTicket(ctx context.Context, icmd any) (any, error) {
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter,
"CSPP Server set, but error on mixedSplitAccount: %v", err)
}
_, err = w.AccountNumber(ctx, s.cfg.MixChangeAccount)
changeAccount, err = w.AccountNumber(ctx, s.cfg.MixChangeAccount)
if err != nil {
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter,
"CSPP Server set, but error on changeAccount: %v", err)
Expand Down Expand Up @@ -4821,6 +4823,18 @@ func (s *Server) setVoteChoice(ctx context.Context, icmd any) (any, error) {
func (s *Server) updateVSPVoteChoices(ctx context.Context, w *wallet.Wallet, ticketHash *chainhash.Hash,
choices map[string]string, tspendPolicy map[string]string, treasuryPolicy map[string]string) error {

// Ensure empty (as opposed to nil) choices on every category (required
// by the contract of the VSP API).
if choices == nil {
choices = map[string]string{}
}
if tspendPolicy == nil {
tspendPolicy = map[string]string{}
}
if treasuryPolicy == nil {
treasuryPolicy = map[string]string{}
}

if ticketHash != nil {
vspHost, err := w.VSPHostForTicket(ctx, ticketHash)
if err != nil {
Expand Down Expand Up @@ -5639,7 +5653,7 @@ func (s *Server) mixOutput(ctx context.Context, icmd any) (any, error) {
}

func (s *Server) mixAccount(ctx context.Context, icmd any) (any, error) {
if s.cfg.Mixing {
if !s.cfg.Mixing {
return nil, errors.E("Mixing is not configured")
}
w, ok := s.walletLoader.LoadedWallet()
Expand Down
97 changes: 62 additions & 35 deletions p2p/peering.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,10 @@ type RemotePeer struct {

// headers message management. Headers can either be fetched synchronously
// or used to push block notifications with sendheaders.
requestedHeaders chan<- *wire.MsgHeaders // non-nil result chan when synchronous getheaders in process
sendheaders bool // whether a sendheaders message was sent
requestedHeadersMu sync.Mutex
requestedHeaders chan<- *wire.MsgHeaders // non-nil result chan when synchronous getheaders in process
requestedHeadersLoc []*chainhash.Hash // non-nil when requested headers with getheaders
sendheaders bool // whether a sendheaders message was sent
requestedHeadersMu sync.Mutex

// init state message management.
requestedInitState chan<- *wire.MsgInitState // non-nil result chan when synchronous getinitstate in process
Expand Down Expand Up @@ -1097,7 +1098,7 @@ func (rp *RemotePeer) receivedCFilterV2(ctx context.Context, msg *wire.MsgCFilte
}
}

func (rp *RemotePeer) addRequestedHeaders(c chan<- *wire.MsgHeaders) (sendheaders, newRequest bool) {
func (rp *RemotePeer) addRequestedHeaders(c chan<- *wire.MsgHeaders, loc []*chainhash.Hash) (sendheaders, newRequest bool) {
rp.requestedHeadersMu.Lock()
if rp.sendheaders {
rp.requestedHeadersMu.Unlock()
Expand All @@ -1108,25 +1109,75 @@ func (rp *RemotePeer) addRequestedHeaders(c chan<- *wire.MsgHeaders) (sendheader
return false, false
}
rp.requestedHeaders = c
rp.requestedHeadersLoc = loc
rp.requestedHeadersMu.Unlock()
return false, true
}

func (rp *RemotePeer) deleteRequestedHeaders() {
rp.requestedHeadersMu.Lock()
rp.requestedHeaders = nil
rp.requestedHeadersLoc = nil
rp.requestedHeadersMu.Unlock()
}

func (rp *RemotePeer) receivedHeaders(ctx context.Context, msg *wire.MsgHeaders) {
const opf = "remotepeer(%v).receivedHeaders"
rp.requestedHeadersMu.Lock()

// Ensure the wallet requested headers from this peer.
if !rp.sendheaders && rp.requestedHeaders == nil {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol, "received unrequested headers")
rp.Disconnect(err)
rp.requestedHeadersMu.Unlock()
return
}

// Ensure the remote peer sent as many headers as it could. It can only
// send fewer than 2k headers when the last one is >= their advertised
// height (their tip height). This handles cases where a peer might
// drip headers instead of sending a full batch.
tooFewHeaders := len(msg.Headers) > 0 &&
len(msg.Headers) < wire.MaxBlockHeadersPerMsg &&
msg.Headers[len(msg.Headers)-1].Height < uint32(rp.initHeight)
if tooFewHeaders {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol, "peer sent too few headers")
rp.Disconnect(err)
rp.requestedHeadersMu.Unlock()
return
}

// The parent of the first header (if there is one) MUST be one of the
// block locators we used to request headers from the peer when this
// is a response to a getheaders request.
if len(msg.Headers) > 0 && rp.requestedHeadersLoc != nil {
wantParent := msg.Headers[0].PrevBlock
contains := false
for _, loc := range rp.requestedHeadersLoc {
if *loc == wantParent {
contains = true
break
}
}
if !contains {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol,
"peer sent headers that do not connect "+
"to block locators")
rp.Disconnect(err)
rp.requestedHeadersMu.Unlock()
return
}
}

// Sanity check the headers connect to each other in sequence.
var prevHash chainhash.Hash
var prevHeight uint32
for i, h := range msg.Headers {
hash := h.BlockHash()

// Sanity check the headers connect to each other in sequence.
if i > 0 && (!prevHash.IsEqual(&h.PrevBlock) || h.Height != prevHeight+1) {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol, "received out-of-sequence headers")
Expand All @@ -1139,6 +1190,7 @@ func (rp *RemotePeer) receivedHeaders(ctx context.Context, msg *wire.MsgHeaders)
prevHeight = h.Height
}

// Track the height of the last received header.
if prevHeight > 0 {
rp.lastHeightMu.Lock()
if int32(prevHeight) > rp.lastHeight {
Expand All @@ -1147,6 +1199,7 @@ func (rp *RemotePeer) receivedHeaders(ctx context.Context, msg *wire.MsgHeaders)
rp.lastHeightMu.Unlock()
}

// Async headers.
if rp.sendheaders {
rp.requestedHeadersMu.Unlock()
select {
Expand All @@ -1155,15 +1208,11 @@ func (rp *RemotePeer) receivedHeaders(ctx context.Context, msg *wire.MsgHeaders)
}
return
}
if rp.requestedHeaders == nil {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol, "received unrequested headers")
rp.Disconnect(err)
rp.requestedHeadersMu.Unlock()
return
}

// Headers as a response to getheaders.
c := rp.requestedHeaders
rp.requestedHeaders = nil
rp.requestedHeadersLoc = nil
rp.requestedHeadersMu.Unlock()
select {
case <-ctx.Done():
Expand Down Expand Up @@ -1966,7 +2015,7 @@ func (rp *RemotePeer) Headers(ctx context.Context, blockLocators []*chainhash.Ha
HashStop: *hashStop,
}
c := make(chan *wire.MsgHeaders, 1)
sendheaders, newRequest := rp.addRequestedHeaders(c)
sendheaders, newRequest := rp.addRequestedHeaders(c, blockLocators)
if sendheaders {
op := errors.Opf(opf, rp.raddr)
return nil, errors.E(op, errors.Invalid, "synchronous getheaders after sendheaders is unsupported")
Expand Down Expand Up @@ -1998,28 +2047,6 @@ func (rp *RemotePeer) Headers(ctx context.Context, blockLocators []*chainhash.Ha
case m := <-c:
stalled.Stop()

// The parent of the first header (if there is one) MUST
// be one of the block locators we used to request
// headers from the peer.
if len(m.Headers) > 0 {
wantParent := m.Headers[0].PrevBlock
contains := false
for _, loc := range blockLocators {
if *loc == wantParent {
contains = true
break
}
}
if !contains {
op := errors.Opf(opf, rp.raddr)
err := errors.E(op, errors.Protocol,
"peer sent headers that do not connect "+
"to block locators")
rp.Disconnect(err)
return nil, err
}
}

return m.Headers, nil
}
}
Expand Down
27 changes: 25 additions & 2 deletions spv/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ func pickForGetCfilters(lastHeaderHeight int32) func(rp *p2p.RemotePeer) bool {
// blocks are generated while performing the sync, therefore
// the initial advertised peer height would be lower than the
// last header height. Therefore, accept peers that are
// close, but not quite at the tip.
return rp.InitialHeight() >= lastHeaderHeight-6
// close, but not quite at the tip. It's possible that sync
// until now took longer than six blocks. In that case get
// cfilters from a peer that gave us headers.
return rp.InitialHeight() >= lastHeaderHeight-6 || rp.LastHeight() >= lastHeaderHeight
}
}

Expand Down Expand Up @@ -619,3 +621,24 @@ func (s *Syncer) Rescan(ctx context.Context, blockHashes []chainhash.Hash, save
func (s *Syncer) StakeDifficulty(ctx context.Context) (dcrutil.Amount, error) {
return 0, errors.E(errors.Invalid, "stake difficulty is not queryable over wire protocol")
}

func (s *Syncer) Done() <-chan struct{} {
s.doneMu.Lock()
c := s.done
s.doneMu.Unlock()
return c
}

func (s *Syncer) Err() error {
s.doneMu.Lock()
c := s.done
err := s.err
s.doneMu.Unlock()

select {
case <-c:
return err
default:
return nil
}
}
Loading
Loading