Skip to content

Commit

Permalink
mixclient: Detect exited csppsolver processes
Browse files Browse the repository at this point in the history
If the csppsolver process has unexpectedly exited after successful startup
(due to crash, signal, oom-killer, etc.) unset the PR flag indicating root
solving support for future mixes.  Wait for other peers to publish roots (if
any do), otherwise our peer will be (correctly) blamed for not publishing
roots.
  • Loading branch information
jrick committed Nov 8, 2024
1 parent 6447650 commit 0b7f593
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
2 changes: 1 addition & 1 deletion mixing/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/decred/dcrd/mixing
go 1.18

require (
decred.org/cspp/v2 v2.2.0
decred.org/cspp/v2 v2.3.0
github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
Expand Down
4 changes: 2 additions & 2 deletions mixing/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a h1:clYxJ3Os0EQUKDDVU8M0oipllX0EkuFNBfhVQuIfyF0=
Expand Down
29 changes: 23 additions & 6 deletions mixing/mixclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"runtime"
"sort"
"sync"
"sync/atomic"
"time"

"decred.org/cspp/v2/solverrpc"
Expand Down Expand Up @@ -264,6 +265,9 @@ type queueWork struct {

// Client manages local mixing client sessions.
type Client struct {
// atomics
atomicPRFlags uint32

wallet Wallet
mixpool *mixpool.Pool

Expand All @@ -281,8 +285,7 @@ type Client struct {
blake256Hasher hash.Hash
blake256HasherMu sync.Mutex

epoch time.Duration
prFlags byte
epoch time.Duration

logger slog.Logger

Expand All @@ -300,14 +303,14 @@ func NewClient(w Wallet) *Client {

height, _ := w.BestBlock()
return &Client{
atomicPRFlags: uint32(prFlags),
wallet: w,
mixpool: w.Mixpool(),
pairings: make(map[string]*pairedSessions),
warming: make(chan struct{}),
workQueue: make(chan *queueWork, runtime.NumCPU()),
blake256Hasher: blake256.New(),
epoch: w.Mixpool().Epoch(),
prFlags: prFlags,
height: height,
}
}
Expand Down Expand Up @@ -718,10 +721,11 @@ func (c *Client) Dicemix(ctx context.Context, cj *CoinJoin) error {
return err
}

prFlags := byte(atomic.LoadUint32(&c.atomicPRFlags))
pr, err := wire.NewMsgMixPairReq(*p.id, cj.prExpiry, cj.mixValue,
string(mixing.ScriptClassP2PKHv0), cj.tx.Version,
cj.tx.LockTime, cj.mcount, cj.inputValue, cj.prUTXOs,
cj.change, c.prFlags, pairingFlags)
cj.change, prFlags, pairingFlags)
if err != nil {
return err
}
Expand Down Expand Up @@ -1694,7 +1698,8 @@ func (c *Client) run(ctx context.Context, ps *pairedSessions, madePairing *bool)
}

func (c *Client) solvesRoots() bool {
return c.prFlags&mixing.PRFlagCanSolveRoots != 0
prFlags := byte(atomic.LoadUint32(&c.atomicPRFlags))
return prFlags&mixing.PRFlagCanSolveRoots != 0
}

// roots returns the solutions to the slot reservation polynomial. If the
Expand All @@ -1704,8 +1709,20 @@ func (c *Client) solvesRoots() bool {
func (c *Client) roots(ctx context.Context, seenSRs []chainhash.Hash,
sesRun *sessionRun, a []*big.Int, F *big.Int, publishedRoots chan struct{}) ([]*big.Int, error) {

if c.solvesRoots() {
switch {
case c.solvesRoots():
roots, err := solverrpc.Roots(a, F)
if errors.Is(err, solverrpc.ErrSolverProcessExited) {
// Unset root-solving capability and future advertisement
prFlags := byte(atomic.LoadUint32(&c.atomicPRFlags))
prFlags &^= mixing.PRFlagCanSolveRoots
atomic.StoreUint32(&c.atomicPRFlags, uint32(prFlags))

// Wait for other peers to publish roots as a fallback
// in this run. If we are the only solver, we will be
// blamed for not publishing any.
break
}
if err != nil || len(roots) != len(a)-1 {
c.forLocalPeers(ctx, sesRun, func(p *peer) error {
p.triggeredBlame = true
Expand Down

0 comments on commit 0b7f593

Please sign in to comment.