From 1214f72167c0386f86feeb7f982b4cf2ce639aa4 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Thu, 25 Apr 2024 20:18:33 +0000 Subject: [PATCH] wire: Add epoch field to mix key exchange message The epoch will be included in the derivation of the session hash, instead of only deriving a session from previous pair requests. This allows new messages in following epochs to not conflict with previous session attempts of the same pair request set. This also provides a decent heuristic to discover and exclude any peers that were unresponsive for a full epoch or more. This is a breaking API change but the wire module has not seen a release since mixing messages were added. --- wire/message_test.go | 4 ++-- wire/msgmixkeyexchange.go | 15 +++++++++------ wire/msgmixkeyexchange_test.go | 29 ++++++++++++++++------------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/wire/message_test.go b/wire/message_test.go index fee3629630..e7f899ab8e 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -84,7 +84,7 @@ func TestMessage(t *testing.T) { if err != nil { t.Errorf("NewMsgMixPairReq: %v", err) } - msgMixKE := NewMsgMixKeyExchange([33]byte{}, [32]byte{}, 1, [33]byte{}, [1218]byte{}, [32]byte{}, []chainhash.Hash{}) + msgMixKE := NewMsgMixKeyExchange([33]byte{}, [32]byte{}, 1, 1, [33]byte{}, [1218]byte{}, [32]byte{}, []chainhash.Hash{}) msgMixCT := NewMsgMixCiphertexts([33]byte{}, [32]byte{}, 1, [][1047]byte{}, []chainhash.Hash{}) msgMixSR := NewMsgMixSlotReserve([33]byte{}, [32]byte{}, 1, [][][]byte{{{}}}, []chainhash.Hash{}) msgMixDC := NewMsgMixDCNet([33]byte{}, [32]byte{}, 1, []MixVect{make(MixVect, 1)}, []chainhash.Hash{}) @@ -123,7 +123,7 @@ func TestMessage(t *testing.T) { {msgGetInitState, msgGetInitState, pver, MainNet, 25}, {msgInitState, msgInitState, pver, MainNet, 28}, {msgMixPR, msgMixPR, pver, MainNet, 165}, - {msgMixKE, msgMixKE, pver, MainNet, 1441}, + {msgMixKE, msgMixKE, pver, MainNet, 1449}, {msgMixCT, msgMixCT, pver, MainNet, 158}, {msgMixSR, msgMixSR, pver, MainNet, 161}, {msgMixDC, msgMixDC, pver, MainNet, 181}, diff --git a/wire/msgmixkeyexchange.go b/wire/msgmixkeyexchange.go index e7bfa4ab8d..62c4553f16 100644 --- a/wire/msgmixkeyexchange.go +++ b/wire/msgmixkeyexchange.go @@ -30,6 +30,7 @@ type MsgMixKeyExchange struct { Signature [64]byte Identity [33]byte SessionID [32]byte + Epoch uint64 Run uint32 ECDH [33]byte // Secp256k1 public key PQPK [1218]byte // Sntrup4591761 public key @@ -53,7 +54,7 @@ func (msg *MsgMixKeyExchange) BtcDecode(r io.Reader, pver uint32) error { } err := readElements(r, &msg.Signature, &msg.Identity, &msg.SessionID, - &msg.Run, &msg.ECDH, &msg.PQPK, &msg.Commitment) + &msg.Epoch, &msg.Run, &msg.ECDH, &msg.PQPK, &msg.Commitment) if err != nil { return err } @@ -146,8 +147,8 @@ func (msg *MsgMixKeyExchange) writeMessageNoSignature(op string, w io.Writer, pv return messageError(op, ErrTooManyPrevMixMsgs, msg) } - err := writeElements(w, &msg.Identity, &msg.SessionID, msg.Run, - &msg.ECDH, &msg.PQPK, &msg.Commitment) + err := writeElements(w, &msg.Identity, &msg.SessionID, msg.Epoch, + msg.Run, &msg.ECDH, &msg.PQPK, &msg.Commitment) if err != nil { return err } @@ -188,7 +189,7 @@ func (msg *MsgMixKeyExchange) MaxPayloadLength(pver uint32) uint32 { } // See tests for this calculation. - return 17803 + return 17811 } // Pub returns the message sender's public key identity. @@ -219,12 +220,14 @@ func (msg *MsgMixKeyExchange) GetRun() uint32 { // NewMsgMixKeyExchange returns a new mixkeyxchg message that conforms to the // Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgMixKeyExchange(identity [33]byte, sid [32]byte, run uint32, - ecdh [33]byte, pqpk [1218]byte, commitment [32]byte, seenPRs []chainhash.Hash) *MsgMixKeyExchange { +func NewMsgMixKeyExchange(identity [33]byte, sid [32]byte, epoch uint64, + run uint32, ecdh [33]byte, pqpk [1218]byte, commitment [32]byte, + seenPRs []chainhash.Hash) *MsgMixKeyExchange { return &MsgMixKeyExchange{ Identity: identity, SessionID: sid, + Epoch: epoch, Run: run, ECDH: ecdh, PQPK: pqpk, diff --git a/wire/msgmixkeyexchange_test.go b/wire/msgmixkeyexchange_test.go index e5f83a32f5..94118c975a 100644 --- a/wire/msgmixkeyexchange_test.go +++ b/wire/msgmixkeyexchange_test.go @@ -21,18 +21,19 @@ func newTestMixKeyExchange() *MsgMixKeyExchange { id := *(*[33]byte)(repeat(0x81, 33)) sid := *(*[32]byte)(repeat(0x82, 32)) - const run = uint32(0x83838383) + const epoch = uint64(0x8383838383838383) + const run = uint32(0x84848484) - ecdh := *(*[33]byte)(repeat(0x84, 33)) - pqpk := *(*[1218]byte)(repeat(0x85, 1218)) - commitment := *(*[32]byte)(repeat(0x86, 32)) + ecdh := *(*[33]byte)(repeat(0x85, 33)) + pqpk := *(*[1218]byte)(repeat(0x86, 1218)) + commitment := *(*[32]byte)(repeat(0x87, 32)) seenPRs := make([]chainhash.Hash, 4) - for b := byte(0x87); b < 0x8B; b++ { - copy(seenPRs[b-0x87][:], repeat(b, 32)) + for b := byte(0x88); b < 0x8C; b++ { + copy(seenPRs[b-0x88][:], repeat(b, 32)) } - ke := NewMsgMixKeyExchange(id, sid, run, ecdh, pqpk, commitment, seenPRs) + ke := NewMsgMixKeyExchange(id, sid, epoch, run, ecdh, pqpk, commitment, seenPRs) ke.Signature = sig return ke @@ -53,16 +54,17 @@ func TestMsgMixKeyExchangeWire(t *testing.T) { expected = append(expected, repeat(0x80, 64)...) // Signature expected = append(expected, repeat(0x81, 33)...) // Identity expected = append(expected, repeat(0x82, 32)...) // Session ID - expected = append(expected, repeat(0x83, 4)...) // Run - expected = append(expected, repeat(0x84, 33)...) // ECDH public key - expected = append(expected, repeat(0x85, 1218)...) // PQ public key - expected = append(expected, repeat(0x86, 32)...) // Secrets commitment - // Four seen PRs (repeating 32 bytes of 0x87, 0x88, 0x89, 0x8a) + expected = append(expected, repeat(0x83, 8)...) // Epoch + expected = append(expected, repeat(0x84, 4)...) // Run + expected = append(expected, repeat(0x85, 33)...) // ECDH public key + expected = append(expected, repeat(0x86, 1218)...) // PQ public key + expected = append(expected, repeat(0x87, 32)...) // Secrets commitment + // Four seen PRs (repeating 32 bytes of 0x88, 0x89, 0x8a, 0x8b) expected = append(expected, 0x04) - expected = append(expected, repeat(0x87, 32)...) expected = append(expected, repeat(0x88, 32)...) expected = append(expected, repeat(0x89, 32)...) expected = append(expected, repeat(0x8a, 32)...) + expected = append(expected, repeat(0x8b, 32)...) expectedSerializationEqual(t, buf.Bytes(), expected) @@ -155,6 +157,7 @@ func TestMsgMixKeyExchangeMaxPayloadLength(t *testing.T) { var expectedLen uint32 = 64 + // Signature 33 + // Identity 32 + // Session ID + 8 + // Epoch 4 + // Run 33 + // ECDH public key 1218 + // sntrup4591761 public key