mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
Two halves of opening a secret were missing, and both showed up the first time this ran against the real ring rather than an in-process one. The request reached no party. Parties subscribed to "mpc.reveal_request.*" and the requester published to "mpc.reveal_request.<session>". This transport delivers by exact map lookup on the topic — it has no wildcards — so the subscription matched nothing, every node stayed silent, and the opening failed as "0 of 2 answered" with all three shares present and nobody having been asked. That reads like a quorum fault and is a routing one. Both sides name one literal now; the session rides in the body, where a reader wants it anyway. The pattern came from the NATS-era topics next door, where wildcards do work. And nothing could seal. mpcrek requires a sealed root to bring and no tool in the estate produced one, so the protocol had no beginning. reveal.Seal takes the published group key and a secret — no share, no node, no round, because writing to the committee needs none of that — and `mpcd seal` is that from a shell, with the secret on stdin so it never becomes an argument other processes can read. Sealing to the identity is refused. It decodes as a valid point, so the decoder lets it through, and every answer verifies against it: a secret sealed there is readable by anyone. A test asked for that and the first version did not do it.
42 lines
1.6 KiB
Go
42 lines
1.6 KiB
Go
package event
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// The consensus transport delivers by exact map lookup on the topic string. It
|
|
// has no wildcards, so a party subscribed to a pattern is subscribed to nothing
|
|
// and hears no request — the opening then times out with every share present
|
|
// and nobody having been asked, which reads like a quorum problem and is not
|
|
// one. That is how this shipped, and a "*" here is the whole of it.
|
|
func TestTopicsAreLiteral(t *testing.T) {
|
|
for name, topic := range map[string]string{
|
|
"RevealRequestTopic": RevealRequestTopic,
|
|
"RevealAnswerTopicBase": RevealAnswerTopicBase,
|
|
} {
|
|
if strings.ContainsAny(topic, "*>") {
|
|
t.Errorf("%s = %q carries a wildcard; this transport matches exactly", name, topic)
|
|
}
|
|
}
|
|
}
|
|
|
|
// One request reaches every party, so both sides have to name the same string.
|
|
// The session that separates two openings in flight rides in the body, and the
|
|
// answers come back on their own per-session topic built from the base.
|
|
func TestARequestIsOneTopicAndAnAnswerIsPerSession(t *testing.T) {
|
|
if RevealRequestTopic != "mpc.reveal_request" {
|
|
t.Errorf("request topic = %q", RevealRequestTopic)
|
|
}
|
|
if RevealAnswerTopicBase != "mpc.reveal_answer" {
|
|
t.Errorf("answer base = %q", RevealAnswerTopicBase)
|
|
}
|
|
if strings.HasPrefix(RevealAnswerTopicBase, RevealRequestTopic) {
|
|
t.Error("the answer base is a prefix of the request topic; a request would land on the answer path")
|
|
}
|
|
var r RevealRequest
|
|
if _, ok := any(r.SessionID).(string); !ok {
|
|
t.Error("the request must carry its session, since the topic no longer does")
|
|
}
|
|
}
|