The node-engine answers compose-candidate in its seat's contract: the input as a JSON object, a module's fingerprint Fp
mesh-sdk's ComposeCandidateAnswer and ModuleComposed are now the generated nodeengine types (ADR 0613 §3, §5), so the input sent for the checker's sandbox is decoded once into the object the contract carries, its numbers kept as written (json.Number), and its size still counted from the bytes it was marshalled to. Claude-Session: https://claude.ai/code/session_01JG73KG7AfSdh6FP8VrBqCn
This commit is contained in:
@@ -603,7 +603,7 @@ func h8candidate(t *testing.T, b *itBed, fp, running string) {
|
||||
t.Fatalf("the answer %s: %v", raw, err)
|
||||
}
|
||||
if a.Verdict != delivery.ComposeCandidateComposed || len(a.Modules) != 1 || a.Modules[0].Module != "web" ||
|
||||
a.Modules[0].FP != fpIt("c") || !a.Modules[0].Changed || a.Took > delivery.ComposeAnswerBound.Milliseconds() {
|
||||
a.Modules[0].Fp != fpIt("c") || !a.Modules[0].Changed || a.Took > delivery.ComposeAnswerBound.Milliseconds() {
|
||||
t.Errorf("the node's answer to a candidate changing web: %+v", a)
|
||||
}
|
||||
after, _ := b.composed.Status()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package selfcompose
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -181,6 +182,7 @@ func (s *Shadow) composeCandidate(ctx context.Context, c *Composer, ask delivery
|
||||
if err != nil {
|
||||
return unready(err.Error())
|
||||
}
|
||||
sentSize := 0
|
||||
laidComps, laidHeld, laidErr := laid.composeShadow(ctx, running, touched, func(scope frombus.Scope, fps map[string]string) {
|
||||
if !ask.Input {
|
||||
return
|
||||
@@ -196,13 +198,19 @@ func (s *Shadow) composeCandidate(ctx context.Context, c *Composer, ask delivery
|
||||
in.ComposedHow.HeldBefore = maps.Clone(baseHeld)
|
||||
// As the sandbox reads it (composer.SentInput, the one shape): this node's own modules as taken in from their
|
||||
// builds, every other module's manifest left to the cases.
|
||||
// The seat's contract carries it as a JSON object; its numbers are kept as written (json.Number).
|
||||
if body, err := json.Marshal(composer.SentInput(in, laid.env.Node)); err == nil {
|
||||
a.Input = body
|
||||
d := json.NewDecoder(bytes.NewReader(body))
|
||||
d.UseNumber()
|
||||
var obj map[string]any
|
||||
if d.Decode(&obj) == nil {
|
||||
a.Input, sentSize = obj, len(body)
|
||||
}
|
||||
}
|
||||
})
|
||||
if len(a.Input) > maxSentInput {
|
||||
if sentSize > maxSentInput {
|
||||
// Past what the bus carries in one answer, the checker would hear nothing: refused, saying so.
|
||||
size := len(a.Input)
|
||||
size := sentSize
|
||||
a.Input = nil
|
||||
return refuse(fmt.Sprintf("the composition input this node composed from is %d bytes, more than the %d an answer on the bus carries", size, maxSentInput))
|
||||
}
|
||||
@@ -251,7 +259,7 @@ func (s *Shadow) composeCandidate(ctx context.Context, c *Composer, ask delivery
|
||||
m.State, m.Words = delivery.ModuleRefusedState, err.Error()
|
||||
return m, true
|
||||
}
|
||||
m.State, m.FP, m.Digest = delivery.ModuleComposedState, comp.FP, dig
|
||||
m.State, m.Fp, m.Digest = delivery.ModuleComposedState, comp.FP, dig
|
||||
if before, ok := was[module]; !ok {
|
||||
m.Changed = true
|
||||
} else if d, err := delivery.ComposedDigestOf(before); err != nil || d != dig {
|
||||
|
||||
@@ -103,7 +103,7 @@ func TestTheNodeComposesACandidateOnAsk(t *testing.T) {
|
||||
t.Fatalf("the answer does not fit the seat's shape: %v (%+v)", err, a)
|
||||
}
|
||||
if a.Verdict != delivery.ComposeCandidateComposed || len(a.Modules) != 1 || a.Modules[0].Module != "lemurs" ||
|
||||
a.Modules[0].State != delivery.ModuleComposedState || a.Modules[0].FP != fpNew || !a.Modules[0].Changed ||
|
||||
a.Modules[0].State != delivery.ModuleComposedState || a.Modules[0].Fp != fpNew || !a.Modules[0].Changed ||
|
||||
a.Own.Module != delivery.HaveNodeWord || a.Took > delivery.ComposeAnswerBound.Milliseconds() {
|
||||
t.Errorf("an accepted candidate answered %+v", a)
|
||||
}
|
||||
@@ -111,7 +111,8 @@ func TestTheNodeComposesACandidateOnAsk(t *testing.T) {
|
||||
// through the same path.
|
||||
sent := s.ComposeCandidate(ctx, delivery.ComposeCandidateAsk{Candidate: accepted, Input: true})
|
||||
var in compose.Input
|
||||
if err := json.Unmarshal(sent.Input, &in); err != nil || in.ComposedHow == nil || in.ComposedHow.Node != "n1" ||
|
||||
raw, _ := json.Marshal(sent.Input)
|
||||
if err := json.Unmarshal(raw, &in); err != nil || in.ComposedHow == nil || in.ComposedHow.Node != "n1" ||
|
||||
in.ComposedHow.Builds["lemurs"] != fpNew {
|
||||
t.Errorf("the input sent for the sandbox does not say how the node composes: %+v, %v", in.ComposedHow, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user