This repository has been archived by the owner on Jul 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathauthorize.go
122 lines (109 loc) · 4.07 KB
/
authorize.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package actions
import (
"context"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/hypersdk/chain"
"github.com/ava-labs/hypersdk/codec"
"github.com/ava-labs/hypersdk/crypto"
"github.com/ava-labs/hypersdk/utils"
"github.com/ava-labs/indexvm/auth"
"github.com/ava-labs/indexvm/genesis"
"github.com/ava-labs/indexvm/storage"
)
var _ chain.Action = (*Authorize)(nil)
type Authorize struct {
// Actor must be specified so we can enumerate read keys
Actor crypto.PublicKey `json:"actor"`
// Signer is the new permissions
//
// Any balance pull must come from actor to avoid being able to steal other's
// money.
Signer crypto.PublicKey `json:"signer"`
// TODO: based on order of index in permissions
// if 0, then remove all perms
ActionPermissions uint8 `json:"actionPermissions"`
MiscPermissions uint8 `json:"miscPermissions"`
}
func (a *Authorize) StateKeys(chain.Auth) [][]byte {
return [][]byte{storage.PrefixPermissionsKey(a.Actor, a.Signer)}
}
func (a *Authorize) Execute(
ctx context.Context,
r chain.Rules,
db chain.Database,
_ int64,
rauth chain.Auth,
_ ids.ID,
) (*chain.Result, error) {
unitsUsed := a.MaxUnits(r) // max units == units
// Ensure auth actor is the same as actor specified in tx.
actor := auth.GetActor(rauth)
if actor != a.Actor {
return &chain.Result{Success: false, Units: unitsUsed, Output: OutputActorMismatch}, nil
}
// Ensure permissions actually do something
actionPermissions, miscPermissions, err := storage.GetPermissions(ctx, db, a.Actor, a.Signer)
if err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
if actionPermissions == a.ActionPermissions && miscPermissions == a.MiscPermissions {
return &chain.Result{
Success: false,
Units: unitsUsed,
Output: OutputPermissionsUseless,
}, nil
}
stateLockup, err := genesis.GetStateLockup(r)
if err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
switch {
case actionPermissions == 0 && miscPermissions == 0:
// need to pay state lockup
if err := storage.LockBalance(ctx, db, a.Actor, stateLockup); err != nil { // new accounts must lock funds
// TODO: where should lock funds?
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
if err := storage.SetPermissions(ctx, db, a.Actor, a.Signer, a.ActionPermissions, a.MiscPermissions); err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
case a.ActionPermissions == 0 && a.MiscPermissions == 0:
// get refund
if err := storage.UnlockBalance(ctx, db, a.Actor, stateLockup); err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
if err := storage.DeletePermissions(ctx, db, a.Actor, a.Signer); err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
default:
// Simple override of permissions
if err := storage.SetPermissions(ctx, db, a.Actor, a.Signer, a.ActionPermissions, a.MiscPermissions); err != nil {
return &chain.Result{Success: false, Units: unitsUsed, Output: utils.ErrBytes(err)}, nil
}
}
return &chain.Result{Success: true, Units: unitsUsed}, nil
}
func (*Authorize) MaxUnits(chain.Rules) uint64 {
// TODO: add a "state touch" constant based on number of times touching state
// minUnits == size, maxUnits == size + max state touches
return crypto.PublicKeyLen*2 + 2
}
func (a *Authorize) Marshal(p *codec.Packer) {
p.PackPublicKey(a.Actor)
p.PackPublicKey(a.Signer)
p.PackByte(a.ActionPermissions)
p.PackByte(a.MiscPermissions)
}
func UnmarshalAuthorize(p *codec.Packer) (chain.Action, error) {
var authorize Authorize
p.UnpackPublicKey(&authorize.Actor)
p.UnpackPublicKey(&authorize.Signer)
authorize.ActionPermissions = p.UnpackByte()
authorize.MiscPermissions = p.UnpackByte()
return &authorize, p.Err()
}
func (*Authorize) ValidRange(chain.Rules) (int64, int64) {
return -1, -1
}