diff --git a/node-tools/internal/bus/sent.go b/node-tools/internal/bus/sent.go index 7cd2406..271252e 100644 --- a/node-tools/internal/bus/sent.go +++ b/node-tools/internal/bus/sent.go @@ -15,7 +15,7 @@ import ( // SentGet reads one object of a sender's store of sent objects by the reference that carried it (ADR 0666 §16): the // store is the sender's `_sent-objects`, and no other — a state's objects are reached through their owner's // bindings alone. It reads as this connection's account, which the bus lets read a sender's sent store only where the -// grants part granted it, from the manifests' callers and consumers; a refusal says the store. +// grants part granted it (a bundle is held to what its runtime channel carries by the runtime call, not here), from the manifests' callers and consumers; a refusal says the store. func (c *Conn) SentGet(r buscalls.ObjectsSentGetRequest) (*buscalls.ObjectData, error) { ref := stateobjects.Ref{Store: r.Store, Object: r.Object, Size: r.Size, Digest: r.Digest, Form: stateobjects.FormVersion} if _, ok := stateobjects.ReadRef(stateobjects.Wrap(ref)); !ok { @@ -25,10 +25,6 @@ func (c *Conn) SentGet(r buscalls.ObjectsSentGetRequest) (*buscalls.ObjectData, return nil, fmt.Errorf("%s is no sent store (a module's is `%s%s`): only a sent object is read by its reference", r.Store, catalogue.BusNameSeparator, catalogue.SentObjectsLocal) } - if r.Size > stateobjects.BundleObjectMost { - return nil, fmt.Errorf("the sent object %s is %d bytes and a bundle's runtime channel carries at most %d: it is not read "+ - "through a bundle", r.Object, r.Size, stateobjects.BundleObjectMost) - } js, err := c.jetStream() if err != nil { return nil, err diff --git a/node-tools/internal/bus/sent_test.go b/node-tools/internal/bus/sent_test.go index 26ce44d..ca7d1b4 100644 --- a/node-tools/internal/bus/sent_test.go +++ b/node-tools/internal/bus/sent_test.go @@ -5,14 +5,12 @@ import ( "testing" "git.novox.be/novox/mesh-sdk/go/buscalls" - "git.novox.be/novox/mesh-sdk/go/stateobjects" ) // Design 47 G §347, §59, §462: a sent object is read by the reference that carried it, from a sender's sent store only; a -// state's objects, a reference that is none and an object too large for a bundle's channel are refused before the bus is asked. +// state's objects, and a reference that is none are refused before the bus is asked. func TestSentGetRefusesWhatIsNoSentObjectsReference(t *testing.T) { digest := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - big := int64(stateobjects.BundleObjectMost) + 1 for _, c := range []struct { name string req buscalls.ObjectsSentGetRequest @@ -20,7 +18,6 @@ func TestSentGetRefusesWhatIsNoSentObjectsReference(t *testing.T) { }{ {"no digest", buscalls.ObjectsSentGetRequest{Store: "m_sent-objects", Object: "o", Size: 3}, "named by the reference"}, {"a state's objects", buscalls.ObjectsSentGetRequest{Store: "m_asks-objects", Object: "o", Size: 3, Digest: digest}, "no sent store"}, - {"over the channel", buscalls.ObjectsSentGetRequest{Store: "m_sent-objects", Object: "o", Size: big, Digest: digest}, "not read through a bundle"}, } { _, err := (&Conn{}).SentGet(c.req) if err == nil || !strings.Contains(err.Error(), c.want) { diff --git a/node-tools/internal/console/sent_test.go b/node-tools/internal/console/sent_test.go index bd1d0c9..80cd477 100644 --- a/node-tools/internal/console/sent_test.go +++ b/node-tools/internal/console/sent_test.go @@ -33,7 +33,7 @@ func TestAnAnswerSentAsAReferenceIsReadForThePersonAsking(t *testing.T) { t.Fatal(err) } defer conn.Close() - body := []byte(`{"lines":"` + strings.Repeat("x", 3<<20) + `"}`) + body := []byte(`{"lines":"` + strings.Repeat("x", 9<<20) + `"}`) sum := sha256.Sum256(body) ref := stateobjects.Ref{Store: "m_sent-objects", Object: "tool.lines." + hex.EncodeToString(sum[:]), Size: int64(len(body)), Digest: hex.EncodeToString(sum[:]), Form: stateobjects.FormVersion} @@ -47,7 +47,7 @@ func TestAnAnswerSentAsAReferenceIsReadForThePersonAsking(t *testing.T) { missing.Store = "gone_sent-objects" wrapped := stateobjects.Wrap(missing) got, unread := resolveSent(conn, wrapped) - if string(got) != string(wrapped) || !strings.Contains(unread, "3145") || !strings.Contains(unread, "gone_sent-objects") { + if string(got) != string(wrapped) || !strings.Contains(unread, "9437") || !strings.Contains(unread, "gone_sent-objects") { t.Fatalf("an unread answer showed %q and %q", got, unread) } if got, unread := resolveSent(conn, []byte(`{"a":1}`)); unread != "" || string(got) != `{"a":1}` { diff --git a/node-tools/internal/runtime/busstate.go b/node-tools/internal/runtime/busstate.go index 3d55731..1c9dacc 100644 --- a/node-tools/internal/runtime/busstate.go +++ b/node-tools/internal/runtime/busstate.go @@ -7,6 +7,7 @@ import ( stdio "git.novox.be/novox/mesh-sdk/go" "git.novox.be/novox/mesh-sdk/go/buscalls" + "git.novox.be/novox/mesh-sdk/go/stateobjects" ) // The capabilities the tool runner states of the calls it answers (novox/hq ADR 0595 §9, ADR 0597; design 25 § 12.4): each is @@ -69,7 +70,10 @@ func (b *moduleBus) BusState(method string, params json.RawMessage) (json.RawMes var r buscalls.ObjectsSentGetRequest if err = decode(method, params, &r); err == nil { var got *buscalls.ObjectData - if got, err = conn.SentGet(r); err == nil { + if r.Size > stateobjects.BundleObjectMost { + // Only the bundle's channel is limited (design 47 "Any size"): the console reads a larger one whole. + err = fmt.Errorf("the sent object %s is %d bytes and a bundle's runtime channel carries at most %d: it is not read through a bundle", r.Object, r.Size, stateobjects.BundleObjectMost) + } else if got, err = conn.SentGet(r); err == nil { answer = got } } diff --git a/node-tools/internal/runtime/sent_cap_test.go b/node-tools/internal/runtime/sent_cap_test.go new file mode 100644 index 0000000..1498a39 --- /dev/null +++ b/node-tools/internal/runtime/sent_cap_test.go @@ -0,0 +1,21 @@ +package runtime + +import ( + "encoding/json" + "strings" + "testing" + + "git.novox.be/novox/mesh-sdk/go/buscalls" + "git.novox.be/novox/mesh-sdk/go/stateobjects" +) + +// Design 47 G §69, §62, §407: only a bundle's runtime channel holds the cap, so the runtime call refuses a sent object over +// it before the bus is asked, where the console (which reads through the bus) reads it whole. +func TestARuntimeCallRefusesASentObjectOverTheBundleChannel(t *testing.T) { + params, _ := json.Marshal(buscalls.ObjectsSentGetRequest{Store: "m_sent-objects", Object: "o", + Size: int64(stateobjects.BundleObjectMost) + 1, Digest: strings.Repeat("a", 64)}) + _, err := (&moduleBus{all: &consumers{}}).BusState(buscalls.ObjectsSentGet, params) + if err == nil || !strings.Contains(err.Error(), "not read through a bundle") { + t.Fatalf("a sent object over the channel was answered %v", err) + } +}