carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostexec
2
3import (
4 "bytes"
5 "context"
6 "errors"
7 "os"
8
9 "github.com/carlosframework/platform/internal/rootparticipation"
10 "github.com/carlosframework/platform/internal/rootstate"
11)
12
13func ReadRoot(ctx context.Context, store rootstate.Store, clock Clock, q ExecutionRequest, serving bool) (ExecutionRecord, error) {
14 var r ExecutionRecord
15 if store == nil || clock == nil {
16 return r, ErrState
17 }
18 if _, err := store.Read("update.json"); !errors.Is(err, os.ErrNotExist) {
19 return r, ErrLost
20 }
21 ledger := rootparticipation.Ledger{State: store}
22 census, err := ledger.Census()
23 if err != nil || census.NeverEnrolled {
24 return r, errors.Join(err, ErrState)
25 }
26 raw, err := store.Read(q.Host + ".json")
27 if serving {
28 if errors.Is(err, os.ErrNotExist) {
29 return r, nil
30 }
31 if err != nil {
32 return r, err
33 }
34 if rootparticipation.Decode(raw, &r) != nil || r.Schema != 1 || !r.Request.Valid() || r.Token == "" || r.Replay == nil || r.Request.Host != q.Host || r.Status != "settled" || r.Authority.Migration != census.Migration || r.Authority.Box != census.Box || r.Authority.Enrollment != census.Enrollment {
35 return r, ErrLost
36 }
37 return r, nil
38 }
39 if err != nil {
40 return r, err
41 }
42 if rootparticipation.Decode(raw, &r) != nil || r.Schema != 1 || !r.Request.Valid() || !sameExecution(q, r) || r.Status != "active" || r.Authority.ParticipationOnly || r.Authority.Installation == "" || r.Authority.Migration != census.Migration || r.Authority.Box != census.Box || r.Authority.Enrollment != census.Enrollment || r.Token == "" {
43 return r, ErrLost
44 }
45 boot, err := BootID()
46 if err != nil || r.Peer.KernelBootID != boot {
47 return r, ErrLost
48 }
49 _, now, err := clock.Now()
50 if err != nil || now >= r.SafeUntil {
51 return r, ErrLost
52 }
53 if err = ControllerAlive(ctx, r.Peer); err != nil {
54 return r, err
55 }
56 if err := ctx.Err(); err != nil {
57 return r, err
58 }
59 alive, err := rootstate.LiveHeld(store, q.Host+".live")
60 if err != nil || !alive {
61 return r, errors.Join(ErrLost, err)
62 }
63 again, err := store.Read(q.Host + ".json")
64 if err != nil || !bytes.Equal(raw, again) {
65 return r, ErrLost
66 }
67 _, now, err = clock.Now()
68 if err != nil || now >= r.SafeUntil {
69 return r, ErrLost
70 }
71 return r, nil
72}
73