Skip to content

test(app): add unit tests for app package #544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -129,20 +129,20 @@
}
],
"results": {
"client/app/privkey_test.go": [
"client/app/privkey_internal_test.go": [
{
"type": "Secret Keyword",
"filename": "client/app/privkey_test.go",
"filename": "client/app/privkey_internal_test.go",
"hashed_secret": "8bb6118f8fd6935ad0876a3be34a717d32708ffd",
"is_verified": false,
"line_number": 20
"line_number": 119
},
{
"type": "Secret Keyword",
"filename": "client/app/privkey_test.go",
"filename": "client/app/privkey_internal_test.go",
"hashed_secret": "d8ecf7db8fc9ec9c31bc5c9ae2929cc599c75f8d",
"is_verified": false,
"line_number": 43
"line_number": 142
}
],
"client/app/prompt.go": [
Expand Down Expand Up @@ -974,5 +974,5 @@
}
]
},
"generated_at": "2025-03-26T14:30:28Z"
"generated_at": "2025-05-14T05:17:21Z"
}
19 changes: 0 additions & 19 deletions client/app/privkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ import (
"github.com/cometbft/cometbft/crypto"
cmtjson "github.com/cometbft/cometbft/libs/json"
"github.com/cometbft/cometbft/privval"
"github.com/ethereum/go-ethereum/accounts/keystore"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"

"github.com/piplabs/story/lib/errors"
"github.com/piplabs/story/lib/k1util"
)

// loadPrivVal returns a privval.FilePV by loading either a CometBFT priv validator key or an Ethereum keystore file.
Expand Down Expand Up @@ -71,23 +69,6 @@ func loadPrivVal(cfg Config) (*privval.FilePV, error) {
return resp, nil
}

// loadEthKeystore loads an Ethereum keystore file and returns the private key.
//
//nolint:unused //Ignore unused function temporarily
func loadEthKeystore(keystoreFile string, password string) (crypto.PrivKey, error) {
bz, err := os.ReadFile(keystoreFile)
if err != nil {
return nil, errors.Wrap(err, "read keystore file", "path", keystoreFile)
}

key, err := keystore.DecryptKey(bz, password)
if err != nil {
return nil, errors.Wrap(err, "decrypt keystore file", "path", keystoreFile)
}

return k1util.StdPrivKeyToComet(key.PrivateKey)
}

// loadCometFilePV loads a CometBFT privval file and returns the private key.
func loadCometFilePV(file string) (crypto.PrivKey, error) {
bz, err := os.ReadFile(file)
Expand Down
162 changes: 162 additions & 0 deletions client/app/privkey_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package app

import (
"os"
"path/filepath"
"testing"

cmtconfig "github.com/cometbft/cometbft/config"
k1 "github.com/cometbft/cometbft/crypto/secp256k1"
"github.com/cometbft/cometbft/privval"
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

storycfg "github.com/piplabs/story/client/config"
"github.com/piplabs/story/lib/k1util"
)

func TestLoadPrivVal(t *testing.T) {
t.Parallel()

tests := []struct {
name string
cmtPrivval bool
cmtPrivState bool
err bool
}{
{
name: "comet privval and state",
cmtPrivval: true,
cmtPrivState: true,
},
{
name: "no files",
cmtPrivval: false,
cmtPrivState: false,
err: true,
},
{
name: "comet privval only",
cmtPrivval: true,
cmtPrivState: false,
err: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
homeDir := t.TempDir()

// Define the file paths
cmtPrivvalFile := filepath.Join(homeDir, "config", "priv_validator_key.json")
cmtPrivStateFile := filepath.Join(homeDir, "data", "priv_validator_state.json")

// Ensure the config and data directories exist
require.NoError(t, os.Mkdir(filepath.Dir(cmtPrivvalFile), 0755))
require.NoError(t, os.Mkdir(filepath.Dir(cmtPrivStateFile), 0755))

// Generate the expected private key
privKey, err := crypto.GenerateKey()
require.NoError(t, err)

// Convert the private key to a comet private key
cmtPrivKey, err := k1util.StdPrivKeyToComet(privKey)
require.NoError(t, err)

// Write the comet privval file (with non-zero state)
key := privval.NewFilePV(cmtPrivKey, cmtPrivvalFile, cmtPrivStateFile)
err = key.SignVote("chain", &cmtproto.Vote{
Type: cmtproto.PrecommitType,
})
require.NoError(t, err)
key.Save()

// Remove the files if they are not needed
if !tt.cmtPrivval {
require.NoError(t, os.Remove(cmtPrivvalFile))
}
if !tt.cmtPrivState {
require.NoError(t, os.Remove(cmtPrivStateFile))
}

// Setup the config
cfg := Config{
Config: storycfg.Config{
HomeDir: homeDir,
},
Comet: cmtconfig.Config{
BaseConfig: cmtconfig.BaseConfig{
RootDir: homeDir,
PrivValidatorKey: "config/priv_validator_key.json",
PrivValidatorState: "data/priv_validator_state.json",
},
},
}

// Run the test
pv, err := loadPrivVal(cfg)

// Assert the results
if tt.err {
require.Error(t, err)
} else {
require.NoError(t, err)
require.NotNil(t, pv)
require.True(t, pv.Key.PrivKey.Equals(cmtPrivKey))
}
})
}
}

func setupTestEnv(t *testing.T) (string, string, string) {
t.Helper()

stateFileDir := filepath.Join(t.TempDir(), "stateFileDir")
encFileDir := filepath.Join(t.TempDir(), "encFileDir")
password := "testpassword"

return stateFileDir, encFileDir, password
}

func TestEncryptAndDecrypt_Success(t *testing.T) {
stateFileDir, encFileDir, password := setupTestEnv(t)

pv := privval.NewFilePV(k1.GenPrivKey(), "", stateFileDir)

// Encryption
err := EncryptAndStoreKey(pv.Key, password, encFileDir)
require.NoError(t, err)

// Decryption
loadedKey, err := LoadEncryptedPrivKey(password, encFileDir)
require.NoError(t, err)

assert.Equal(t, pv.Key, loadedKey, "The decrypted key must match the original.")
}

func TestLoadEncryptedPrivKey_WrongPassword(t *testing.T) {
stateFileDir, encFileDir, password := setupTestEnv(t)
wrongPassword := "wrongpassword"

pv := privval.NewFilePV(k1.GenPrivKey(), "", stateFileDir)

// Encryption
err := EncryptAndStoreKey(pv.Key, password, encFileDir)
require.NoError(t, err)

// Decrypt with wrong password
_, err = LoadEncryptedPrivKey(wrongPassword, encFileDir)
require.Error(t, err)
assert.Contains(t, err.Error(), "wrong password for wallet entered")
}

func TestLoadEncryptedPrivKey_FileNotFound(t *testing.T) {
_, encFileDir, password := setupTestEnv(t)

_, err := LoadEncryptedPrivKey(password, encFileDir)
require.Error(t, err)
assert.Contains(t, err.Error(), "failed to read enc_priv_key.json file")
}
63 changes: 0 additions & 63 deletions client/app/privkey_test.go

This file was deleted.

Loading
Loading