github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/types/account_test.go (about) 1 package types 2 3 import ( 4 "encoding/json" 5 "fmt" 6 authtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types" 7 "math/big" 8 "testing" 9 10 ethcrypto "github.com/ethereum/go-ethereum/crypto" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported" 12 tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 13 "github.com/stretchr/testify/require" 14 15 "github.com/stretchr/testify/suite" 16 17 tmamino "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/encoding/amino" 18 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/secp256k1" 19 20 "github.com/fibonacci-chain/fbc/app/crypto/ethsecp256k1" 21 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 22 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 23 24 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 25 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519" 26 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/sr25519" 27 ) 28 29 func init() { 30 tmamino.RegisterKeyType(ethsecp256k1.PubKey{}, ethsecp256k1.PubKeyName) 31 tmamino.RegisterKeyType(ethsecp256k1.PrivKey{}, ethsecp256k1.PrivKeyName) 32 } 33 34 type AccountTestSuite struct { 35 suite.Suite 36 37 account *EthAccount 38 } 39 40 func (suite *AccountTestSuite) SetupTest() { 41 pubkey := secp256k1.GenPrivKey().PubKey() 42 addr := sdk.AccAddress(pubkey.Address()) 43 balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) 44 baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) 45 suite.account = &EthAccount{ 46 BaseAccount: baseAcc, 47 CodeHash: []byte{1, 2}, 48 } 49 } 50 51 func TestAccountTestSuite(t *testing.T) { 52 suite.Run(t, new(AccountTestSuite)) 53 } 54 55 func (suite *AccountTestSuite) TestEthAccount_Balance() { 56 57 testCases := []struct { 58 name string 59 denom string 60 initialCoins sdk.Coins 61 amount sdk.Int 62 }{ 63 {"positive diff", NativeToken, sdk.Coins{}, sdk.OneInt()}, 64 {"zero diff, same coin", NativeToken, sdk.NewCoins(NewPhotonCoin(sdk.ZeroInt())), sdk.ZeroInt()}, 65 {"zero diff, other coin", sdk.DefaultBondDenom, sdk.NewCoins(NewPhotonCoin(sdk.ZeroInt())), sdk.ZeroInt()}, 66 {"negative diff", NativeToken, sdk.NewCoins(NewPhotonCoin(sdk.NewInt(10))), sdk.NewInt(1)}, 67 } 68 69 for _, tc := range testCases { 70 suite.Run(tc.name, func() { 71 suite.SetupTest() // reset values 72 suite.account.SetCoins(tc.initialCoins) 73 74 suite.account.SetBalance(tc.denom, sdk.NewDecFromInt(tc.amount)) 75 suite.Require().Equal(sdk.NewDecFromInt(tc.amount), suite.account.Balance(tc.denom)) 76 }) 77 } 78 79 } 80 81 func (suite *AccountTestSuite) TestEthermintAccountJSON() { 82 bz, err := json.Marshal(suite.account) 83 suite.Require().NoError(err) 84 85 bz1, err := suite.account.MarshalJSON() 86 suite.Require().NoError(err) 87 suite.Require().Equal(string(bz1), string(bz)) 88 89 var a EthAccount 90 suite.Require().NoError(a.UnmarshalJSON(bz)) 91 suite.Require().Equal(suite.account.String(), a.String()) 92 suite.Require().Equal(suite.account.PubKey, a.PubKey) 93 } 94 95 func (suite *AccountTestSuite) TestEthermintPubKeyJSON() { 96 privkey, err := ethsecp256k1.GenerateKey() 97 suite.Require().NoError(err) 98 bz := privkey.PubKey().Bytes() 99 100 pubk, err := tmamino.PubKeyFromBytes(bz) 101 suite.Require().NoError(err) 102 suite.Require().Equal(pubk, privkey.PubKey()) 103 } 104 105 func (suite *AccountTestSuite) TestSecpPubKeyJSON() { 106 pubkey := secp256k1.GenPrivKey().PubKey() 107 bz := pubkey.Bytes() 108 109 pubk, err := tmamino.PubKeyFromBytes(bz) 110 suite.Require().NoError(err) 111 suite.Require().Equal(pubk, pubkey) 112 } 113 114 func (suite *AccountTestSuite) TestEthermintAccount_String() { 115 config := sdk.GetConfig() 116 SetBech32Prefixes(config) 117 118 bech32pubkey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, suite.account.PubKey) 119 suite.Require().NoError(err) 120 121 accountStr := fmt.Sprintf(`| 122 address: %s 123 eth_address: %s 124 coins: 125 - denom: %s 126 amount: "1.000000000000000000" 127 public_key: %s 128 account_number: 10 129 sequence: 50 130 code_hash: "0102" 131 `, suite.account.Address, suite.account.EthAddress().String(), sdk.DefaultBondDenom, bech32pubkey) 132 133 suite.Require().Equal(accountStr, suite.account.String()) 134 135 i, err := suite.account.MarshalYAML() 136 suite.Require().NoError(err) 137 138 var ok bool 139 accountStr, ok = i.(string) 140 suite.Require().True(ok) 141 suite.Require().Contains(accountStr, suite.account.Address.String()) 142 suite.Require().Contains(accountStr, bech32pubkey) 143 } 144 145 func (suite *AccountTestSuite) TestEthermintAccount_MarshalJSON() { 146 bz, err := suite.account.MarshalJSON() 147 suite.Require().NoError(err) 148 suite.Require().Contains(string(bz), suite.account.EthAddress().String()) 149 150 res := new(EthAccount) 151 err = res.UnmarshalJSON(bz) 152 suite.Require().NoError(err) 153 suite.Require().Equal(suite.account, res) 154 155 bech32pubkey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, suite.account.PubKey) 156 suite.Require().NoError(err) 157 158 // test that the sdk.AccAddress is populated from the hex address 159 jsonAcc := fmt.Sprintf( 160 `{"address":"","eth_address":"%s","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`, 161 suite.account.EthAddress().String(), bech32pubkey, 162 ) 163 164 res = new(EthAccount) 165 err = res.UnmarshalJSON([]byte(jsonAcc)) 166 suite.Require().NoError(err) 167 suite.Require().Equal(suite.account.Address.String(), res.Address.String()) 168 169 jsonAcc = fmt.Sprintf( 170 `{"address":"","eth_address":"","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`, 171 bech32pubkey, 172 ) 173 174 res = new(EthAccount) 175 err = res.UnmarshalJSON([]byte(jsonAcc)) 176 suite.Require().Error(err, "should fail if both address are empty") 177 178 // test that the sdk.AccAddress is populated from the hex address 179 jsonAcc = fmt.Sprintf( 180 `{"address": "%s","eth_address":"0x0000000000000000000000000000000000000000","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`, 181 suite.account.Address.String(), bech32pubkey, 182 ) 183 184 res = new(EthAccount) 185 err = res.UnmarshalJSON([]byte(jsonAcc)) 186 suite.Require().Error(err, "should fail if addresses mismatch") 187 } 188 189 func TestEthAccountAmino(t *testing.T) { 190 cdc := codec.New() 191 cdc.RegisterInterface((*exported.Account)(nil), nil) 192 RegisterCodec(cdc) 193 194 cdc.RegisterInterface((*tmcrypto.PubKey)(nil), nil) 195 cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, 196 ed25519.PubKeyAminoName, nil) 197 cdc.RegisterConcrete(sr25519.PubKeySr25519{}, 198 sr25519.PubKeyAminoName, nil) 199 cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, 200 secp256k1.PubKeyAminoName, nil) 201 202 privKey := secp256k1.GenPrivKey() 203 pubKey := privKey.PubKey() 204 addr := sdk.AccAddress(pubKey.Address()) 205 206 accounts := []EthAccount{ 207 {}, 208 { 209 auth.NewBaseAccount( 210 addr, 211 sdk.NewCoins(NewPhotonCoin(sdk.OneInt()), sdk.Coin{"heco", sdk.Dec{big.NewInt(1)}}), 212 pubKey, 213 1, 214 1, 215 ), 216 ethcrypto.Keccak256(nil), 217 }, 218 { 219 auth.NewBaseAccount( 220 addr, 221 sdk.NewCoins(NewPhotonCoin(sdk.ZeroInt()), sdk.Coin{"heco", sdk.Dec{big.NewInt(0)}}), 222 pubKey, 223 0, 224 0, 225 ), 226 ethcrypto.Keccak256(nil), 227 }, 228 { 229 auth.NewBaseAccount( 230 nil, 231 nil, 232 nil, 233 0, 234 0, 235 ), 236 ethcrypto.Keccak256(nil), 237 }, 238 { 239 BaseAccount: &auth.BaseAccount{}, 240 }, 241 } 242 243 for _, testAccount := range accounts { 244 data, err := cdc.MarshalBinaryBare(&testAccount) 245 if err != nil { 246 t.Fatal("marshal error") 247 } 248 require.Equal(t, len(data), 4+testAccount.AminoSize(cdc)) 249 250 var accountFromAmino exported.Account 251 252 err = cdc.UnmarshalBinaryBare(data, &accountFromAmino) 253 if err != nil { 254 t.Fatal("unmarshal error") 255 } 256 257 var accountFromUnmarshaller exported.Account 258 v, err := cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(data, (*exported.Account)(nil)) 259 require.NoError(t, err) 260 accountFromUnmarshaller, ok := v.(exported.Account) 261 require.True(t, ok) 262 263 require.EqualValues(t, accountFromAmino, accountFromUnmarshaller) 264 265 var ethAccount EthAccount 266 err = ethAccount.UnmarshalFromAmino(cdc, data[4:]) 267 require.NoError(t, err) 268 require.EqualValues(t, accountFromAmino, ðAccount) 269 270 dataFromMarshaller, err := cdc.MarshalBinaryBareWithRegisteredMarshaller(&testAccount) 271 require.NoError(t, err) 272 require.EqualValues(t, data, dataFromMarshaller) 273 274 dataFromSizer, err := cdc.MarshalBinaryWithSizer(&testAccount, false) 275 require.NoError(t, err) 276 require.EqualValues(t, data, dataFromSizer) 277 278 dataFromMarshaller, err = ethAccount.MarshalToAmino(cdc) 279 if dataFromMarshaller == nil { 280 dataFromMarshaller = []byte{} 281 } 282 require.Equal(t, data[4:], dataFromMarshaller) 283 } 284 } 285 286 func BenchmarkEthAccountAminoUnmarshal(b *testing.B) { 287 cdc := codec.New() 288 cdc.RegisterInterface((*exported.Account)(nil), nil) 289 RegisterCodec(cdc) 290 291 cdc.RegisterInterface((*tmcrypto.PubKey)(nil), nil) 292 cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, 293 ed25519.PubKeyAminoName, nil) 294 cdc.RegisterConcrete(sr25519.PubKeySr25519{}, 295 sr25519.PubKeyAminoName, nil) 296 cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, 297 secp256k1.PubKeyAminoName, nil) 298 299 privKey := secp256k1.GenPrivKey() 300 pubKey := privKey.PubKey() 301 addr := sdk.AccAddress(pubKey.Address()) 302 303 balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) 304 testAccount := EthAccount{ 305 BaseAccount: auth.NewBaseAccount(addr, balance, pubKey, 1, 1), 306 CodeHash: ethcrypto.Keccak256(nil), 307 } 308 309 data, _ := cdc.MarshalBinaryBare(&testAccount) 310 311 b.ResetTimer() 312 b.ReportAllocs() 313 314 b.Run("amino", func(b *testing.B) { 315 b.ReportAllocs() 316 for i := 0; i < b.N; i++ { 317 var account exported.Account 318 _ = cdc.UnmarshalBinaryBare(data, &account) 319 } 320 }) 321 322 b.Run("unmarshaller", func(b *testing.B) { 323 b.ReportAllocs() 324 for i := 0; i < b.N; i++ { 325 // var account exported.Account 326 _, _ = cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(data, (*exported.Account)(nil)) 327 } 328 }) 329 } 330 331 func BenchmarkEthAccountAminoMarshal(b *testing.B) { 332 cdc := codec.New() 333 cdc.RegisterInterface((*exported.Account)(nil), nil) 334 RegisterCodec(cdc) 335 336 cdc.RegisterInterface((*tmcrypto.PubKey)(nil), nil) 337 cdc.RegisterConcrete(ed25519.PubKeyEd25519{}, 338 ed25519.PubKeyAminoName, nil) 339 cdc.RegisterConcrete(sr25519.PubKeySr25519{}, 340 sr25519.PubKeyAminoName, nil) 341 cdc.RegisterConcrete(secp256k1.PubKeySecp256k1{}, 342 secp256k1.PubKeyAminoName, nil) 343 344 privKey := secp256k1.GenPrivKey() 345 pubKey := privKey.PubKey() 346 addr := sdk.AccAddress(pubKey.Address()) 347 348 balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) 349 testAccount := EthAccount{ 350 BaseAccount: auth.NewBaseAccount(addr, balance, pubKey, 1, 1), 351 CodeHash: ethcrypto.Keccak256(nil), 352 } 353 354 b.ResetTimer() 355 b.ReportAllocs() 356 357 b.Run("amino", func(b *testing.B) { 358 b.ReportAllocs() 359 for i := 0; i < b.N; i++ { 360 data, _ := cdc.MarshalBinaryBare(&testAccount) 361 _ = data 362 } 363 }) 364 365 b.Run("marshaller", func(b *testing.B) { 366 b.ReportAllocs() 367 for i := 0; i < b.N; i++ { 368 data, _ := cdc.MarshalBinaryBareWithRegisteredMarshaller(&testAccount) 369 _ = data 370 } 371 }) 372 373 b.Run("sizer", func(b *testing.B) { 374 b.ReportAllocs() 375 for i := 0; i < b.N; i++ { 376 data, _ := cdc.MarshalBinaryWithSizer(&testAccount, false) 377 _ = data 378 } 379 }) 380 } 381 382 func (acc EthAccount) utOldCopy() sdk.Account { 383 return &EthAccount{ 384 authtypes.NewBaseAccount(acc.Address, acc.Coins, acc.PubKey, acc.AccountNumber, acc.Sequence), 385 acc.CodeHash, 386 } 387 } 388 389 func BenchmarkEthAccountCopy(b *testing.B) { 390 privKey := secp256k1.GenPrivKey() 391 pubKey := privKey.PubKey() 392 addr := sdk.AccAddress(pubKey.Address()) 393 394 balance := sdk.NewCoins(NewPhotonCoin(sdk.OneInt())) 395 testAccount := EthAccount{ 396 BaseAccount: auth.NewBaseAccount(addr, balance, pubKey, 1, 1), 397 CodeHash: ethcrypto.Keccak256(nil), 398 } 399 400 var copied sdk.Account 401 402 b.Run("copy", func(b *testing.B) { 403 b.ReportAllocs() 404 for i := 0; i < b.N; i++ { 405 copied = testAccount.Copy() 406 } 407 }) 408 b.Run("old", func(b *testing.B) { 409 b.ReportAllocs() 410 for i := 0; i < b.N; i++ { 411 copied = testAccount.utOldCopy() 412 } 413 }) 414 _ = copied 415 }