diff --git a/go/delivery/gate.go b/go/delivery/gate.go index 5fbe9fb..6a3db12 100644 --- a/go/delivery/gate.go +++ b/go/delivery/gate.go @@ -7,6 +7,7 @@ import ( "fmt" "reflect" "regexp" + "sort" "strconv" "strings" @@ -87,6 +88,29 @@ func MergeAskKey(group string, heads []Head) (string, error) { return AskKindMerge + "." + part + "." + hash, nil } +// SettleGroupPrefix begins the group of a settle ask (novox/hq ADR 0556 clause 5): a person's ask to settle deliveries held +// because their merge reached the trunk without a passing check. It is kept in the gate's asks under MergeAskKey like a merge +// ask, so the teller carries it unchanged; its options bind the act AskVerb names for it. +const SettleGroupPrefix = "settle/" + +// SettleGroup is the group of the settle ask of these delivery ids: the prefix and twelve hex digits of the sha256 over the +// ids, sorted and joined by a newline, so the same deliveries asked again keep one key. +func SettleGroup(ids []string) string { + sorted := append([]string(nil), ids...) + sort.Strings(sorted) + sum := sha256.Sum256([]byte(strings.Join(sorted, "\n"))) + return SettleGroupPrefix + hex.EncodeToString(sum[:])[:12] +} + +// AskVerb is the act the options of an ask of the gate bind, by its group: a settle ask's `mesh-delivery.settle`, any other +// `mesh-delivery.merge`. The gate composes the act with it and the teller checks a warrant against it. +func AskVerb(group string) string { + if strings.HasPrefix(group, SettleGroupPrefix) { + return "mesh-delivery.settle" + } + return "mesh-delivery.merge" +} + // ParseAskKey is the inverse of MergeAskKey: the kind, the group and the heads hash. func ParseAskKey(key string) (kind, group, hash string, err error) { parts := strings.Split(key, ".") diff --git a/go/delivery/gate_test.go b/go/delivery/gate_test.go index 71ea691..1378d48 100644 --- a/go/delivery/gate_test.go +++ b/go/delivery/gate_test.go @@ -77,6 +77,18 @@ func TestAskID(t *testing.T) { // 1201/AC2 if AskID(k1) != AskID(k1) { t.Error("the id is not stable") } + // 1280 (ADR 0556 clause 5): a settle ask's group is the same for the same ids in any order, keys like any group, and its + // options bind mesh-delivery.settle; every other ask binds mesh-delivery.merge. + g := SettleGroup([]string{"novox/b@222222222222", "novox/a@111111111111"}) + if g != SettleGroup([]string{"novox/a@111111111111", "novox/b@222222222222"}) || !strings.HasPrefix(g, SettleGroupPrefix) || len(g) != len(SettleGroupPrefix)+12 { + t.Errorf("SettleGroup = %q", g) + } + if k, err := MergeAskKey(g, gateHeads()); err != nil || !asks.UsableID(AskID(k)) { + t.Errorf("the settle ask's key %q: %v", k, err) + } + if AskVerb(g) != "mesh-delivery.settle" || AskVerb("feat/x") != "mesh-delivery.merge" { + t.Errorf("AskVerb = %q, %q", AskVerb(g), AskVerb("feat/x")) + } } func TestOwedKey(t *testing.T) { // 1201/AC3