ceremonyclient/bedlam/circuit/evaluator.go
Cassandra Heart dbd95bd9e9
v2.1.0 (#439)
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete

* 2.1.0 main node rollup
2025-09-30 02:48:15 -05:00

160 lines
3.3 KiB
Go

//
// evaluator.go
//
// Copyright (c) 2019-2023 Markku Rossi
//
// All rights reserved.
//
package circuit
import (
"fmt"
"math/big"
"source.quilibrium.com/quilibrium/monorepo/bedlam/ot"
"source.quilibrium.com/quilibrium/monorepo/bedlam/p2p"
)
var (
debug = false
)
// Evaluator runs the evaluator on the P2P network.
func Evaluator(conn *p2p.Conn, oti ot.OT, circ *Circuit, inputs *big.Int,
verbose bool) ([]*big.Int, error) {
timing := NewTiming()
garbled := make([][]ot.Label, circ.NumGates)
// Receive program info.
if verbose {
fmt.Printf(" - Waiting for circuit info...\n")
}
key, err := conn.ReceiveData()
if err != nil {
return nil, err
}
// Receive garbled tables.
timing.Sample("Wait", nil)
if verbose {
fmt.Printf(" - Receiving garbled circuit...\n")
}
count, err := conn.ReceiveUint32()
if err != nil {
return nil, err
}
if count != circ.NumGates {
return nil, fmt.Errorf("wrong number of gates: got %d, expected %d",
count, circ.NumGates)
}
var label ot.Label
var labelData ot.LabelData
for i := 0; i < circ.NumGates; i++ {
count, err := conn.ReceiveUint32()
if err != nil {
return nil, err
}
values := make([]ot.Label, count)
for j := 0; j < count; j++ {
err := conn.ReceiveLabel(&label, &labelData)
if err != nil {
return nil, err
}
values[j] = label
}
garbled[i] = values
}
wires := make([]ot.Label, circ.NumWires)
// Receive peer inputs.
for i := 0; i < int(circ.Inputs[0].Type.Bits); i++ {
err := conn.ReceiveLabel(&label, &labelData)
if err != nil {
return nil, err
}
wires[Wire(i)] = label
}
// Init oblivious transfer.
err = oti.InitReceiver(conn)
if err != nil {
return nil, err
}
ioStats := conn.Stats.Sum()
timing.Sample("Recv", []string{FileSize(ioStats).String()})
// Query our inputs.
if verbose {
fmt.Printf(" - Querying our inputs...\n")
}
// Wire offset.
if err := conn.SendUint32(int(circ.Inputs[0].Type.Bits)); err != nil {
return nil, err
}
// Wire count.
if err := conn.SendUint32(int(circ.Inputs[1].Type.Bits)); err != nil {
return nil, err
}
if err := conn.Flush(); err != nil {
return nil, err
}
flags := make([]bool, int(circ.Inputs[1].Type.Bits))
for i := 0; i < int(circ.Inputs[1].Type.Bits); i++ {
if inputs.Bit(i) == 1 {
flags[i] = true
}
}
if err := oti.Receive(flags, wires[circ.Inputs[0].Type.Bits:]); err != nil {
return nil, err
}
xfer := conn.Stats.Sum() - ioStats
ioStats = conn.Stats.Sum()
timing.Sample("Inputs", []string{FileSize(xfer).String()})
// Evaluate gates.
if verbose {
fmt.Printf(" - Evaluating circuit...\n")
}
err = circ.Eval(key[:], wires, garbled)
if err != nil {
return nil, err
}
timing.Sample("Eval", nil)
// Resolve result values.
var labels []ot.Label
for i := 0; i < circ.Outputs.Size(); i++ {
r := wires[Wire(circ.NumWires-circ.Outputs.Size()+i)]
labels = append(labels, r)
}
for _, l := range labels {
if err := conn.SendLabel(l, &labelData); err != nil {
return nil, err
}
}
if err := conn.Flush(); err != nil {
return nil, err
}
result, err := conn.ReceiveData()
if err != nil {
return nil, err
}
raw := big.NewInt(0).SetBytes(result)
xfer = conn.Stats.Sum() - ioStats
timing.Sample("Result", []string{FileSize(xfer).String()})
if verbose {
timing.Print(conn.Stats)
}
return circ.Outputs.Split(raw), nil
}