github.com/onflow/flow-go@v0.33.17/fvm/environment/account_key_updater_test.go (about) 1 package environment_test 2 3 import ( 4 "fmt" 5 "testing" 6 "unicode/utf8" 7 8 "github.com/fxamacker/cbor/v2" 9 "github.com/onflow/atree" 10 "github.com/onflow/cadence/runtime" 11 "github.com/onflow/cadence/runtime/sema" 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/onflow/flow-go/crypto" 16 "github.com/onflow/flow-go/crypto/hash" 17 "github.com/onflow/flow-go/fvm/environment" 18 "github.com/onflow/flow-go/fvm/errors" 19 "github.com/onflow/flow-go/fvm/tracing" 20 "github.com/onflow/flow-go/model/flow" 21 ) 22 23 func TestAddEncodedAccountKey_error_handling_produces_valid_utf8(t *testing.T) { 24 25 akh := environment.NewAccountKeyUpdater( 26 tracing.NewTracerSpan(), 27 nil, 28 FakeAccounts{}, 29 nil, 30 nil) 31 32 address := flow.BytesToAddress([]byte{1, 2, 3, 4}) 33 34 // emulate encoded public key (which comes as a user input) 35 // containing bytes which are invalid UTF8 36 37 invalidEncodedKey := make([]byte, 64) 38 invalidUTF8 := []byte{0xc3, 0x28} 39 copy(invalidUTF8, invalidEncodedKey) 40 accountPublicKey := FakePublicKey{data: invalidEncodedKey}.toAccountPublicKey() 41 42 encodedPublicKey, err := flow.EncodeRuntimeAccountPublicKey(accountPublicKey) 43 require.NoError(t, err) 44 45 err = akh.InternalAddEncodedAccountKey(address, encodedPublicKey) 46 require.Error(t, err) 47 48 require.True(t, errors.IsValueError(err)) 49 50 errorString := err.Error() 51 assert.True(t, utf8.ValidString(errorString)) 52 53 // check if they can encoded and decoded using CBOR 54 marshalledBytes, err := cbor.Marshal(errorString) 55 require.NoError(t, err) 56 57 var unmarshalledString string 58 59 err = cbor.Unmarshal(marshalledBytes, &unmarshalledString) 60 require.NoError(t, err) 61 62 require.Equal(t, errorString, unmarshalledString) 63 } 64 65 func TestNewAccountKey_error_handling_produces_valid_utf8_and_sign_algo(t *testing.T) { 66 67 invalidSignAlgo := runtime.SignatureAlgorithm(254) 68 publicKey := &runtime.PublicKey{ 69 PublicKey: nil, 70 SignAlgo: invalidSignAlgo, 71 } 72 73 _, err := environment.NewAccountPublicKey( 74 publicKey, 75 sema.HashAlgorithmSHA2_384, 76 0, 77 0) 78 79 require.True(t, errors.IsValueError(err)) 80 81 require.Contains(t, err.Error(), fmt.Sprintf("%d", invalidSignAlgo)) 82 83 errorString := err.Error() 84 assert.True(t, utf8.ValidString(errorString)) 85 86 // check if they can encoded and decoded using CBOR 87 marshalledBytes, err := cbor.Marshal(errorString) 88 require.NoError(t, err) 89 90 var unmarshalledString string 91 92 err = cbor.Unmarshal(marshalledBytes, &unmarshalledString) 93 require.NoError(t, err) 94 95 require.Equal(t, errorString, unmarshalledString) 96 } 97 98 func TestNewAccountKey_error_handling_produces_valid_utf8_and_hash_algo(t *testing.T) { 99 100 publicKey := &runtime.PublicKey{ 101 PublicKey: nil, 102 SignAlgo: runtime.SignatureAlgorithmECDSA_P256, 103 } 104 105 invalidHashAlgo := sema.HashAlgorithm(112) 106 107 _, err := environment.NewAccountPublicKey(publicKey, invalidHashAlgo, 0, 0) 108 109 require.True(t, errors.IsValueError(err)) 110 111 require.Contains(t, err.Error(), fmt.Sprintf("%d", invalidHashAlgo)) 112 113 errorString := err.Error() 114 assert.True(t, utf8.ValidString(errorString)) 115 116 // check if they can encoded and decoded using CBOR 117 marshalledBytes, err := cbor.Marshal(errorString) 118 require.NoError(t, err) 119 120 var unmarshalledString string 121 122 err = cbor.Unmarshal(marshalledBytes, &unmarshalledString) 123 require.NoError(t, err) 124 125 require.Equal(t, errorString, unmarshalledString) 126 } 127 128 func TestNewAccountKey_error_handling_produces_valid_utf8(t *testing.T) { 129 130 publicKey := &runtime.PublicKey{ 131 PublicKey: []byte{0xc3, 0x28}, // some invalid UTF8 132 SignAlgo: runtime.SignatureAlgorithmECDSA_P256, 133 } 134 135 _, err := environment.NewAccountPublicKey( 136 publicKey, 137 runtime.HashAlgorithmSHA2_256, 138 0, 139 0) 140 141 require.True(t, errors.IsValueError(err)) 142 143 errorString := err.Error() 144 assert.True(t, utf8.ValidString(errorString)) 145 146 // check if they can encoded and decoded using CBOR 147 marshalledBytes, err := cbor.Marshal(errorString) 148 require.NoError(t, err) 149 150 var unmarshalledString string 151 152 err = cbor.Unmarshal(marshalledBytes, &unmarshalledString) 153 require.NoError(t, err) 154 155 require.Equal(t, errorString, unmarshalledString) 156 } 157 158 type FakePublicKey struct { 159 data []byte 160 } 161 162 var _ crypto.PublicKey = &FakePublicKey{} 163 164 func (f FakePublicKey) toAccountPublicKey() flow.AccountPublicKey { 165 return flow.AccountPublicKey{ 166 Index: 1, 167 PublicKey: f, 168 SignAlgo: crypto.ECDSASecp256k1, 169 HashAlgo: hash.SHA3_256, 170 SeqNumber: 0, 171 Weight: 1000, 172 Revoked: false, 173 } 174 } 175 176 func (f FakePublicKey) Encode() []byte { 177 return f.data 178 } 179 180 func (f FakePublicKey) Algorithm() crypto.SigningAlgorithm { return crypto.ECDSASecp256k1 } 181 func (f FakePublicKey) Size() int { return 0 } 182 func (f FakePublicKey) String() string { return "" } 183 func (f FakePublicKey) Verify(_ crypto.Signature, _ []byte, _ hash.Hasher) (bool, error) { 184 return false, nil 185 } 186 func (f FakePublicKey) EncodeCompressed() []byte { return nil } 187 func (f FakePublicKey) Equals(key crypto.PublicKey) bool { return false } 188 189 type FakeAccounts struct { 190 keyCount uint64 191 } 192 193 var _ environment.Accounts = &FakeAccounts{} 194 195 func (f FakeAccounts) Exists(address flow.Address) (bool, error) { return true, nil } 196 func (f FakeAccounts) Get(address flow.Address) (*flow.Account, error) { return &flow.Account{}, nil } 197 func (f FakeAccounts) GetPublicKeyCount(_ flow.Address) (uint64, error) { 198 return f.keyCount, nil 199 } 200 func (f FakeAccounts) AppendPublicKey(_ flow.Address, _ flow.AccountPublicKey) error { return nil } 201 func (f FakeAccounts) GetPublicKey(address flow.Address, keyIndex uint64) (flow.AccountPublicKey, error) { 202 if keyIndex >= f.keyCount { 203 return flow.AccountPublicKey{}, errors.NewAccountPublicKeyNotFoundError(address, keyIndex) 204 } 205 return FakePublicKey{}.toAccountPublicKey(), nil 206 } 207 208 func (f FakeAccounts) SetPublicKey(_ flow.Address, _ uint64, _ flow.AccountPublicKey) ([]byte, error) { 209 return nil, nil 210 } 211 func (f FakeAccounts) GetContractNames(_ flow.Address) ([]string, error) { return nil, nil } 212 func (f FakeAccounts) GetContract(_ string, _ flow.Address) ([]byte, error) { return nil, nil } 213 func (f FakeAccounts) ContractExists(_ string, _ flow.Address) (bool, error) { return false, nil } 214 func (f FakeAccounts) SetContract(_ string, _ flow.Address, _ []byte) error { return nil } 215 func (f FakeAccounts) DeleteContract(_ string, _ flow.Address) error { return nil } 216 func (f FakeAccounts) Create(_ []flow.AccountPublicKey, _ flow.Address) error { return nil } 217 func (f FakeAccounts) GetValue(_ flow.RegisterID) (flow.RegisterValue, error) { return nil, nil } 218 func (f FakeAccounts) GetStorageUsed(_ flow.Address) (uint64, error) { return 0, nil } 219 func (f FakeAccounts) SetValue(_ flow.RegisterID, _ []byte) error { return nil } 220 func (f FakeAccounts) AllocateStorageIndex(_ flow.Address) (atree.StorageIndex, error) { 221 return atree.StorageIndex{}, nil 222 } 223 func (f FakeAccounts) GenerateAccountLocalID(address flow.Address) (uint64, error) { 224 return 0, nil 225 }