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  }