Skip to content

Commit

Permalink
More work on network protocol.
Browse files Browse the repository at this point in the history
  • Loading branch information
markkurossi committed Jan 11, 2024
1 parent 92bbc20 commit 6c1deab
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 108 deletions.
29 changes: 14 additions & 15 deletions bmr/3party_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
package bmr

import (
"io"
"testing"

"github.com/markkurossi/mpc/circuit"
"github.com/markkurossi/mpc/p2p"
"github.com/markkurossi/mpc/ot"
)

func Test3Party(t *testing.T) {
Expand All @@ -38,22 +37,22 @@ func Test3Party(t *testing.T) {
// Add peers to players.
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
inR, inW := io.Pipe()
outR, outW := io.Pipe()

players[i].AddPeer(j, p2p.NewConn(&pipe{
r: inR,
w: outW,
}))
players[j].AddPeer(i, p2p.NewConn(&pipe{
r: outR,
w: inW,
}))
this, other := ot.NewPipe()

players[i].AddPeer(j, this)
players[j].AddPeer(i, other)
}
}

err = players[0].offlinePhase()
// Start other peers.
for i := 1; i < n; i++ {
go players[i].Play()
}

// Play player 0.
players[0].Verbose = true
err = players[0].Play()
if err != nil {
t.Fatalf("offlinePhase: %v", err)
t.Fatalf("Play: %v", err)
}
}
8 changes: 7 additions & 1 deletion bmr/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@

package bmr

// Operand defines protocol operands.
//
//go:generate stringer -type=Operand -trimprefix=Op
type Operand byte

// Network protocol messages.
const (
OpFx byte = iota
OpInit Operand = iota
OpFx
)
24 changes: 24 additions & 0 deletions bmr/operand_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 0 additions & 24 deletions bmr/pipe.go

This file was deleted.

