Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

migrate.gno

2.22 Kb · 66 lines
 1package basedao
 2
 3import (
 4	"errors"
 5
 6	"gno.land/p/samcrew/daokit"
 7)
 8
 9// Making this action name extra explicit.
10const ActionChangeDAOImplementationKind = "gno.land/p/samcrew/basedao.ChangeDAOImplementation"
11
12type MigrateFn = func(prev *DAOPrivate, params []any, rlm realm) daokit.DAO
13
14type MigrationParamsFn = func() []any
15
16type actionChangeDAOImplementation struct {
17	label   string
18	migrate MigrateFn
19}
20
21func (a *actionChangeDAOImplementation) String() string {
22	return "WARNING: this replaces the DAO's implementation.\n\n" +
23		"The migration function receives the DAO's live realm and full private\n" +
24		"state, so approving it grants whoever wrote it the DAO's authority.\n" +
25		"Read the code it refers to before voting.\n\n" +
26		"Migration: " + a.label
27}
28
29func NewChangeDAOImplementationHandler(dao *DAOPrivate, setImplem daokit.SetImplemFn, paramsFn MigrationParamsFn) daokit.ActionHandler {
30	if dao == nil || setImplem == nil || paramsFn == nil {
31		panic("nil arg")
32	}
33	return daokit.NewActionHandler(ActionChangeDAOImplementationKind, func(i interface{}, rlm realm) {
34		action, ok := i.(*actionChangeDAOImplementation)
35		if !ok {
36			panic(errors.New("invalid action type"))
37		}
38
39		migrated := action.migrate(dao, paramsFn(), rlm)
40		setImplem(migrated)
41	})
42}
43
44// The label is required and appears in the proposal a member votes on.
45//
46// Without it every migration renders as the same fixed sentence, so a voter sees
47// nothing distinguishing a routine upgrade from a takeover. A function value
48// cannot be rendered, so the caller has to say what it is — name the version,
49// the commit, or the change.
50//
51// It is NOT a safety control. Whoever writes the migration writes the label, so
52// a takeover can ship as "routine security patch". It exists so an honest
53// proposal can be told apart from another honest proposal, and so a voter has
54// something to check the code against. Read the migration.
55func NewChangeDAOImplementationAction(label string, migrate MigrateFn) daokit.Action {
56	if label == "" {
57		panic("migration label must not be empty")
58	}
59	if migrate == nil {
60		panic("migration function must not be nil")
61	}
62	return daokit.NewAction(ActionChangeDAOImplementationKind, &actionChangeDAOImplementation{
63		label:   label,
64		migrate: migrate,
65	})
66}