github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/crypto/ledger_test.go (about)

     1  package crypto
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
    10  	cryptoAmino "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/encoding/amino"
    11  
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys/hd"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/tests"
    14  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    15  )
    16  
    17  func TestLedgerErrorHandling(t *testing.T) {
    18  	// first, try to generate a key, must return an error
    19  	// (no panic)
    20  	path := *hd.NewParams(44, 555, 0, false, 0)
    21  	_, err := NewPrivKeyLedgerSecp256k1Unsafe(path)
    22  	require.Error(t, err)
    23  }
    24  
    25  func TestPublicKeyUnsafe(t *testing.T) {
    26  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
    27  	priv, err := NewPrivKeyLedgerSecp256k1Unsafe(path)
    28  	require.NoError(t, err)
    29  	require.NotNil(t, priv)
    30  
    31  	require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87",
    32  		fmt.Sprintf("%x", priv.PubKey().Bytes()),
    33  		"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
    34  
    35  	pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
    36  	require.NoError(t, err)
    37  	require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
    38  		pubKeyAddr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
    39  
    40  	addr := sdk.AccAddress(priv.PubKey().Address()).String()
    41  	require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
    42  		addr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
    43  }
    44  
    45  func TestPublicKeyUnsafeHDPath(t *testing.T) {
    46  	expectedAnswers := []string{
    47  		"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
    48  		"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
    49  		"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
    50  		"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
    51  		"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
    52  		"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
    53  		"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
    54  		"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
    55  		"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
    56  		"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
    57  	}
    58  
    59  	const numIters = 10
    60  
    61  	privKeys := make([]tmcrypto.PrivKey, numIters)
    62  
    63  	// Check with device
    64  	for i := uint32(0); i < 10; i++ {
    65  		path := *hd.NewFundraiserParams(0, sdk.CoinType, i)
    66  		t.Logf("Checking keys at %v\n", path)
    67  
    68  		priv, err := NewPrivKeyLedgerSecp256k1Unsafe(path)
    69  		require.NoError(t, err)
    70  		require.NotNil(t, priv)
    71  
    72  		// Check other methods
    73  		require.NoError(t, priv.(PrivKeyLedgerSecp256k1).ValidateKey())
    74  		tmp := priv.(PrivKeyLedgerSecp256k1)
    75  		(&tmp).AssertIsPrivKeyInner()
    76  
    77  		pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
    78  		require.NoError(t, err)
    79  		require.Equal(t,
    80  			expectedAnswers[i], pubKeyAddr,
    81  			"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
    82  
    83  		// Store and restore
    84  		serializedPk := priv.Bytes()
    85  		require.NotNil(t, serializedPk)
    86  		require.True(t, len(serializedPk) >= 50)
    87  
    88  		privKeys[i] = priv
    89  	}
    90  
    91  	// Now check equality
    92  	for i := 0; i < 10; i++ {
    93  		for j := 0; j < 10; j++ {
    94  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
    95  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
    96  		}
    97  	}
    98  }
    99  
   100  func TestPublicKeySafe(t *testing.T) {
   101  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   102  	priv, addr, err := NewPrivKeyLedgerSecp256k1(path, "cosmos")
   103  
   104  	require.NoError(t, err)
   105  	require.NotNil(t, priv)
   106  
   107  	require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87",
   108  		fmt.Sprintf("%x", priv.PubKey().Bytes()),
   109  		"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   110  
   111  	pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
   112  	require.NoError(t, err)
   113  	require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
   114  		pubKeyAddr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   115  
   116  	require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
   117  		addr, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   118  
   119  	addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   120  	require.Equal(t, addr, addr2)
   121  }
   122  
   123  func TestPublicKeyHDPath(t *testing.T) {
   124  	expectedPubKeys := []string{
   125  		"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
   126  		"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
   127  		"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
   128  		"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
   129  		"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
   130  		"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
   131  		"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
   132  		"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
   133  		"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
   134  		"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
   135  	}
   136  
   137  	expectedAddrs := []string{
   138  		"cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
   139  		"cosmos19ewxwemt6uahejvwf44u7dh6tq859tkyvarh2q",
   140  		"cosmos1a07dzdjgjsntxpp75zg7cgatgq0udh3pcdcxm3",
   141  		"cosmos1qvw52lmn9gpvem8welghrkc52m3zczyhlqjsl7",
   142  		"cosmos17m78ka80fqkkw2c4ww0v4xm5nsu2drgrlm8mn2",
   143  		"cosmos1ferh9ll9c452d2p8k2v7heq084guygkn43up9e",
   144  		"cosmos10vf3sxmjg96rqq36axcphzfsl74dsntuehjlw5",
   145  		"cosmos1cq83av8cmnar79h0rg7duh9gnr7wkh228a7fxg",
   146  		"cosmos1dszhfrt226jy5rsre7e48vw9tgwe90uerfyefa",
   147  		"cosmos1734d7qsylzrdt05muhqqtpd90j8mp4y6rzch8l",
   148  	}
   149  
   150  	const numIters = 10
   151  
   152  	privKeys := make([]tmcrypto.PrivKey, numIters)
   153  
   154  	// Check with device
   155  	for i := uint32(0); i < 10; i++ {
   156  		path := *hd.NewFundraiserParams(0, sdk.CoinType, i)
   157  		t.Logf("Checking keys at %s\n", path)
   158  
   159  		priv, addr, err := NewPrivKeyLedgerSecp256k1(path, "cosmos")
   160  		require.NoError(t, err)
   161  		require.NotNil(t, addr)
   162  		require.NotNil(t, priv)
   163  
   164  		addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   165  		require.Equal(t, addr2, addr)
   166  		require.Equal(t,
   167  			expectedAddrs[i], addr,
   168  			"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   169  
   170  		// Check other methods
   171  		require.NoError(t, priv.(PrivKeyLedgerSecp256k1).ValidateKey())
   172  		tmp := priv.(PrivKeyLedgerSecp256k1)
   173  		(&tmp).AssertIsPrivKeyInner()
   174  
   175  		pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
   176  		require.NoError(t, err)
   177  		require.Equal(t,
   178  			expectedPubKeys[i], pubKeyAddr,
   179  			"Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   180  
   181  		// Store and restore
   182  		serializedPk := priv.Bytes()
   183  		require.NotNil(t, serializedPk)
   184  		require.True(t, len(serializedPk) >= 50)
   185  
   186  		privKeys[i] = priv
   187  	}
   188  
   189  	// Now check equality
   190  	for i := 0; i < 10; i++ {
   191  		for j := 0; j < 10; j++ {
   192  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
   193  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
   194  		}
   195  	}
   196  }
   197  
   198  func getFakeTx(accountNumber uint32) []byte {
   199  	tmp := fmt.Sprintf(
   200  		`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
   201  		accountNumber)
   202  
   203  	return []byte(tmp)
   204  }
   205  
   206  func TestSignaturesHD(t *testing.T) {
   207  	for account := uint32(0); account < 100; account += 30 {
   208  		msg := getFakeTx(account)
   209  
   210  		path := *hd.NewFundraiserParams(account, sdk.CoinType, account/5)
   211  		t.Logf("Checking signature at %v    ---   PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path)
   212  
   213  		priv, err := NewPrivKeyLedgerSecp256k1Unsafe(path)
   214  		require.NoError(t, err)
   215  
   216  		pub := priv.PubKey()
   217  		sig, err := priv.Sign(msg)
   218  		require.NoError(t, err)
   219  
   220  		valid := pub.VerifyBytes(msg, sig)
   221  		require.True(t, valid, "Is your device using test mnemonic: %s ?", tests.TestMnemonic)
   222  	}
   223  }
   224  
   225  func TestRealLedgerSecp256k1(t *testing.T) {
   226  	msg := getFakeTx(50)
   227  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   228  	priv, err := NewPrivKeyLedgerSecp256k1Unsafe(path)
   229  	require.NoError(t, err)
   230  
   231  	pub := priv.PubKey()
   232  	sig, err := priv.Sign(msg)
   233  	require.NoError(t, err)
   234  
   235  	valid := pub.VerifyBytes(msg, sig)
   236  	require.True(t, valid)
   237  
   238  	// now, let's serialize the public key and make sure it still works
   239  	bs := priv.PubKey().Bytes()
   240  	pub2, err := cryptoAmino.PubKeyFromBytes(bs)
   241  	require.Nil(t, err, "%+v", err)
   242  
   243  	// make sure we get the same pubkey when we load from disk
   244  	require.Equal(t, pub, pub2)
   245  
   246  	// signing with the loaded key should match the original pubkey
   247  	sig, err = priv.Sign(msg)
   248  	require.NoError(t, err)
   249  	valid = pub.VerifyBytes(msg, sig)
   250  	require.True(t, valid)
   251  
   252  	// make sure pubkeys serialize properly as well
   253  	bs = pub.Bytes()
   254  	bpub, err := cryptoAmino.PubKeyFromBytes(bs)
   255  	require.NoError(t, err)
   256  	require.Equal(t, pub, bpub)
   257  }