Skip to content

Commit

Permalink
wire: add p2p mixing messages
Browse files Browse the repository at this point in the history
These messages implement the stages of a cspp mix.  Messages will be
broadcast to all full nodes and all peers participating in mixing
through inventory messages.
  • Loading branch information
jrick committed Nov 7, 2023
1 parent c1e4cdd commit 89bc803
Show file tree
Hide file tree
Showing 23 changed files with 2,598 additions and 5 deletions.
91 changes: 91 additions & 0 deletions wire/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

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

const (
Expand Down Expand Up @@ -322,6 +323,38 @@ func readElement(r io.Reader, element interface{}) error {
}
return nil

// Mix identity
case *[33]byte:
_, err := io.ReadFull(r, e[:])
if err != nil {
return err
}
return nil

// Mix signature
case *[64]byte:
_, err := io.ReadFull(r, e[:])
if err != nil {
return err
}
return nil

// sntrup4591651 ciphertext
case *[1047]byte:
_, err := io.ReadFull(r, e[:])
if err != nil {
return err
}
return nil

// sntrup4591651 public key
case *[1218]byte:
_, err := io.ReadFull(r, e[:])
if err != nil {
return err
}
return nil

case *ServiceFlag:
rv, err := binarySerializer.Uint64(r, littleEndian)
if err != nil {
Expand Down Expand Up @@ -377,6 +410,20 @@ func writeElement(w io.Writer, element interface{}) error {
// Attempt to write the element based on the concrete type via fast
// type assertions first.
switch e := element.(type) {
case uint8:
err := binarySerializer.PutUint8(w, e)
if err != nil {
return err
}
return nil

case uint16:
err := binarySerializer.PutUint16(w, littleEndian, e)
if err != nil {
return err
}
return nil

case int32:
err := binarySerializer.PutUint32(w, littleEndian, uint32(e))
if err != nil {
Expand Down Expand Up @@ -441,13 +488,44 @@ func writeElement(w io.Writer, element interface{}) error {
}
return nil

case *[32]byte:
_, err := w.Write(e[:])
if err != nil {
return err
}
return nil

case *chainhash.Hash:
_, err := w.Write(e[:])
if err != nil {
return err
}
return nil

// Mix signature
case *[64]byte:
_, err := w.Write(e[:])
if err != nil {
return err
}
return nil

// sntrup4591761 ciphertext
case *[1047]byte:
_, err := w.Write(e[:])
if err != nil {
return err
}
return nil

// sntrup4591761 public key
case *[1218]byte:
_, err := w.Write(e[:])
if err != nil {
return err
}
return nil

case ServiceFlag:
err := binarySerializer.PutUint64(w, littleEndian, uint64(e))
if err != nil {
Expand Down Expand Up @@ -765,3 +843,16 @@ func isStrictAscii(s string) bool {

return true
}

// mustHash returns the hash of the serialized message. If message
// serialization errors, it panics with a wrapped error.
func mustHash(msg Message, pver uint32) chainhash.Hash {
h := blake256.New()
err := msg.BtcEncode(h, pver)
if err != nil {
err := fmt.Errorf("hash of %T failed due to serialization "+
"error: %w", msg, err)
panic(err)
}
return *(*chainhash.Hash)(h.Sum(nil))
}
15 changes: 15 additions & 0 deletions wire/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,18 @@ const (
// ErrTooManyTSpends is returned when the number of tspend hashes
// exceeds the maximum allowed.
ErrTooManyTSpends

// ErrMixPRScriptClassTooLong is returned when a mixing script class
// type string is longer than allowed by the protocol.
ErrMixPRScriptClassTooLong

// ErrTooManyMixPRUTXOs is returned when a MixPR message contains
// more UTXOs than allowed by the protocol.
ErrTooManyMixPRUTXOs

// ErrTooManyPrevMixMsgs is returned when too many previous messages of
// a mix run are referenced by a message.
ErrTooManyPrevMixMsgs
)

// Map of ErrorCode values back to their constant names for pretty printing.
Expand Down Expand Up @@ -168,6 +180,9 @@ var errorCodeStrings = map[ErrorCode]string{
ErrTooManyInitStateTypes: "ErrTooManyInitStateTypes",
ErrInitStateTypeTooLong: "ErrInitStateTypeTooLong",
ErrTooManyTSpends: "ErrTooManyTSpends",
ErrMixPRScriptClassTooLong: "ErrMixPRScriptClassTooLong",
ErrTooManyMixPRUTXOs: "ErrTooManyMixPRUTXOs",
ErrTooManyPrevMixMsgs: "ErrTooManyPrevMixMsgs",
}

// String returns the ErrorCode as a human-readable name.
Expand Down
6 changes: 2 additions & 4 deletions wire/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ go 1.17
require (
github.com/davecgh/go-spew v1.1.1
github.com/decred/dcrd/chaincfg/chainhash v1.0.4
github.com/decred/dcrd/crypto/blake256 v1.0.1
lukechampine.com/blake3 v1.2.1
)

require (
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
)
require github.com/klauspost/cpuid/v2 v2.0.9 // indirect
2 changes: 2 additions & 0 deletions wire/invvect.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
InvTypeTx InvType = 1
InvTypeBlock InvType = 2
InvTypeFilteredBlock InvType = 3
InvTypeMix InvType = 4
)

// Map of service flags back to their constant names for pretty printing.
Expand All @@ -38,6 +39,7 @@ var ivStrings = map[InvType]string{
InvTypeTx: "MSG_TX",
InvTypeBlock: "MSG_BLOCK",
InvTypeFilteredBlock: "MSG_FILTERED_BLOCK",
InvTypeMix: "MSG_MIX",
}

// String returns the InvType in human-readable form.
Expand Down
28 changes: 28 additions & 0 deletions wire/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ const (
CmdCFilterV2 = "cfilterv2"
CmdGetInitState = "getinitstate"
CmdInitState = "initstate"
CmdMixPR = "mixpr"
CmdMixKE = "mixke"
CmdMixCT = "mixct"
CmdMixSR = "mixsr"
CmdMixDC = "mixdc"
CmdMixCM = "mixcm"
CmdMixRS = "mixrs"
)

// Message is an interface that describes a Decred message. A type that
Expand Down Expand Up @@ -168,6 +175,27 @@ func makeEmptyMessage(command string) (Message, error) {
case CmdInitState:
msg = &MsgInitState{}

case CmdMixPR:
msg = &MsgMixPR{}

case CmdMixKE:
msg = &MsgMixKE{}

case CmdMixCT:
msg = &MsgMixCT{}

case CmdMixSR:
msg = &MsgMixSR{}

case CmdMixDC:
msg = &MsgMixDC{}

case CmdMixCM:
msg = &MsgMixCM{}

case CmdMixRS:
msg = &MsgMixRS{}

default:
str := fmt.Sprintf("unhandled command [%s]", command)
return nil, messageError(op, ErrUnknownCmd, str)
Expand Down
45 changes: 45 additions & 0 deletions wire/mixvec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2023 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package wire

import (
"fmt"
"strings"
)

// MixVec is a N-element vector of Msize []byte messages.
type MixVec struct {
N uint32
Msize uint32
Data []byte
}

// NewMixVec returns a zero vector for holding n messages of msize length.
func NewMixVec(n, msize uint32) *MixVec {
return &MixVec{
N: n,
Msize: msize,
Data: make([]byte, n*msize),
}
}

func (v *MixVec) String() string {
m := func(i int) []byte {
off := uint32(i) * v.Msize
return v.Data[off : off+v.Msize]
}

b := new(strings.Builder)
b.Grow(2 + int(v.N*(2*v.Msize+1)))
b.WriteString("[")
for i := 0; uint32(i) < v.N; i++ {
if i != 0 {
b.WriteString(" ")
}
fmt.Fprintf(b, "%x", m(i))
}
b.WriteString("]")
return b.String()
}
4 changes: 4 additions & 0 deletions wire/msggetinitstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const (
// InitStateTSpends is the init state type used to request tpends for
// voting.
InitStateTSpends = "tspends"

// InitStateMixPRs is the init state type used to request mixing pair
// request messages.
InitStateMixPRs = "mixprs"
)

// MsgGetInitState implements the Message interface and represents a
Expand Down
1 change: 1 addition & 0 deletions wire/msginitstate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type MsgInitState struct {
BlockHashes []chainhash.Hash
VoteHashes []chainhash.Hash
TSpendHashes []chainhash.Hash
MixPRHashes []chainhash.Hash // XXX serialize this depending on the protocol version
}

// AddBlockHash adds a new block hash to the message. Up to
Expand Down
Loading

0 comments on commit 89bc803

Please sign in to comment.