100 changes: 88 additions & 12 deletions bmr/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ package bmr
import (
"crypto/rand"
"fmt"
"io"
"math/big"

"github.com/markkurossi/mpc/circuit"
"github.com/markkurossi/mpc/p2p"
"github.com/markkurossi/mpc/ot"
"github.com/markkurossi/text/superscript"
"github.com/markkurossi/text/symbols"
)
Expand All @@ -24,23 +25,66 @@ const (

// Player implements a multi-party player.
type Player struct {
Verbose bool
ot ot.OT
id int
numPlayers int
r Label
peers []*p2p.Conn
peers []*Peer
c *circuit.Circuit
lambda *big.Int
}

// Peer contains information about a protocol peer.
type Peer struct {
this *Player
id int
conn ot.IO
ot ot.OT
}

func (peer *Peer) consumer() {
peer.this.Debugf("consumer for peer%s\n", superscript.Itoa(peer.id))
for {
v, err := peer.conn.ReceiveByte()
if err != nil {
if err != io.EOF {
fmt.Printf("consumer: %v\n", err)
}
return
}
op := Operand(v)
peer.this.Debugf("%s\n", op)
switch op {
case OpInit:
err = peer.ot.InitReceiver(peer.conn)
if err != nil {
fmt.Printf("%s: %s\n", op, err)
return
}
}
}
}

// NewPlayer creates a new multi-party player.
func NewPlayer(id, numPlayers int) (*Player, error) {
return &Player{
id: id,
ot: ot.NewCO(),
numPlayers: numPlayers,
peers: make([]*p2p.Conn, numPlayers),
peers: make([]*Peer, numPlayers),
}, nil
}

// Debugf prints debugging message if Verbose debugging is enabled for
// this Player.
func (p *Player) Debugf(format string, a ...interface{}) {
if !p.Verbose {
return
}
fmt.Printf(format, a...)
}

// IDString returns the player ID as string.
func (p *Player) IDString() string {
return superscript.Itoa(p.id)
Expand All @@ -57,8 +101,41 @@ func (p *Player) SetCircuit(c *circuit.Circuit) error {
}

// AddPeer adds a peer.
func (p *Player) AddPeer(idx int, peer *p2p.Conn) {
p.peers[idx] = peer
func (p *Player) AddPeer(idx int, peer ot.IO) {
p.peers[idx] = &Peer{
this: p,
id: idx,
conn: peer,
ot: ot.NewCO(),
}
}

// Play runs the protocol with the peers.
func (p *Player) Play() error {
// Init peers.
for _, peer := range p.peers {
if peer != nil {
// Start consumer.
go peer.consumer()

// Init protocol.
err := peer.conn.SendByte(byte(OpInit))
if err != nil {
return err
}
err = p.ot.InitSender(peer.conn)
if err != nil {
return err
}
}
}

err := p.offlinePhase()
if err != nil {
return err
}

return nil
}

// offlinePhase implements the BMR Offline Phase (BMR Figure 2 - Page 6).
Expand All @@ -80,7 +157,7 @@ func (p *Player) offlinePhase() error {
return err
}
p.r = r
fmt.Printf("R%s:\t%v\n", p.IDString(), p.r)
p.Debugf("R%s:\t%v\n", p.IDString(), p.r)

// Step 2.a: create random permutation bits lambda. We set the
// bits initially for all wires but later reset the output bits of
Expand Down Expand Up @@ -119,10 +196,9 @@ func (p *Player) offlinePhase() error {
}

for i := 0; i < len(wires); i++ {
fmt.Printf("W%d:\t%v\n", i, wires[i])
p.Debugf("W%d:\t%v\n", i, wires[i])
}

fmt.Printf("%c%s:\t%v\n", symbols.Lambda, p.IDString(), p.lambda.Text(2))
p.Debugf("%c%s:\t%v\n", symbols.Lambda, p.IDString(), p.lambda.Text(2))

// Step 3: patch output wires and permutation bits for XOR output
// wires.
Expand All @@ -142,7 +218,7 @@ func (p *Player) offlinePhase() error {
lo := li0 ^ li1
p.lambda.SetBit(p.lambda, ow, lo)

fmt.Printf("%c[%d]: %v ^ %v = %v\n", symbols.Lambda, ow, li0, li1, lo)
p.Debugf("%c[%d]: %v ^ %v = %v\n", symbols.Lambda, ow, li0, li1, lo)

// 3.b: set garbled label on wire 0: k_{w,0} = k_{u,0} ⊕ k_{v,0}
wires[ow].L0 = wires[i0].L0
Expand All @@ -154,10 +230,10 @@ func (p *Player) offlinePhase() error {
}

for i := 0; i < len(wires); i++ {
fmt.Printf("W%d:\t%v\n", i, wires[i])
p.Debugf("W%d:\t%v\n", i, wires[i])
}

fmt.Printf("%c%s:\t%v\n", symbols.Lambda, p.IDString(), p.lambda.Text(2))
p.Debugf("%c%s:\t%v\n", symbols.Lambda, p.IDString(), p.lambda.Text(2))

return nil
}
16 changes: 11 additions & 5 deletions ot/io.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// io.go
//
// Copyright (c) 2023 Markku Rossi
// Copyright (c) 2023-2024 Markku Rossi
//
// All rights reserved.

Expand All @@ -13,20 +13,26 @@ import (

// IO defines an I/O interface to communicate between peers.
type IO interface {
// SendData sends binary data.
SendData(val []byte) error
// SendByte sends a byte value.
SendByte(val byte) error

// SendUint32 sends an uint32 value.
SendUint32(val int) error

// SendData sends binary data.
SendData(val []byte) error

// Flush flushed any pending data in the connection.
Flush() error

// ReceiveData receives binary data.
ReceiveData() ([]byte, error)
// ReceiveByte receives a byte value.
ReceiveByte() (byte, error)

// ReceiveUint32 receives an uint32 value.
ReceiveUint32() (int, error)

// ReceiveData receives binary data.
ReceiveData() ([]byte, error)
}

// SendString sends a string value.
Expand Down
Loading

0 comments on commit 6c1deab

Please sign in to comment.