carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package release
2
3import (
4 "os"
5 "slices"
6 "strings"
7
8 "github.com/carlosframework/platform/internal/rootstate"
9)
10
11// Recovery uses usable denials without asserting that the inventory is complete.
12// Minting continues to require Refusals and its durable completeness checks.
13func (h *RootHistory) recoveryDenials(b HistoryBinding) []Refusal {
14 if h == nil || h.Store == nil || !b.valid() {
15 return nil
16 }
17 var refs []Refusal
18 raw, err := h.Store.Read(historyKey(b))
19 var record historyRecord
20 if err == nil && len(raw) <= rootstate.MaxRecord && strictCanonicalJSON(raw, &record) == nil && record.Schema == 1 && record.Binding == b {
21 for _, ref := range record.Refusals.Values {
22 if ref.Schema == 1 && ref.Host == b.Host && ref.App == b.App && ref.Version != "" && !ref.RefusedAt.IsZero() && ref.MoveOp == "" &&
23 (ref.Kind == RefusalNotUp || ref.Kind == RefusalWrongProgram || ref.Kind == RefusalNotProven) {
24 refs = append(refs, ref)
25 }
26 }
27 }
28 names, _ := h.Store.Names()
29 var outcomes []HistoryRecovery
30 for _, name := range names {
31 if !strings.HasSuffix(name, ".outcome") {
32 continue
33 }
34 raw, err := h.Store.Read(name)
35 var r historyRecoveryRecord
36 if err != nil || len(raw) > rootstate.MaxRecord || strictCanonicalJSON(raw, &r) != nil || r.Schema != 1 || !validHistoryRecovery(r.HistoryRecovery) || historyRecoveryKey(r.HistoryRecovery) != name {
37 continue
38 }
39 outcomes = append(outcomes, r.HistoryRecovery)
40 }
41 for _, r := range outcomes {
42 if r.Binding != b || (!r.Failed && !r.Recovering) {
43 continue
44 }
45 retired, err := h.recoveryRetired(r, outcomes)
46 if err == nil && retired {
47 continue
48 }
49 refs = append(refs, Refusal{Schema: 1, Host: b.Host, App: b.App, Version: r.Attempt.Version, SHA256: r.Attempt.SHA256, Platform: r.Attempt.Platform, PointerPromotedAt: r.Attempt.PromotedAt, RefusedAt: r.Attempt.Started, Kind: RefusalNotUp})
50 }
51 return refs
52}
53
54// RetireD1 accepts only an independently verified later promotion of this
55// version. Program and proof refusals keep their separate authorization rules.
56func (h *RootHistory) RetireD1(b HistoryBinding, p *ChannelPointer) error {
57 if p == nil || p.Version == "" || p.PromotedAt.IsZero() {
58 return os.ErrPermission
59 }
60 r, err := h.read(b)
61 if err != nil {
62 return err
63 }
64 refs := slices.DeleteFunc(slices.Clone(r.Refusals.Values), func(v Refusal) bool {
65 return v.Kind == RefusalNotUp && v.Version == p.Version && p.PromotedAt.After(v.PointerPromotedAt)
66 })
67 if len(refs) == len(r.Refusals.Values) {
68 return nil
69 }
70 if r.Revision == ^uint64(0) {
71 return os.ErrPermission
72 }
73 r.Revision++
74 r.Refusals.Values, r.Refusals.Revision = refs, r.Revision
75 return h.write(r)
76}
77