Skip to content

Commit

Permalink
mixing: add mixpool package
Browse files Browse the repository at this point in the history
The mixpool package implements a memory pool of recently observed mix
messages.  Similar to the transaction mempool, the mixpool allows these
messages to be temporarily stored in memory to be relayed through the P2P
network.  It handles message acceptance, expiry, UTXO ownership proof checks,
and that previously referenced messages have also been accepted to the
mixpool.

The mixpool is designed with both full-node and wallet usage in mind,
providing all of these same acceptance rules to mixing wallets with the
exception of UTXO proof checks.  For wallets, it also implements query
functions for messages matching compatible pairings and messages belong to
ongoing sessions.
  • Loading branch information
jrick committed May 11, 2024
1 parent b6219c7 commit c19fc08
Show file tree
Hide file tree
Showing 6 changed files with 2,407 additions and 0 deletions.
87 changes: 87 additions & 0 deletions mixing/mixpool/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) 2024 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package mixpool

import (
"errors"

"github.com/decred/dcrd/chaincfg/chainhash"
)

// RuleError represents a mixpool rule violation.
//
// RuleErrors can be treated as a bannable offense.
type RuleError struct {
Err error
}

func ruleError(err error) *RuleError {
return &RuleError{Err: err}
}

func (e *RuleError) Error() string {
return e.Err.Error()
}

func (e *RuleError) Unwrap() error {
return e.Err
}

// Errors wrapped by RuleError.
var (
// ErrChangeDust is returned by AcceptMessage if a pair request's
// change amount is dust.
ErrChangeDust = errors.New("change output is dust")

// ErrInvalidMessageCount is returned by AcceptMessage if a
// pair request contains an invalid message count.
ErrInvalidMessageCount = errors.New("message count must be positive")

// ErrInvalidScript is returned by AcceptMessage if a pair request
// contains an invalid script.
ErrInvalidScript = errors.New("invalid script")

// ErrInvalidSessionID is returned by AcceptMessage if the message
// contains an invalid session id.
ErrInvalidSessionID = errors.New("invalid session ID")

// ErrInvalidSignature is returned by AcceptMessage if the message is
// not properly signed for the claimed identity.
ErrInvalidSignature = errors.New("invalid message signature")

// ErrInvalidTotalMixAmount is returned by AcceptMessage if a pair
// request contains the product of the message count and mix amount
// that exceeds the total input value.
ErrInvalidTotalMixAmount = errors.New("invalid total mix amount")

// ErrInvalidUTXOProof is returned by AcceptMessage if a pair request
// fails to prove ownership of each utxo.
ErrInvalidUTXOProof = errors.New("invalid UTXO ownership proof")

// ErrMissingUTXOs is returned by AcceptMessage if a pair request
// message does not reference any previous UTXOs.
ErrMissingUTXOs = errors.New("pair request contains no UTXOs")
)

var (
// ErrSecretsRevealed is returned by Receive if any peer has
// unexpectedly revealed their secrets during a run stage
// (Received.RSs field is nil). This requires all other peers to quit
// the run, reveal their secrets, and perform blame assignment.
ErrSecretsRevealed = errors.New("secrets revealed by peer")
)

// MissingOwnPRError represents the error condition where a key exchange
// message cannot be accepted to the mixpool due to it not referencing the
// owner's own pair request. The KE is recorded as an orphan and may be
// processed later. The error contains all unknown PR hashes so they can be
// fetched from another instance.
type MissingOwnPRError struct {
UnknownPRs []chainhash.Hash
}

func (e *MissingOwnPRError) Error() string {
return "KE identity's own PR is missing from mixpool"
}
31 changes: 31 additions & 0 deletions mixing/mixpool/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) 2020-2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package mixpool

import (
"github.com/decred/slog"
)

// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
// The default amount of logging is none.
var log = slog.Disabled

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using slog.
func UseLogger(logger slog.Logger) {
log = logger
}

// pickNoun returns the singular or plural form of a noun depending on the
// provided count.
func pickNoun(n uint64, singular, plural string) string {
if n == 1 {
return singular
}
return plural
}

0 comments on commit c19fc08

Please sign in to comment.