package release import ( "context" "crypto/ed25519" "errors" "os" "strconv" "time" ) func HistoryReconstructionKey(acct, app, identity string, revision uint64) string { return appPrefix(acct, app) + "release-history/" + identity + "/" + strconv.FormatUint(revision, 10) + ".json" } func (h *RootHistory) ReceiveReconstruction(ctx context.Context, store Store, pub ed25519.PublicKey, b HistoryBinding, now time.Time, resolve func(HistoryBinding) (string, error)) error { if !b.valid() || store == nil { return os.ErrPermission } resumeErr := h.ResumeReconstruction(resolve) status, err := h.ReconstructionStatus() if err != nil { return err } wire, _, err := store.Get(ctx, HistoryReconstructionKey(b.Account, b.App, status.Identity, status.Revision)) if errors.Is(err, os.ErrNotExist) { return resumeErr } if err != nil { return err } return h.Reconstruct(pub, wire, b.Account, b.App, now, resolve) } func HistoryRecoveryRetirementKey(b HistoryBinding, identity, outcomeDigest string) string { return appPrefix(b.Account, b.App) + "release-history/" + identity + "/recovery/" + outcomeDigest + ".json" } func (h *RootHistory) ReceiveRecoveryRetirements(ctx context.Context, store Store, pub ed25519.PublicKey, b HistoryBinding, now time.Time, resolve func(HistoryBinding) (string, error)) error { if !b.valid() || store == nil { return os.ErrPermission } status, err := h.ReconstructionStatus() if err != nil { return err } if status.Pending { return os.ErrPermission } outcomes, err := h.recoveryOutcomes() if err != nil { return err } count := 0 for _, r := range outcomes { if r.Binding != b { continue } count++ if count > historyLimit { return os.ErrPermission } if !r.Settled || (r.Verified && !r.Failed && !r.Recovering) { continue } retired, err := h.recoveryRetired(r, outcomes) if err != nil { return err } if retired { continue } wire, _, err := store.Get(ctx, HistoryRecoveryRetirementKey(b, status.Identity, historyRecoveryDigest(r))) if errors.Is(err, os.ErrNotExist) { continue } if err != nil { return err } if err := h.RetireRecovery(pub, wire, b, now, resolve); err != nil { return err } } return nil }