-
Notifications
You must be signed in to change notification settings - Fork 179
/
account_freezer.go
138 lines (111 loc) · 3.03 KB
/
account_freezer.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package environment
import (
"fmt"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/flow-go/fvm/errors"
"github.com/onflow/flow-go/fvm/state"
"github.com/onflow/flow-go/model/flow"
)
// AccountFreezer disables accounts.
//
// Note that scripts cannot freeze accounts, but must expose the API in
// compliance with the environment interface.
type AccountFreezer interface {
// Note that the script variant will return OperationNotSupportedError.
SetAccountFrozen(address common.Address, frozen bool) error
FrozenAccounts() []common.Address
Reset()
}
type ParseRestrictedAccountFreezer struct {
txnState *state.TransactionState
impl AccountFreezer
}
func NewParseRestrictedAccountFreezer(
txnState *state.TransactionState,
impl AccountFreezer,
) AccountFreezer {
return ParseRestrictedAccountFreezer{
txnState: txnState,
impl: impl,
}
}
func (freezer ParseRestrictedAccountFreezer) SetAccountFrozen(
address common.Address,
frozen bool,
) error {
return parseRestrict2Arg(
freezer.txnState,
"SetAccountFrozen",
freezer.impl.SetAccountFrozen,
address,
frozen)
}
func (freezer ParseRestrictedAccountFreezer) FrozenAccounts() []common.Address {
return freezer.impl.FrozenAccounts()
}
func (freezer ParseRestrictedAccountFreezer) Reset() {
freezer.impl.Reset()
}
type NoAccountFreezer struct{}
func (NoAccountFreezer) FrozenAccounts() []common.Address {
return nil
}
func (NoAccountFreezer) SetAccountFrozen(_ common.Address, _ bool) error {
return errors.NewOperationNotSupportedError("SetAccountFrozen")
}
func (NoAccountFreezer) Reset() {
}
type accountFreezer struct {
serviceAddress flow.Address
accounts Accounts
transactionInfo TransactionInfo
frozenAccounts []common.Address
}
func NewAccountFreezer(
serviceAddress flow.Address,
accounts Accounts,
transactionInfo TransactionInfo,
) *accountFreezer {
freezer := &accountFreezer{
serviceAddress: serviceAddress,
accounts: accounts,
transactionInfo: transactionInfo,
}
freezer.Reset()
return freezer
}
func (freezer *accountFreezer) Reset() {
freezer.frozenAccounts = nil
}
func (freezer *accountFreezer) FrozenAccounts() []common.Address {
return freezer.frozenAccounts
}
func (freezer *accountFreezer) SetAccountFrozen(
address common.Address,
frozen bool,
) error {
flowAddress := flow.Address(address)
if flowAddress == freezer.serviceAddress {
return fmt.Errorf(
"setting account frozen failed: %w",
errors.NewValueErrorf(
flowAddress.String(),
"cannot freeze service account"))
}
if !freezer.transactionInfo.IsServiceAccountAuthorizer() {
return fmt.Errorf(
"setting account frozen failed: %w",
errors.NewOperationAuthorizationErrorf(
"SetAccountFrozen",
"accounts can be frozen only by transactions authorized by "+
"the service account"))
}
err := freezer.accounts.SetAccountFrozen(flowAddress, frozen)
if err != nil {
return fmt.Errorf("setting account frozen failed: %w", err)
}
if frozen {
freezer.frozenAccounts = append(freezer.frozenAccounts, address)
}
return nil
}