github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/account_key_reader.go (about) 1 package environment 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/cadence/runtime" 7 8 "github.com/koko1123/flow-go-1/fvm/crypto" 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 // AccountKeyReader provide read access to account keys. 17 type AccountKeyReader interface { 18 // GetAccountKey retrieves a public key by index from an existing account. 19 // 20 // This function returns a nil key with no errors, if a key doesn't exist at 21 // the given index. An error is returned if the specified account does not 22 // exist, the provided index is not valid, or if the key retrieval fails. 23 GetAccountKey( 24 address runtime.Address, 25 keyIndex int, 26 ) ( 27 *runtime.AccountKey, 28 error, 29 ) 30 AccountKeysCount(address runtime.Address) (uint64, error) 31 } 32 33 type ParseRestrictedAccountKeyReader struct { 34 txnState *state.TransactionState 35 impl AccountKeyReader 36 } 37 38 func NewParseRestrictedAccountKeyReader( 39 txnState *state.TransactionState, 40 impl AccountKeyReader, 41 ) AccountKeyReader { 42 return ParseRestrictedAccountKeyReader{ 43 txnState: txnState, 44 impl: impl, 45 } 46 } 47 48 func (reader ParseRestrictedAccountKeyReader) GetAccountKey( 49 address runtime.Address, 50 keyIndex int, 51 ) ( 52 *runtime.AccountKey, 53 error, 54 ) { 55 return parseRestrict2Arg1Ret( 56 reader.txnState, 57 trace.FVMEnvGetAccountKey, 58 reader.impl.GetAccountKey, 59 address, 60 keyIndex) 61 } 62 63 func (reader ParseRestrictedAccountKeyReader) AccountKeysCount(address runtime.Address) (uint64, error) { 64 return parseRestrict1Arg1Ret( 65 reader.txnState, 66 "AccountKeysCount", 67 reader.impl.AccountKeysCount, 68 address, 69 ) 70 } 71 72 type accountKeyReader struct { 73 tracer tracing.TracerSpan 74 meter Meter 75 76 accounts Accounts 77 } 78 79 func NewAccountKeyReader( 80 tracer tracing.TracerSpan, 81 meter Meter, 82 accounts Accounts, 83 ) AccountKeyReader { 84 return &accountKeyReader{ 85 tracer: tracer, 86 meter: meter, 87 accounts: accounts, 88 } 89 } 90 91 func (reader *accountKeyReader) GetAccountKey( 92 address runtime.Address, 93 keyIndex int, 94 ) ( 95 *runtime.AccountKey, 96 error, 97 ) { 98 defer reader.tracer.StartChildSpan(trace.FVMEnvGetAccountKey).End() 99 100 formatErr := func(err error) (*runtime.AccountKey, error) { 101 return nil, fmt.Errorf("getting account key failed: %w", err) 102 } 103 104 err := reader.meter.MeterComputation(ComputationKindGetAccountKey, 1) 105 if err != nil { 106 return formatErr(err) 107 } 108 109 // Don't return an error for invalid key indices 110 if keyIndex < 0 { 111 return nil, nil 112 } 113 114 accountAddress := flow.Address(address) 115 116 // address verification is also done in this step 117 accountPublicKey, err := reader.accounts.GetPublicKey( 118 accountAddress, 119 uint64(keyIndex)) 120 if err != nil { 121 // If a key is not found at a given index, then return a nil key with 122 // no errors. This is to be inline with the Cadence runtime. Otherwise, 123 // Cadence runtime cannot distinguish between a 'key not found error' 124 // vs other internal errors. 125 if errors.IsAccountAccountPublicKeyNotFoundError(err) { 126 return nil, nil 127 } 128 129 return formatErr(err) 130 } 131 132 // Prepare the account key to return 133 runtimeAccountKey, err := FlowToRuntimeAccountKey(accountPublicKey) 134 if err != nil { 135 return formatErr(err) 136 } 137 138 return runtimeAccountKey, nil 139 } 140 141 func (reader *accountKeyReader) AccountKeysCount(address runtime.Address) (uint64, error) { 142 defer reader.tracer.StartChildSpan(trace.FVMEnvAccountKeysCount).End() 143 144 formatErr := func(err error) (uint64, error) { 145 return 0, fmt.Errorf("fetching account key count failed: %w", err) 146 } 147 148 err := reader.meter.MeterComputation(ComputationKindAccountKeysCount, 1) 149 if err != nil { 150 return formatErr(err) 151 } 152 153 accountAddress := flow.Address(address) 154 155 // address verification is also done in this step 156 return reader.accounts.GetPublicKeyCount(accountAddress) 157 } 158 159 func FlowToRuntimeAccountKey(flowKey flow.AccountPublicKey) (*runtime.AccountKey, error) { 160 signAlgo := crypto.CryptoToRuntimeSigningAlgorithm(flowKey.SignAlgo) 161 if signAlgo == runtime.SignatureAlgorithmUnknown { 162 return nil, errors.NewValueErrorf( 163 flowKey.SignAlgo.String(), 164 "signature algorithm type not found", 165 ) 166 } 167 168 hashAlgo := crypto.CryptoToRuntimeHashingAlgorithm(flowKey.HashAlgo) 169 if hashAlgo == runtime.HashAlgorithmUnknown { 170 return nil, errors.NewValueErrorf( 171 flowKey.HashAlgo.String(), 172 "hashing algorithm type not found", 173 ) 174 } 175 176 publicKey := &runtime.PublicKey{ 177 PublicKey: flowKey.PublicKey.Encode(), 178 SignAlgo: signAlgo, 179 } 180 181 return &runtime.AccountKey{ 182 KeyIndex: flowKey.Index, 183 PublicKey: publicKey, 184 HashAlgo: hashAlgo, 185 Weight: flowKey.Weight, 186 IsRevoked: flowKey.Revoked, 187 }, nil 188 }