github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/account_creator.go (about) 1 package environment 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/cadence/runtime" 7 "github.com/onflow/cadence/runtime/common" 8 9 "github.com/koko1123/flow-go-1/fvm/errors" 10 "github.com/koko1123/flow-go-1/fvm/state" 11 "github.com/koko1123/flow-go-1/fvm/tracing" 12 "github.com/koko1123/flow-go-1/model/flow" 13 "github.com/koko1123/flow-go-1/module/trace" 14 ) 15 16 const ( 17 FungibleTokenAccountIndex = 2 18 FlowTokenAccountIndex = 3 19 FlowFeesAccountIndex = 4 20 ) 21 22 type AddressGenerator interface { 23 Bytes() []byte 24 NextAddress() (flow.Address, error) 25 CurrentAddress() flow.Address 26 AddressCount() uint64 27 } 28 29 type BootstrapAccountCreator interface { 30 CreateBootstrapAccount( 31 publicKeys []flow.AccountPublicKey, 32 ) ( 33 flow.Address, 34 error, 35 ) 36 } 37 38 // This ensures cadence can't access unexpected operations while parsing 39 // programs. 40 type ParseRestrictedAccountCreator struct { 41 txnState *state.TransactionState 42 impl AccountCreator 43 } 44 45 func NewParseRestrictedAccountCreator( 46 txnState *state.TransactionState, 47 creator AccountCreator, 48 ) AccountCreator { 49 return ParseRestrictedAccountCreator{ 50 txnState: txnState, 51 impl: creator, 52 } 53 } 54 55 func (creator ParseRestrictedAccountCreator) CreateAccount( 56 payer runtime.Address, 57 ) ( 58 runtime.Address, 59 error, 60 ) { 61 return parseRestrict1Arg1Ret( 62 creator.txnState, 63 trace.FVMEnvCreateAccount, 64 creator.impl.CreateAccount, 65 payer) 66 } 67 68 type AccountCreator interface { 69 CreateAccount(payer runtime.Address) (runtime.Address, error) 70 } 71 72 type NoAccountCreator struct { 73 } 74 75 func (NoAccountCreator) CreateAccount( 76 payer runtime.Address, 77 ) ( 78 runtime.Address, 79 error, 80 ) { 81 return runtime.Address{}, errors.NewOperationNotSupportedError( 82 "CreateAccount") 83 } 84 85 // accountCreator make use of the storage state and the chain's address 86 // generator to create accounts. 87 // 88 // It also serves as a decorator for the chain's address generator which 89 // updates the state when next address is called (This secondary functionality 90 // is only used in utility command line). 91 type accountCreator struct { 92 txnState *state.TransactionState 93 chain flow.Chain 94 accounts Accounts 95 96 isServiceAccountEnabled bool 97 98 tracer tracing.TracerSpan 99 meter Meter 100 metrics MetricsReporter 101 102 systemContracts *SystemContracts 103 } 104 105 func NewAddressGenerator( 106 txnState *state.TransactionState, 107 chain flow.Chain, 108 ) AddressGenerator { 109 return &accountCreator{ 110 txnState: txnState, 111 chain: chain, 112 } 113 } 114 115 func NewBootstrapAccountCreator( 116 txnState *state.TransactionState, 117 chain flow.Chain, 118 accounts Accounts, 119 ) BootstrapAccountCreator { 120 return &accountCreator{ 121 txnState: txnState, 122 chain: chain, 123 accounts: accounts, 124 } 125 } 126 127 func NewAccountCreator( 128 txnState *state.TransactionState, 129 chain flow.Chain, 130 accounts Accounts, 131 isServiceAccountEnabled bool, 132 tracer tracing.TracerSpan, 133 meter Meter, 134 metrics MetricsReporter, 135 systemContracts *SystemContracts, 136 ) AccountCreator { 137 return &accountCreator{ 138 txnState: txnState, 139 chain: chain, 140 accounts: accounts, 141 isServiceAccountEnabled: isServiceAccountEnabled, 142 tracer: tracer, 143 meter: meter, 144 metrics: metrics, 145 systemContracts: systemContracts, 146 } 147 } 148 149 func (creator *accountCreator) bytes() ([]byte, error) { 150 stateBytes, err := creator.txnState.Get( 151 "", 152 state.AddressStateKey, 153 creator.txnState.EnforceLimits()) 154 if err != nil { 155 return nil, fmt.Errorf( 156 "failed to read address generator state from the state: %w", 157 err) 158 } 159 return stateBytes, nil 160 } 161 162 // TODO return error instead of a panic 163 // this requires changes outside of fvm since the type is defined on flow model 164 // and emulator and others might be dependent on that 165 func (creator *accountCreator) Bytes() []byte { 166 stateBytes, err := creator.bytes() 167 if err != nil { 168 panic(err) 169 } 170 return stateBytes 171 } 172 173 func (creator *accountCreator) constructAddressGen() ( 174 flow.AddressGenerator, 175 error, 176 ) { 177 stateBytes, err := creator.bytes() 178 if err != nil { 179 return nil, err 180 } 181 return creator.chain.BytesToAddressGenerator(stateBytes), nil 182 } 183 184 func (creator *accountCreator) NextAddress() (flow.Address, error) { 185 var address flow.Address 186 addressGenerator, err := creator.constructAddressGen() 187 if err != nil { 188 return address, err 189 } 190 191 address, err = addressGenerator.NextAddress() 192 if err != nil { 193 return address, err 194 } 195 196 // update the ledger state 197 err = creator.txnState.Set( 198 "", 199 state.AddressStateKey, 200 addressGenerator.Bytes(), 201 creator.txnState.EnforceLimits()) 202 if err != nil { 203 return address, fmt.Errorf( 204 "failed to update the state with address generator state: %w", 205 err) 206 } 207 return address, nil 208 } 209 210 func (creator *accountCreator) CurrentAddress() flow.Address { 211 var address flow.Address 212 addressGenerator, err := creator.constructAddressGen() 213 if err != nil { 214 // TODO update CurrentAddress to return an error if needed 215 panic(err) 216 } 217 218 address = addressGenerator.CurrentAddress() 219 return address 220 } 221 222 func (creator *accountCreator) AddressCount() uint64 { 223 addressGenerator, err := creator.constructAddressGen() 224 if err != nil { 225 // TODO update CurrentAddress to return an error if needed 226 panic(err) 227 } 228 229 return addressGenerator.AddressCount() 230 } 231 232 func (creator *accountCreator) createBasicAccount( 233 publicKeys []flow.AccountPublicKey, 234 ) ( 235 flow.Address, 236 error, 237 ) { 238 flowAddress, err := creator.NextAddress() 239 if err != nil { 240 return flow.Address{}, err 241 } 242 243 err = creator.accounts.Create(publicKeys, flowAddress) 244 if err != nil { 245 return flow.Address{}, fmt.Errorf("create account failed: %w", err) 246 } 247 248 return flowAddress, nil 249 } 250 251 func (creator *accountCreator) CreateBootstrapAccount( 252 publicKeys []flow.AccountPublicKey, 253 ) ( 254 flow.Address, 255 error, 256 ) { 257 return creator.createBasicAccount(publicKeys) 258 } 259 260 func (creator *accountCreator) CreateAccount( 261 payer runtime.Address, 262 ) ( 263 runtime.Address, 264 error, 265 ) { 266 defer creator.tracer.StartChildSpan(trace.FVMEnvCreateAccount).End() 267 268 err := creator.meter.MeterComputation(ComputationKindCreateAccount, 1) 269 if err != nil { 270 return common.Address{}, err 271 } 272 273 // don't enforce limit during account creation 274 var addr runtime.Address 275 creator.txnState.RunWithAllLimitsDisabled(func() { 276 addr, err = creator.createAccount(payer) 277 }) 278 279 return addr, err 280 } 281 282 func (creator *accountCreator) createAccount( 283 payer runtime.Address, 284 ) ( 285 runtime.Address, 286 error, 287 ) { 288 flowAddress, err := creator.createBasicAccount(nil) 289 if err != nil { 290 return common.Address{}, err 291 } 292 293 if creator.isServiceAccountEnabled { 294 _, invokeErr := creator.systemContracts.SetupNewAccount( 295 flowAddress, 296 payer) 297 if invokeErr != nil { 298 return common.Address{}, invokeErr 299 } 300 } 301 302 creator.metrics.RuntimeSetNumberOfAccounts(creator.AddressCount()) 303 return runtime.Address(flowAddress), nil 304 }