diff --git a/app/apptesting/test_suite.go b/app/apptesting/test_suite.go index 12de421d03..8d88be906a 100644 --- a/app/apptesting/test_suite.go +++ b/app/apptesting/test_suite.go @@ -165,7 +165,7 @@ func (s *KeeperTestHelper) BuildTx( func CreateRandomAccounts(numAccts int) []sdk.AccAddress { testAddrs := make([]sdk.AccAddress, numAccts) for i := 0; i < numAccts; i++ { - pk := ed25519.GenPrivKey().PubKey() + pk := ed25519.GenerateSecretKey().Public() testAddrs[i] = sdk.AccAddress(pk.Address()) } @@ -173,7 +173,7 @@ func CreateRandomAccounts(numAccts int) []sdk.AccAddress { } func GenerateTestAddrs() (string, string) { - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() validAddr := sdk.AccAddress(pk1.Address()).String() invalidAddr := sdk.AccAddress("invalid").String() return validAddr, invalidAddr diff --git a/sei-cosmos/client/rpc/status.go b/sei-cosmos/client/rpc/status.go index 6f93cbf712..bd9a92a18e 100644 --- a/sei-cosmos/client/rpc/status.go +++ b/sei-cosmos/client/rpc/status.go @@ -50,10 +50,12 @@ func StatusCommand() *cobra.Command { return err } + var addr cryptotypes.Address var pk cryptotypes.PubKey // `status` has TM pubkeys, we need to convert them to our pubkeys. - if status.ValidatorInfo.PubKey != nil { - pk, err = cryptocodec.FromTmPubKeyInterface(status.ValidatorInfo.PubKey) + if k, ok := status.ValidatorInfo.PubKey.Get(); ok { + addr = k.Address() + pk, err = cryptocodec.FromTmPubKeyInterface(k) if err != nil { return err } @@ -63,7 +65,7 @@ func StatusCommand() *cobra.Command { NodeInfo: status.NodeInfo, SyncInfo: status.SyncInfo, ValidatorInfo: validatorInfo{ - Address: status.ValidatorInfo.Address, + Address: addr, PubKey: pk, VotingPower: status.ValidatorInfo.VotingPower, }, diff --git a/sei-cosmos/crypto/codec/tm.go b/sei-cosmos/crypto/codec/tm.go index 080ae6eb9a..3adc02dc8b 100644 --- a/sei-cosmos/crypto/codec/tm.go +++ b/sei-cosmos/crypto/codec/tm.go @@ -41,19 +41,14 @@ func ToTmProtoPublicKey(pk cryptotypes.PubKey) (tmprotocrypto.PublicKey, error) // FromTmPubKeyInterface converts TM's tmcrypto.PubKey to our own PubKey. func FromTmPubKeyInterface(tmPk tmcrypto.PubKey) (cryptotypes.PubKey, error) { - tmProtoPk, err := encoding.PubKeyToProto(tmPk) - if err != nil { - return nil, err - } - - return FromTmProtoPublicKey(tmProtoPk) + return FromTmProtoPublicKey(encoding.PubKeyToProto(tmPk)) } // ToTmPubKeyInterface converts our own PubKey to TM's tmcrypto.PubKey. func ToTmPubKeyInterface(pk cryptotypes.PubKey) (tmcrypto.PubKey, error) { tmProtoPk, err := ToTmProtoPublicKey(pk) if err != nil { - return nil, err + return tmcrypto.PubKey{}, err } return encoding.PubKeyFromProto(tmProtoPk) diff --git a/sei-cosmos/crypto/keys/ed25519/ed25519_test.go b/sei-cosmos/crypto/keys/ed25519/ed25519_test.go index 83622ee430..9e0699e1ab 100644 --- a/sei-cosmos/crypto/keys/ed25519/ed25519_test.go +++ b/sei-cosmos/crypto/keys/ed25519/ed25519_test.go @@ -139,7 +139,7 @@ func TestMarshalAmino(t *testing.T) { testCases := []struct { desc string msg codec.AminoMarshaler - typ interface{} + typ any expBinary []byte expJSON string }{ @@ -187,17 +187,17 @@ func TestMarshalAmino(t *testing.T) { func TestMarshalAmino_BackwardsCompatibility(t *testing.T) { aminoCdc := codec.NewLegacyAmino() // Create Tendermint keys. - tmPrivKey := tmed25519.GenPrivKey() - tmPubKey := tmPrivKey.PubKey() + tmPrivKey := tmed25519.GenerateSecretKey() + tmPubKey := tmPrivKey.Public() // Create our own keys, with the same private key as Tendermint's. - privKey := &ed25519.PrivKey{Key: []byte(tmPrivKey)} + privKey := &ed25519.PrivKey{Key: tmPrivKey.SecretBytes()} pubKey := privKey.PubKey().(*ed25519.PubKey) testCases := []struct { desc string - tmKey interface{} - ourKey interface{} - marshalFn func(o interface{}) ([]byte, error) + tmKey any + ourKey any + marshalFn func(o any) ([]byte, error) }{ { "ed25519 private key, binary", diff --git a/sei-cosmos/crypto/keys/sr25519/internal/privkey.go b/sei-cosmos/crypto/keys/sr25519/internal/privkey.go index 33a691e752..36d4a7cf4e 100644 --- a/sei-cosmos/crypto/keys/sr25519/internal/privkey.go +++ b/sei-cosmos/crypto/keys/sr25519/internal/privkey.go @@ -10,17 +10,9 @@ import ( "github.com/oasisprotocol/curve25519-voi/primitives/sr25519" ) -var ( - signingCtx = sr25519.NewSigningContext([]byte{}) -) - -const ( - PrivKeyName = "tendermint/PrivKeySr25519" - // PrivKeySize is the size of a sr25519 signature in bytes. - PrivKeySize = sr25519.MiniSecretKeySize +var signingCtx = sr25519.NewSigningContext([]byte{}) - KeyType = "sr25519" -) +const KeyType = "sr25519" // PrivKey implements crypto.PrivKey. type PrivKey struct { @@ -28,8 +20,6 @@ type PrivKey struct { kp *sr25519.KeyPair } -// TypeTag satisfies the jsontypes.Tagged interface. -func (PrivKey) TypeTag() string { return PrivKeyName } func (privKey PrivKey) Type() string { return KeyType } // Bytes returns the byte-encoded PrivKey. diff --git a/sei-cosmos/server/in_place.go b/sei-cosmos/server/in_place.go deleted file mode 100644 index f843cedab6..0000000000 --- a/sei-cosmos/server/in_place.go +++ /dev/null @@ -1,371 +0,0 @@ -package server - -import ( - "bufio" - "context" - "fmt" - "io" - "os" - "path/filepath" - "runtime/debug" - "strings" - "time" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/server/config" - "github.com/cosmos/cosmos-sdk/server/types" - "github.com/cosmos/cosmos-sdk/telemetry" - "github.com/spf13/cobra" - abciclient "github.com/tendermint/tendermint/abci/client" - abci "github.com/tendermint/tendermint/abci/types" - tmcfg "github.com/tendermint/tendermint/config" - tmexport "github.com/tendermint/tendermint/export" - tmjson "github.com/tendermint/tendermint/libs/json" - "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/node" - "github.com/tendermint/tendermint/privval" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmtypes "github.com/tendermint/tendermint/types" - dbm "github.com/tendermint/tm-db" - "go.opentelemetry.io/otel/sdk/trace" -) - -const ( - KeyIsTestnet = "is-testnet" - KeyNewChainID = "new-chain-ID" - KeyNewValAddr = "new-validator-addr" - KeyUserPubKey = "user-pub-key" - FlagShutdownGrace = "shutdown-grace" -) - -// Copied from osmosis-lab/cosmos-sdk -// -// InPlaceTestnetCreator utilizes the provided chainID and operatorAddress as well as the local private validator key to -// control the network represented in the data folder. This is useful to create testnets nearly identical to your -// mainnet environment. -func InPlaceTestnetCreator(testnetAppCreator types.AppCreator, defaultNodeHome string) *cobra.Command { - cmd := &cobra.Command{ - Use: "in-place-testnet [newChainID] [newOperatorAddress]", - Short: "Create and start a testnet from current local state", - Long: `Create and start a testnet from current local state. -After utilizing this command the network will start. If the network is stopped, -the normal "start" command should be used. Re-using this command on state that -has already been modified by this command could result in unexpected behavior. - -Additionally, the first block may take up to one minute to be committed, depending -on how old the block is. For instance, if a snapshot was taken weeks ago and we want -to turn this into a testnet, it is possible lots of pending state needs to be committed -(expiring locks, etc.). It is recommended that you should wait for this block to be committed -before stopping the daemon. - -If the --trigger-testnet-upgrade flag is set, the upgrade handler specified by the flag will be run -on the first block of the testnet. - -Regardless of whether the flag is set or not, if any new stores are introduced in the daemon being run, -those stores will be registered in order to prevent panics. Therefore, you only need to set the flag if -you want to test the upgrade handler itself. -`, - Example: "in-place-testnet localsei", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - defer func() { - if e := recover(); e != nil { - debug.PrintStack() - panic(e) - } - }() - serverCtx := GetServerContextFromCmd(cmd) - _, err := GetPruningOptionsFromFlags(serverCtx.Viper) - if err != nil { - return err - } - - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - - newChainID := args[0] - - skipConfirmation, _ := cmd.Flags().GetBool("skip-confirmation") - - if !skipConfirmation { - // Confirmation prompt to prevent accidental modification of state. - reader := bufio.NewReader(os.Stdin) - fmt.Println("This operation will modify state in your data folder and cannot be undone. Do you want to continue? (y/n)") - text, _ := reader.ReadString('\n') - response := strings.TrimSpace(strings.ToLower(text)) - if response != "y" && response != "yes" { - fmt.Println("Operation canceled.") - return nil - } - } - - // Set testnet keys to be used by the application. - // This is done to prevent changes to existing start API. - serverCtx.Viper.Set(KeyIsTestnet, true) - serverCtx.Viper.Set(KeyNewChainID, newChainID) - - config, _ := config.GetConfig(serverCtx.Viper) - apiMetrics, err := telemetry.New(config.Telemetry) - if err != nil { - return fmt.Errorf("failed to initialize telemetry: %w", err) - } - restartCoolDownDuration := time.Second * time.Duration(serverCtx.Config.SelfRemediation.RestartCooldownSeconds) - // Set the first restart time to be now - restartCoolDownDuration so that the first restart can trigger whenever - canRestartAfter := time.Now().Add(-restartCoolDownDuration) - err = startInProcess( - serverCtx, - clientCtx, - func(l log.Logger, d dbm.DB, w io.Writer, c *tmcfg.Config, ao types.AppOptions) types.Application { - testApp, err := testnetify(serverCtx, testnetAppCreator, d, w) - if err != nil { - panic(err) - } - return testApp - }, - []trace.TracerProviderOption{}, - node.DefaultMetricsProvider(serverCtx.Config.Instrumentation)(clientCtx.ChainID), - apiMetrics, - canRestartAfter, - ) - - serverCtx.Logger.Debug("received quit signal") - graceDuration, _ := cmd.Flags().GetDuration(FlagShutdownGrace) - if graceDuration > 0 { - serverCtx.Logger.Info("graceful shutdown start", FlagShutdownGrace, graceDuration) - <-time.After(graceDuration) - serverCtx.Logger.Info("graceful shutdown complete") - } - - return err - }, - } - - addStartNodeFlags(cmd, defaultNodeHome) - cmd.Flags().Bool("skip-confirmation", false, "Skip the confirmation prompt") - return cmd -} - -// testnetify modifies both state and blockStore, allowing the provided operator address and local validator key to control the network -// that the state in the data folder represents. The chainID of the local genesis file is modified to match the provided chainID. -func testnetify(ctx *Context, testnetAppCreator types.AppCreator, db dbm.DB, traceWriter io.Writer) (types.Application, error) { - config := ctx.Config - - newChainID, ok := ctx.Viper.Get(KeyNewChainID).(string) - if !ok { - return nil, fmt.Errorf("expected string for key %s", KeyNewChainID) - } - - // Modify app genesis chain ID and save to genesis file. - genFilePath := config.GenesisFile() - genDoc, err := tmtypes.GenesisDocFromFile(config.GenesisFile()) - if err != nil { - panic(err) - } - genDoc.ChainID = newChainID - - if err := genDoc.ValidateAndComplete(); err != nil { - panic(err) - } - if err := genDoc.SaveAs(genFilePath); err != nil { - panic(err) - } - - // Regenerate addrbook.json to prevent peers on old network from causing error logs. - addrBookPath := filepath.Join(config.RootDir, "config", "addrbook.json") - if err := os.Remove(addrBookPath); err != nil && !os.IsNotExist(err) { - return nil, fmt.Errorf("failed to remove existing addrbook.json: %w", err) - } - - emptyAddrBook := []byte("{}") - if err := os.WriteFile(addrBookPath, emptyAddrBook, 0o600); err != nil { - return nil, fmt.Errorf("failed to create empty addrbook.json: %w", err) - } - - // Initialize blockStore and stateDB. - blockStoreDB, err := tmcfg.DefaultDBProvider(&tmcfg.DBContext{ID: "blockstore", Config: config}) - if err != nil { - panic(err) - } - blockStore := tmexport.NewBlockStore(blockStoreDB) - - stateDB, err := tmcfg.DefaultDBProvider(&tmcfg.DBContext{ID: "state", Config: config}) - if err != nil { - panic(err) - } - - privValidator, err := privval.LoadOrGenFilePV(ctx.Config.PrivValidator.KeyFile(), ctx.Config.PrivValidator.StateFile()) - if err != nil { - panic(err) - } - userPubKey, err := privValidator.GetPubKey(context.Background()) - if err != nil { - panic(err) - } - validatorAddress := userPubKey.Address() - - stateStore := tmexport.NewStore(stateDB) - - state, err := node.LoadStateFromDBOrGenesisDocProvider(stateStore, genDoc) - if err != nil { - panic(err) - } - - blockStore.Close() - stateDB.Close() - - ctx.Viper.Set(KeyNewValAddr, validatorAddress) - ctx.Viper.Set(KeyUserPubKey, userPubKey) - ctx.Viper.Set(FlagChainID, newChainID) - testnetApp := testnetAppCreator(ctx.Logger, db, traceWriter, ctx.Config, ctx.Viper) - - // We need to create a temporary proxyApp to get the initial state of the application. - // Depending on how the node was stopped, the application height can differ from the blockStore height. - // This height difference changes how we go about modifying the state. - localClient := abciclient.NewLocalClient(ctx.Logger, testnetApp) - res, err := localClient.Info(context.Background(), &abci.RequestInfo{}) - if err != nil { - return nil, fmt.Errorf("error calling Info: %v", err) - } - - blockStoreDB, err = tmcfg.DefaultDBProvider(&tmcfg.DBContext{ID: "blockstore", Config: config}) - if err != nil { - panic(err) - } - blockStore = tmexport.NewBlockStore(blockStoreDB) - - stateDB, err = tmcfg.DefaultDBProvider(&tmcfg.DBContext{ID: "state", Config: config}) - if err != nil { - panic(err) - } - - stateStore = tmexport.NewStore(stateDB) - - defer blockStore.Close() - defer stateStore.Close() - - appHash := res.LastBlockAppHash - appHeight := res.LastBlockHeight - - var block *tmtypes.Block - switch { - case appHeight == blockStore.Height(): - block = blockStore.LoadBlock(blockStore.Height()) - // If the state's last blockstore height does not match the app and blockstore height, we likely stopped with the halt height flag. - if state.LastBlockHeight != appHeight { - state.LastBlockHeight = appHeight - block.AppHash = appHash - state.AppHash = appHash - } else { - // Node was likely stopped via SIGTERM, delete the next block's seen commit - err := blockStoreDB.Delete([]byte(fmt.Sprintf("SC:%v", blockStore.Height()+1))) - if err != nil { - panic(err) - } - } - case blockStore.Height() > state.LastBlockHeight: - // This state usually occurs when we gracefully stop the node. - err = blockStore.DeleteLatestBlock() - if err != nil { - panic(err) - } - block = blockStore.LoadBlock(blockStore.Height()) - default: - // If there is any other state, we just load the block - block = blockStore.LoadBlock(blockStore.Height()) - } - - block.ChainID = newChainID - state.ChainID = newChainID - - block.LastBlockID = state.LastBlockID - block.LastCommit.BlockID = state.LastBlockID - - // Create a vote from our validator - vote := tmtypes.Vote{ - Type: tmproto.PrecommitType, - Height: state.LastBlockHeight, - Round: 0, - BlockID: state.LastBlockID, - Timestamp: time.Now(), - ValidatorAddress: validatorAddress, - ValidatorIndex: 0, - Signature: []byte{}, - } - - // Sign the vote, and copy the proto changes from the act of signing to the vote itself - voteProto := vote.ToProto() - privValidator.LastSignState.Round = 0 - privValidator.LastSignState.Step = 0 - if privValidator.LastSignState.Height > state.LastBlockHeight { - privValidator.LastSignState.Height = state.LastBlockHeight - } - err = privValidator.SignVote(context.Background(), newChainID, voteProto) - if err != nil { - panic(err) - } - vote.Signature = voteProto.Signature - vote.Timestamp = voteProto.Timestamp - - // Modify the block's lastCommit to be signed only by our validator - block.LastCommit.Signatures[0].ValidatorAddress = validatorAddress - block.LastCommit.Signatures[0].Signature = vote.Signature - block.LastCommit.Signatures = []tmtypes.CommitSig{block.LastCommit.Signatures[0]} - - seenCommit := tmtypes.Commit{} - seenCommit.Height = state.LastBlockHeight - seenCommit.Round = vote.Round - seenCommit.BlockID = state.LastBlockID - seenCommit.Round = vote.Round - seenCommit.Signatures = []tmtypes.CommitSig{{}} - seenCommit.Signatures[0].BlockIDFlag = tmtypes.BlockIDFlagCommit - seenCommit.Signatures[0].Signature = vote.Signature - seenCommit.Signatures[0].ValidatorAddress = validatorAddress - seenCommit.Signatures[0].Timestamp = vote.Timestamp - err = blockStore.SaveSeenCommit(state.LastBlockHeight, &seenCommit) - if err != nil { - panic(err) - } - - // Create ValidatorSet struct containing just our valdiator. - newVal := &tmtypes.Validator{ - Address: validatorAddress, - PubKey: userPubKey, - VotingPower: 900000000000000, - } - newValSet := &tmtypes.ValidatorSet{ - Validators: []*tmtypes.Validator{newVal}, - Proposer: newVal, - } - - // Replace all valSets in state to be the valSet with just our validator. - state.Validators = newValSet - state.LastValidators = newValSet - state.NextValidators = newValSet - state.LastHeightValidatorsChanged = blockStore.Height() - - err = stateStore.Save(state) - if err != nil { - panic(err) - } - - // Modfiy Validators stateDB entry. - stateStore.SaveValidatorSets(blockStore.Height()-1, blockStore.Height()-1, newValSet) - stateStore.SaveValidatorSets(blockStore.Height(), blockStore.Height(), newValSet) - stateStore.SaveValidatorSets(blockStore.Height()+1, blockStore.Height()+1, newValSet) - - // Since we modified the chainID, we set the new genesisDoc in the stateDB. - b, err := tmjson.Marshal(genDoc) - if err != nil { - panic(err) - } - if err := stateDB.SetSync([]byte("genesisDoc"), b); err != nil { - panic(err) - } - - testnetApp.InplaceTestnetInitialize(&ed25519.PubKey{Key: userPubKey.Bytes()}) - - return testnetApp, err -} diff --git a/sei-cosmos/server/rollback_test.go b/sei-cosmos/server/rollback_test.go index 1536a01f21..21f1b1e2ba 100644 --- a/sei-cosmos/server/rollback_test.go +++ b/sei-cosmos/server/rollback_test.go @@ -157,8 +157,8 @@ func setupTendermintStateDB(t *testing.T, tempDir string, height int64) *tmconfi // Create a simple validator set for testing // We need at least one validator for rollback to work - valPrivKey := ed25519.GenPrivKey() - valPubKey := valPrivKey.PubKey() + valPrivKey := ed25519.GenerateSecretKey() + valPubKey := valPrivKey.Public() validator := &tmtypes.Validator{ Address: valPubKey.Address(), PubKey: valPubKey, diff --git a/sei-cosmos/server/util.go b/sei-cosmos/server/util.go index 60a1c5b078..937029caff 100644 --- a/sei-cosmos/server/util.go +++ b/sei-cosmos/server/util.go @@ -340,8 +340,6 @@ func AddCommands( startCmd := StartCmd(appCreator, defaultNodeHome, tracerProviderOptions) addStartFlags(startCmd) - inPlaceTestnetCmd := InPlaceTestnetCreator(appCreator, defaultNodeHome) - addStartFlags(inPlaceTestnetCmd) rootCmd.AddCommand( startCmd, @@ -350,7 +348,6 @@ func AddCommands( version.NewVersionCommand(), NewRollbackCmd(appCreator, defaultNodeHome), LatestVersionCmd(defaultNodeHome), - inPlaceTestnetCmd, ) } diff --git a/sei-cosmos/x/genutil/utils.go b/sei-cosmos/x/genutil/utils.go index 5b0bab809e..b6679dc6b2 100644 --- a/sei-cosmos/x/genutil/utils.go +++ b/sei-cosmos/x/genutil/utils.go @@ -82,7 +82,7 @@ func InitializeNodeValidatorFilesFromMnemonic(config *cfg.Config, mnemonic strin if len(mnemonic) == 0 { filePV, _ = privval.LoadOrGenFilePV(pvKeyFile, pvStateFile) } else { - privKey := tmed25519.GenPrivKeyFromSecret([]byte(mnemonic)) + privKey := tmed25519.TestSecretKey([]byte(mnemonic)) filePV = privval.NewFilePV(privKey, pvKeyFile, pvStateFile) } diff --git a/sei-cosmos/x/staking/teststaking/tm.go b/sei-cosmos/x/staking/teststaking/tm.go index e927c0e038..f81161f33b 100644 --- a/sei-cosmos/x/staking/teststaking/tm.go +++ b/sei-cosmos/x/staking/teststaking/tm.go @@ -13,7 +13,7 @@ import ( func GetTmConsPubKey(v types.Validator) (tmcrypto.PubKey, error) { pk, err := v.ConsPubKey() if err != nil { - return nil, err + return tmcrypto.PubKey{}, err } return cryptocodec.ToTmPubKeyInterface(pk) diff --git a/sei-ibc-go/testing/chain.go b/sei-ibc-go/testing/chain.go index 1c486641f3..7cc4b1febb 100644 --- a/sei-ibc-go/testing/chain.go +++ b/sei-ibc-go/testing/chain.go @@ -27,7 +27,9 @@ import ( ibckeeper "github.com/sei-protocol/sei-chain/sei-ibc-go/modules/core/keeper" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" tmversion "github.com/tendermint/tendermint/version" @@ -497,7 +499,7 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, v := vote.ToProto() err := privVal.SignVote(chain.Context(), chainID, v) require.NoError(chain.T, err) - vote.Signature = v.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) _, err = voteSet.AddVote(vote) require.NoError(chain.T, err) } diff --git a/sei-ibc-go/testing/mock/privval_test.go b/sei-ibc-go/testing/mock/privval_test.go index 4d38d794d2..aa5aac9b50 100644 --- a/sei-ibc-go/testing/mock/privval_test.go +++ b/sei-ibc-go/testing/mock/privval_test.go @@ -3,7 +3,9 @@ package mock_test import ( "testing" - "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" @@ -27,8 +29,7 @@ func TestSignVote(t *testing.T) { pv.SignVote(t.Context(), chainID, vote) msg := tmtypes.VoteSignBytes(chainID, vote) - ok := pk.VerifySignature(msg, vote.Signature) - require.True(t, ok) + require.NoError(t, pk.Verify(msg, utils.OrPanic1(crypto.SigFromBytes(vote.Signature)))) } func TestSignProposal(t *testing.T) { @@ -39,6 +40,5 @@ func TestSignProposal(t *testing.T) { pv.SignProposal(t.Context(), chainID, proposal) msg := tmtypes.ProposalSignBytes(chainID, proposal) - ok := pk.VerifySignature(msg, proposal.Signature) - require.True(t, ok) + require.NoError(t, pk.Verify(msg, utils.OrPanic1(crypto.SigFromBytes(proposal.Signature)))) } diff --git a/sei-tendermint/abci/example/kvstore/helpers.go b/sei-tendermint/abci/example/kvstore/helpers.go index 8a2a8a35b1..a287a2f8ed 100644 --- a/sei-tendermint/abci/example/kvstore/helpers.go +++ b/sei-tendermint/abci/example/kvstore/helpers.go @@ -5,27 +5,26 @@ import ( mrand "math/rand" "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" tmrand "github.com/tendermint/tendermint/libs/rand" ) -// RandVal creates one random validator, with a key derived -// from the input value -func RandVal(i int) types.ValidatorUpdate { - pubkey := tmrand.Bytes(32) - // Random value between [0, 2^16 - 1] - power := mrand.Uint32() & (1<<16 - 1) // nolint:gosec // G404: Use of weak random number generator - v := types.UpdateValidator(pubkey, int64(power), "") - return v -} - // RandVals returns a list of cnt validators for initializing // the application. Note that the keys are deterministically // derived from the index in the array, while the power is // random (Change this if not desired) func RandVals(cnt int) []types.ValidatorUpdate { res := make([]types.ValidatorUpdate, cnt) - for i := 0; i < cnt; i++ { - res[i] = RandVal(i) + for i := range res { + // Random value between [0, 2^16 - 1] + power := mrand.Uint32() & (1<<16 - 1) // nolint:gosec // G404: Use of weak random number generator + keyBytes := tmrand.Bytes(len(crypto.PubKey{}.Bytes())) + pubKey, err := ed25519.PublicKeyFromBytes(keyBytes) + if err != nil { + panic(err) + } + res[i] = types.UpdateValidator(pubKey, int64(power), "") } return res } diff --git a/sei-tendermint/abci/example/kvstore/kvstore.go b/sei-tendermint/abci/example/kvstore/kvstore.go index bd28d95070..4c219f8db1 100644 --- a/sei-tendermint/abci/example/kvstore/kvstore.go +++ b/sei-tendermint/abci/example/kvstore/kvstore.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/tendermint/abci/example/code" "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/log" cryptoproto "github.com/tendermint/tendermint/proto/tendermint/crypto" @@ -371,7 +372,14 @@ func (app *Application) execValidatorTx(tx []byte) *types.ExecTxResult { } // update - return app.updateValidator(types.UpdateValidator(pubkey, power, "")) + key, err := ed25519.PublicKeyFromBytes(pubkey) + if err != nil { + return &types.ExecTxResult{ + Code: code.CodeTypeEncodingError, + Log: fmt.Sprintf("can't decode ed25519 key: %v", err), + } + } + return app.updateValidator(types.UpdateValidator(key, power, "")) } // add, update, or remove a validator diff --git a/sei-tendermint/abci/tests/server/client.go b/sei-tendermint/abci/tests/server/client.go index 46deafcb03..2b7f4bcb73 100644 --- a/sei-tendermint/abci/tests/server/client.go +++ b/sei-tendermint/abci/tests/server/client.go @@ -9,14 +9,19 @@ import ( abciclient "github.com/tendermint/tendermint/abci/client" "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" tmrand "github.com/tendermint/tendermint/libs/rand" ) func InitChain(ctx context.Context, client abciclient.Client) error { - total := 10 - vals := make([]types.ValidatorUpdate, total) - for i := 0; i < total; i++ { - pubkey := tmrand.Bytes(33) + vals := make([]types.ValidatorUpdate, 10) + for i := range vals { + keyBytes := tmrand.Bytes(len(crypto.PubKey{}.Bytes())) + pubkey, err := ed25519.PublicKeyFromBytes(keyBytes) + if err != nil { + return err + } // nolint:gosec // G404: Use of weak random number generator power := mrand.Int() vals[i] = types.UpdateValidator(pubkey, int64(power), "") diff --git a/sei-tendermint/abci/types/pubkey.go b/sei-tendermint/abci/types/pubkey.go index 2b08dbbdbe..c556e11f3b 100644 --- a/sei-tendermint/abci/types/pubkey.go +++ b/sei-tendermint/abci/types/pubkey.go @@ -1,29 +1,13 @@ package types import ( - fmt "fmt" - - "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/encoding" ) -func Ed25519ValidatorUpdate(pk []byte, power int64) ValidatorUpdate { - pke := ed25519.PubKey(pk) - - pkp, err := encoding.PubKeyToProto(pke) - if err != nil { - panic(err) - } - +func UpdateValidator(pk crypto.PubKey, power int64, keyType string) ValidatorUpdate { return ValidatorUpdate{ - PubKey: pkp, + PubKey: encoding.PubKeyToProto(pk), Power: power, } } - -func UpdateValidator(pk []byte, power int64, keyType string) ValidatorUpdate { - if keyType != "" && keyType != ed25519.KeyType { - panic(fmt.Sprintf("key type %s not supported", keyType)) - } - return Ed25519ValidatorUpdate(pk, power) -} diff --git a/sei-tendermint/abci/types/types.go b/sei-tendermint/abci/types/types.go index 902833e087..c9bc0f8153 100644 --- a/sei-tendermint/abci/types/types.go +++ b/sei-tendermint/abci/types/types.go @@ -156,11 +156,7 @@ func (v *ValidatorUpdate) UnmarshalJSON(data []byte) error { if err := jsontypes.Unmarshal(vu.PubKey, &key); err != nil { return err } - pkey, err := encoding.PubKeyToProto(key) - if err != nil { - return err - } - v.PubKey = pkey + v.PubKey = encoding.PubKeyToProto(key) v.Power = vu.Power return nil } diff --git a/sei-tendermint/cmd/tendermint/commands/show_validator.go b/sei-tendermint/cmd/tendermint/commands/show_validator.go index 60e664797d..a0e8d75666 100644 --- a/sei-tendermint/cmd/tendermint/commands/show_validator.go +++ b/sei-tendermint/cmd/tendermint/commands/show_validator.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto" - tmjson "github.com/tendermint/tendermint/libs/json" + "github.com/tendermint/tendermint/internal/jsontypes" "github.com/tendermint/tendermint/libs/log" tmnet "github.com/tendermint/tendermint/libs/net" tmos "github.com/tendermint/tendermint/libs/os" @@ -70,7 +70,7 @@ func MakeShowValidatorCommand(conf *config.Config, logger log.Logger) *cobra.Com } } - bz, err := tmjson.Marshal(pubKey) + bz, err := jsontypes.Marshal(pubKey) if err != nil { return fmt.Errorf("failed to marshal private validator pubkey: %w", err) } diff --git a/sei-tendermint/crypto/crypto.go b/sei-tendermint/crypto/crypto.go index ca46e44638..d883f0258c 100644 --- a/sei-tendermint/crypto/crypto.go +++ b/sei-tendermint/crypto/crypto.go @@ -35,9 +35,15 @@ func Checksum(bz []byte) []byte { return h[:] } -type PubKey = ed25519.PubKey -type PrivKey = ed25519.PrivKey +type PubKey = ed25519.PublicKey +type PrivKey = ed25519.SecretKey +type Sig = ed25519.Signature type BatchVerifier = ed25519.BatchVerifier +type ErrBadSig = ed25519.ErrBadSig + +func SigFromBytes(raw []byte) (Sig, error) { + return ed25519.SignatureFromBytes(raw) +} func NewBatchVerifier() *BatchVerifier { return ed25519.NewBatchVerifier() diff --git a/sei-tendermint/crypto/crypto_test.go b/sei-tendermint/crypto/crypto_test.go new file mode 100644 index 0000000000..fc5b9194d3 --- /dev/null +++ b/sei-tendermint/crypto/crypto_test.go @@ -0,0 +1,59 @@ +package crypto + +import ( + "crypto/sha256" + "encoding/hex" + "encoding/json" + "testing" + + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/internal/jsontypes" + "github.com/tendermint/tendermint/libs/utils/require" +) + +var privKey = ed25519.TestSecretKey([]byte("tm-test-key-json-seed")) + +func hexHash(data []byte) string { + hash := sha256.Sum256(data) + return hex.EncodeToString(hash[:]) +} + +// tests if hash(jsontypes.Marshal(want)) == wantHash +// returns jsontypes.Unmarshal(jsontypes.Marshal(want)) +func testTaggedJSON[T jsontypes.Tagged](t *testing.T, want T, wantHash string) T { + t.Helper() + raw, err := jsontypes.Marshal(want) + require.NoError(t, err) + t.Logf("%T -> %v", want, string(raw)) + require.Equal(t, wantHash, hexHash(raw)) + var got T + require.NoError(t, jsontypes.Unmarshal(raw, &got)) + return got +} + +func TestTaggedJSON(t *testing.T) { + pubKey := privKey.Public() + require.Equal(t, pubKey, testTaggedJSON(t, privKey, "f36adf0dc679100837e9819a73ccefdf073b5a2129db8d200a4262bfd47cd883").Public()) + require.Equal(t, pubKey, testTaggedJSON(t, pubKey, "0b0b97c108fbd1305b323676bc33dc5c9309fb947d5cd29f88e9dce1457c6362")) +} + +// tests if hash(json.Marshal(want)) == wantHash +// returns json.Unmarshal(json.Marshal(want)) +func testJSON[T any](t *testing.T, want T, wantHash string) T { + t.Helper() + raw, err := json.Marshal(want) + require.NoError(t, err) + t.Logf("%T -> %v", want, string(raw)) + require.Equal(t, wantHash, hexHash(raw)) + var got T + require.NoError(t, json.Unmarshal(raw, &got)) + return got +} + +func TestJSON(t *testing.T) { + pubKey := privKey.Public() + sig := privKey.Sign([]byte{1, 2, 3}) + require.Equal(t, pubKey, testJSON(t, privKey, "ecaae500bfb3a28fe1f6108cb7c18743e0242d37c8e41ddd672d8c62563bec1b").Public()) + require.Equal(t, pubKey, testJSON(t, pubKey, "f7874c043989887e8cfa6a3a3c1dd22432f95745481123e29201ebd21bc4d844")) + require.Equal(t, sig, testJSON(t, sig, "dd48379c6c07eb1e36b188ea0cf35772a697c1a45ad4d47986ca819262743b71")) +} diff --git a/sei-tendermint/crypto/ed25519/amino.go b/sei-tendermint/crypto/ed25519/amino.go new file mode 100644 index 0000000000..e2229701f1 --- /dev/null +++ b/sei-tendermint/crypto/ed25519/amino.go @@ -0,0 +1,28 @@ +package ed25519 + +// Another way to leak a secret. Needed for LegacyAminoEncoding. +func (k SecretKey) MarshalAmino() ([]byte, error) { + return k.SecretBytes(), nil +} + +func (k *SecretKey) UnmarshalAmino(secretBytes []byte) error { + x, err := SecretKeyFromSecretBytes(secretBytes) + if err != nil { + return err + } + *k = x + return nil +} + +func (k PublicKey) MarshalAmino() ([]byte, error) { + return k.Bytes(), nil +} + +func (k *PublicKey) UnmarshalAmino(bytes []byte) error { + x, err := PublicKeyFromBytes(bytes) + if err != nil { + return err + } + *k = x + return nil +} diff --git a/sei-tendermint/crypto/ed25519/bench_test.go b/sei-tendermint/crypto/ed25519/bench_test.go index cf5131076b..341897e058 100644 --- a/sei-tendermint/crypto/ed25519/bench_test.go +++ b/sei-tendermint/crypto/ed25519/bench_test.go @@ -2,84 +2,39 @@ package ed25519 import ( "fmt" - "io" "testing" - - "github.com/stretchr/testify/require" ) -type zeroReader struct{} - -func (zeroReader) Read(buf []byte) (int, error) { - for i := range buf { - buf[i] = 0 - } - return len(buf), nil -} - -func benchmarkKeyGeneration(b *testing.B, generateKey func(reader io.Reader) PrivKey) { - var zero zeroReader - for i := 0; i < b.N; i++ { - generateKey(zero) - } -} - -func benchmarkSigning(b *testing.B, priv PrivKey) { +func BenchmarkSigning(b *testing.B) { + priv := TestSecretKey([]byte("test")) message := []byte("Hello, world!") - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := priv.Sign(message) - if err != nil { - b.FailNow() - } + for b.Loop() { + priv.Sign(message) } } -func benchmarkVerification(b *testing.B, priv PrivKey) { - pub := priv.PubKey() +func BenchmarkVerification(b *testing.B) { + priv := TestSecretKey([]byte("test")) + pub := priv.Public() message := []byte("Hello, world!") - signature, err := priv.Sign(message) - if err != nil { - b.Fatal(err) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - pub.VerifySignature(message, signature) + sig := priv.Sign(message) + for b.Loop() { + pub.Verify(message, sig) } } -func BenchmarkKeyGeneration(b *testing.B) { - benchmarkKeygenWrapper := func(reader io.Reader) PrivKey { - return genPrivKey(reader) - } - benchmarkKeyGeneration(b, benchmarkKeygenWrapper) -} - -func BenchmarkSigning(b *testing.B) { - priv := GenPrivKey() - benchmarkSigning(b, priv) -} - -func BenchmarkVerification(b *testing.B) { - priv := GenPrivKey() - benchmarkVerification(b, priv) -} - func BenchmarkVerifyBatch(b *testing.B) { msg := []byte("BatchVerifyTest") - for _, sigsCount := range []int{1, 8, 64, 1024} { - sigsCount := sigsCount b.Run(fmt.Sprintf("sig-count-%d", sigsCount), func(b *testing.B) { // Pre-generate all of the keys, and signatures, but do not // benchmark key-generation and signing. - pubs := make([]PubKey, 0, sigsCount) - sigs := make([][]byte, 0, sigsCount) - for i := 0; i < sigsCount; i++ { - priv := GenPrivKey() - sig, _ := priv.Sign(msg) - pubs = append(pubs, priv.PubKey()) - sigs = append(sigs, sig) + pubs := make([]PublicKey, 0, sigsCount) + sigs := make([]Signature, 0, sigsCount) + for i := range sigsCount { + priv := TestSecretKey(fmt.Appendf(nil, "test-%v", i)) + pubs = append(pubs, priv.Public()) + sigs = append(sigs, priv.Sign(msg)) } b.ResetTimer() @@ -91,13 +46,11 @@ func BenchmarkVerifyBatch(b *testing.B) { // with BatchVerifier.Add(), which should be included // in the benchmark. v := NewBatchVerifier() - for i := 0; i < sigsCount; i++ { - err := v.Add(pubs[i], msg, sigs[i]) - require.NoError(b, err) + for i := range sigsCount { + v.Add(pubs[i], msg, sigs[i]) } - - if ok, _ := v.Verify(); !ok { - b.Fatal("signature set failed batch verification") + if err := v.Verify(); err != nil { + b.Fatal(err) } } }) diff --git a/sei-tendermint/crypto/ed25519/conv.go b/sei-tendermint/crypto/ed25519/conv.go new file mode 100644 index 0000000000..99f2b4db9e --- /dev/null +++ b/sei-tendermint/crypto/ed25519/conv.go @@ -0,0 +1,70 @@ +package ed25519 + +import ( + "crypto/ed25519" + "crypto/sha256" + "encoding/hex" + "errors" + "fmt" + tmbytes "github.com/tendermint/tendermint/libs/bytes" + "strings" +) + +// Bytes converts the public key or signature to bytes. +func (k PublicKey) Bytes() []byte { return k.key[:] } + +// Bytes converts the signature to bytes. +func (s Signature) Bytes() []byte { return s.sig[:] } + +// PublicKeyFromBytes constructs a public key from bytes. +func PublicKeyFromBytes(key []byte) (PublicKey, error) { + if got, want := len(key), ed25519.PublicKeySize; got != want { + return PublicKey{}, fmt.Errorf("ed25519: bad public key length: got %d, want %d", got, want) + } + return PublicKey{key: ([ed25519.PublicKeySize]byte)(key)}, nil +} + +// SignatureFromBytes constructs a signature from bytes. +func SignatureFromBytes(sig []byte) (Signature, error) { + if got, want := len(sig), ed25519.SignatureSize; got != want { + return Signature{}, fmt.Errorf("ed25519: bad signature length: got %d, want %d", got, want) + } + return Signature{sig: ([ed25519.SignatureSize]byte)(sig)}, nil +} + +// String returns a string representation. +func (k PublicKey) String() string { return fmt.Sprintf("ed25519:public:%x", k.key[:]) } + +// String returns a log-safe representation of the secret key. +func (k SecretKey) String() string { return fmt.Sprintf("", k.Public()) } + +// String returns a string representation. +func (s Signature) String() string { return fmt.Sprintf("ed25519:sig:%x", s.sig[:]) } + +// GoString returns a strings representation. +func (k PublicKey) GoString() string { return k.String() } + +// GoString returns a log-safe representation of the secret key. +func (k SecretKey) GoString() string { return k.String() } + +// GoString returns a strings representation. +func (s Signature) GoString() string { return s.String() } + +// PublicKeyFromString constructs a public key from a string representation. +func PublicKeyFromString(s string) (PublicKey, error) { + s2 := strings.TrimPrefix(s, "ed25519:public:") + if s == s2 { + return PublicKey{}, errors.New("bad prefix") + } + b, err := hex.DecodeString(s2) + if err != nil { + return PublicKey{}, fmt.Errorf("hex.DecodeString: %w", err) + } + return PublicKeyFromBytes(b) +} + +// Address is the SHA256-20 of the raw pubkey bytes. +func (k PublicKey) Address() tmbytes.HexBytes { + h := sha256.Sum256(k.Bytes()) + return tmbytes.HexBytes(h[:20]) +} diff --git a/sei-tendermint/crypto/ed25519/ed25519.go b/sei-tendermint/crypto/ed25519/ed25519.go index 6723de7ad2..b17f3dda4f 100644 --- a/sei-tendermint/crypto/ed25519/ed25519.go +++ b/sei-tendermint/crypto/ed25519/ed25519.go @@ -4,219 +4,165 @@ import ( "bytes" "crypto/rand" "crypto/sha256" - "crypto/subtle" - "errors" "fmt" - "io" + "runtime" "github.com/oasisprotocol/curve25519-voi/primitives/ed25519" "github.com/oasisprotocol/curve25519-voi/primitives/ed25519/extra/cache" - "github.com/tendermint/tendermint/internal/jsontypes" - tmbytes "github.com/tendermint/tendermint/libs/bytes" - tmjson "github.com/tendermint/tendermint/libs/json" + "github.com/tendermint/tendermint/libs/utils" ) -//------------------------------------- - -var ( - // curve25519-voi's Ed25519 implementation supports configurable - // verification behavior, and tendermint uses the ZIP-215 verification - // semantics. - verifyOptions = &ed25519.Options{ - Verify: ed25519.VerifyOptionsZIP_215, - } - - cachingVerifier = cache.NewVerifier(cache.NewLRUCache(cacheSize)) -) - -const ( - PrivKeyName = "tendermint/PrivKeyEd25519" - PubKeyName = "tendermint/PubKeyEd25519" - // PubKeySize is is the size, in bytes, of public keys as used in this package. - PubKeySize = 32 - // PrivateKeySize is the size, in bytes, of private keys as used in this package. - PrivateKeySize = 64 - // Size of an Edwards25519 signature. Namely the size of a compressed - // Edwards25519 point, and a field element. Both of which are 32 bytes. - SignatureSize = 64 - // SeedSize is the size, in bytes, of private key seeds. These are the - // private key representations used by RFC 8032. - SeedSize = 32 - - KeyType = "ed25519" - - // cacheSize is the number of public keys that will be cached in - // an expanded format for repeated signature verification. - // - // TODO/perf: Either this should exclude single verification, or be - // tuned to `> validatorSize + maxTxnsPerBlock` to avoid cache - // thrashing. - cacheSize = 4096 -) - -func init() { - tmjson.RegisterType(PubKey{}, PubKeyName) - tmjson.RegisterType(PrivKey{}, PrivKeyName) - - jsontypes.MustRegister(PubKey{}) - jsontypes.MustRegister(PrivKey{}) -} - -type PrivKey []byte - -// TypeTag satisfies the jsontypes.Tagged interface. -func (PrivKey) TypeTag() string { return PrivKeyName } - -// Bytes returns the privkey byte format. -func (privKey PrivKey) Bytes() []byte { - return []byte(privKey) +type ErrBadSig struct { + Idx int // Index of the first invalid signature. } -// Sign produces a signature on the provided message. -// This assumes the privkey is wellformed in the golang format. -// The first 32 bytes should be random, -// corresponding to the normal ed25519 private key. -// The latter 32 bytes should be the compressed public key. -// If these conditions aren't met, Sign will panic or produce an -// incorrect signature. -func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { - signatureBytes := ed25519.Sign(ed25519.PrivateKey(privKey), msg) - return signatureBytes, nil +func (e ErrBadSig) Error() string { + return fmt.Sprintf("invalid %vth signature", e.Idx) } -// PubKey gets the corresponding public key from the private key. +// cacheSize is the number of public keys that will be cached in +// an expanded format for repeated signature verification. // -// Panics if the private key is not initialized. -func (privKey PrivKey) PubKey() PubKey { - // If the latter 32 bytes of the privkey are all zero, privkey is not - // initialized. - initialized := false - for _, v := range privKey[32:] { - if v != 0 { - initialized = true - break - } +// TODO/perf: Either this should exclude single verification, or be +// tuned to `> validatorSize + maxTxnsPerBlock` to avoid cache +// thrashing. +const cacheSize = 4096 + +// curve25519-voi's Ed25519 implementation supports configurable +// verification behavior, and tendermint uses the ZIP-215 verification +// semantics. +var verifyOptions = &ed25519.Options{Verify: ed25519.VerifyOptionsZIP_215} +var cachingVerifier = cache.NewVerifier(cache.NewLRUCache(cacheSize)) + +// SecretKey represents a secret key in the Ed25519 signature scheme. +type SecretKey struct { + // This is a pointer to avoid copying the secret all over the memory. + // This is a pointer to pointer, so that runtime.AddCleanup can actually work: + // Cleanup requires the referenced pointer to be unreachable, even from + // the cleanup function. + key **[ed25519.PrivateKeySize]byte + // Comparing the secrets is not allowed. + // If you have to, compare the public keys instead. + _ utils.NoCompare +} + +// WARNING: this function should only be used when persisting the private key. +// TODO(gprusak): this should return a read-only slice - in particular, +// SecretKeyFromSecretBytes(k.SecretBytes()) would wipe k currently. +func (k SecretKey) SecretBytes() []byte { + return (*k.key)[:] +} + +// SecretKeyFromSecretBytes constructs a secret key from a raw secret material. +// WARNING: this function zeroes the content of the input slice. +func SecretKeyFromSecretBytes(b []byte) (SecretKey, error) { + if got, want := len(b), ed25519.PrivateKeySize; got != want { + return SecretKey{}, fmt.Errorf("ed25519: bad private key length: got %d, want %d", got, want) } - - if !initialized { - panic("Expected ed25519 PrivKey to include concatenated pubkey bytes") + raw := utils.Alloc([ed25519.PrivateKeySize]byte(b)) + runtime.AddCleanup(&raw, func(int) { + // Zero the memory to avoid leaking the secret. + for i := range raw { + raw[i] = 0 + } + }, 0) + key := SecretKey{key: &raw} + // Zero the input slice to avoid leaking the secret. + for i := range b { + b[i] = 0 } - - pubkeyBytes := make([]byte, PubKeySize) - copy(pubkeyBytes, privKey[32:]) - return PubKey(pubkeyBytes) -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKey) Equals(other PrivKey) bool { - return subtle.ConstantTimeCompare(privKey[:], other[:]) == 1 + return key, nil } -func (privKey PrivKey) Type() string { - return KeyType -} - -// GenPrivKey generates a new ed25519 private key. -// It uses OS randomness in conjunction with the current global random seed -// in tendermint/libs/common to generate the private key. -func GenPrivKey() PrivKey { - return genPrivKey(rand.Reader) +// TestSecretKey generates a testonly secret key. +func TestSecretKey(seed []byte) SecretKey { + h := sha256.Sum256(seed) + key, err := SecretKeyFromSecretBytes(ed25519.NewKeyFromSeed(h[:])) + if err != nil { + panic(err) + } + return key } -// genPrivKey generates a new ed25519 private key using the provided reader. -func genPrivKey(rand io.Reader) PrivKey { - _, priv, err := ed25519.GenerateKey(rand) +// GenerateSecretKey generates a new secret key using a cryptographically secure random number generator. +func GenerateSecretKey() SecretKey { + var seed [ed25519.SeedSize]byte + // rand.Read is documented to never return an error. + if _, err := rand.Read(seed[:]); err != nil { + panic(err) + } + // Generated key is always valid. + key, err := SecretKeyFromSecretBytes(ed25519.NewKeyFromSeed(seed[:])) if err != nil { panic(err) } - - return PrivKey(priv) + // Zeroize the seed after generation. + for i := range seed { + seed[i] = 0 + } + return key } -// GenPrivKeyFromSecret hashes the secret with SHA2, and uses -// that 32 byte output to create the private key. -// NOTE: secret should be the output of a KDF like bcrypt, -// if it's derived from user input. -func GenPrivKeyFromSecret(secret []byte) PrivKey { - seed := sha256.Sum256(secret) - return PrivKey(ed25519.NewKeyFromSeed(seed[:])) +// Public returns the public key corresponding to the secret key. +func (k SecretKey) Public() PublicKey { + p := ed25519.PrivateKey((*k.key)[:]).Public().(ed25519.PublicKey) + return PublicKey{key: [ed25519.PublicKeySize]byte(p)} } -//------------------------------------- - -// PubKeyEd25519 implements the Ed25519 signature scheme. -type PubKey []byte - -// TypeTag satisfies the jsontypes.Tagged interface. -func (PubKey) TypeTag() string { return PubKeyName } - -// Address is the SHA256-20 of the raw pubkey bytes. -func (pubKey PubKey) Address() tmbytes.HexBytes { - if len(pubKey) != PubKeySize { - panic("pubkey is incorrect size") - } - return addressHash(pubKey) +// PublicKey represents a public key in the Ed25519 signature scheme. +type PublicKey struct { + utils.ReadOnly + key [ed25519.PublicKeySize]byte } -// Bytes returns the PubKey byte format. -func (pubKey PubKey) Bytes() []byte { - return []byte(pubKey) +// Signature represents a signature in the Ed25519 signature scheme. +type Signature struct { + utils.ReadOnly + sig [ed25519.SignatureSize]byte } -func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool { - // make sure we use the same algorithm to sign - if len(sig) != SignatureSize { - return false +// Sign signs a message using the secret key. +func (k SecretKey) Sign(message []byte) Signature { + return Signature{ + sig: [ed25519.SignatureSize]byte(ed25519.Sign((*k.key)[:], message)), } - - return cachingVerifier.VerifyWithOptions(ed25519.PublicKey(pubKey), msg, sig, verifyOptions) -} - -func (pubKey PubKey) String() string { - return fmt.Sprintf("PubKeyEd25519{%X}", []byte(pubKey)) } -func (pubKey PubKey) Type() string { - return KeyType +// Compare defines a total order on public keys. +func (k PublicKey) Compare(other PublicKey) int { + return bytes.Compare(k.key[:], other.key[:]) } -func (pubKey PubKey) Equals(other PubKey) bool { - return bytes.Equal(pubKey[:], other[:]) +// Verify verifies a signature using the public key. +func (k PublicKey) Verify(msg []byte, sig Signature) error { + if !cachingVerifier.VerifyWithOptions(k.key[:], msg, sig.sig[:], verifyOptions) { + return ErrBadSig{} + } + return nil } // BatchVerifier implements batch verification for ed25519. -type BatchVerifier struct { - *ed25519.BatchVerifier -} +type BatchVerifier struct{ inner *ed25519.BatchVerifier } -func NewBatchVerifier() *BatchVerifier { - return &BatchVerifier{ed25519.NewBatchVerifier()} -} +func NewBatchVerifier() *BatchVerifier { return &BatchVerifier{ed25519.NewBatchVerifier()} } -func (b *BatchVerifier) Add(key PubKey, msg, signature []byte) error { - pkBytes := key.Bytes() +func (b *BatchVerifier) Add(key PublicKey, msg []byte, sig Signature) { + cachingVerifier.AddWithOptions(b.inner, key.key[:], msg, sig.sig[:], verifyOptions) +} - if l := len(pkBytes); l != PubKeySize { - return fmt.Errorf("pubkey size is incorrect; expected: %d, got %d", PubKeySize, l) +// Verify verifies the batched signatures using OS entropy. +// If any signature is invalid, returns ErrBadSig with an index +// of the first invalid signature. +func (b *BatchVerifier) Verify() error { + ok, res := b.inner.Verify(rand.Reader) + if ok { + return nil } - - // check that the signature is the correct length - if len(signature) != SignatureSize { - return errors.New("invalid signature") + for idx, ok := range res { + if !ok { + return ErrBadSig{idx} + } } - - cachingVerifier.AddWithOptions(b.BatchVerifier, ed25519.PublicKey(pkBytes), msg, signature, verifyOptions) - - return nil -} - -func (b *BatchVerifier) Verify() (bool, []bool) { - return b.BatchVerifier.Verify(rand.Reader) -} - -func addressHash(bz []byte) tmbytes.HexBytes { - h := sha256.Sum256(bz) - return tmbytes.HexBytes(h[:20]) + panic("unreachable") } diff --git a/sei-tendermint/crypto/ed25519/ed25519_test.go b/sei-tendermint/crypto/ed25519/ed25519_test.go index a6acafc580..3357e1e652 100644 --- a/sei-tendermint/crypto/ed25519/ed25519_test.go +++ b/sei-tendermint/crypto/ed25519/ed25519_test.go @@ -1,40 +1,33 @@ -package ed25519_test +package ed25519 import ( + "fmt" + "github.com/tendermint/tendermint/libs/utils/require" "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" ) -func TestSignAndValidateEd25519(t *testing.T) { - - privKey := ed25519.GenPrivKey() - pubKey := privKey.PubKey() - - msg := crypto.CRandBytes(128) - sig, err := privKey.Sign(msg) - require.NoError(t, err) - - // Test the signature - assert.True(t, pubKey.VerifySignature(msg, sig)) - - // Mutate the signature, just one bit. - // TODO: Replace this with a much better fuzzer, tendermint/ed25519/issues/10 - sig[7] ^= byte(0x01) - - assert.False(t, pubKey.VerifySignature(msg, sig)) +func TestSign(t *testing.T) { + var keys []SecretKey + for i := range byte(3) { + keys = append(keys, TestSecretKey([]byte{i})) + } + t.Logf("keys = %+v", keys) + msg := []byte("test message") + for i := range keys { + for j := range keys { + if wantErr, err := i != j, keys[j].Public().Verify(msg, keys[i].Sign(msg)); wantErr != (err != nil) { + t.Errorf("keys[%d].Verify(keys[%d].Sign()) = %v, wantErr = %v", j, i, err, wantErr) + } + } + } } func TestBatchSafe(t *testing.T) { - v := ed25519.NewBatchVerifier() + v := NewBatchVerifier() for i := 0; i <= 38; i++ { - priv := ed25519.GenPrivKey() - pub := priv.PubKey() + priv := TestSecretKey(fmt.Appendf(nil, "test-%v", i)) + pub := priv.Public() var msg []byte if i%2 == 0 { @@ -43,13 +36,8 @@ func TestBatchSafe(t *testing.T) { msg = []byte("egg") } - sig, err := priv.Sign(msg) - require.NoError(t, err) - - err = v.Add(pub, msg, sig) - require.NoError(t, err) + v.Add(pub, msg, priv.Sign(msg)) } - ok, _ := v.Verify() - require.True(t, ok) + require.NoError(t, v.Verify()) } diff --git a/sei-tendermint/crypto/ed25519/json.go b/sei-tendermint/crypto/ed25519/json.go new file mode 100644 index 0000000000..d2f8d7a1cc --- /dev/null +++ b/sei-tendermint/crypto/ed25519/json.go @@ -0,0 +1,75 @@ +package ed25519 + +import ( + "encoding/json" + "github.com/tendermint/tendermint/internal/jsontypes" +) + +const SecretKeyName = "tendermint/PrivKeyEd25519" +const PublicKeyName = "tendermint/PubKeyEd25519" +const KeyType = "ed25519" + +func init() { + jsontypes.MustRegister(PublicKey{}) + jsontypes.MustRegister(SecretKey{}) +} + +func (k SecretKey) TypeTag() string { return SecretKeyName } +func (k SecretKey) Type() string { return KeyType } + +func (k PublicKey) TypeTag() string { return PublicKeyName } +func (k PublicKey) Type() string { return KeyType } + +// WARNING: this is very BAD that one can leak a secret by embedding +// a private key in some struct and then calling json.Marshal on it. +// TODO(gprusak): get rid of it. +func (k SecretKey) MarshalJSON() ([]byte, error) { + return json.Marshal((*k.key)[:]) +} + +func (k *SecretKey) UnmarshalJSON(j []byte) error { + var raw []byte + if err := json.Unmarshal(j, &raw); err != nil { + return err + } + x, err := SecretKeyFromSecretBytes(raw) + if err != nil { + return err + } + *k = x + return nil +} + +func (k PublicKey) MarshalJSON() ([]byte, error) { + return json.Marshal(k.Bytes()) +} + +func (k *PublicKey) UnmarshalJSON(j []byte) error { + var raw []byte + if err := json.Unmarshal(j, &raw); err != nil { + return err + } + x, err := PublicKeyFromBytes(raw) + if err != nil { + return err + } + *k = x + return nil +} + +func (s Signature) MarshalJSON() ([]byte, error) { + return json.Marshal(s.Bytes()) +} + +func (s *Signature) UnmarshalJSON(j []byte) error { + var raw []byte + if err := json.Unmarshal(j, &raw); err != nil { + return err + } + x, err := SignatureFromBytes(raw) + if err != nil { + return err + } + *s = x + return nil +} diff --git a/sei-tendermint/crypto/encoding/codec.go b/sei-tendermint/crypto/encoding/codec.go index c5891c4eef..210979e4d6 100644 --- a/sei-tendermint/crypto/encoding/codec.go +++ b/sei-tendermint/crypto/encoding/codec.go @@ -15,26 +15,16 @@ func init() { } // PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey -func PubKeyToProto(k crypto.PubKey) (cryptoproto.PublicKey, error) { - pk := make([]byte, len(k)) - copy(pk, k.Bytes()) - return cryptoproto.PublicKey{ - Sum: &cryptoproto.PublicKey_Ed25519{Ed25519: pk}, - }, nil +func PubKeyToProto(k crypto.PubKey) cryptoproto.PublicKey { + return cryptoproto.PublicKey{Sum: &cryptoproto.PublicKey_Ed25519{Ed25519: k.Bytes()}} } // PubKeyFromProto takes a protobuf Pubkey and transforms it to a crypto.Pubkey func PubKeyFromProto(k cryptoproto.PublicKey) (crypto.PubKey, error) { switch k := k.Sum.(type) { case *cryptoproto.PublicKey_Ed25519: - if len(k.Ed25519) != ed25519.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", - len(k.Ed25519), ed25519.PubKeySize) - } - pk := make(ed25519.PubKey, ed25519.PubKeySize) - copy(pk, k.Ed25519) - return pk, nil + return ed25519.PublicKeyFromBytes(k.Ed25519) default: - return nil, fmt.Errorf("fromproto: key type %v is not supported", k) + return crypto.PubKey{}, fmt.Errorf("fromproto: key type %v is not supported", k) } } diff --git a/sei-tendermint/internal/consensus/common_test.go b/sei-tendermint/internal/consensus/common_test.go index b573a6c627..154a699850 100644 --- a/sei-tendermint/internal/consensus/common_test.go +++ b/sei-tendermint/internal/consensus/common_test.go @@ -21,6 +21,7 @@ import ( "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" cstypes "github.com/tendermint/tendermint/internal/consensus/types" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/mempool" @@ -140,14 +141,16 @@ func (vs *validatorStub) signVote( // ref: signVote in FilePV, the vote should use the previous vote info when the sign data is the same. if signDataIsEqual(vs.lastVote, v) { - v.Signature = vs.lastVote.Signature + sig, ok := vs.lastVote.Signature.Get() + if !ok { + panic("last vote missing signature") + } + v.Signature = sig.Bytes() v.Timestamp = vs.lastVote.Timestamp } - - vote.Signature = v.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) vote.Timestamp = v.Timestamp - - return vote, err + return vote, nil } // Sign vote for type/hash/header @@ -259,9 +262,7 @@ func decideProposal( proposal = types.NewProposal(height, round, polRound, propBlockID, block.Header.Time, block.GetTxKeys(), block.Header, block.LastCommit, block.Evidence, address) p := proposal.ToProto() require.NoError(t, vs.SignProposal(ctx, chainID, p)) - - proposal.Signature = p.Signature - + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) return } diff --git a/sei-tendermint/internal/consensus/invalid_test.go b/sei-tendermint/internal/consensus/invalid_test.go index 257875122b..bfddd6cbd8 100644 --- a/sei-tendermint/internal/consensus/invalid_test.go +++ b/sei-tendermint/internal/consensus/invalid_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/p2p" "github.com/tendermint/tendermint/libs/bytes" @@ -146,8 +147,7 @@ func invalidDoPrevoteFunc( p := precommit.ToProto() require.NoError(t, pv.SignVote(ctx, cs.state.ChainID, p)) - - precommit.Signature = p.Signature + precommit.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(p.Signature))) t.Logf("disable priv val so we don't do normal votes") cs.privValidator = utils.None[types.PrivValidator]() cs.mtx.Unlock() diff --git a/sei-tendermint/internal/consensus/memory_limit_test.go b/sei-tendermint/internal/consensus/memory_limit_test.go index 61e193d8dd..51e7a9f2b6 100644 --- a/sei-tendermint/internal/consensus/memory_limit_test.go +++ b/sei-tendermint/internal/consensus/memory_limit_test.go @@ -5,11 +5,19 @@ import ( "time" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) +var testKey = ed25519.TestSecretKey([]byte("test")) + +func makeSig(data string) crypto.Sig { + return testKey.Sign([]byte(data)) +} + func TestPeerStateMemoryLimits(t *testing.T) { logger := log.NewTestingLogger(t) peerID := types.NodeID("test-peer") @@ -47,7 +55,7 @@ func TestPeerStateMemoryLimits(t *testing.T) { POLRound: -1, BlockID: blockID, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), } ps.SetHasProposal(proposal) if tc.expectError { diff --git a/sei-tendermint/internal/consensus/msgs_test.go b/sei-tendermint/internal/consensus/msgs_test.go index 2c84868824..147e556fcf 100644 --- a/sei-tendermint/internal/consensus/msgs_test.go +++ b/sei-tendermint/internal/consensus/msgs_test.go @@ -69,7 +69,7 @@ func TestMsgToProto(t *testing.T) { POLRound: 1, BlockID: bi, Timestamp: time.Now(), - Signature: tmrand.Bytes(20), + Signature: testKey.Sign([]byte("somedata")), Header: header, Evidence: types.EvidenceList{}, LastCommit: &types.Commit{Signatures: []types.CommitSig{}}, @@ -339,9 +339,10 @@ func TestConsMsgsVectors(t *testing.T) { POLRound: 1, BlockID: bi, Timestamp: date, - Signature: []byte("add_more_exclamation"), } pbProposal := proposal.ToProto() + // We populate the signature with invalid data to match the hash. + pbProposal.Signature = []byte("add_more_exclamation") v := &types.Vote{ ValidatorAddress: []byte("add_more_exclamation"), diff --git a/sei-tendermint/internal/consensus/pbts_test.go b/sei-tendermint/internal/consensus/pbts_test.go index 0ed1dfd9c2..bcec5f43cb 100644 --- a/sei-tendermint/internal/consensus/pbts_test.go +++ b/sei-tendermint/internal/consensus/pbts_test.go @@ -10,11 +10,13 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/abci/example/kvstore" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/eventbus" tmpubsub "github.com/tendermint/tendermint/internal/pubsub" "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" tmtimemocks "github.com/tendermint/tendermint/libs/time/mocks" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -224,7 +226,7 @@ func (p *pbtsTestHarness) nextHeight(ctx context.Context, t *testing.T, proposer } time.Sleep(time.Until(deliverTime)) - prop.Signature = tp.Signature + prop.Signature = utils.OrPanic1(crypto.SigFromBytes(tp.Signature)) if err := p.observedState.SetProposalAndBlock(ctx, prop, b, ps, "peerID"); err != nil { t.Fatal(err) } diff --git a/sei-tendermint/internal/consensus/peer_state_test.go b/sei-tendermint/internal/consensus/peer_state_test.go index 9db8e15b86..24047d4377 100644 --- a/sei-tendermint/internal/consensus/peer_state_test.go +++ b/sei-tendermint/internal/consensus/peer_state_test.go @@ -141,7 +141,7 @@ func TestSetHasProposal(t *testing.T) { Hash: crypto.CRandBytes(crypto.HashSize), }, }, - Signature: []byte("signature"), + Signature: makeSig("signature"), } ps3.SetHasProposal(tooLargeTotalProposal) require.False(t, ps3.PRS.Proposal, "Proposal with too large Total should be silently ignored") @@ -159,7 +159,7 @@ func TestSetHasProposal(t *testing.T) { Hash: crypto.CRandBytes(crypto.HashSize), }, }, - Signature: []byte("signature"), + Signature: makeSig("signature"), } ps.SetHasProposal(validProposal) require.True(t, ps.PRS.Proposal, "Valid proposal should be accepted") @@ -178,7 +178,7 @@ func TestSetHasProposal(t *testing.T) { Hash: crypto.CRandBytes(crypto.HashSize), }, }, - Signature: []byte("signature"), + Signature: makeSig("signature"), } ps2.SetHasProposal(differentProposal) require.True(t, ps2.PRS.Proposal, "Proposal with matching height should be accepted") @@ -193,7 +193,7 @@ func TestSetHasProposalMemoryLimit(t *testing.T) { hash := crypto.CRandBytes(crypto.HashSize) // Create a dummy signature - sig := crypto.CRandBytes(types.MaxSignatureSize) + sig := makeSig("dummy-sig") // Create a proposal with a large PartSetHeader.Total proposal := &types.Proposal{ @@ -349,7 +349,7 @@ func TestSetHasProposalEdgeCases(t *testing.T) { }, }, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), }, expectProposal: false, // Should silently ignore expectPanic: false, @@ -373,7 +373,7 @@ func TestSetHasProposalEdgeCases(t *testing.T) { }, }, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), }, expectProposal: false, expectPanic: false, @@ -398,7 +398,7 @@ func TestSetHasProposalEdgeCases(t *testing.T) { }, }, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), }, expectProposal: true, // Should remain true expectPanic: false, @@ -422,7 +422,7 @@ func TestSetHasProposalEdgeCases(t *testing.T) { }, }, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), }, expectProposal: true, // Should be set expectPanic: false, diff --git a/sei-tendermint/internal/consensus/reactor_test.go b/sei-tendermint/internal/consensus/reactor_test.go index d3eb9db4c8..0e75cfc5cd 100644 --- a/sei-tendermint/internal/consensus/reactor_test.go +++ b/sei-tendermint/internal/consensus/reactor_test.go @@ -501,8 +501,7 @@ func TestReactorValidatorSetChanges(t *testing.T) { pv, _ := states[nodeIdx].privValidator.Get() key, err := pv.GetPubKey(ctx) require.NoError(t, err) - keyProto, err := encoding.PubKeyToProto(key) - require.NoError(t, err) + keyProto := encoding.PubKeyToProto(key) newPower := int64(rng.Intn(100000)) tx := kvstore.MakeValSetChangeTx(keyProto, newPower) require.NoError(t, finalizeTx(ctx, valSet, blocksSubs, states, tx)) @@ -537,7 +536,7 @@ func TestReactorMemoryLimitCoverage(t *testing.T) { }, }, Timestamp: time.Now(), - Signature: []byte("test-signature"), + Signature: makeSig("test-signature"), } // Test direct SetHasProposal call (this is what reactor calls) diff --git a/sei-tendermint/internal/consensus/replay_test.go b/sei-tendermint/internal/consensus/replay_test.go index 12c2b7ca5a..a63ea8a2f3 100644 --- a/sei-tendermint/internal/consensus/replay_test.go +++ b/sei-tendermint/internal/consensus/replay_test.go @@ -20,6 +20,7 @@ import ( "github.com/tendermint/tendermint/abci/example/kvstore" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/mempool" @@ -342,8 +343,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { pv, _ := css[nVals].privValidator.Get() newValidatorPubKey1, err := pv.GetPubKey(ctx) require.NoError(t, err) - valPubKey1ABCI, err := encoding.PubKeyToProto(newValidatorPubKey1) - require.NoError(t, err) + valPubKey1ABCI := encoding.PubKeyToProto(newValidatorPubKey1) newValidatorTx1 := kvstore.MakeValSetChangeTx(valPubKey1ABCI, testMinPower) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, newValidatorTx1, nil, mempool.TxInfo{}) assert.NoError(t, err) @@ -360,7 +360,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { if err := vss[1].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // set the proposal block if err := css[0].SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -379,8 +379,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { pv, _ = css[nVals].privValidator.Get() updateValidatorPubKey1, err := pv.GetPubKey(ctx) require.NoError(t, err) - updatePubKey1ABCI, err := encoding.PubKeyToProto(updateValidatorPubKey1) - require.NoError(t, err) + updatePubKey1ABCI := encoding.PubKeyToProto(updateValidatorPubKey1) updateValidatorTx1 := kvstore.MakeValSetChangeTx(updatePubKey1ABCI, 25) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, updateValidatorTx1, nil, mempool.TxInfo{}) assert.NoError(t, err) @@ -396,7 +395,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { if err := vss[2].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // set the proposal block if err := css[0].SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -415,16 +414,14 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { pv, _ = css[nVals+1].privValidator.Get() newValidatorPubKey2, err := pv.GetPubKey(ctx) require.NoError(t, err) - newVal2ABCI, err := encoding.PubKeyToProto(newValidatorPubKey2) - require.NoError(t, err) + newVal2ABCI := encoding.PubKeyToProto(newValidatorPubKey2) newValidatorTx2 := kvstore.MakeValSetChangeTx(newVal2ABCI, testMinPower) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, newValidatorTx2, nil, mempool.TxInfo{}) assert.NoError(t, err) pv, _ = css[nVals+2].privValidator.Get() newValidatorPubKey3, err := pv.GetPubKey(ctx) require.NoError(t, err) - newVal3ABCI, err := encoding.PubKeyToProto(newValidatorPubKey3) - require.NoError(t, err) + newVal3ABCI := encoding.PubKeyToProto(newValidatorPubKey3) newValidatorTx3 := kvstore.MakeValSetChangeTx(newVal3ABCI, testMinPower) err = assertMempool(t, css[0].txNotifier).CheckTx(ctx, newValidatorTx3, nil, mempool.TxInfo{}) assert.NoError(t, err) @@ -446,7 +443,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { cssPubKey, err := pv.GetPubKey(ctx) require.NoError(t, err) - if vsPubKey.Equals(cssPubKey) { + if vsPubKey == cssPubKey { return i } } @@ -463,7 +460,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { if err := vss[3].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // set the proposal block if err := css[0].SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer"); err != nil { @@ -536,7 +533,7 @@ func setupSimulator(ctx context.Context, t *testing.T) *simulatorTestSuite { if err := vss[1].SignProposal(ctx, cfg.ChainID(), p); err != nil { t.Fatal("failed to sign bad proposal", err) } - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // set the proposal block if err := css[0].SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer"); err != nil { diff --git a/sei-tendermint/internal/consensus/state.go b/sei-tendermint/internal/consensus/state.go index f34d043ada..08fcd36353 100644 --- a/sei-tendermint/internal/consensus/state.go +++ b/sei-tendermint/internal/consensus/state.go @@ -1268,7 +1268,12 @@ func (cs *State) decideProposal(ctx context.Context, height int64, round int32, ctxto, cancel := context.WithTimeout(ctx, cs.state.ConsensusParams.Timeout.Propose) defer cancel() if err := privValidator.SignProposal(ctxto, cs.state.ChainID, p); err == nil { - proposal.Signature = p.Signature + sig, err := crypto.SigFromBytes(p.Signature) + if err != nil { + cs.logger.Error("propose step; failed signing proposal", "height", height, "round", round, "err", err) + return + } + proposal.Signature = sig // send proposal and block parts on internal msg queue cs.sendInternalMessage(ctx, msgInfo{&ProposalMessage{proposal}, "", tmtime.Now()}) @@ -2147,13 +2152,11 @@ func (cs *State) defaultSetProposal(proposal *types.Proposal, recvTime time.Time p := proposal.ToProto() // Verify signature - if !cs.roundState.Validators().GetProposer().PubKey.VerifySignature( + if err := cs.roundState.Validators().GetProposer().PubKey.Verify( types.ProposalSignBytes(cs.state.ChainID, p), proposal.Signature, - ) { + ); err != nil { return ErrInvalidProposalSignature } - - proposal.Signature = p.Signature cs.roundState.SetProposal(proposal) cs.roundState.SetProposalReceiveTime(recvTime) cs.calculateProposalTimestampDifferenceMetric() @@ -2611,11 +2614,17 @@ func (cs *State) signVote( ctxto, cancel := context.WithTimeout(ctx, timeout) defer cancel() - err := privValidator.SignVote(ctxto, cs.state.ChainID, v) - vote.Signature = v.Signature + if err := privValidator.SignVote(ctxto, cs.state.ChainID, v); err != nil { + return nil, err + } + sig, err := crypto.SigFromBytes(v.Signature) + if err != nil { + return nil, fmt.Errorf("crypto.SigFromBytes(): %w", err) + } + vote.Signature = utils.Some(sig) vote.Timestamp = v.Timestamp - return vote, err + return vote, nil } // sign the vote and publish on internalMsgQueue diff --git a/sei-tendermint/internal/consensus/state_test.go b/sei-tendermint/internal/consensus/state_test.go index 63afd5a44c..f946a478e1 100644 --- a/sei-tendermint/internal/consensus/state_test.go +++ b/sei-tendermint/internal/consensus/state_test.go @@ -250,10 +250,8 @@ func TestStateBadProposal(t *testing.T) { require.NoError(t, err) proposal := types.NewProposal(vs2.Height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) p := proposal.ToProto() - err = vs2.SignProposal(ctx, config.ChainID(), p) - require.NoError(t, err) - - proposal.Signature = p.Signature + require.NoError(t, vs2.SignProposal(ctx, config.ChainID(), p)) + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // set the proposal block err = cs1.SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer") @@ -308,9 +306,8 @@ func TestStateOversizedBlock(t *testing.T) { require.NoError(t, err) proposal := types.NewProposal(height, round, -1, blockID, propBlock.Header.Time, propBlock.GetTxKeys(), propBlock.Header, propBlock.LastCommit, propBlock.Evidence, pubKey.Address()) p := proposal.ToProto() - err = vs2.SignProposal(ctx, config.ChainID(), p) - require.NoError(t, err) - proposal.Signature = p.Signature + require.NoError(t, vs2.SignProposal(ctx, config.ChainID(), p)) + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) totalBytes := 0 for i := 0; i < int(propBlockParts.Total()); i++ { @@ -808,9 +805,9 @@ func TestStateLock_POLRelock(t *testing.T) { require.NoError(t, err) propR1 := types.NewProposal(height, round, cs1.roundState.ValidRound(), blockID, theBlock.Header.Time, theBlock.GetTxKeys(), theBlock.Header, theBlock.LastCommit, theBlock.Evidence, pubKey.Address()) p := propR1.ToProto() - err = vs2.SignProposal(ctx, cs1.state.ChainID, p) - require.NoError(t, err) - propR1.Signature = p.Signature + require.NoError(t, vs2.SignProposal(ctx, cs1.state.ChainID, p)) + propR1.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) + err = cs1.SetProposalAndBlock(ctx, propR1, theBlock, theBlockParts, "") require.NoError(t, err) @@ -1488,7 +1485,7 @@ func TestStateLock_POLSafety2(t *testing.T) { err = vs3.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) - newProp.Signature = p.Signature + newProp.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) err = cs1.SetProposalAndBlock(ctx, newProp, propBlock0, propBlockParts0, "some peer") require.NoError(t, err) @@ -1625,7 +1622,7 @@ func TestState_PrevotePOLFromPreviousRound(t *testing.T) { p := propR2.ToProto() err = vs3.SignProposal(ctx, cs1.state.ChainID, p) require.NoError(t, err) - propR2.Signature = p.Signature + propR2.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // cs1 receives a proposal for D, the block that received a POL in round 1. err = cs1.SetProposalAndBlock(ctx, propR2, propBlockR1, propBlockR1Parts, "") @@ -2439,7 +2436,7 @@ func TestGossipTransactionKeyOnlyConfig(t *testing.T) { p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) proposalMsg := ProposalMessage{&proposal} peerID, err := types.NewNodeID("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") @@ -2554,7 +2551,7 @@ func TestStateTimestamp_ProposalNotMatch(t *testing.T) { p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) require.NoError(t, cs1.SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer")) startTestRound(ctx, cs1, height, round) @@ -2601,7 +2598,7 @@ func TestStateTimestamp_ProposalMatch(t *testing.T) { p := proposal.ToProto() err = vs2.SignProposal(ctx, config.ChainID(), p) require.NoError(t, err) - proposal.Signature = p.Signature + proposal.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) require.NoError(t, cs1.SetProposalAndBlock(ctx, proposal, propBlock, propBlockParts, "some peer")) startTestRound(ctx, cs1, height, round) diff --git a/sei-tendermint/internal/consensus/types/height_vote_set_test.go b/sei-tendermint/internal/consensus/types/height_vote_set_test.go index 38a65bec6d..b7ce709aff 100644 --- a/sei-tendermint/internal/consensus/types/height_vote_set_test.go +++ b/sei-tendermint/internal/consensus/types/height_vote_set_test.go @@ -11,6 +11,7 @@ import ( "github.com/tendermint/tendermint/internal/test/factory" tmrand "github.com/tendermint/tendermint/libs/rand" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -83,10 +84,7 @@ func makeVoteHR( } v := vote.ToProto() - err = privVal.SignVote(ctx, chainID, v) - require.NoError(t, err, "Error signing vote") - - vote.Signature = v.Signature - + require.NoError(t, privVal.SignVote(ctx, chainID, v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) return vote } diff --git a/sei-tendermint/internal/evidence/pool_test.go b/sei-tendermint/internal/evidence/pool_test.go index 9eb2612bd2..bc01a5a61c 100644 --- a/sei-tendermint/internal/evidence/pool_test.go +++ b/sei-tendermint/internal/evidence/pool_test.go @@ -11,6 +11,8 @@ import ( dbm "github.com/tendermint/tm-db" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/internal/eventbus" "github.com/tendermint/tendermint/internal/evidence" "github.com/tendermint/tendermint/internal/evidence/mocks" @@ -20,6 +22,7 @@ import ( "github.com/tendermint/tendermint/internal/store" "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/version" @@ -34,6 +37,12 @@ var ( defaultEvidenceMaxBytes int64 = 1000 ) +var testKey = ed25519.TestSecretKey([]byte("test")) + +func makeEvidenceSignature(data []byte) crypto.Sig { + return testKey.Sign(data) +} + func startPool(t *testing.T, pool *evidence.Pool, store sm.Store) { t.Helper() state, err := store.Load() @@ -174,7 +183,7 @@ func TestReportConflictingVotes(t *testing.T) { pool, pv, _ := defaultTestPool(ctx, t, height) - val := types.NewValidator(pv.PrivKey.PubKey(), 10) + val := types.NewValidator(pv.PrivKey.Public(), 10) ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, height+1, defaultEvidenceTime, pv, evidenceChainID) require.NoError(t, err) @@ -243,7 +252,7 @@ func TestEvidencePoolUpdate(t *testing.T) { evidenceChainID, ) require.NoError(t, err) - lastCommit := makeCommit(height, val.PrivKey.PubKey().Address()) + lastCommit := makeCommit(height, val.PrivKey.Public().Address()) block := types.MakeBlock(height+1, []types.Tx{}, lastCommit, []types.Evidence{ev}) // update state (partially) @@ -437,7 +446,7 @@ func TestRecoverPendingEvidence(t *testing.T) { height := int64(10) val := types.NewMockPV() - valAddress := val.PrivKey.PubKey().Address() + valAddress := val.PrivKey.Public().Address() evidenceDB := dbm.NewMemDB() stateStore := initializeValidatorState(ctx, t, val, height) @@ -582,7 +591,7 @@ func makeCommit(height int64, valAddr []byte) *types.Commit { BlockIDFlag: types.BlockIDFlagCommit, ValidatorAddress: valAddr, Timestamp: defaultEvidenceTime, - Signature: []byte("Signature"), + Signature: utils.Some(makeEvidenceSignature([]byte("Signature"))), }}, } } @@ -590,7 +599,7 @@ func makeCommit(height int64, valAddr []byte) *types.Commit { func defaultTestPool(ctx context.Context, t *testing.T, height int64) (*evidence.Pool, types.MockPV, *eventbus.EventBus) { t.Helper() val := types.NewMockPV() - valAddress := val.PrivKey.PubKey().Address() + valAddress := val.PrivKey.Public().Address() evidenceDB := dbm.NewMemDB() stateStore := initializeValidatorState(ctx, t, val, height) state, err := stateStore.Load() diff --git a/sei-tendermint/internal/evidence/verify.go b/sei-tendermint/internal/evidence/verify.go index 9e8f87e65d..bc81c0f237 100644 --- a/sei-tendermint/internal/evidence/verify.go +++ b/sei-tendermint/internal/evidence/verify.go @@ -243,10 +243,18 @@ func VerifyDuplicateVote(e *types.DuplicateVoteEvidence, chainID string, valSet va := e.VoteA.ToProto() vb := e.VoteB.ToProto() // Signatures must be valid - if !pubKey.VerifySignature(types.VoteSignBytes(chainID, va), e.VoteA.Signature) { + sigA, ok := e.VoteA.Signature.Get() + if !ok { + return errors.New("VoteA.Signature missing") + } + sigB, ok := e.VoteB.Signature.Get() + if !ok { + return errors.New("VoteB.Signature missing") + } + if err := pubKey.Verify(types.VoteSignBytes(chainID, va), sigA); err != nil { return fmt.Errorf("verifying VoteA: %w", types.ErrVoteInvalidSignature) } - if !pubKey.VerifySignature(types.VoteSignBytes(chainID, vb), e.VoteB.Signature) { + if err := pubKey.Verify(types.VoteSignBytes(chainID, vb), sigB); err != nil { return fmt.Errorf("verifying VoteB: %w", types.ErrVoteInvalidSignature) } diff --git a/sei-tendermint/internal/evidence/verify_test.go b/sei-tendermint/internal/evidence/verify_test.go index d4751c9c6f..4cb0300607 100644 --- a/sei-tendermint/internal/evidence/verify_test.go +++ b/sei-tendermint/internal/evidence/verify_test.go @@ -18,6 +18,7 @@ import ( smmocks "github.com/tendermint/tendermint/internal/state/mocks" "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -421,8 +422,8 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { err = val2.SignVote(ctx, chainID, bv) require.NoError(t, err) - vote1.Signature = v1.Signature - badVote.Signature = bv.Signature + vote1.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v1.Signature))) + badVote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(bv.Signature))) cases := []voteData{ {vote1, makeVote(ctx, t, val, chainID, 0, 10, 2, 1, blockID2, defaultEvidenceTime), true}, // different block ids @@ -605,7 +606,7 @@ func makeVote( vpb := v.ToProto() err = val.SignVote(ctx, chainID, vpb) require.NoError(t, err) - v.Signature = vpb.Signature + v.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(vpb.Signature))) return v } diff --git a/sei-tendermint/internal/jsontypes/jsontypes.go b/sei-tendermint/internal/jsontypes/jsontypes.go index c10fcb6990..2f8179b86a 100644 --- a/sei-tendermint/internal/jsontypes/jsontypes.go +++ b/sei-tendermint/internal/jsontypes/jsontypes.go @@ -78,7 +78,7 @@ func Marshal(v Tagged) ([]byte, error) { func Unmarshal(data []byte, v any) error { // Verify that the target is some kind of pointer. target := reflect.ValueOf(v) - if target.Kind() != reflect.Ptr { + if target.Kind() != reflect.Pointer { return fmt.Errorf("target %T is not a pointer", v) } else if target.IsZero() { return fmt.Errorf("target is a nil %T", v) @@ -101,7 +101,7 @@ func Unmarshal(data []byte, v any) error { } if typ.AssignableTo(baseType) { // ok: registered type is directly assignable to the target - } else if typ.Kind() == reflect.Ptr && typ.Elem().AssignableTo(baseType) { + } else if typ.Kind() == reflect.Pointer && typ.Elem().AssignableTo(baseType) { typ = typ.Elem() // ok: registered type is a pointer to a value assignable to the target } else { diff --git a/sei-tendermint/internal/libs/wal/log_test.go b/sei-tendermint/internal/libs/wal/log_test.go index 55666fda71..41e4211b64 100644 --- a/sei-tendermint/internal/libs/wal/log_test.go +++ b/sei-tendermint/internal/libs/wal/log_test.go @@ -11,23 +11,10 @@ import ( "github.com/tendermint/tendermint/libs/utils/require" ) -func OrPanic(err error) { - if err != nil { - panic(err) - } -} - -func OrPanic1[T any](v T, err error) T { - if err != nil { - panic(err) - } - return v -} - func dump(l *Log) [][]byte { var entries [][]byte for offset := l.MinOffset(); offset <= 0; offset++ { - entries = append(entries, OrPanic1(l.ReadFile(offset))...) + entries = append(entries, utils.OrPanic1(l.ReadFile(offset))...) } return entries } @@ -36,7 +23,7 @@ func TestReadAfterAppend(t *testing.T) { headPath := path.Join(t.TempDir(), "testlog") cfg := &Config{} entry := []byte{25} - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() // Append minimal amount of data. require.NoError(t, l.Append(entry)) @@ -52,7 +39,7 @@ func TestAppendRead(t *testing.T) { cfg := &Config{FileSizeLimit: 1000} var want [][]byte t.Logf("Open a log") - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) // Wrapped defer, since we assign to l multiple times. defer func() { l.Close() }() @@ -60,7 +47,7 @@ func TestAppendRead(t *testing.T) { t.Logf("ITERATION %v", it) if reopen { l.Close() - l = OrPanic1(OpenLog(headPath, cfg)) + l = utils.OrPanic1(OpenLog(headPath, cfg)) } t.Logf("Opening a log again should fail - previous instance holds a lock on it.") _, err := OpenLog(headPath, cfg) @@ -77,7 +64,7 @@ func TestAppendRead(t *testing.T) { t.Logf("Read entries.") if reopen { l.Close() - l = OrPanic1(OpenLog(headPath, cfg)) + l = utils.OrPanic1(OpenLog(headPath, cfg)) } require.NoError(t, utils.TestDiff(want, dump(l))) } @@ -90,7 +77,7 @@ func TestNoSync(t *testing.T) { headPath := path.Join(t.TempDir(), "testlog") cfg := &Config{FileSizeLimit: 1000} - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() // Insert entries and sync in the middle. var want [][]byte @@ -106,7 +93,7 @@ func TestNoSync(t *testing.T) { l.Close() // Read Entries - expect entries at least to the sync point. - l = OrPanic1(OpenLog(headPath, cfg)) + l = utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() got := dump(l) require.True(t, len(got) >= syncEntries) @@ -119,7 +106,7 @@ func TestTruncation(t *testing.T) { cfg := &Config{FileSizeLimit: 1000} // Insert entries. - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() var want [][]byte for range 100 { @@ -136,7 +123,7 @@ func TestTruncation(t *testing.T) { require.NoError(t, os.Truncate(headPath, fi.Size()/2)) // Read Entries - expect a prefix. - l = OrPanic1(OpenLog(headPath, cfg)) + l = utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() got := dump(l) require.NoError(t, utils.TestDiff(want[:len(got)], got)) @@ -150,7 +137,7 @@ func TestSizeLimitsAndOffsets(t *testing.T) { cfg := &Config{FileSizeLimit: 100, TotalSizeLimit: 3000} // Populate the log. - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() minEntrySize := int64(10) maxEntrySize := int64(20) @@ -185,7 +172,7 @@ func TestSizeLimitsAndOffsets(t *testing.T) { require.True(t, total >= cfg.TotalSizeLimit-cfg.FileSizeLimit-maxEntrySize-headerSize) // Read the log, expect a suffix of entries. - l = OrPanic1(OpenLog(headPath, cfg)) + l = utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() got := dump(l) require.NoError(t, utils.TestDiff(want[len(want)-len(got):], got)) @@ -202,10 +189,10 @@ func BenchmarkAppendSync(b *testing.B) { for range 10000 { entries = append(entries, utils.GenBytes(rng, rng.Intn(100)+1000)) } - l := OrPanic1(OpenLog(headPath, cfg)) + l := utils.OrPanic1(OpenLog(headPath, cfg)) defer l.Close() for i := 0; b.Loop(); i++ { - OrPanic(l.Append(entries[i%len(entries)])) - OrPanic(l.Sync()) + utils.OrPanic(l.Append(entries[i%len(entries)])) + utils.OrPanic(l.Sync()) } } diff --git a/sei-tendermint/internal/mempool/reactor_test.go b/sei-tendermint/internal/mempool/reactor_test.go index 262c1f4a69..7f9eb1ccf3 100644 --- a/sei-tendermint/internal/mempool/reactor_test.go +++ b/sei-tendermint/internal/mempool/reactor_test.go @@ -326,8 +326,8 @@ func TestDontExhaustMaxActiveIDs(t *testing.T) { // ensure the reactor does not panic (i.e. exhaust active IDs) for range MaxActiveIDs + 1 { - privKey := ed25519.GenPrivKey() - peerID := types.NodeIDFromPubKey(privKey.PubKey()) + privKey := ed25519.GenerateSecretKey() + peerID := types.NodeIDFromPubKey(privKey.Public()) rts.reactors[nodeID].processPeerUpdate(ctx, p2p.PeerUpdate{ Status: p2p.PeerStatusUp, NodeID: peerID, diff --git a/sei-tendermint/internal/p2p/address_test.go b/sei-tendermint/internal/p2p/address_test.go index d1a6dccb3b..6a522545a3 100644 --- a/sei-tendermint/internal/p2p/address_test.go +++ b/sei-tendermint/internal/p2p/address_test.go @@ -38,9 +38,8 @@ func TestNewNodeID(t *testing.T) { } func TestNewNodeIDFromPubKey(t *testing.T) { - privKey := ed25519.GenPrivKeyFromSecret([]byte("foo")) - nodeID := types.NodeIDFromPubKey(privKey.PubKey()) - require.Equal(t, types.NodeID("045f5600654182cfeaccfe6cb19f0642e8a59898"), nodeID) + privKey := ed25519.TestSecretKey([]byte{43, 55, 33}) + nodeID := types.NodeIDFromPubKey(privKey.Public()) require.NoError(t, nodeID.Validate()) } diff --git a/sei-tendermint/internal/p2p/conn/evil_secret_connection_test.go b/sei-tendermint/internal/p2p/conn/evil_secret_connection_test.go index 3ad61bb1ca..0c5b68daf9 100644 --- a/sei-tendermint/internal/p2p/conn/evil_secret_connection_test.go +++ b/sei-tendermint/internal/p2p/conn/evil_secret_connection_test.go @@ -58,7 +58,7 @@ type evilConn struct { } func newEvilConn(shareEphKey, badEphKey, shareAuthSignature, badAuthSignature bool) *evilConn { - privKey := ed25519.GenPrivKey() + privKey := ed25519.GenerateSecretKey() locEphPub, locEphPriv := genEphKeys() var rep [32]byte c := &evilConn{ @@ -113,11 +113,8 @@ func (c *evilConn) Read(data []byte) (n int, err error) { case 1: signature := c.signChallenge() if !c.badAuthSignature { - pkpb, err := encoding.PubKeyToProto(c.privKey.PubKey()) - if err != nil { - panic(err) - } - bz, err := protoio.MarshalDelimited(&tmp2p.AuthSigMessage{PubKey: pkpb, Sig: signature}) + pkpb := encoding.PubKeyToProto(c.privKey.Public()) + bz, err := protoio.MarshalDelimited(&tmp2p.AuthSigMessage{PubKey: pkpb, Sig: signature.Bytes()}) if err != nil { panic(err) } @@ -180,7 +177,7 @@ func (c *evilConn) Close() error { return nil } -func (c *evilConn) signChallenge() []byte { +func (c *evilConn) signChallenge() ed25519.Signature { // Sort by lexical order. loEphPub, hiEphPub := sort32(c.locEphPub, c.remEphPub) @@ -231,12 +228,7 @@ func (c *evilConn) signChallenge() []byte { c.buffer = b // Sign the challenge bytes for authentication. - locSignature, err := signChallenge(&challenge, c.privKey) - if err != nil { - panic(err) - } - - return locSignature + return signChallenge(&challenge, c.privKey) } // TestMakeSecretConnection creates an evil connection and tests that @@ -256,7 +248,7 @@ func TestMakeSecretConnection(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - privKey := ed25519.GenPrivKey() + privKey := ed25519.GenerateSecretKey() _, err := MakeSecretConnection(tc.conn, privKey) if tc.errMsg != "" { if assert.Error(t, err) { diff --git a/sei-tendermint/internal/p2p/conn/secret_connection.go b/sei-tendermint/internal/p2p/conn/secret_connection.go index e147d13066..5988976ed9 100644 --- a/sei-tendermint/internal/p2p/conn/secret_connection.go +++ b/sei-tendermint/internal/p2p/conn/secret_connection.go @@ -65,7 +65,7 @@ type SecretConnection struct { recvAead cipher.AEAD sendAead cipher.AEAD - remPubKey ed25519.PubKey + remPubKey ed25519.PublicKey conn io.ReadWriteCloser // net.Conn must be thread safe: @@ -88,10 +88,8 @@ type SecretConnection struct { // Returns nil if there is an error in handshake. // Caller should call conn.Close() // See docs/sts-final.pdf for more information. -func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) (*SecretConnection, error) { - var ( - locPubKey = locPrivKey.PubKey() - ) +func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.SecretKey) (*SecretConnection, error) { + locPubKey := locPrivKey.Public() // Generate ephemeral keys for perfect forward secrecy. locEphPub, locEphPriv := genEphKeys() @@ -152,10 +150,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( } // Sign the challenge bytes for authentication. - locSignature, err := signChallenge(&challenge, locPrivKey) - if err != nil { - return nil, err - } + locSignature := signChallenge(&challenge, locPrivKey) // Share (in secret) each other's pubkey & challenge signature authSigMsg, err := shareAuthSignature(sc, locPubKey, locSignature) @@ -165,8 +160,8 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig - if !remPubKey.VerifySignature(challenge[:], remSignature) { - return nil, errors.New("challenge verification failed") + if err := remPubKey.Verify(challenge[:], remSignature); err != nil { + return nil, fmt.Errorf("challenge verification failed: %w", err) } // We've authorized. @@ -175,7 +170,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( } // RemotePubKey returns authenticated remote pubkey -func (sc *SecretConnection) RemotePubKey() ed25519.PubKey { +func (sc *SecretConnection) RemotePubKey() ed25519.PublicKey { return sc.remPubKey } @@ -297,7 +292,7 @@ func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byt // Send our pubkey and receive theirs in tandem. var trs, _ = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { lc := *locEphPub _, err = protoio.NewDelimitedWriter(conn).WriteMsg(&gogotypes.BytesValue{Value: lc[:]}) if err != nil { @@ -305,7 +300,7 @@ func shareEphPubKey(conn io.ReadWriter, locEphPub *[32]byte) (remEphPub *[32]byt } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { var bytes gogotypes.BytesValue _, err = protoio.NewDelimitedReader(conn, 1024*1024).ReadMsg(&bytes) if err != nil { @@ -383,55 +378,45 @@ func sort32(foo, bar *[32]byte) (lo, hi *[32]byte) { return } -func signChallenge(challenge *[32]byte, locPrivKey ed25519.PrivKey) ([]byte, error) { - signature, err := locPrivKey.Sign(challenge[:]) - if err != nil { - return nil, err - } - return signature, nil +func signChallenge(challenge *[32]byte, locPrivKey ed25519.SecretKey) ed25519.Signature { + return locPrivKey.Sign(challenge[:]) } type authSigMessage struct { - Key ed25519.PubKey - Sig []byte + Key ed25519.PublicKey + Sig ed25519.Signature } -func shareAuthSignature(sc io.ReadWriter, pubKey ed25519.PubKey, signature []byte) (recvMsg authSigMessage, err error) { - +func shareAuthSignature(sc io.ReadWriter, pubKey ed25519.PublicKey, sig ed25519.Signature) (authSigMessage, error) { // Send our info and receive theirs in tandem. var trs, _ = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { - pk := tmproto.PublicKey{Sum: &tmproto.PublicKey_Ed25519{Ed25519: pubKey}} - _, err = protoio.NewDelimitedWriter(sc).WriteMsg(&tmp2p.AuthSigMessage{PubKey: pk, Sig: signature}) - if err != nil { - return nil, true, err // abort + func(_ int) (val any, abort bool, err error) { + pk := tmproto.PublicKey{Sum: &tmproto.PublicKey_Ed25519{Ed25519: pubKey.Bytes()}} + if _, err := protoio.NewDelimitedWriter(sc).WriteMsg(&tmp2p.AuthSigMessage{PubKey: pk, Sig: sig.Bytes()}); err != nil { + return nil, true, err } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { var pba tmp2p.AuthSigMessage - _, err = protoio.NewDelimitedReader(sc, 1024*1024).ReadMsg(&pba) - if err != nil { - return nil, true, err // abort + if _, err := protoio.NewDelimitedReader(sc, 1024*1024).ReadMsg(&pba); err != nil { + return nil, true, err } - - pk := pba.PubKey.GetEd25519() - if len(pk) != ed25519.PubKeySize { - return nil, true, fmt.Errorf("invalid ed25519 key size") + key, err := ed25519.PublicKeyFromBytes(pba.PubKey.GetEd25519()) + if err != nil { + return nil, true, fmt.Errorf("ed25519.PublicKeyFromBytes(): %w", err) } - - _recvMsg := authSigMessage{ - Key: ed25519.PubKey(pk), - Sig: pba.Sig, + sig, err := ed25519.SignatureFromBytes(pba.Sig) + if err != nil { + return nil, true, fmt.Errorf("ed25519.SignatureFromBytes(): %w", err) } - return _recvMsg, false, nil + return authSigMessage{Key: key, Sig: sig}, false, nil }, ) // If error: if trs.FirstError() != nil { - err = trs.FirstError() - return + return authSigMessage{}, trs.FirstError() } var _recvMsg = trs.FirstValue().(authSigMessage) diff --git a/sei-tendermint/internal/p2p/conn/secret_connection_test.go b/sei-tendermint/internal/p2p/conn/secret_connection_test.go index 42589702ff..032b75bcfe 100644 --- a/sei-tendermint/internal/p2p/conn/secret_connection_test.go +++ b/sei-tendermint/internal/p2p/conn/secret_connection_test.go @@ -110,7 +110,7 @@ func TestSecretConnectionReadWrite(t *testing.T) { genNodeRunner := func(id string, nodeConn kvstoreConn, nodeWrites []string, nodeReads *[]string) async.Task { return func(_ int) (interface{}, bool, error) { // Initiate cryptographic private key and secret connection trhough nodeConn. - nodePrvKey := ed25519.GenPrivKey() + nodePrvKey := ed25519.GenerateSecretKey() nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey) if err != nil { t.Errorf("failed to establish SecretConnection for node: %v", err) @@ -293,10 +293,10 @@ func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) { var ( fooConn, barConn = makeKVStoreConnPair() - fooPrvKey = ed25519.GenPrivKey() - fooPubKey = fooPrvKey.PubKey() - barPrvKey = ed25519.GenPrivKey() - barPubKey = barPrvKey.PubKey() + fooPrvKey = ed25519.GenerateSecretKey() + fooPubKey = fooPrvKey.Public() + barPrvKey = ed25519.GenerateSecretKey() + barPubKey = barPrvKey.Public() ) // Make connections from both sides in parallel. @@ -307,10 +307,10 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection tb.Errorf("failed to establish SecretConnection for foo: %v", err) return nil, true, err } - remotePubBytes := fooSecConn.RemotePubKey() - if !remotePubBytes.Equals(barPubKey) { + remotePubKey := fooSecConn.RemotePubKey() + if remotePubKey != barPubKey { err = fmt.Errorf("unexpected fooSecConn.RemotePubKey. Expected %v, got %v", - barPubKey, fooSecConn.RemotePubKey()) + barPubKey, remotePubKey) tb.Error(err) return nil, true, err } @@ -322,10 +322,10 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection tb.Errorf("failed to establish SecretConnection for bar: %v", err) return nil, true, err } - remotePubBytes := barSecConn.RemotePubKey() - if !remotePubBytes.Equals(fooPubKey) { + remotePubKey := barSecConn.RemotePubKey() + if remotePubKey != fooPubKey { err = fmt.Errorf("unexpected barSecConn.RemotePubKey. Expected %v, got %v", - fooPubKey, barSecConn.RemotePubKey()) + fooPubKey, remotePubKey) tb.Error(err) return nil, true, err } diff --git a/sei-tendermint/internal/p2p/peermanager_test.go b/sei-tendermint/internal/p2p/peermanager_test.go index f26f5e1719..22f3f2527a 100644 --- a/sei-tendermint/internal/p2p/peermanager_test.go +++ b/sei-tendermint/internal/p2p/peermanager_test.go @@ -55,14 +55,14 @@ func makePeerManager(selfID types.NodeID, options *RouterOptions) *peerManager[* return newPeerManager[*fakeConn](selfID, options) } -var selfID = types.NodeIDFromPubKey(ed25519.GenPrivKeyFromSecret([]byte("selfID")).PubKey()) +var selfID = types.NodeIDFromPubKey(ed25519.TestSecretKey([]byte{12, 43}).Public()) -func makeKey(rng utils.Rng) ed25519.PrivKey { - return ed25519.GenPrivKeyFromSecret(utils.GenBytes(rng, 32)) +func makeKey(rng utils.Rng) ed25519.SecretKey { + return ed25519.TestSecretKey(utils.GenBytes(rng, 32)) } func makeNodeID(rng utils.Rng) types.NodeID { - return types.NodeIDFromPubKey(makeKey(rng).PubKey()) + return types.NodeIDFromPubKey(makeKey(rng).Public()) } func makeAddrFor(rng utils.Rng, id types.NodeID) NodeAddress { diff --git a/sei-tendermint/internal/p2p/pex/reactor_test.go b/sei-tendermint/internal/p2p/pex/reactor_test.go index bc3e3fd7e3..eebd954b2e 100644 --- a/sei-tendermint/internal/p2p/pex/reactor_test.go +++ b/sei-tendermint/internal/p2p/pex/reactor_test.go @@ -521,5 +521,5 @@ func (r *reactorTestSuite) addAddresses(t *testing.T, node int, addrIDs []int) { } func randomNodeID() types.NodeID { - return types.NodeIDFromPubKey(ed25519.GenPrivKey().PubKey()) + return types.NodeIDFromPubKey(ed25519.GenerateSecretKey().Public()) } diff --git a/sei-tendermint/internal/p2p/router.go b/sei-tendermint/internal/p2p/router.go index dae58e7e37..481302f845 100644 --- a/sei-tendermint/internal/p2p/router.go +++ b/sei-tendermint/internal/p2p/router.go @@ -72,7 +72,7 @@ func NewRouter( if err := options.Validate(); err != nil { return nil, err } - selfID := types.NodeIDFromPubKey(privKey.PubKey()) + selfID := types.NodeIDFromPubKey(privKey.Public()) peerManager := newPeerManager[*Connection](selfID, options) peerDB, err := newPeerDB(db, options.maxPeers()) if err != nil { diff --git a/sei-tendermint/internal/p2p/testonly.go b/sei-tendermint/internal/p2p/testonly.go index c726e66b14..08c196a7e4 100644 --- a/sei-tendermint/internal/p2p/testonly.go +++ b/sei-tendermint/internal/p2p/testonly.go @@ -278,8 +278,8 @@ func (n *TestNode) Disconnect(ctx context.Context, target types.NodeID) { // running peer manager, but does not add it to the existing // network. Callers are responsible for updating peering relationships. func (n *TestNetwork) MakeNode(t *testing.T, opts TestNodeOptions) *TestNode { - privKey := ed25519.GenPrivKey() - nodeID := types.NodeIDFromPubKey(privKey.PubKey()) + privKey := ed25519.GenerateSecretKey() + nodeID := types.NodeIDFromPubKey(privKey.Public()) logger := n.logger.With("node", nodeID[:5]) routerOpts := &RouterOptions{ diff --git a/sei-tendermint/internal/p2p/transport_test.go b/sei-tendermint/internal/p2p/transport_test.go index 2417889066..5f342e5580 100644 --- a/sei-tendermint/internal/p2p/transport_test.go +++ b/sei-tendermint/internal/p2p/transport_test.go @@ -22,7 +22,7 @@ import ( ) func makeInfo(key crypto.PrivKey) types.NodeInfo { - nodeID := types.NodeIDFromPubKey(key.PubKey()) + nodeID := types.NodeIDFromPubKey(key.Public()) peerInfo := types.NodeInfo{ NodeID: nodeID, ListenAddr: "127.0.0.1:1239", diff --git a/sei-tendermint/internal/rpc/core/env.go b/sei-tendermint/internal/rpc/core/env.go index ed5ee13979..94e1e7439f 100644 --- a/sei-tendermint/internal/rpc/core/env.go +++ b/sei-tendermint/internal/rpc/core/env.go @@ -27,6 +27,7 @@ import ( tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/strings" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/rpc/coretypes" rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server" "github.com/tendermint/tendermint/types" @@ -86,7 +87,7 @@ type Environment struct { PeerManager peerManager // objects - PubKey crypto.PubKey + PubKey utils.Option[crypto.PubKey] GenDoc *types.GenesisDoc // cache the genesis structure EventSinks []indexer.EventSink EventBus *eventbus.EventBus // thread safe diff --git a/sei-tendermint/internal/rpc/core/status.go b/sei-tendermint/internal/rpc/core/status.go index 870c134248..f46eca9670 100644 --- a/sei-tendermint/internal/rpc/core/status.go +++ b/sei-tendermint/internal/rpc/core/status.go @@ -7,6 +7,7 @@ import ( "time" tmbytes "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/rpc/coretypes" "github.com/tendermint/tendermint/types" ) @@ -47,19 +48,10 @@ func (env *Environment) Status(ctx context.Context) (*coretypes.ResultStatus, er // Return the very last voting power, not the voting power of this validator // during the last block. - var votingPower int64 - if val := env.validatorAtHeight(env.latestUncommittedHeight()); val != nil { - votingPower = val.VotingPower + validatorInfo := coretypes.ValidatorInfo{PubKey: env.PubKey} + if val, ok := env.validatorAtHeight(env.latestUncommittedHeight()).Get(); ok { + validatorInfo.VotingPower = val.VotingPower } - validatorInfo := coretypes.ValidatorInfo{} - if env.PubKey != nil { - validatorInfo = coretypes.ValidatorInfo{ - Address: env.PubKey.Address(), - PubKey: env.PubKey, - VotingPower: votingPower, - } - } - var applicationInfo coretypes.ApplicationInfo if abciInfo, err := env.ABCIInfo(ctx); err == nil { applicationInfo.Version = fmt.Sprint(abciInfo.Response.AppVersion) @@ -109,29 +101,34 @@ func (env *Environment) Status(ctx context.Context) (*coretypes.ResultStatus, er return result, nil } -func (env *Environment) validatorAtHeight(h int64) *types.Validator { +func (env *Environment) validatorAtHeight(h int64) utils.Option[*types.Validator] { + none := utils.None[*types.Validator]() + k, ok := env.PubKey.Get() + if !ok { + return none + } valsWithH, err := env.StateStore.LoadValidators(h) if err != nil { - return nil + return none } if env.ConsensusState == nil { - return nil - } - if env.PubKey == nil { - return nil + return none } - privValAddress := env.PubKey.Address() + privValAddress := k.Address() // If we're still at height h, search in the current validator set. lastBlockHeight, vals := env.ConsensusState.GetValidators() if lastBlockHeight == h { for _, val := range vals { if bytes.Equal(val.Address, privValAddress) { - return val + return utils.Some(val) } } } _, val := valsWithH.GetByAddress(privValAddress) - return val + if val != nil { + return utils.Some(val) + } + return none } diff --git a/sei-tendermint/internal/state/execution_test.go b/sei-tendermint/internal/state/execution_test.go index cf2f404047..dbd6d9eff6 100644 --- a/sei-tendermint/internal/state/execution_test.go +++ b/sei-tendermint/internal/state/execution_test.go @@ -28,6 +28,7 @@ import ( "github.com/tendermint/tendermint/internal/store" "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/version" ) @@ -207,7 +208,8 @@ func TestFinalizeBlockByzantineValidators(t *testing.T) { BlockIDFlag: types.BlockIDFlagNil, ValidatorAddress: crypto.AddressHash([]byte("validator_address")), Timestamp: defaultEvidenceTime, - Signature: crypto.CRandBytes(types.MaxSignatureSize)}}, + Signature: utils.Some(utils.OrPanic1(crypto.SigFromBytes(crypto.CRandBytes(64)))), + }}, }, }, ValidatorSet: state.Validators, @@ -371,12 +373,10 @@ func TestProcessProposal(t *testing.T) { } func TestValidateValidatorUpdates(t *testing.T) { - pubkey1 := ed25519.GenPrivKey().PubKey() - pubkey2 := ed25519.GenPrivKey().PubKey() - pk1, err := encoding.PubKeyToProto(pubkey1) - assert.NoError(t, err) - pk2, err := encoding.PubKeyToProto(pubkey2) - assert.NoError(t, err) + pubkey1 := ed25519.GenerateSecretKey().Public() + pubkey2 := ed25519.GenerateSecretKey().Public() + pk1 := encoding.PubKeyToProto(pubkey1) + pk2 := encoding.PubKeyToProto(pubkey2) defaultValidatorParams := types.ValidatorParams{PubKeyTypes: []string{types.ABCIPubKeyTypeEd25519}} @@ -427,15 +427,13 @@ func TestValidateValidatorUpdates(t *testing.T) { } func TestUpdateValidators(t *testing.T) { - pubkey1 := ed25519.GenPrivKey().PubKey() + pubkey1 := ed25519.GenerateSecretKey().Public() val1 := types.NewValidator(pubkey1, 10) - pubkey2 := ed25519.GenPrivKey().PubKey() + pubkey2 := ed25519.GenerateSecretKey().Public() val2 := types.NewValidator(pubkey2, 20) - pk, err := encoding.PubKeyToProto(pubkey1) - require.NoError(t, err) - pk2, err := encoding.PubKeyToProto(pubkey2) - require.NoError(t, err) + pk := encoding.PubKeyToProto(pubkey1) + pk2 := encoding.PubKeyToProto(pubkey2) testCases := []struct { name string @@ -552,9 +550,8 @@ func TestFinalizeBlockValidatorUpdates(t *testing.T) { require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - pubkey := ed25519.GenPrivKey().PubKey() - pk, err := encoding.PubKeyToProto(pubkey) - require.NoError(t, err) + pubkey := ed25519.GenerateSecretKey().Public() + pk := encoding.PubKeyToProto(pubkey) app.ValidatorUpdates = []abci.ValidatorUpdate{ {PubKey: pk, Power: 10}, } @@ -618,8 +615,7 @@ func TestFinalizeBlockValidatorUpdatesResultingInEmptySet(t *testing.T) { require.NoError(t, err) blockID := types.BlockID{Hash: block.Hash(), PartSetHeader: bps.Header()} - vp, err := encoding.PubKeyToProto(state.Validators.Validators[0].PubKey) - require.NoError(t, err) + vp := encoding.PubKeyToProto(state.Validators.Validators[0].PubKey) // Remove the only validator app.ValidatorUpdates = []abci.ValidatorUpdate{ {PubKey: vp, Power: 0}, diff --git a/sei-tendermint/internal/state/helpers_test.go b/sei-tendermint/internal/state/helpers_test.go index 624ec2c630..91d351ff43 100644 --- a/sei-tendermint/internal/state/helpers_test.go +++ b/sei-tendermint/internal/state/helpers_test.go @@ -1,7 +1,6 @@ package state_test import ( - "bytes" "context" "fmt" "math/rand" @@ -100,16 +99,19 @@ func makeValidCommit( }, votes } +func makePrivKey(i int) ed25519.SecretKey { + return ed25519.TestSecretKey(fmt.Appendf(nil, "%d", i)) +} + func makeState(t *testing.T, nVals, height int) (sm.State, dbm.DB, map[string]types.PrivValidator) { vals := make([]types.GenesisValidator, nVals) privVals := make(map[string]types.PrivValidator, nVals) for i := 0; i < nVals; i++ { - secret := []byte(fmt.Sprintf("test%d", i)) - pk := ed25519.GenPrivKeyFromSecret(secret) - valAddr := pk.PubKey().Address() + pk := makePrivKey(i) + valAddr := pk.Public().Address() vals[i] = types.GenesisValidator{ Address: valAddr, - PubKey: pk.PubKey(), + PubKey: pk.Public(), Power: 1000, Name: fmt.Sprintf("test%d", i), } @@ -138,7 +140,7 @@ func makeState(t *testing.T, nVals, height int) (sm.State, dbm.DB, map[string]ty func genValSet(size int) *types.ValidatorSet { vals := make([]*types.Validator, size) for i := 0; i < size; i++ { - vals[i] = types.NewValidator(ed25519.GenPrivKey().PubKey(), 10) + vals[i] = types.NewValidator(ed25519.GenerateSecretKey().Public(), 10) } return types.NewValidatorSet(vals) } @@ -153,11 +155,9 @@ func makeHeaderPartsResponsesValPubKeyChange( finalizeBlockResponses := &abci.ResponseFinalizeBlock{} // If the pubkey is new, remove the old and add the new. _, val := state.NextValidators.GetByIndex(0) - if !bytes.Equal(pubkey.Bytes(), val.PubKey.Bytes()) { - vPbPk, err := encoding.PubKeyToProto(val.PubKey) - require.NoError(t, err) - pbPk, err := encoding.PubKeyToProto(pubkey) - require.NoError(t, err) + if pubkey != val.PubKey { + vPbPk := encoding.PubKeyToProto(val.PubKey) + pbPk := encoding.PubKeyToProto(pubkey) finalizeBlockResponses.ValidatorUpdates = []abci.ValidatorUpdate{ {PubKey: vPbPk, Power: 0}, @@ -181,8 +181,7 @@ func makeHeaderPartsResponsesValPowerChange( // If the pubkey is new, remove the old and add the new. _, val := state.NextValidators.GetByIndex(0) if val.VotingPower != power { - vPbPk, err := encoding.PubKeyToProto(val.PubKey) - require.NoError(t, err) + vPbPk := encoding.PubKeyToProto(val.PubKey) finalizeBlockResponses.ValidatorUpdates = []abci.ValidatorUpdate{ {PubKey: vPbPk, Power: power}, @@ -206,7 +205,7 @@ func makeHeaderPartsResponsesParams( } func randomGenesisDoc() *types.GenesisDoc { - pubkey := ed25519.GenPrivKey().PubKey() + pubkey := ed25519.GenerateSecretKey().Public() return &types.GenesisDoc{ GenesisTime: tmtime.Now(), ChainID: "abc", diff --git a/sei-tendermint/internal/state/state_test.go b/sei-tendermint/internal/state/state_test.go index 5dbe6b52fa..34a1d7c456 100644 --- a/sei-tendermint/internal/state/state_test.go +++ b/sei-tendermint/internal/state/state_test.go @@ -117,12 +117,10 @@ func TestFinalizeBlockResponsesSaveLoad1(t *testing.T) { finalizeBlockResponses.TxResults[0] = &abci.ExecTxResult{Data: []byte("foo"), Events: nil} finalizeBlockResponses.TxResults[1] = &abci.ExecTxResult{Data: []byte("bar"), Log: "ok", Events: nil} - pbpk, err := encoding.PubKeyToProto(ed25519.GenPrivKey().PubKey()) - require.NoError(t, err) + pbpk := encoding.PubKeyToProto(ed25519.GenerateSecretKey().Public()) finalizeBlockResponses.ValidatorUpdates = []abci.ValidatorUpdate{{PubKey: pbpk, Power: 10}} - err = stateStore.SaveFinalizeBlockResponses(block.Height, finalizeBlockResponses) - require.NoError(t, err) + require.NoError(t, stateStore.SaveFinalizeBlockResponses(block.Height, finalizeBlockResponses)) loadedFinalizeBlockResponses, err := stateStore.LoadFinalizeBlockResponses(block.Height) require.NoError(t, err) assert.Equal(t, finalizeBlockResponses, loadedFinalizeBlockResponses, @@ -395,7 +393,7 @@ func genValSetWithPowers(powers []int64) *types.ValidatorSet { totalVotePower := int64(0) for i := 0; i < size; i++ { totalVotePower += powers[i] - val := types.NewValidator(ed25519.GenPrivKey().PubKey(), powers[i]) + val := types.NewValidator(ed25519.GenerateSecretKey().Public(), powers[i]) val.ProposerPriority = mrand.Int63() vals[i] = val } @@ -446,7 +444,7 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { tearDown, _, state := setupTestCase(t) defer tearDown(t) val1VotingPower := int64(10) - val1PubKey := ed25519.GenPrivKey().PubKey() + val1PubKey := ed25519.GenerateSecretKey().Public() val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower} state.Validators = types.NewValidatorSet([]*types.Validator{val1}) @@ -474,10 +472,9 @@ func TestProposerPriorityDoesNotGetResetToZero(t *testing.T) { assert.Equal(t, 0+val1VotingPower-curTotal, updatedState.NextValidators.Validators[0].ProposerPriority) // add a validator - val2PubKey := ed25519.GenPrivKey().PubKey() + val2PubKey := ed25519.GenerateSecretKey().Public() val2VotingPower := int64(100) - fvp, err := encoding.PubKeyToProto(val2PubKey) - require.NoError(t, err) + fvp := encoding.PubKeyToProto(val2PubKey) updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val2VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) @@ -570,7 +567,7 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { tearDown, _, state := setupTestCase(t) defer tearDown(t) val1VotingPower := int64(10) - val1PubKey := ed25519.GenPrivKey().PubKey() + val1PubKey := ed25519.GenerateSecretKey().Public() val1 := &types.Validator{Address: val1PubKey.Address(), PubKey: val1PubKey, VotingPower: val1VotingPower} // reset state validators to above validator @@ -603,9 +600,8 @@ func TestProposerPriorityProposerAlternates(t *testing.T) { assert.Equal(t, val1PubKey.Address(), updatedState.NextValidators.Proposer.Address) // add a validator with the same voting power as the first - val2PubKey := ed25519.GenPrivKey().PubKey() - fvp, err := encoding.PubKeyToProto(val2PubKey) - require.NoError(t, err) + val2PubKey := ed25519.GenerateSecretKey().Public() + fvp := encoding.PubKeyToProto(val2PubKey) updateAddVal := abci.ValidatorUpdate{PubKey: fvp, Power: val1VotingPower} validatorUpdates, err = types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{updateAddVal}) assert.NoError(t, err) @@ -756,7 +752,7 @@ func TestLargeGenesisValidator(t *testing.T) { defer tearDown(t) genesisVotingPower := types.MaxTotalVotingPower / 1000 - genesisPubKey := ed25519.GenPrivKey().PubKey() + genesisPubKey := ed25519.GenerateSecretKey().Public() // fmt.Println("genesis addr: ", genesisPubKey.Address()) genesisVal := &types.Validator{ Address: genesisPubKey.Address(), @@ -802,10 +798,9 @@ func TestLargeGenesisValidator(t *testing.T) { // let the genesis validator "unbond", // see how long it takes until the effect wears off and both begin to alternate // see: https://github.com/tendermint/tendermint/issues/2960 - firstAddedValPubKey := ed25519.GenPrivKey().PubKey() + firstAddedValPubKey := ed25519.GenerateSecretKey().Public() firstAddedValVotingPower := int64(10) - fvp, err := encoding.PubKeyToProto(firstAddedValPubKey) - require.NoError(t, err) + fvp := encoding.PubKeyToProto(firstAddedValPubKey) firstAddedVal := abci.ValidatorUpdate{PubKey: fvp, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{firstAddedVal}) assert.NoError(t, err) @@ -862,9 +857,8 @@ func TestLargeGenesisValidator(t *testing.T) { // add 10 validators with the same voting power as the one added directly after genesis: for i := 0; i < 10; i++ { - addedPubKey := ed25519.GenPrivKey().PubKey() - ap, err := encoding.PubKeyToProto(addedPubKey) - require.NoError(t, err) + addedPubKey := ed25519.GenerateSecretKey().Public() + ap := encoding.PubKeyToProto(addedPubKey) addedVal := abci.ValidatorUpdate{PubKey: ap, Power: firstAddedValVotingPower} validatorUpdates, err := types.PB2TM.ValidatorUpdates([]abci.ValidatorUpdate{addedVal}) assert.NoError(t, err) @@ -886,8 +880,7 @@ func TestLargeGenesisValidator(t *testing.T) { require.Equal(t, 10+2, len(state.NextValidators.Validators)) // remove genesis validator: - gp, err := encoding.PubKeyToProto(genesisPubKey) - require.NoError(t, err) + gp := encoding.PubKeyToProto(genesisPubKey) removeGenesisVal := abci.ValidatorUpdate{PubKey: gp, Power: 0} fb = &abci.ResponseFinalizeBlock{ ValidatorUpdates: []abci.ValidatorUpdate{removeGenesisVal}, @@ -1012,7 +1005,7 @@ func TestManyValidatorChangesSaveLoad(t *testing.T) { _, valOld := state.Validators.GetByIndex(0) var pubkeyOld = valOld.PubKey - pubkey := ed25519.GenPrivKey().PubKey() + pubkey := ed25519.GenerateSecretKey().Public() // Swap the first validator with a new one (validator set size stays the same). header, blockID, responses := makeHeaderPartsResponsesValPubKeyChange(t, state, pubkey) diff --git a/sei-tendermint/internal/state/store_test.go b/sei-tendermint/internal/state/store_test.go index 7c0a1ad9e1..c6908a1c85 100644 --- a/sei-tendermint/internal/state/store_test.go +++ b/sei-tendermint/internal/state/store_test.go @@ -191,7 +191,7 @@ func TestPruneStates(t *testing.T) { db := dbm.NewMemDB() stateStore := sm.NewStore(db) - pk := ed25519.GenPrivKey().PubKey() + pk := ed25519.GenerateSecretKey().Public() // Generate a bunch of state data. Validators change for heights ending with 3, and // parameters when ending with 5. diff --git a/sei-tendermint/internal/state/validation_test.go b/sei-tendermint/internal/state/validation_test.go index 6ef9d245c5..20e78fd7e9 100644 --- a/sei-tendermint/internal/state/validation_test.go +++ b/sei-tendermint/internal/state/validation_test.go @@ -24,6 +24,7 @@ import ( testfactory "github.com/tendermint/tendermint/internal/test/factory" "github.com/tendermint/tendermint/libs/log" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -97,7 +98,9 @@ func TestValidateBlockHeader(t *testing.T) { {"LastResultsHash wrong", func(block *types.Block) { block.LastResultsHash = wrongHash }}, {"EvidenceHash wrong", func(block *types.Block) { block.EvidenceHash = wrongHash }}, - {"Proposer wrong", func(block *types.Block) { block.ProposerAddress = ed25519.GenPrivKey().PubKey().Address() }}, + {"Proposer wrong", func(block *types.Block) { + block.ProposerAddress = ed25519.GenerateSecretKey().Public().Address() + }}, {"Proposer invalid", func(block *types.Block) { block.ProposerAddress = []byte("wrong size") }}, {"first LastCommit contains signatures", func(block *types.Block) { @@ -265,7 +268,8 @@ func TestValidateBlockCommit(t *testing.T) { err = badPrivVal.SignVote(ctx, chainID, b) require.NoError(t, err, "height %d", height) - goodVote.Signature, badVote.Signature = g.Signature, b.Signature + goodVote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(g.Signature))) + badVote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(b.Signature))) wrongSigsCommit = &types.Commit{ Height: goodVote.Height, diff --git a/sei-tendermint/internal/store/store_test.go b/sei-tendermint/internal/store/store_test.go index 76bc7f049d..3ddbb824eb 100644 --- a/sei-tendermint/internal/store/store_test.go +++ b/sei-tendermint/internal/store/store_test.go @@ -14,14 +14,18 @@ import ( "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" sm "github.com/tendermint/tendermint/internal/state" "github.com/tendermint/tendermint/internal/state/test/factory" tmrand "github.com/tendermint/tendermint/libs/rand" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/types" "github.com/tendermint/tendermint/version" ) +var testKey = ed25519.TestSecretKey([]byte("test")) + // A cleanupFunc cleans up any config / test files created for a particular // test. type cleanupFunc func() @@ -33,7 +37,7 @@ func makeTestCommit(height int64, timestamp time.Time) *types.Commit { BlockIDFlag: types.BlockIDFlagCommit, ValidatorAddress: tmrand.Bytes(crypto.AddressSize), Timestamp: timestamp, - Signature: []byte("Signature"), + Signature: utils.Some(testKey.Sign([]byte("Signature"))), }} return &types.Commit{ Height: height, diff --git a/sei-tendermint/internal/test/factory/commit.go b/sei-tendermint/internal/test/factory/commit.go index 1a8691855e..1fe5b30a40 100644 --- a/sei-tendermint/internal/test/factory/commit.go +++ b/sei-tendermint/internal/test/factory/commit.go @@ -2,15 +2,18 @@ package factory import ( "context" + "fmt" "time" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) func MakeCommit(ctx context.Context, blockID types.BlockID, height int64, round int32, voteSet *types.VoteSet, validators []types.PrivValidator, now time.Time) (*types.Commit, error) { // all sign - for i := 0; i < len(validators); i++ { + for i := range validators { pubKey, err := validators[i].GetPubKey(ctx) if err != nil { return nil, err @@ -30,7 +33,11 @@ func MakeCommit(ctx context.Context, blockID types.BlockID, height int64, round if err := validators[i].SignVote(ctx, voteSet.ChainID(), v); err != nil { return nil, err } - vote.Signature = v.Signature + sig, err := crypto.SigFromBytes(v.Signature) + if err != nil { + return nil, fmt.Errorf("crypto.SigFromBytes(): %w", err) + } + vote.Signature = utils.Some(sig) if _, err := voteSet.AddVote(vote); err != nil { return nil, err } diff --git a/sei-tendermint/internal/test/factory/vote.go b/sei-tendermint/internal/test/factory/vote.go index fc63e8d681..92a583382a 100644 --- a/sei-tendermint/internal/test/factory/vote.go +++ b/sei-tendermint/internal/test/factory/vote.go @@ -2,8 +2,11 @@ package factory import ( "context" + "fmt" "time" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -38,7 +41,10 @@ func MakeVote( if err := val.SignVote(ctx, chainID, vpb); err != nil { return nil, err } - - v.Signature = vpb.Signature + sig, err := crypto.SigFromBytes(vpb.Signature) + if err != nil { + return nil, fmt.Errorf("crypto.SigFromBytes(): %w", err) + } + v.Signature = utils.Some(sig) return v, nil } diff --git a/sei-tendermint/libs/json/decoder.go b/sei-tendermint/libs/json/decoder.go index 86ff27d393..ae516eefde 100644 --- a/sei-tendermint/libs/json/decoder.go +++ b/sei-tendermint/libs/json/decoder.go @@ -23,17 +23,7 @@ func decode(bz []byte, v interface{}) error { if rv.Kind() != reflect.Ptr { return errors.New("must decode into a pointer") } - rv = rv.Elem() - - // If this is a registered type, defer to interface decoder regardless of whether the input is - // an interface or a bare value. This retains Amino's behavior, but is inconsistent with - // behavior in structs where an interface field will get the type wrapper while a bare value - // field will not. - if typeRegistry.name(rv.Type()) != "" { - return decodeReflectInterface(bz, rv) - } - - return decodeReflect(bz, rv) + return decodeReflect(bz, rv.Elem()) } func decodeReflect(bz []byte, rv reflect.Value) error { @@ -82,7 +72,7 @@ func decodeReflect(bz []byte, rv reflect.Value) error { return decodeReflectStruct(bz, rv) case reflect.Interface: - return decodeReflectInterface(bz, rv) + return fmt.Errorf("decoding interfaces is not supported") // For 64-bit integers, unwrap expected string and defer to stdlib for integer decoding. case reflect.Int64, reflect.Int, reflect.Uint64, reflect.Uint: @@ -201,60 +191,6 @@ func decodeReflectStruct(bz []byte, rv reflect.Value) error { return nil } -func decodeReflectInterface(bz []byte, rv reflect.Value) error { - if !rv.CanAddr() { - return errors.New("interface value not addressable") - } - - // Decode the interface wrapper. - wrapper := interfaceWrapper{} - if err := json.Unmarshal(bz, &wrapper); err != nil { - return err - } - if wrapper.Type == "" { - return errors.New("interface type cannot be empty") - } - if len(wrapper.Value) == 0 { - return errors.New("interface value cannot be empty") - } - - // Dereference-and-construct pointers, to handle nested pointers. - for rv.Kind() == reflect.Ptr { - if rv.IsNil() { - rv.Set(reflect.New(rv.Type().Elem())) - } - rv = rv.Elem() - } - - // Look up the interface type, and construct a concrete value. - rt, returnPtr := typeRegistry.lookup(wrapper.Type) - if rt == nil { - return fmt.Errorf("unknown type %q", wrapper.Type) - } - - cptr := reflect.New(rt) - crv := cptr.Elem() - if err := decodeReflect(wrapper.Value, crv); err != nil { - return err - } - - // This makes sure interface implementations with pointer receivers (e.g. func (c *Car)) are - // constructed as pointers behind the interface. The types must be registered as pointers with - // RegisterType(). - if rv.Type().Kind() == reflect.Interface && returnPtr { - if !cptr.Type().AssignableTo(rv.Type()) { - return fmt.Errorf("invalid type %q for this value", wrapper.Type) - } - rv.Set(cptr) - } else { - if !crv.Type().AssignableTo(rv.Type()) { - return fmt.Errorf("invalid type %q for this value", wrapper.Type) - } - rv.Set(crv) - } - return nil -} - func decodeStdlib(bz []byte, rv reflect.Value) error { if !rv.CanAddr() && rv.Kind() != reflect.Ptr { return errors.New("value must be addressable or pointer") diff --git a/sei-tendermint/libs/json/decoder_test.go b/sei-tendermint/libs/json/decoder_test.go index 97b2bf710f..ab41e9a7cd 100644 --- a/sei-tendermint/libs/json/decoder_test.go +++ b/sei-tendermint/libs/json/decoder_test.go @@ -21,63 +21,49 @@ func TestUnmarshal(t *testing.T) { testcases := map[string]struct { json string - value interface{} + value any err bool }{ - "bool true": {"true", true, false}, - "bool false": {"false", false, false}, - "float32": {"3.14", float32(3.14), false}, - "float64": {"3.14", float64(3.14), false}, - "int32": {`32`, int32(32), false}, - "int32 string": {`"32"`, int32(32), true}, - "int32 ptr": {`32`, &i32, false}, - "int64": {`"64"`, int64(64), false}, - "int64 noend": {`"64`, int64(64), true}, - "int64 number": {`64`, int64(64), true}, - "int64 ptr": {`"64"`, &i64, false}, - "int64 ptr nil": {`null`, i64Nil, false}, - "string": {`"foo"`, "foo", false}, - "string noend": {`"foo`, "foo", true}, - "string ptr": {`"string"`, &str, false}, - "slice byte": {`"AQID"`, []byte{1, 2, 3}, false}, - "slice bytes": {`["AQID"]`, [][]byte{{1, 2, 3}}, false}, - "slice int32": {`[1,2,3]`, []int32{1, 2, 3}, false}, - "slice int64": {`["1","2","3"]`, []int64{1, 2, 3}, false}, - "slice int64 number": {`[1,2,3]`, []int64{1, 2, 3}, true}, - "slice int64 ptr": {`["64"]`, []*int64{&i64}, false}, - "slice int64 empty": {`[]`, []int64(nil), false}, - "slice int64 null": {`null`, []int64(nil), false}, - "array byte": {`"AQID"`, [3]byte{1, 2, 3}, false}, - "array byte large": {`"AQID"`, [4]byte{1, 2, 3, 4}, true}, - "array byte small": {`"AQID"`, [2]byte{1, 2}, true}, - "array int32": {`[1,2,3]`, [3]int32{1, 2, 3}, false}, - "array int64": {`["1","2","3"]`, [3]int64{1, 2, 3}, false}, - "array int64 number": {`[1,2,3]`, [3]int64{1, 2, 3}, true}, - "array int64 large": {`["1","2","3"]`, [4]int64{1, 2, 3, 4}, true}, - "array int64 small": {`["1","2","3"]`, [2]int64{1, 2}, true}, - "map bytes": {`{"b":"AQID"}`, map[string][]byte{"b": {1, 2, 3}}, false}, - "map int32": {`{"a":1,"b":2}`, map[string]int32{"a": 1, "b": 2}, false}, - "map int64": {`{"a":"1","b":"2"}`, map[string]int64{"a": 1, "b": 2}, false}, - "map int64 empty": {`{}`, map[string]int64{}, false}, - "map int64 null": {`null`, map[string]int64(nil), false}, - "map int key": {`{}`, map[int]int{}, true}, - "time": {`"2020-06-03T17:35:30Z"`, time.Date(2020, 6, 3, 17, 35, 30, 0, time.UTC), false}, - "time non-utc": {`"2020-06-03T17:35:30+02:00"`, time.Time{}, true}, - "time nozone": {`"2020-06-03T17:35:30"`, time.Time{}, true}, - "car": {`{"type":"vehicle/car","value":{"Wheels":4}}`, Car{Wheels: 4}, false}, - "car ptr": {`{"type":"vehicle/car","value":{"Wheels":4}}`, &Car{Wheels: 4}, false}, - "car iface": {`{"type":"vehicle/car","value":{"Wheels":4}}`, Vehicle(&Car{Wheels: 4}), false}, - "boat": {`{"type":"vehicle/boat","value":{"Sail":true}}`, Boat{Sail: true}, false}, - "boat ptr": {`{"type":"vehicle/boat","value":{"Sail":true}}`, &Boat{Sail: true}, false}, - "boat iface": {`{"type":"vehicle/boat","value":{"Sail":true}}`, Vehicle(Boat{Sail: true}), false}, - "boat into car": {`{"type":"vehicle/boat","value":{"Sail":true}}`, Car{}, true}, - "boat into car iface": {`{"type":"vehicle/boat","value":{"Sail":true}}`, Vehicle(&Car{}), true}, - "shoes": {`{"type":"vehicle/shoes","value":{"Soles":"rubber"}}`, Car{}, true}, - "shoes ptr": {`{"type":"vehicle/shoes","value":{"Soles":"rubber"}}`, &Car{}, true}, - "shoes iface": {`{"type":"vehicle/shoes","value":{"Soles":"rubbes"}}`, Vehicle(&Car{}), true}, - "key public": {`{"type":"key/public","value":"AQIDBAUGBwg="}`, PublicKey{1, 2, 3, 4, 5, 6, 7, 8}, false}, - "key wrong": {`{"type":"key/public","value":"AQIDBAUGBwg="}`, PrivateKey{1, 2, 3, 4, 5, 6, 7, 8}, true}, - "key into car": {`{"type":"key/public","value":"AQIDBAUGBwg="}`, Vehicle(&Car{}), true}, + "bool true": {"true", true, false}, + "bool false": {"false", false, false}, + "float32": {"3.14", float32(3.14), false}, + "float64": {"3.14", float64(3.14), false}, + "int32": {`32`, int32(32), false}, + "int32 string": {`"32"`, int32(32), true}, + "int32 ptr": {`32`, &i32, false}, + "int64": {`"64"`, int64(64), false}, + "int64 noend": {`"64`, int64(64), true}, + "int64 number": {`64`, int64(64), true}, + "int64 ptr": {`"64"`, &i64, false}, + "int64 ptr nil": {`null`, i64Nil, false}, + "string": {`"foo"`, "foo", false}, + "string noend": {`"foo`, "foo", true}, + "string ptr": {`"string"`, &str, false}, + "slice byte": {`"AQID"`, []byte{1, 2, 3}, false}, + "slice bytes": {`["AQID"]`, [][]byte{{1, 2, 3}}, false}, + "slice int32": {`[1,2,3]`, []int32{1, 2, 3}, false}, + "slice int64": {`["1","2","3"]`, []int64{1, 2, 3}, false}, + "slice int64 number": {`[1,2,3]`, []int64{1, 2, 3}, true}, + "slice int64 ptr": {`["64"]`, []*int64{&i64}, false}, + "slice int64 empty": {`[]`, []int64(nil), false}, + "slice int64 null": {`null`, []int64(nil), false}, + "array byte": {`"AQID"`, [3]byte{1, 2, 3}, false}, + "array byte large": {`"AQID"`, [4]byte{1, 2, 3, 4}, true}, + "array byte small": {`"AQID"`, [2]byte{1, 2}, true}, + "array int32": {`[1,2,3]`, [3]int32{1, 2, 3}, false}, + "array int64": {`["1","2","3"]`, [3]int64{1, 2, 3}, false}, + "array int64 number": {`[1,2,3]`, [3]int64{1, 2, 3}, true}, + "array int64 large": {`["1","2","3"]`, [4]int64{1, 2, 3, 4}, true}, + "array int64 small": {`["1","2","3"]`, [2]int64{1, 2}, true}, + "map bytes": {`{"b":"AQID"}`, map[string][]byte{"b": {1, 2, 3}}, false}, + "map int32": {`{"a":1,"b":2}`, map[string]int32{"a": 1, "b": 2}, false}, + "map int64": {`{"a":"1","b":"2"}`, map[string]int64{"a": 1, "b": 2}, false}, + "map int64 empty": {`{}`, map[string]int64{}, false}, + "map int64 null": {`null`, map[string]int64(nil), false}, + "map int key": {`{}`, map[int]int{}, true}, + "time": {`"2020-06-03T17:35:30Z"`, time.Date(2020, 6, 3, 17, 35, 30, 0, time.UTC), false}, + "time non-utc": {`"2020-06-03T17:35:30+02:00"`, time.Time{}, true}, + "time nozone": {`"2020-06-03T17:35:30"`, time.Time{}, true}, "tags": { `{"name":"name","OmitEmpty":"foo","Hidden":"bar","tags":{"name":"child"}}`, Tags{JSONName: "name", OmitEmpty: "foo", Tags: &Tags{JSONName: "child"}}, @@ -96,15 +82,11 @@ func TestUnmarshal(t *testing.T) { "Time":"2020-06-02T16:05:13.004346374Z", "Car":{"Wheels":4}, "Boat":{"Sail":true}, - "Vehicles":[ - {"type":"vehicle/car","value":{"Wheels":4}}, - {"type":"vehicle/boat","value":{"Sail":true}} - ], "Child":{ "Bool":false, "Float64":0, "Int32":0, "Int64":"0", "Int64Ptr":null, "String":"child", "StringPtrPtr":null, "Bytes":null, "Time":"0001-01-01T00:00:00Z", - "Car":null, "Boat":{"Sail":false}, "Vehicles":null, "Child":null + "Car":null, "Boat":{"Sail":false}, "Child":null }, "private": "foo", "unknown": "bar" }`, @@ -112,18 +94,11 @@ func TestUnmarshal(t *testing.T) { Bool: true, Float64: 3.14, Int32: 32, Int64: 64, Int64Ptr: &i64, String: "foo", StringPtrPtr: &strPtr, Bytes: []byte{1, 2, 3}, Time: time.Date(2020, 6, 2, 16, 5, 13, 4346374, time.UTC), - Car: &Car{Wheels: 4}, Boat: Boat{Sail: true}, Vehicles: []Vehicle{ - Vehicle(&Car{Wheels: 4}), - Vehicle(Boat{Sail: true}), - }, + Car: &Car{Wheels: 4}, Boat: Boat{Sail: true}, Child: &Struct{Bool: false, String: "child"}, }, false, }, - "struct key into vehicle": {`{"Vehicles":[ - {"type":"vehicle/car","value":{"Wheels":4}}, - {"type":"key/public","value":"MTIzNDU2Nzg="} - ]}`, Struct{}, true}, "struct ptr null": {`null`, structNil, false}, "custom value": {`{"Value":"foo"}`, CustomValue{}, false}, "custom ptr": {`"foo"`, &CustomPtr{Value: "custom"}, false}, diff --git a/sei-tendermint/libs/json/encoder.go b/sei-tendermint/libs/json/encoder.go index cd404d9bfd..8d1c24f71c 100644 --- a/sei-tendermint/libs/json/encoder.go +++ b/sei-tendermint/libs/json/encoder.go @@ -48,15 +48,6 @@ func encode(w io.Writer, v any) error { return writeStr(w, "null") } rv := reflect.ValueOf(v) - - // If this is a registered type, defer to interface encoder regardless of whether the input is - // an interface or a bare value. This retains Amino's behavior, but is inconsistent with - // behavior in structs where an interface field will get the type wrapper while a bare value - // field will not. - if typeRegistry.name(rv.Type()) != "" { - return encodeReflectInterface(w, rv) - } - return encodeReflect(w, rv) } @@ -66,7 +57,7 @@ func encodeReflect(w io.Writer, rv reflect.Value) error { } // Recursively dereference if pointer. - for rv.Kind() == reflect.Ptr { + for rv.Kind() == reflect.Pointer { if rv.IsNil() { return writeStr(w, "null") } @@ -90,7 +81,7 @@ func encodeReflect(w io.Writer, rv reflect.Value) error { switch rv.Type().Kind() { // Complex types must be recursively encoded. case reflect.Interface: - return encodeReflectInterface(w, rv) + return fmt.Errorf("encoding interfaces is not supported") case reflect.Array, reflect.Slice: return encodeReflectList(w, rv) @@ -137,7 +128,7 @@ func encodeReflectList(w io.Writer, rv reflect.Value) error { if err := writeStr(w, "["); err != nil { return err } - for i := 0; i < length; i++ { + for i := range length { if err := encodeReflect(w, rv.Index(i)); err != nil { return err } @@ -212,31 +203,6 @@ func encodeReflectStruct(w io.Writer, rv reflect.Value) error { return writeStr(w, "}") } -func encodeReflectInterface(w io.Writer, rv reflect.Value) error { - // Get concrete value and dereference pointers. - for rv.Kind() == reflect.Ptr || rv.Kind() == reflect.Interface { - if rv.IsNil() { - return writeStr(w, "null") - } - rv = rv.Elem() - } - - // Look up the name of the concrete type - name := typeRegistry.name(rv.Type()) - if name == "" { - return fmt.Errorf("cannot encode unregistered type %v", rv.Type()) - } - - // Write value wrapped in interface envelope - if err := writeStr(w, fmt.Sprintf(`{"type":%q,"value":`, name)); err != nil { - return err - } - if err := encodeReflect(w, rv); err != nil { - return err - } - return writeStr(w, "}") -} - func encodeStdlib(w io.Writer, v any) error { // Doesn't stream the output because that adds a newline, as per: // https://golang.org/pkg/encoding/json/#Encoder.Encode diff --git a/sei-tendermint/libs/json/encoder_test.go b/sei-tendermint/libs/json/encoder_test.go index 8de611c9ef..d6af582cb4 100644 --- a/sei-tendermint/libs/json/encoder_test.go +++ b/sei-tendermint/libs/json/encoder_test.go @@ -19,7 +19,7 @@ func TestMarshal(t *testing.T) { boat := Boat{Sail: true} testcases := map[string]struct { - value interface{} + value any output string }{ "nil": {nil, `null`}, @@ -50,14 +50,7 @@ func TestMarshal(t *testing.T) { "map nil": {map[string]int64(nil), `{}`}, // retain Amino compatibility "map empty": {map[string]int64{}, `{}`}, "map int64": {map[string]int64{"a": 1, "b": 2, "c": 3}, `{"a":"1","b":"2","c":"3"}`}, - "car": {car, `{"type":"vehicle/car","value":{"Wheels":4}}`}, - "car value": {*car, `{"type":"vehicle/car","value":{"Wheels":4}}`}, - "car iface": {Vehicle(car), `{"type":"vehicle/car","value":{"Wheels":4}}`}, "car nil": {(*Car)(nil), `null`}, - "boat": {boat, `{"type":"vehicle/boat","value":{"Sail":true}}`}, - "boat ptr": {&boat, `{"type":"vehicle/boat","value":{"Sail":true}}`}, - "boat iface": {Vehicle(boat), `{"type":"vehicle/boat","value":{"Sail":true}}`}, - "key public": {PublicKey{1, 2, 3, 4, 5, 6, 7, 8}, `{"type":"key/public","value":"AQIDBAUGBwg="}`}, "tags": { Tags{JSONName: "name", OmitEmpty: "foo", Hidden: "bar", Tags: &Tags{JSONName: "child"}}, `{"name":"name","OmitEmpty":"foo","tags":{"name":"child"}}`, @@ -71,7 +64,7 @@ func TestMarshal(t *testing.T) { Struct{ Bool: true, Float64: 3.14, Int32: 32, Int64: 64, Int64Ptr: &i64, String: "foo", StringPtrPtr: &sPtr, Bytes: []byte{1, 2, 3}, - Time: ti, Car: car, Boat: boat, Vehicles: []Vehicle{car, boat}, + Time: ti, Car: car, Boat: boat, Child: &Struct{Bool: false, String: "child"}, private: "private", }, `{ @@ -80,15 +73,11 @@ func TestMarshal(t *testing.T) { "Time":"2020-06-02T16:05:13.004346374Z", "Car":{"Wheels":4}, "Boat":{"Sail":true}, - "Vehicles":[ - {"type":"vehicle/car","value":{"Wheels":4}}, - {"type":"vehicle/boat","value":{"Sail":true}} - ], "Child":{ "Bool":false, "Float64":0, "Int32":0, "Int64":"0", "Int64Ptr":null, "String":"child", "StringPtrPtr":null, "Bytes":null, "Time":"0001-01-01T00:00:00Z", - "Car":null, "Boat":{"Sail":false}, "Vehicles":null, "Child":null + "Car":null, "Boat":{"Sail":false}, "Child":null } }`, }, diff --git a/sei-tendermint/libs/json/helpers_test.go b/sei-tendermint/libs/json/helpers_test.go index ccb3c00388..969a23fbba 100644 --- a/sei-tendermint/libs/json/helpers_test.go +++ b/sei-tendermint/libs/json/helpers_test.go @@ -2,22 +2,8 @@ package json_test import ( "time" - - "github.com/tendermint/tendermint/libs/json" ) -// Register Car, an instance of the Vehicle interface. -func init() { - json.RegisterType(&Car{}, "vehicle/car") - json.RegisterType(Boat{}, "vehicle/boat") - json.RegisterType(PublicKey{}, "key/public") - json.RegisterType(PrivateKey{}, "key/private") -} - -type Vehicle interface { - Drive() error -} - // Car is a pointer implementation of Vehicle. type Car struct { Wheels int32 @@ -85,7 +71,6 @@ type Struct struct { Time time.Time Car *Car Boat Boat - Vehicles []Vehicle Child *Struct private string } diff --git a/sei-tendermint/libs/json/types.go b/sei-tendermint/libs/json/types.go deleted file mode 100644 index 13f20d2bc9..0000000000 --- a/sei-tendermint/libs/json/types.go +++ /dev/null @@ -1,109 +0,0 @@ -package json - -import ( - "errors" - "fmt" - "reflect" - - tmsync "github.com/tendermint/tendermint/libs/sync" -) - -var ( - // typeRegistry contains globally registered types for JSON encoding/decoding. - typeRegistry = newTypes() -) - -// RegisterType registers a type for Amino-compatible interface encoding in the global type -// registry. These types will be encoded with a type wrapper `{"type":"","value":}` -// regardless of which interface they are wrapped in (if any). If the type is a pointer, it will -// still be valid both for value and pointer types, but decoding into an interface will generate -// the a value or pointer based on the registered type. -// -// Should only be called in init() functions, as it panics on error. -func RegisterType(_type interface{}, name string) { - if _type == nil { - panic("cannot register nil type") - } - err := typeRegistry.register(name, reflect.ValueOf(_type).Type()) - if err != nil { - panic(err) - } -} - -// typeInfo contains type information. -type typeInfo struct { - name string - rt reflect.Type - returnPtr bool -} - -// types is a type registry. It is safe for concurrent use. -type types struct { - tmsync.RWMutex - byType map[reflect.Type]*typeInfo - byName map[string]*typeInfo -} - -// newTypes creates a new type registry. -func newTypes() types { - return types{ - byType: map[reflect.Type]*typeInfo{}, - byName: map[string]*typeInfo{}, - } -} - -// registers the given type with the given name. The name and type must not be registered already. -func (t *types) register(name string, rt reflect.Type) error { - if name == "" { - return errors.New("name cannot be empty") - } - // If this is a pointer type, we recursively resolve until we get a bare type, but register that - // we should return pointers. - returnPtr := false - for rt.Kind() == reflect.Ptr { - returnPtr = true - rt = rt.Elem() - } - tInfo := &typeInfo{ - name: name, - rt: rt, - returnPtr: returnPtr, - } - - t.Lock() - defer t.Unlock() - if _, ok := t.byName[tInfo.name]; ok { - return fmt.Errorf("a type with name %q is already registered", name) - } - if _, ok := t.byType[tInfo.rt]; ok { - return fmt.Errorf("the type %v is already registered", rt) - } - t.byName[name] = tInfo - t.byType[rt] = tInfo - return nil -} - -// lookup looks up a type from a name, or nil if not registered. -func (t *types) lookup(name string) (reflect.Type, bool) { - t.RLock() - defer t.RUnlock() - tInfo := t.byName[name] - if tInfo == nil { - return nil, false - } - return tInfo.rt, tInfo.returnPtr -} - -// name looks up the name of a type, or empty if not registered. Unwraps pointers as necessary. -func (t *types) name(rt reflect.Type) string { - for rt.Kind() == reflect.Ptr { - rt = rt.Elem() - } - t.RLock() - defer t.RUnlock() - tInfo := t.byType[rt] - if tInfo == nil { - return "" - } - return tInfo.name -} diff --git a/sei-tendermint/libs/utils/option.go b/sei-tendermint/libs/utils/option.go index 85fd6a471c..210ba32ee5 100644 --- a/sei-tendermint/libs/utils/option.go +++ b/sei-tendermint/libs/utils/option.go @@ -40,6 +40,13 @@ func (o *Option[T]) Or(def T) T { return def } +func (o Option[T]) OrPanic() T { + if o.isPresent { + return o.value + } + panic("value missing") +} + // MapOpt applies a function to the value if present, returning a new Option. func MapOpt[T, R any](o Option[T], f func(T) R) Option[R] { if o.isPresent { diff --git a/sei-tendermint/libs/utils/proto.go b/sei-tendermint/libs/utils/proto.go index bff1474408..a2bd14f315 100644 --- a/sei-tendermint/libs/utils/proto.go +++ b/sei-tendermint/libs/utils/proto.go @@ -3,9 +3,9 @@ package utils import ( "errors" "fmt" - "sync" - "github.com/gogo/protobuf/proto" + "golang.org/x/exp/constraints" + "sync" ) func ErrorAs[T error](err error) Option[T] { @@ -16,14 +16,8 @@ func ErrorAs[T error](err error) Option[T] { return None[T]() } -// Int is a type constraint for integer types. -type Int interface { - ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uint | - ~int8 | ~int16 | ~int32 | ~int64 | ~int -} - // SafeCast casts between integer types, checking for overflows. -func SafeCast[To Int, From Int](v From) (x To, ok bool) { +func SafeCast[To constraints.Integer, From constraints.Integer](v From) (x To, ok bool) { x = To(v) // This can be further optimized by: // * making compiler detect if From -> To conversion is always safe diff --git a/sei-tendermint/libs/utils/testonly.go b/sei-tendermint/libs/utils/testonly.go index 23a1faa8be..aab2ac4f68 100644 --- a/sei-tendermint/libs/utils/testonly.go +++ b/sei-tendermint/libs/utils/testonly.go @@ -48,6 +48,17 @@ var cmpOpts = []cmp.Option{ cmp.Comparer(cmpComparer[big.Int]), } +func OrPanic(err error) { + if err != nil { + panic(err) + } +} + +func OrPanic1[T any](v T, err error) T { + OrPanic(err) + return v +} + // TestDiff generates a human-readable diff between two objects. func TestDiff[T any](want, got T) error { if diff := cmp.Diff(want, got, cmpOpts...); diff != "" { diff --git a/sei-tendermint/light/helpers_test.go b/sei-tendermint/light/helpers_test.go index 9187cc3c30..1a095c4365 100644 --- a/sei-tendermint/light/helpers_test.go +++ b/sei-tendermint/light/helpers_test.go @@ -5,11 +5,11 @@ import ( "time" "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" provider_mocks "github.com/tendermint/tendermint/light/provider/mocks" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" @@ -29,7 +29,7 @@ type privKeys []crypto.PrivKey func genPrivKeys(n int) privKeys { res := make(privKeys, n) for i := range res { - res[i] = ed25519.GenPrivKey() + res[i] = ed25519.GenerateSecretKey() } return res } @@ -47,7 +47,7 @@ func (pkz privKeys) Extend(n int) privKeys { func (pkz privKeys) ToValidators(init, inc int64) *types.ValidatorSet { res := make([]*types.Validator, len(pkz)) for i, k := range pkz { - res[i] = types.NewValidator(k.PubKey(), init+int64(i)*inc) + res[i] = types.NewValidator(k.Public(), init+int64(i)*inc) } return types.NewValidatorSet(res) } @@ -57,7 +57,7 @@ func (pkz privKeys) signHeader(t testing.TB, header *types.Header, valSet *types t.Helper() commitSigs := make([]types.CommitSig, len(pkz)) - for i := 0; i < len(pkz); i++ { + for i := range commitSigs { commitSigs[i] = types.NewCommitSigAbsent() } @@ -83,7 +83,7 @@ func (pkz privKeys) signHeader(t testing.TB, header *types.Header, valSet *types func makeVote(t testing.TB, header *types.Header, valset *types.ValidatorSet, key crypto.PrivKey, blockID types.BlockID) *types.Vote { t.Helper() - addr := key.PubKey().Address() + addr := key.Public().Address() idx, _ := valset.GetByAddress(addr) vote := &types.Vote{ ValidatorAddress: addr, @@ -94,15 +94,8 @@ func makeVote(t testing.TB, header *types.Header, valset *types.ValidatorSet, ke Type: tmproto.PrecommitType, BlockID: blockID, } - - v := vote.ToProto() // Sign it - signBytes := types.VoteSignBytes(header.ChainID, v) - sig, err := key.Sign(signBytes) - require.NoError(t, err) - - vote.Signature = sig - + vote.Signature = utils.Some(key.Sign(types.VoteSignBytes(header.ChainID, vote.ToProto()))) return vote } diff --git a/sei-tendermint/node/node.go b/sei-tendermint/node/node.go index 552da2a98c..5a35372436 100644 --- a/sei-tendermint/node/node.go +++ b/sei-tendermint/node/node.go @@ -2,7 +2,6 @@ package node import ( "context" - "errors" "fmt" "net" "net/http" @@ -205,21 +204,15 @@ func makeNode( return nil, combineCloseError(err, makeCloser(closers)) } - var pubKey crypto.PubKey - pubKey, err = privValidator.GetPubKey(ctx) - if err != nil { - return nil, combineCloseError(fmt.Errorf("can't get pubkey: %w", err), - makeCloser(closers)) - } - + pubKey := utils.None[crypto.PubKey]() if cfg.Mode == config.ModeValidator { - if pubKey == nil { - return nil, combineCloseError( - errors.New("could not retrieve public key from private validator"), + key, err := privValidator.GetPubKey(ctx) + if err != nil { + return nil, combineCloseError(fmt.Errorf("can't get pubkey: %w", err), makeCloser(closers)) } + pubKey = utils.Some(key) } - // TODO construct node here: node := &nodeImpl{ config: cfg, diff --git a/sei-tendermint/node/node_test.go b/sei-tendermint/node/node_test.go index 2ea9ee39b0..1699d726a3 100644 --- a/sei-tendermint/node/node_test.go +++ b/sei-tendermint/node/node_test.go @@ -34,6 +34,7 @@ import ( tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/libs/service" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/privval" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" @@ -162,7 +163,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { defer os.RemoveAll(cfg.RootDir) cfg.PrivValidator.ListenAddr = addr - dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenPrivKey()) + dialer := privval.DialTCPFn(addr, 100*time.Millisecond, ed25519.GenerateSecretKey()) dialerEndpoint := privval.NewSignerDialerEndpoint(logger, dialer) privval.SignerDialerEndpointTimeoutReadWrite(100 * time.Millisecond)(dialerEndpoint) @@ -468,10 +469,9 @@ func TestMaxProposalBlockSize(t *testing.T) { assert.NoError(t, err) // now produce more txs than what a normal block can hold with 10 smaller txs // At the end of the test, only the single big tx should be added - for i := 0; i < 10; i++ { + for range 10 { tx := tmrand.Bytes(10) - err = mp.CheckTx(ctx, tx, nil, mempool.TxInfo{}) - assert.NoError(t, err) + assert.NoError(t, mp.CheckTx(ctx, tx, nil, mempool.TxInfo{})) } eventBus := eventbus.NewDefault(logger) @@ -537,7 +537,7 @@ func TestMaxProposalBlockSize(t *testing.T) { } vpb := vote.ToProto() require.NoError(t, privVals[i].SignVote(ctx, state.ChainID, vpb)) - vote.Signature = vpb.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(vpb.Signature))) added, err := voteSet.AddVote(vote) require.NoError(t, err) @@ -712,8 +712,8 @@ func state(t *testing.T, nVals int, height int64) (sm.State, dbm.DB, []types.Pri privVal := types.NewMockPV() privVals[i] = privVal vals[i] = types.GenesisValidator{ - Address: privVal.PrivKey.PubKey().Address(), - PubKey: privVal.PrivKey.PubKey(), + Address: privVal.PrivKey.Public().Address(), + PubKey: privVal.PrivKey.Public(), Power: 1000, Name: fmt.Sprintf("test%d", i), } diff --git a/sei-tendermint/node/setup.go b/sei-tendermint/node/setup.go index 53b9742c03..001596bb40 100644 --- a/sei-tendermint/node/setup.go +++ b/sei-tendermint/node/setup.go @@ -94,7 +94,7 @@ func initDBs( return blockStore, stateDB, makeCloser(closers), nil } -func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger log.Logger, mode string) { +func logNodeStartupInfo(state sm.State, pubKey utils.Option[crypto.PubKey], logger log.Logger, mode string) { // Log the version info. logger.Info("Version info", "tmVersion", version.TMVersion, @@ -115,28 +115,33 @@ func logNodeStartupInfo(state sm.State, pubKey crypto.PubKey, logger log.Logger, case config.ModeFull: logger.Info("This node is a fullnode") case config.ModeValidator: - addr := pubKey.Address() + k := pubKey.OrPanic() + addr := k.Address() // Log whether this node is a validator or an observer if state.Validators.HasAddress(addr) { logger.Info("This node is a validator", "addr", addr, - "pubKey", pubKey.Bytes(), + "pubKey", k.Bytes(), ) } else { logger.Info("This node is a validator (NOT in the active validator set)", "addr", addr, - "pubKey", pubKey.Bytes(), + "pubKey", k.Bytes(), ) } } } -func onlyValidatorIsUs(state sm.State, pubKey crypto.PubKey) bool { +func onlyValidatorIsUs(state sm.State, pubKey utils.Option[crypto.PubKey]) bool { + k, ok := pubKey.Get() + if !ok { + return false + } if state.Validators.Size() > 1 { return false } addr, _ := state.Validators.GetByIndex(0) - return pubKey != nil && bytes.Equal(pubKey.Address(), addr) + return bytes.Equal(k.Address(), addr) } func createMempoolReactor( diff --git a/sei-tendermint/privval/file.go b/sei-tendermint/privval/file.go index aa5eca2f2a..205dc0de28 100644 --- a/sei-tendermint/privval/file.go +++ b/sei-tendermint/privval/file.go @@ -197,8 +197,8 @@ var _ types.PrivValidator = (*FilePV)(nil) func NewFilePV(privKey crypto.PrivKey, keyFilePath, stateFilePath string) *FilePV { return &FilePV{ Key: FilePVKey{ - Address: privKey.PubKey().Address(), - PubKey: privKey.PubKey(), + Address: privKey.Public().Address(), + PubKey: privKey.Public(), PrivKey: privKey, filePath: keyFilePath, }, @@ -215,7 +215,8 @@ func GenFilePV(keyFilePath, stateFilePath, keyType string) (*FilePV, error) { if keyType != "" && keyType != types.ABCIPubKeyTypeEd25519 { return nil, fmt.Errorf("key type: %s is not supported", keyType) } - return NewFilePV(ed25519.GenPrivKey(), keyFilePath, stateFilePath), nil + privKey := ed25519.GenerateSecretKey() + return NewFilePV(privKey, keyFilePath, stateFilePath), nil } // LoadFilePV loads a FilePV from the filePaths. The FilePV handles double @@ -244,7 +245,7 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) (*FilePV, err } // overwrite pubkey and address for convenience - pvKey.PubKey = pvKey.PrivKey.PubKey() + pvKey.PubKey = pvKey.PrivKey.Public() pvKey.Address = pvKey.PubKey.Address() pvKey.filePath = keyFilePath @@ -396,14 +397,12 @@ func (pv *FilePV) signVote(chainID string, vote *tmproto.Vote) error { } // It passed the checks. Sign the vote - sig, err := pv.Key.PrivKey.Sign(signBytes) - if err != nil { - return err - } - if err := pv.saveSigned(height, round, step, signBytes, sig); err != nil { + sig := pv.Key.PrivKey.Sign(signBytes) + sigBytes := sig.Bytes() + if err := pv.saveSigned(height, round, step, signBytes, sigBytes); err != nil { return err } - vote.Signature = sig + vote.Signature = sigBytes return nil } @@ -433,14 +432,12 @@ func (pv *FilePV) signProposal(chainID string, proposal *tmproto.Proposal) error } // It passed the checks. Sign the proposal - sig, err := pv.Key.PrivKey.Sign(signBytes) - if err != nil { - return err - } - if err := pv.saveSigned(height, round, step, signBytes, sig); err != nil { + sig := pv.Key.PrivKey.Sign(signBytes) + sigBytes := sig.Bytes() + if err := pv.saveSigned(height, round, step, signBytes, sigBytes); err != nil { return err } - proposal.Signature = sig + proposal.Signature = sigBytes return nil } diff --git a/sei-tendermint/privval/file_test.go b/sei-tendermint/privval/file_test.go index a2decc77c0..6b16775260 100644 --- a/sei-tendermint/privval/file_test.go +++ b/sei-tendermint/privval/file_test.go @@ -108,12 +108,14 @@ func TestUnmarshalValidatorState(t *testing.T) { func TestUnmarshalValidatorKey(t *testing.T) { // create some fixed values - privKey := ed25519.GenPrivKey() - pubKey := privKey.PubKey() + privKey := ed25519.GenerateSecretKey() + pubKey := privKey.Public() addr := pubKey.Address() - pubBytes := pubKey.Bytes() - privBytes := privKey.Bytes() - pubB64 := base64.StdEncoding.EncodeToString(pubBytes) + pubB64 := base64.StdEncoding.EncodeToString(pubKey.Bytes()) + privJSON, err := json.Marshal(privKey) + require.NoError(t, err) + var privBytes []byte + require.NoError(t, json.Unmarshal(privJSON, &privBytes)) privB64 := base64.StdEncoding.EncodeToString(privBytes) serialized := fmt.Sprintf(`{ @@ -129,7 +131,7 @@ func TestUnmarshalValidatorKey(t *testing.T) { }`, addr, pubB64, privB64) val := FilePVKey{} - err := tmjson.Unmarshal([]byte(serialized), &val) + err = tmjson.Unmarshal([]byte(serialized), &val) require.NoError(t, err) // make sure the values match diff --git a/sei-tendermint/privval/grpc/client.go b/sei-tendermint/privval/grpc/client.go index f4c0b7d999..78e9aa22d2 100644 --- a/sei-tendermint/privval/grpc/client.go +++ b/sei-tendermint/privval/grpc/client.go @@ -59,12 +59,12 @@ func (sc *SignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) { if err != nil { errStatus, _ := status.FromError(err) sc.logger.Error("SignerClient::GetPubKey", "err", errStatus.Message()) - return nil, errStatus.Err() + return crypto.PubKey{}, errStatus.Err() } pk, err := encoding.PubKeyFromProto(resp.PubKey) if err != nil { - return nil, err + return crypto.PubKey{}, err } return pk, nil diff --git a/sei-tendermint/privval/grpc/client_test.go b/sei-tendermint/privval/grpc/client_test.go index cd2f6ba3b4..4b4fc64517 100644 --- a/sei-tendermint/privval/grpc/client_test.go +++ b/sei-tendermint/privval/grpc/client_test.go @@ -60,7 +60,7 @@ func TestSignerClient_GetPubKey(t *testing.T) { pk, err := client.GetPubKey(ctx) require.NoError(t, err) - assert.Equal(t, mockPV.PrivKey.PubKey(), pk) + assert.Equal(t, mockPV.PrivKey.Public(), pk) } func TestSignerClient_SignVote(t *testing.T) { diff --git a/sei-tendermint/privval/grpc/server.go b/sei-tendermint/privval/grpc/server.go index 40af824795..8a3de0faa9 100644 --- a/sei-tendermint/privval/grpc/server.go +++ b/sei-tendermint/privval/grpc/server.go @@ -41,15 +41,8 @@ func (ss *SignerServer) GetPubKey(ctx context.Context, req *privvalproto.PubKeyR if err != nil { return nil, status.Errorf(codes.NotFound, "error getting pubkey: %v", err) } - - pk, err := encoding.PubKeyToProto(pubKey) - if err != nil { - return nil, status.Errorf(codes.Internal, "error transitioning pubkey to proto: %v", err) - } - ss.logger.Info("SignerServer: GetPubKey Success") - - return &privvalproto.PubKeyResponse{PubKey: pk}, nil + return &privvalproto.PubKeyResponse{PubKey: encoding.PubKeyToProto(pubKey)}, nil } // SignVote receives a vote sign requests, attempts to sign it diff --git a/sei-tendermint/privval/grpc/server_test.go b/sei-tendermint/privval/grpc/server_test.go index 92bb42d751..ed79468c6c 100644 --- a/sei-tendermint/privval/grpc/server_test.go +++ b/sei-tendermint/privval/grpc/server_test.go @@ -5,11 +5,14 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" tmgrpc "github.com/tendermint/tendermint/privval/grpc" privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -18,6 +21,8 @@ import ( const ChainID = "123" +var testKey = ed25519.TestSecretKey([]byte("test")) + func TestGetPubKey(t *testing.T) { testCases := []struct { @@ -43,7 +48,7 @@ func TestGetPubKey(t *testing.T) { } else { pk, err := tc.pv.GetPubKey(ctx) require.NoError(t, err) - assert.Equal(t, resp.PubKey.GetEd25519(), pk.Bytes()) + require.Equal(t, resp.PubKey, encoding.PubKeyToProto(pk)) } }) } @@ -88,7 +93,7 @@ func TestSignVote(t *testing.T) { Timestamp: ts, ValidatorAddress: valAddr, ValidatorIndex: 1, - Signature: []byte("signed"), + Signature: utils.Some(testKey.Sign([]byte("signed"))), }, want: &types.Vote{ Type: tmproto.PrecommitType, Height: 1, @@ -97,7 +102,7 @@ func TestSignVote(t *testing.T) { Timestamp: ts, ValidatorAddress: valAddr, ValidatorIndex: 1, - Signature: []byte("signed"), + Signature: utils.Some(testKey.Sign([]byte("signed"))), }, err: true}, } @@ -158,7 +163,7 @@ func TestSignProposal(t *testing.T) { POLRound: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, Timestamp: ts, - Signature: []byte("signed"), + Signature: testKey.Sign([]byte("signed")), }, want: &types.Proposal{ Type: tmproto.ProposalType, Height: 1, @@ -166,7 +171,7 @@ func TestSignProposal(t *testing.T) { POLRound: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, Timestamp: ts, - Signature: []byte("signed"), + Signature: testKey.Sign([]byte("signed")), }, err: true}, } diff --git a/sei-tendermint/privval/msgs_test.go b/sei-tendermint/privval/msgs_test.go index 9105f5987c..77a01a8329 100644 --- a/sei-tendermint/privval/msgs_test.go +++ b/sei-tendermint/privval/msgs_test.go @@ -39,7 +39,6 @@ func exampleProposal() *types.Proposal { Round: 2, Timestamp: stamp, POLRound: 2, - Signature: []byte("it's a signature"), BlockID: types.BlockID{ Hash: crypto.Checksum([]byte("blockID_hash")), PartSetHeader: types.PartSetHeader{ @@ -51,9 +50,9 @@ func exampleProposal() *types.Proposal { } func TestPrivvalVectors(t *testing.T) { - pk := ed25519.GenPrivKeyFromSecret([]byte("it's a secret")).PubKey() - ppk, err := encoding.PubKeyToProto(pk) - require.NoError(t, err) + // WARNING: this key has to be stable for hashes to match. + pk := ed25519.TestSecretKey([]byte("it's a secret")).Public() + ppk := encoding.PubKeyToProto(pk) // Generate a simple vote vote := exampleVote() @@ -62,6 +61,8 @@ func TestPrivvalVectors(t *testing.T) { // Generate a simple proposal proposal := exampleProposal() proposalpb := proposal.ToProto() + // we set invalid signature for the hashes to match. + proposalpb.Signature = []byte("it's a signature") // Create a Reuseable remote error remoteError := &privproto.RemoteSignerError{Code: 1, Description: "it's a error"} diff --git a/sei-tendermint/privval/retry_signer_client.go b/sei-tendermint/privval/retry_signer_client.go index 6dacc9a288..71b1dcdb85 100644 --- a/sei-tendermint/privval/retry_signer_client.go +++ b/sei-tendermint/privval/retry_signer_client.go @@ -59,16 +59,16 @@ func (sc *RetrySignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, erro } // If remote signer errors, we don't retry. if _, ok := err.(*RemoteSignerError); ok { - return nil, err + return pk, err } select { case <-ctx.Done(): - return nil, ctx.Err() + return pk, ctx.Err() case <-t.C: t.Reset(sc.timeout) } } - return nil, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) + return pk, fmt.Errorf("exhausted all attempts to get pubkey: %w", err) } func (sc *RetrySignerClient) SignVote(ctx context.Context, chainID string, vote *tmproto.Vote) error { diff --git a/sei-tendermint/privval/secret_connection.go b/sei-tendermint/privval/secret_connection.go index 96a4c8d95a..5264fddc6d 100644 --- a/sei-tendermint/privval/secret_connection.go +++ b/sei-tendermint/privval/secret_connection.go @@ -69,7 +69,7 @@ type SecretConnection struct { recvAead cipher.AEAD sendAead cipher.AEAD - remPubKey ed25519.PubKey + remPubKey ed25519.PublicKey conn io.ReadWriteCloser // net.Conn must be thread safe: @@ -92,10 +92,8 @@ type SecretConnection struct { // Returns nil if there is an error in handshake. // Caller should call conn.Close() // See docs/sts-final.pdf for more information. -func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) (*SecretConnection, error) { - var ( - locPubKey = locPrivKey.PubKey() - ) +func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.SecretKey) (*SecretConnection, error) { + locPubKey := locPrivKey.Public() // Generate ephemeral keys for perfect forward secrecy. locEphPub, locEphPriv, err := genEphKeys() @@ -162,10 +160,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( } // Sign the challenge bytes for authentication. - locSignature, err := signChallenge(&challenge, locPrivKey) - if err != nil { - return nil, err - } + locSignature := signChallenge(&challenge, locPrivKey) // Share (in secret) each other's pubkey & challenge signature authSigMsg, err := shareAuthSignature(sc, locPubKey, locSignature) @@ -174,8 +169,8 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( } remPubKey, remSignature := authSigMsg.Key, authSigMsg.Sig - if !remPubKey.VerifySignature(challenge[:], remSignature) { - return nil, errors.New("challenge verification failed") + if err := remPubKey.Verify(challenge[:], remSignature); err != nil { + return nil, fmt.Errorf("challenge verification failed: %w", err) } // We've authorized. @@ -184,7 +179,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey ed25519.PrivKey) ( } // RemotePubKey returns authenticated remote pubkey -func (sc *SecretConnection) RemotePubKey() ed25519.PubKey { +func (sc *SecretConnection) RemotePubKey() ed25519.PublicKey { return sc.remPubKey } @@ -396,26 +391,22 @@ func sort32(foo, bar *[32]byte) (lo, hi *[32]byte) { return } -func signChallenge(challenge *[32]byte, locPrivKey ed25519.PrivKey) ([]byte, error) { - signature, err := locPrivKey.Sign(challenge[:]) - if err != nil { - return nil, err - } - return signature, nil +func signChallenge(challenge *[32]byte, locPrivKey ed25519.SecretKey) ed25519.Signature { + return locPrivKey.Sign(challenge[:]) } type authSigMessage struct { - Key ed25519.PubKey - Sig []byte + Key ed25519.PublicKey + Sig ed25519.Signature } -func shareAuthSignature(sc io.ReadWriter, pubKey ed25519.PubKey, signature []byte) (recvMsg authSigMessage, err error) { +func shareAuthSignature(sc io.ReadWriter, pubKey ed25519.PublicKey, signature ed25519.Signature) (recvMsg authSigMessage, err error) { // Send our info and receive theirs in tandem. var trs, _ = async.Parallel( func(_ int) (val interface{}, abort bool, err error) { - pk := tmproto.PublicKey{Sum: &tmproto.PublicKey_Ed25519{Ed25519: pubKey}} - _, err = protoio.NewDelimitedWriter(sc).WriteMsg(&tmprivval.AuthSigMessage{PubKey: pk, Sig: signature}) + pk := tmproto.PublicKey{Sum: &tmproto.PublicKey_Ed25519{Ed25519: pubKey.Bytes()}} + _, err = protoio.NewDelimitedWriter(sc).WriteMsg(&tmprivval.AuthSigMessage{PubKey: pk, Sig: signature.Bytes()}) if err != nil { return nil, true, err // abort } @@ -428,16 +419,15 @@ func shareAuthSignature(sc io.ReadWriter, pubKey ed25519.PubKey, signature []byt return nil, true, err // abort } - pk := pba.PubKey.GetEd25519() - if len(pk) != ed25519.PubKeySize { - return nil, true, fmt.Errorf("invalid ed25519 key size") + key, err := ed25519.PublicKeyFromBytes(pba.PubKey.GetEd25519()) + if err != nil { + return nil, true, fmt.Errorf("PubKey: %w", err) } - - _recvMsg := authSigMessage{ - Key: ed25519.PubKey(pk), - Sig: pba.Sig, + sig, err := ed25519.SignatureFromBytes(pba.Sig) + if err != nil { + return nil, true, fmt.Errorf("Sig: %w", err) } - return _recvMsg, false, nil + return authSigMessage{key, sig}, false, nil }, ) diff --git a/sei-tendermint/privval/signer_client.go b/sei-tendermint/privval/signer_client.go index 10ce8bc75a..3a6f194d29 100644 --- a/sei-tendermint/privval/signer_client.go +++ b/sei-tendermint/privval/signer_client.go @@ -83,20 +83,20 @@ func (sc *SignerClient) Ping(ctx context.Context) error { func (sc *SignerClient) GetPubKey(ctx context.Context) (crypto.PubKey, error) { response, err := sc.endpoint.SendRequest(ctx, mustWrapMsg(&privvalproto.PubKeyRequest{ChainId: sc.chainID})) if err != nil { - return nil, fmt.Errorf("send: %w", err) + return crypto.PubKey{}, fmt.Errorf("send: %w", err) } resp := response.GetPubKeyResponse() if resp == nil { - return nil, ErrUnexpectedResponse + return crypto.PubKey{}, ErrUnexpectedResponse } if resp.Error != nil { - return nil, &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} + return crypto.PubKey{}, &RemoteSignerError{Code: int(resp.Error.Code), Description: resp.Error.Description} } pk, err := encoding.PubKeyFromProto(resp.PubKey) if err != nil { - return nil, err + return crypto.PubKey{}, err } return pk, nil diff --git a/sei-tendermint/privval/signer_client_test.go b/sei-tendermint/privval/signer_client_test.go index a293b6378f..7b08c6ce69 100644 --- a/sei-tendermint/privval/signer_client_test.go +++ b/sei-tendermint/privval/signer_client_test.go @@ -11,8 +11,10 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" cryptoproto "github.com/tendermint/tendermint/proto/tendermint/crypto" privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -62,6 +64,8 @@ func getSignerTestCases(ctx context.Context, t *testing.T, logger log.Logger) [] return testCases } +var testKey = ed25519.TestSecretKey([]byte("test")) + func TestSignerClose(t *testing.T) { t.Cleanup(leaktest.Check(t)) @@ -329,7 +333,7 @@ func TestSignerSignProposalErrors(t *testing.T) { POLRound: 2, BlockID: types.BlockID{Hash: hash, PartSetHeader: types.PartSetHeader{Hash: hash, Total: 2}}, Timestamp: ts, - Signature: []byte("signature"), + Signature: testKey.Sign([]byte("signature")), } err := tc.signerClient.SignProposal(ctx, tc.chainID, proposal.ToProto()) @@ -368,7 +372,7 @@ func TestSignerSignVoteErrors(t *testing.T) { Timestamp: ts, ValidatorAddress: valAddr, ValidatorIndex: 1, - Signature: []byte("signature"), + Signature: utils.Some(testKey.Sign([]byte("signature"))), } // Replace signer service privval with one that always fails diff --git a/sei-tendermint/privval/signer_listener_endpoint_test.go b/sei-tendermint/privval/signer_listener_endpoint_test.go index 8419530da7..81d71b76bf 100644 --- a/sei-tendermint/privval/signer_listener_endpoint_test.go +++ b/sei-tendermint/privval/signer_listener_endpoint_test.go @@ -69,7 +69,7 @@ func TestSignerRemoteRetryTCPOnly(t *testing.T) { }(ln, attemptCh) dialerEndpoint := NewSignerDialerEndpoint(logger, - DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, ed25519.GenPrivKey()), + DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, ed25519.GenerateSecretKey()), ) SignerDialerEndpointTimeoutReadWrite(time.Millisecond)(dialerEndpoint) SignerDialerEndpointConnRetries(retries)(dialerEndpoint) @@ -160,7 +160,7 @@ func newSignerListenerEndpoint(t *testing.T, logger log.Logger, addr string, tim UnixListenerTimeoutReadWrite(timeoutReadWrite)(unixLn) listener = unixLn } else { - tcpLn := NewTCPListener(ln, ed25519.GenPrivKey()) + tcpLn := NewTCPListener(ln, ed25519.GenerateSecretKey()) TCPListenerTimeoutAccept(testTimeoutAccept)(tcpLn) TCPListenerTimeoutReadWrite(timeoutReadWrite)(tcpLn) listener = tcpLn diff --git a/sei-tendermint/privval/signer_requestHandler.go b/sei-tendermint/privval/signer_requestHandler.go index d07c656208..b0908c50c6 100644 --- a/sei-tendermint/privval/signer_requestHandler.go +++ b/sei-tendermint/privval/signer_requestHandler.go @@ -37,11 +37,7 @@ func DefaultValidationRequestHandler( if err != nil { return res, err } - pk, err := encoding.PubKeyToProto(pubKey) - if err != nil { - return res, err - } - + pk := encoding.PubKeyToProto(pubKey) if err != nil { res = mustWrapMsg(&privvalproto.PubKeyResponse{ PubKey: cryptoproto.PublicKey{}, Error: &privvalproto.RemoteSignerError{Code: 0, Description: err.Error()}}) diff --git a/sei-tendermint/privval/socket_dialers_test.go b/sei-tendermint/privval/socket_dialers_test.go index 7ec8fe30f6..3ef8a4886e 100644 --- a/sei-tendermint/privval/socket_dialers_test.go +++ b/sei-tendermint/privval/socket_dialers_test.go @@ -30,7 +30,7 @@ func getDialerTestCases(t *testing.T) []dialerTestCase { return []dialerTestCase{ { addr: tcpAddr, - dialer: DialTCPFn(tcpAddr, testTimeoutReadWrite, ed25519.GenPrivKey()), + dialer: DialTCPFn(tcpAddr, testTimeoutReadWrite, ed25519.GenerateSecretKey()), }, { addr: unixAddr, @@ -42,7 +42,7 @@ func getDialerTestCases(t *testing.T) []dialerTestCase { func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) { // Generate a networking timeout tcpAddr := getFreeLocalhostAddrPort(t) - dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) + dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenerateSecretKey()) _, err := dialer() assert.Error(t, err) assert.True(t, IsConnTimeout(err)) @@ -50,7 +50,7 @@ func TestIsConnTimeoutForFundamentalTimeouts(t *testing.T) { func TestIsConnTimeoutForWrappedConnTimeouts(t *testing.T) { tcpAddr := getFreeLocalhostAddrPort(t) - dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenPrivKey()) + dialer := DialTCPFn(tcpAddr, time.Millisecond, ed25519.GenerateSecretKey()) _, err := dialer() assert.Error(t, err) err = fmt.Errorf("%v: %w", err, ErrConnectionTimeout) diff --git a/sei-tendermint/privval/socket_listeners.go b/sei-tendermint/privval/socket_listeners.go index 953c56bfe3..0c08310f6f 100644 --- a/sei-tendermint/privval/socket_listeners.go +++ b/sei-tendermint/privval/socket_listeners.go @@ -43,7 +43,7 @@ var _ net.Listener = (*TCPListener)(nil) type TCPListener struct { *net.TCPListener - secretConnKey ed25519.PrivKey + secretConnKey ed25519.SecretKey timeoutAccept time.Duration timeoutReadWrite time.Duration @@ -51,7 +51,7 @@ type TCPListener struct { // NewTCPListener returns a listener that accepts authenticated encrypted connections // using the given secretConnKey and the default timeout values. -func NewTCPListener(ln net.Listener, secretConnKey ed25519.PrivKey) *TCPListener { +func NewTCPListener(ln net.Listener, secretConnKey ed25519.SecretKey) *TCPListener { return &TCPListener{ TCPListener: ln.(*net.TCPListener), secretConnKey: secretConnKey, diff --git a/sei-tendermint/privval/socket_listeners_test.go b/sei-tendermint/privval/socket_listeners_test.go index ff9c24cab9..4255ca334c 100644 --- a/sei-tendermint/privval/socket_listeners_test.go +++ b/sei-tendermint/privval/socket_listeners_test.go @@ -9,16 +9,6 @@ import ( "github.com/tendermint/tendermint/crypto/ed25519" ) -//------------------------------------------- -// helper funcs - -func newPrivKey() ed25519.PrivKey { - return ed25519.GenPrivKey() -} - -//------------------------------------------- -// tests - type listenerTestCase struct { description string // For test reporting purposes. listener net.Listener @@ -47,13 +37,13 @@ func tcpListenerTestCase(t *testing.T, timeoutAccept, timeoutReadWrite time.Dura t.Fatal(err) } - tcpLn := NewTCPListener(ln, newPrivKey()) + tcpLn := NewTCPListener(ln, ed25519.GenerateSecretKey()) TCPListenerTimeoutAccept(timeoutAccept)(tcpLn) TCPListenerTimeoutReadWrite(timeoutReadWrite)(tcpLn) return listenerTestCase{ description: "TCP", listener: tcpLn, - dialer: DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, newPrivKey()), + dialer: DialTCPFn(ln.Addr().String(), testTimeoutReadWrite, ed25519.GenerateSecretKey()), } } diff --git a/sei-tendermint/privval/utils.go b/sei-tendermint/privval/utils.go index a2cbbf5014..2d345e05a0 100644 --- a/sei-tendermint/privval/utils.go +++ b/sei-tendermint/privval/utils.go @@ -43,7 +43,7 @@ func NewSignerListener(listenAddr string, logger log.Logger) (*SignerListenerEnd listener = NewUnixListener(ln) case "tcp": // TODO: persist this key so external signer can actually authenticate us - listener = NewTCPListener(ln, ed25519.GenPrivKey()) + listener = NewTCPListener(ln, ed25519.GenerateSecretKey()) default: panic("invalid protocol: " + protocol) // semantically unreachable } diff --git a/sei-tendermint/rpc/client/evidence_test.go b/sei-tendermint/rpc/client/evidence_test.go index 0096d09240..87e0f6b29e 100644 --- a/sei-tendermint/rpc/client/evidence_test.go +++ b/sei-tendermint/rpc/client/evidence_test.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/crypto" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" "github.com/tendermint/tendermint/privval" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/rpc/client" @@ -26,11 +27,9 @@ func newEvidence(t *testing.T, val *privval.FilePV, v := vote.ToProto() v2 := vote2.ToProto() - vote.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v)) - require.NoError(t, err) + vote.Signature = utils.Some(val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v))) - vote2.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2)) - require.NoError(t, err) + vote2.Signature = utils.Some(val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2))) validator := types.NewValidator(val.Key.PubKey, 10) valSet := types.NewValidatorSet([]*types.Validator{validator}) diff --git a/sei-tendermint/rpc/client/http/http.go b/sei-tendermint/rpc/client/http/http.go index 915a42bbbb..9191f8ec7e 100644 --- a/sei-tendermint/rpc/client/http/http.go +++ b/sei-tendermint/rpc/client/http/http.go @@ -173,7 +173,7 @@ func (c *HTTP) NewBatch() *BatchHTTP { // compilation of the batched requests and send them off using the client as a // single request. On success, this returns a list of the deserialized results // from each request in the sent batch. -func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) { +func (b *BatchHTTP) Send(ctx context.Context) ([]any, error) { return b.rpcBatch.Send(ctx) } diff --git a/sei-tendermint/rpc/client/rpc_test.go b/sei-tendermint/rpc/client/rpc_test.go index 6b7a2a0ff0..b8c3c5cac5 100644 --- a/sei-tendermint/rpc/client/rpc_test.go +++ b/sei-tendermint/rpc/client/rpc_test.go @@ -13,7 +13,6 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/config" @@ -24,11 +23,12 @@ import ( "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" "github.com/tendermint/tendermint/libs/service" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" "github.com/tendermint/tendermint/privval" "github.com/tendermint/tendermint/rpc/client" rpchttp "github.com/tendermint/tendermint/rpc/client/http" rpclocal "github.com/tendermint/tendermint/rpc/client/local" - "github.com/tendermint/tendermint/rpc/coretypes" rpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" "github.com/tendermint/tendermint/types" ) @@ -125,13 +125,13 @@ func TestClientOperations(t *testing.T) { require.NoError(t, err, "%+v", err) defer resp.Body.Close() - assert.Equal(t, resp.Header.Get("Access-Control-Allow-Origin"), origin) + require.Equal(t, resp.Header.Get("Access-Control-Allow-Origin"), origin) }) t.Run("Batching", func(t *testing.T) { t.Run("JSONRPCCalls", func(t *testing.T) { logger := log.NewTestingLogger(t) c := getHTTPClient(t, logger, conf) - testBatchedJSONRPCCalls(ctx, t, c) + testBatchedJSONRPCCalls(ctx, c) }) t.Run("JSONRPCCallsCancellation", func(t *testing.T) { _, _, tx1 := MakeTxKV() @@ -171,11 +171,11 @@ func TestClientOperations(t *testing.T) { var wg sync.WaitGroup c := getHTTPClient(t, logger, conf) - for i := 0; i < 50; i++ { + for range 50 { wg.Add(1) go func() { defer wg.Done() - testBatchedJSONRPCCalls(ctx, t, c) + testBatchedJSONRPCCalls(ctx, c) }() } wg.Wait() @@ -201,7 +201,7 @@ func TestClientMethodCalls(t *testing.T) { t.Run("Status", func(t *testing.T) { status, err := c.Status(t.Context()) require.NoError(t, err, "%d: %+v", i, err) - assert.Equal(t, conf.Moniker, status.NodeInfo.Moniker) + require.Equal(t, conf.Moniker, status.NodeInfo.Moniker) }) t.Run("Info", func(t *testing.T) { ctx := t.Context() @@ -211,16 +211,16 @@ func TestClientMethodCalls(t *testing.T) { status, err := c.Status(ctx) require.NoError(t, err) - assert.GreaterOrEqual(t, status.SyncInfo.LatestBlockHeight, info.Response.LastBlockHeight) - assert.True(t, strings.Contains(info.Response.Data, "size")) + require.GreaterOrEqual(t, status.SyncInfo.LatestBlockHeight, info.Response.LastBlockHeight) + require.True(t, strings.Contains(info.Response.Data, "size")) }) t.Run("NetInfo", func(t *testing.T) { nc, ok := c.(client.NetworkClient) require.True(t, ok, "%d", i) netinfo, err := nc.NetInfo(t.Context()) require.NoError(t, err, "%d: %+v", i, err) - assert.True(t, netinfo.Listening) - assert.Equal(t, 0, len(netinfo.Peers)) + require.True(t, netinfo.Listening) + require.Equal(t, 0, len(netinfo.Peers)) }) t.Run("DumpConsensusState", func(t *testing.T) { // FIXME: fix server so it doesn't panic on invalid input @@ -228,8 +228,8 @@ func TestClientMethodCalls(t *testing.T) { require.True(t, ok, "%d", i) cons, err := nc.DumpConsensusState(t.Context()) require.NoError(t, err, "%d: %+v", i, err) - assert.NotEmpty(t, cons.RoundState) - assert.Empty(t, cons.Peers) + require.NotEmpty(t, cons.RoundState) + require.Empty(t, cons.Peers) }) t.Run("ConsensusState", func(t *testing.T) { // FIXME: fix server so it doesn't panic on invalid input @@ -237,7 +237,7 @@ func TestClientMethodCalls(t *testing.T) { require.True(t, ok, "%d", i) cons, err := nc.ConsensusState(t.Context()) require.NoError(t, err, "%d: %+v", i, err) - assert.NotEmpty(t, cons.RoundState) + require.NotEmpty(t, cons.RoundState) }) t.Run("Health", func(t *testing.T) { nc, ok := c.(client.NetworkClient) @@ -264,8 +264,8 @@ func TestClientMethodCalls(t *testing.T) { val := vals.Validators[0] // make sure the current set is also the genesis set - assert.Equal(t, gval.Power, val.VotingPower) - assert.Equal(t, gval.PubKey, val.PubKey) + require.Equal(t, gval.Power, val.VotingPower) + require.Equal(t, gval.PubKey, val.PubKey) }) t.Run("GenesisChunked", func(t *testing.T) { ctx := t.Context() @@ -303,7 +303,7 @@ func TestClientMethodCalls(t *testing.T) { res, err := c.ABCIQuery(ctx, "/key", k) qres := res.Response if assert.NoError(t, err) && assert.True(t, qres.IsOK()) { - assert.EqualValues(t, v, qres.Value) + require.Equal(t, v, qres.Value) } }) t.Run("AppCalls", func(t *testing.T) { @@ -335,22 +335,22 @@ func TestClientMethodCalls(t *testing.T) { require.NoError(t, err) qres := _qres.Response if assert.True(t, qres.IsOK()) { - assert.Equal(t, k, qres.Key) - assert.EqualValues(t, v, qres.Value) + require.Equal(t, k, qres.Key) + require.Equal(t, v, qres.Value) } // make sure we can lookup the tx with proof ptx, err := c.Tx(ctx, bres.Hash, true) require.NoError(t, err) - assert.EqualValues(t, txh, ptx.Height) - assert.EqualValues(t, tx, ptx.Tx) + require.Equal(t, txh, ptx.Height) + require.Equal(t, tx, ptx.Tx) // and we can even check the block is added block, err := c.Block(ctx, &apph) require.NoError(t, err) appHash := block.Block.Header.AppHash - assert.True(t, len(appHash) > 0) - assert.EqualValues(t, apph, block.Block.Header.Height) + require.True(t, len(appHash) > 0) + require.Equal(t, apph, block.Block.Header.Height) blockByHash, err := c.BlockByHash(ctx, block.BlockID.Hash) require.NoError(t, err) @@ -368,42 +368,42 @@ func TestClientMethodCalls(t *testing.T) { // now check the results blockResults, err := c.BlockResults(ctx, &txh) require.NoError(t, err, "%d: %+v", i, err) - assert.Equal(t, txh, blockResults.Height) + require.Equal(t, txh, blockResults.Height) if assert.Equal(t, 1, len(blockResults.TxsResults)) { // check success code - assert.EqualValues(t, 0, blockResults.TxsResults[0].Code) + require.Equal(t, 0, blockResults.TxsResults[0].Code) } // check blockchain info, now that we know there is info info, err := c.BlockchainInfo(ctx, apph, apph) require.NoError(t, err) - assert.True(t, info.LastHeight >= apph) + require.True(t, info.LastHeight >= apph) if assert.Equal(t, 1, len(info.BlockMetas)) { lastMeta := info.BlockMetas[0] - assert.EqualValues(t, apph, lastMeta.Header.Height) + require.Equal(t, apph, lastMeta.Header.Height) blockData := block.Block - assert.Equal(t, blockData.Header.AppHash, lastMeta.Header.AppHash) - assert.Equal(t, block.BlockID, lastMeta.BlockID) + require.Equal(t, blockData.Header.AppHash, lastMeta.Header.AppHash) + require.Equal(t, block.BlockID, lastMeta.BlockID) } // and get the corresponding commit with the same apphash commit, err := c.Commit(ctx, &apph) require.NoError(t, err) cappHash := commit.Header.AppHash - assert.Equal(t, appHash, cappHash) - assert.NotNil(t, commit.Commit) + require.Equal(t, appHash, cappHash) + require.NotNil(t, commit.Commit) // compare the commits (note Commit(2) has commit from Block(3)) h = apph - 1 commit2, err := c.Commit(ctx, &h) require.NoError(t, err) - assert.Equal(t, block.Block.LastCommitHash, commit2.Commit.Hash()) + require.Equal(t, block.Block.LastCommitHash, commit2.Commit.Hash()) // and we got a proof that works! _pres, err := c.ABCIQueryWithOptions(ctx, "/key", k, client.ABCIQueryOptions{Prove: true}) require.NoError(t, err) pres := _pres.Response - assert.True(t, pres.IsOK()) + require.True(t, pres.IsOK()) // XXX Test proof }) @@ -415,26 +415,26 @@ func TestClientMethodCalls(t *testing.T) { res, err := c.BlockchainInfo(ctx, 0, 0) require.NoError(t, err, "%d: %+v", i, err) - assert.True(t, res.LastHeight > 0) - assert.True(t, len(res.BlockMetas) > 0) + require.True(t, res.LastHeight > 0) + require.True(t, len(res.BlockMetas) > 0) res, err = c.BlockchainInfo(ctx, 1, 1) require.NoError(t, err, "%d: %+v", i, err) - assert.True(t, res.LastHeight > 0) - assert.True(t, len(res.BlockMetas) == 1) + require.True(t, res.LastHeight > 0) + require.True(t, len(res.BlockMetas) == 1) res, err = c.BlockchainInfo(ctx, 1, 10000) require.NoError(t, err, "%d: %+v", i, err) - assert.True(t, res.LastHeight > 0) - assert.True(t, len(res.BlockMetas) < 100) + require.True(t, res.LastHeight > 0) + require.True(t, len(res.BlockMetas) < 100) for _, m := range res.BlockMetas { - assert.NotNil(t, m) + require.NotNil(t, m) } res, err = c.BlockchainInfo(ctx, 10000, 1) require.Error(t, err) - assert.Nil(t, res) - assert.Contains(t, err.Error(), "can't be greater than max") + require.Nil(t, res) + require.Contains(t, err.Error(), "can't be greater than max") }) t.Run("BroadcastTxCommit", func(t *testing.T) { ctx := t.Context() @@ -457,7 +457,7 @@ func TestClientMethodCalls(t *testing.T) { require.Equal(t, initMempoolSize+1, pool.Size()) txs := pool.ReapMaxTxs(len(tx)) - require.EqualValues(t, tx, txs[0]) + require.Equal(t, tx, txs[0]) pool.Flush() }) t.Run("CheckTx", func(t *testing.T) { @@ -466,9 +466,9 @@ func TestClientMethodCalls(t *testing.T) { res, err := c.CheckTx(ctx, tx) require.NoError(t, err) - assert.Equal(t, abci.CodeTypeOK, res.Code) + require.Equal(t, abci.CodeTypeOK, res.Code) - assert.Equal(t, 0, pool.Size(), "mempool must be empty") + require.Equal(t, 0, pool.Size(), "mempool must be empty") }) t.Run("Events", func(t *testing.T) { t.Run("Header", func(t *testing.T) { @@ -495,7 +495,7 @@ func TestClientMethodCalls(t *testing.T) { }) var firstBlockHeight int64 - for i := int64(0); i < 3; i++ { + for i := range int64(3) { event := <-eventCh blockEvent, ok := event.Data.(types.LegacyEventDataNewBlock) @@ -541,16 +541,14 @@ func TestClientMethodCalls(t *testing.T) { result, err := c.BroadcastEvidence(ctx, correct) require.NoError(t, err, "BroadcastEvidence(%s) failed", correct) - assert.Equal(t, correct.Hash(), result.Hash, "expected result hash to match evidence hash") + require.Equal(t, correct.Hash(), result.Hash, "expected result hash to match evidence hash") status, err := c.Status(ctx) require.NoError(t, err) err = client.WaitForHeight(ctx, c, status.SyncInfo.LatestBlockHeight+2, nil) require.NoError(t, err) - ed25519pub := pv.Key.PubKey - rawpub := ed25519pub.Bytes() - result2, err := c.ABCIQuery(ctx, "/val", rawpub) + result2, err := c.ABCIQuery(ctx, "/val", pv.Key.PubKey.Bytes()) require.NoError(t, err) qres := result2.Response require.True(t, qres.IsOK()) @@ -562,7 +560,7 @@ func TestClientMethodCalls(t *testing.T) { pk, err := encoding.PubKeyFromProto(v.PubKey) require.NoError(t, err) - require.EqualValues(t, rawpub, pk, "Stored PubKey not equal with expected, value %v", string(qres.Value)) + require.Equal(t, pv.Key.PubKey, pk, "Stored PubKey not equal with expected, value %v", string(qres.Value)) require.Equal(t, int64(9), v.Power, "Stored Power not equal with expected, value %v", string(qres.Value)) for _, fake := range fakes { @@ -605,7 +603,7 @@ func TestClientMethodCallsAdvanced(t *testing.T) { // populate mempool with 5 tx txs := make([]types.Tx, 5) ch := make(chan error, 5) - for i := 0; i < 5; i++ { + for i := range 5 { _, _, tx := MakeTxKV() txs[i] = tx @@ -614,7 +612,7 @@ func TestClientMethodCallsAdvanced(t *testing.T) { require.NoError(t, err) } // wait for tx to arrive in mempoool. - for i := 0; i < 5; i++ { + for range 5 { select { case <-ch: case <-time.After(5 * time.Second): @@ -716,16 +714,17 @@ func TestClientMethodCallsAdvanced(t *testing.T) { require.Error(t, err) } else { require.NoError(t, err, "%+v", err) - assert.EqualValues(t, txHeight, ptx.Height) - assert.EqualValues(t, tx, ptx.Tx) - assert.Zero(t, ptx.Index) - assert.True(t, ptx.TxResult.IsOK()) - assert.EqualValues(t, txHash, ptx.Hash) + require.Equal(t, txHeight, ptx.Height) + require.Equal(t, tx, ptx.Tx) + require.Zero(t, ptx.Index) + require.True(t, ptx.TxResult.IsOK()) + require.Equal(t, txHash, ptx.Hash) // time to verify the proof proof := ptx.Proof - if tc.prove && assert.EqualValues(t, tx, proof.Data) { - assert.NoError(t, proof.Proof.Verify(proof.RootHash, txHash)) + if tc.prove { + require.Equal(t, tx, proof.Data) + require.NoError(t, proof.Proof.Verify(proof.RootHash, txHash)) } } }) @@ -754,7 +753,7 @@ func TestClientMethodCallsAdvanced(t *testing.T) { c := getHTTPClient(t, logger, conf) // first we broadcast a few txs - for i := 0; i < 10; i++ { + for range 10 { _, _, tx := MakeTxKV() _, err := c.BroadcastTxSync(ctx, tx) require.NoError(t, err) @@ -779,15 +778,15 @@ func TestClientMethodCallsAdvanced(t *testing.T) { require.Equal(t, find.Hash, result.Txs[0].Hash) ptx := result.Txs[0] - assert.EqualValues(t, find.Height, ptx.Height) - assert.EqualValues(t, find.Tx, ptx.Tx) - assert.Zero(t, ptx.Index) - assert.True(t, ptx.TxResult.IsOK()) - assert.EqualValues(t, find.Hash, ptx.Hash) + require.Equal(t, find.Height, ptx.Height) + require.Equal(t, find.Tx, ptx.Tx) + require.Zero(t, ptx.Index) + require.True(t, ptx.TxResult.IsOK()) + require.Equal(t, find.Hash, ptx.Hash) // time to verify the proof - if assert.EqualValues(t, find.Tx, ptx.Proof.Data) { - assert.NoError(t, ptx.Proof.Proof.Verify(ptx.Proof.RootHash, find.Hash)) + if assert.Equal(t, find.Tx, ptx.Proof.Data) { + require.NoError(t, ptx.Proof.Proof.Verify(ptx.Proof.RootHash, find.Hash)) } // query by height @@ -874,51 +873,25 @@ func TestClientMethodCallsAdvanced(t *testing.T) { }) } -func testBatchedJSONRPCCalls(ctx context.Context, t *testing.T, c *rpchttp.HTTP) { - k1, v1, tx1 := MakeTxKV() - k2, v2, tx2 := MakeTxKV() +// WARNING: this function is called in subgoroutines to it shouldn't use testing.T. +func testBatchedJSONRPCCalls(ctx context.Context, c *rpchttp.HTTP) { + k1, _, tx1 := MakeTxKV() + k2, _, tx2 := MakeTxKV() batch := c.NewBatch() - r1, err := batch.BroadcastTxCommit(ctx, tx1) - require.NoError(t, err) - r2, err := batch.BroadcastTxCommit(ctx, tx2) - require.NoError(t, err) - require.Equal(t, 2, batch.Count()) - bresults, err := batch.Send(ctx) - require.NoError(t, err) - require.Len(t, bresults, 2) - require.Equal(t, 0, batch.Count()) - - bresult1, ok := bresults[0].(*coretypes.ResultBroadcastTxCommit) - require.True(t, ok) - require.Equal(t, *bresult1, *r1) - bresult2, ok := bresults[1].(*coretypes.ResultBroadcastTxCommit) - require.True(t, ok) - require.Equal(t, *bresult2, *r2) - apph := tmmath.MaxInt64(bresult1.Height, bresult2.Height) + 1 - - err = client.WaitForHeight(ctx, c, apph, nil) - require.NoError(t, err) - - q1, err := batch.ABCIQuery(ctx, "/key", k1) - require.NoError(t, err) - q2, err := batch.ABCIQuery(ctx, "/key", k2) - require.NoError(t, err) - require.Equal(t, 2, batch.Count()) - qresults, err := batch.Send(ctx) - require.NoError(t, err) - require.Len(t, qresults, 2) - require.Equal(t, 0, batch.Count()) - - qresult1, ok := qresults[0].(*coretypes.ResultABCIQuery) - require.True(t, ok) - require.Equal(t, *qresult1, *q1) - qresult2, ok := qresults[1].(*coretypes.ResultABCIQuery) - require.True(t, ok) - require.Equal(t, *qresult2, *q2) - - require.Equal(t, qresult1.Response.Key, k1) - require.Equal(t, qresult2.Response.Key, k2) - require.Equal(t, qresult1.Response.Value, v1) - require.Equal(t, qresult2.Response.Value, v2) + r1 := utils.OrPanic1(batch.BroadcastTxCommit(ctx, tx1)) + r2 := utils.OrPanic1(batch.BroadcastTxCommit(ctx, tx2)) + utils.OrPanic(utils.TestDiff(2, batch.Count())) + bresults := utils.OrPanic1(batch.Send(ctx)) + utils.OrPanic(utils.TestDiff(bresults, []any{r1, r2})) + utils.OrPanic(utils.TestDiff(0, batch.Count())) + apph := tmmath.MaxInt64(r1.Height, r2.Height) + 1 + + utils.OrPanic(client.WaitForHeight(ctx, c, apph, nil)) + + q1 := utils.OrPanic1(batch.ABCIQuery(ctx, "/key", k1)) + q2 := utils.OrPanic1(batch.ABCIQuery(ctx, "/key", k2)) + utils.OrPanic(utils.TestDiff(2, batch.Count())) + qresults := utils.OrPanic1(batch.Send(ctx)) + utils.OrPanic(utils.TestDiff(qresults, []any{q1, q2})) } diff --git a/sei-tendermint/rpc/coretypes/responses.go b/sei-tendermint/rpc/coretypes/responses.go index cce419b559..4bc184f037 100644 --- a/sei-tendermint/rpc/coretypes/responses.go +++ b/sei-tendermint/rpc/coretypes/responses.go @@ -11,6 +11,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/jsontypes" "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" ) @@ -124,8 +125,7 @@ type ApplicationInfo struct { // Info about the node's validator type ValidatorInfo struct { - Address bytes.HexBytes - PubKey crypto.PubKey + PubKey utils.Option[crypto.PubKey] VotingPower int64 } @@ -136,24 +136,27 @@ type validatorInfoJSON struct { } func (v ValidatorInfo) MarshalJSON() ([]byte, error) { - pk, err := jsontypes.Marshal(v.PubKey) - if err != nil { - return nil, err + j := validatorInfoJSON{VotingPower: v.VotingPower} + if k, ok := v.PubKey.Get(); ok { + pk, err := jsontypes.Marshal(k) + if err != nil { + return nil, err + } + j.PubKey = pk + j.Address = k.Address() } - return json.Marshal(validatorInfoJSON{ - Address: v.Address, PubKey: pk, VotingPower: v.VotingPower, - }) + return json.Marshal(j) } func (v *ValidatorInfo) UnmarshalJSON(data []byte) error { var val validatorInfoJSON - if err := json.Unmarshal(data, &val); err != nil { - return err - } - if err := jsontypes.Unmarshal(val.PubKey, &v.PubKey); err != nil { - return err + if len(val.PubKey) != 0 { + var pk crypto.PubKey + if err := jsontypes.Unmarshal(val.PubKey, &pk); err != nil { + return err + } + v.PubKey = utils.Some(pk) } - v.Address = val.Address v.VotingPower = val.VotingPower return nil } diff --git a/sei-tendermint/test/e2e/app/app.go b/sei-tendermint/test/e2e/app/app.go index 83d0f9b5b6..b65de0a1b9 100644 --- a/sei-tendermint/test/e2e/app/app.go +++ b/sei-tendermint/test/e2e/app/app.go @@ -14,6 +14,7 @@ import ( "github.com/tendermint/tendermint/abci/example/code" abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/version" @@ -388,7 +389,11 @@ func (app *Application) validatorUpdates(height uint64) (abci.ValidatorUpdates, if err != nil { return nil, fmt.Errorf("invalid base64 pubkey value %q: %w", keyString, err) } - valUpdates = append(valUpdates, abci.UpdateValidator(keyBytes, int64(power), app.cfg.KeyType)) + pubKey, err := ed25519.PublicKeyFromBytes(keyBytes) + if err != nil { + return nil, fmt.Errorf("invalid ed25519 pubkey value %q: %w", keyString, err) + } + valUpdates = append(valUpdates, abci.UpdateValidator(pubKey, int64(power), app.cfg.KeyType)) } // the validator updates could be returned in arbitrary order, diff --git a/sei-tendermint/test/e2e/node/main.go b/sei-tendermint/test/e2e/node/main.go index 360671231d..063e010286 100644 --- a/sei-tendermint/test/e2e/node/main.go +++ b/sei-tendermint/test/e2e/node/main.go @@ -227,7 +227,8 @@ func startSigner(ctx context.Context, logger log.Logger, cfg *Config) error { var dialFn privval.SocketDialer switch protocol { case "tcp": - dialFn = privval.DialTCPFn(address, 3*time.Second, ed25519.GenPrivKey()) + privKey := ed25519.GenerateSecretKey() + dialFn = privval.DialTCPFn(address, 3*time.Second, privKey) case "unix": dialFn = privval.DialUnixFn(address) case "grpc": diff --git a/sei-tendermint/test/e2e/pkg/testnet.go b/sei-tendermint/test/e2e/pkg/testnet.go index 0e74a5859b..25ba1da4a2 100644 --- a/sei-tendermint/test/e2e/pkg/testnet.go +++ b/sei-tendermint/test/e2e/pkg/testnet.go @@ -444,7 +444,8 @@ func (n Node) AddressP2P(withID bool) string { } addr := fmt.Sprintf("%v:26656", ip) if withID { - addr = fmt.Sprintf("%x@%v", n.NodeKey.PubKey().Address().Bytes(), addr) + pubKey := n.NodeKey.Public() + addr = fmt.Sprintf("%x@%v", pubKey.Address().Bytes(), addr) } return addr } @@ -481,8 +482,7 @@ func newKeyGenerator(seed int64) *keyGenerator { } func (g *keyGenerator) Generate(keyType string) crypto.PrivKey { - seed := make([]byte, ed25519.SeedSize) - + seed := make([]byte, 32) _, err := io.ReadFull(g.random, seed) if err != nil { panic(err) // this shouldn't happen @@ -490,7 +490,7 @@ func (g *keyGenerator) Generate(keyType string) crypto.PrivKey { if keyType != "" && keyType != "ed25519" { panic("KeyType not supported") } - return ed25519.GenPrivKeyFromSecret(seed) + return ed25519.TestSecretKey(seed) } // portGenerator generates local Docker proxy ports for each node. diff --git a/sei-tendermint/test/e2e/runner/evidence.go b/sei-tendermint/test/e2e/runner/evidence.go index 63c2442f59..0db664c4c2 100644 --- a/sei-tendermint/test/e2e/runner/evidence.go +++ b/sei-tendermint/test/e2e/runner/evidence.go @@ -228,7 +228,7 @@ func generateDuplicateVoteEvidence( func getRandomValidatorIndex(privVals []types.MockPV, vals *types.ValidatorSet) (types.MockPV, int32, error) { for _, idx := range rand.Perm(len(privVals)) { pv := privVals[idx] - valIdx, _ := vals.GetByAddress(pv.PrivKey.PubKey().Address()) + valIdx, _ := vals.GetByAddress(pv.PrivKey.Public().Address()) if valIdx >= 0 { return pv, valIdx, nil } @@ -239,12 +239,12 @@ func getRandomValidatorIndex(privVals []types.MockPV, vals *types.ValidatorSet) func readPrivKey(keyFilePath string) (crypto.PrivKey, error) { keyJSONBytes, err := os.ReadFile(keyFilePath) if err != nil { - return nil, err + return crypto.PrivKey{}, err } pvKey := privval.FilePVKey{} err = json.Unmarshal(keyJSONBytes, &pvKey) if err != nil { - return nil, fmt.Errorf("error reading PrivValidator key from %v: %w", keyFilePath, err) + return crypto.PrivKey{}, fmt.Errorf("error reading PrivValidator key from %v: %w", keyFilePath, err) } return pvKey.PrivKey, nil @@ -307,7 +307,7 @@ func mutateValidatorSet(ctx context.Context, privVals []types.MockPV, vals *type for idx, val := range newVals.Validators { found := false for _, p := range append(privVals, newPrivVal.(types.MockPV)) { - if bytes.Equal(p.PrivKey.PubKey().Address(), val.Address) { + if bytes.Equal(p.PrivKey.Public().Address(), val.Address) { pv[idx] = p found = true break diff --git a/sei-tendermint/test/e2e/runner/setup.go b/sei-tendermint/test/e2e/runner/setup.go index 0d2c389aea..e32bfd1371 100644 --- a/sei-tendermint/test/e2e/runner/setup.go +++ b/sei-tendermint/test/e2e/runner/setup.go @@ -122,7 +122,8 @@ func Setup(logger log.Logger, testnet *e2e.Testnet) error { // Set up a dummy validator. Tendermint requires a file PV even when not used, so we // give it a dummy such that it will fail if it actually tries to use it. - err = (privval.NewFilePV(ed25519.GenPrivKey(), + dummyKey := ed25519.GenerateSecretKey() + err = (privval.NewFilePV(dummyKey, filepath.Join(nodeDir, PrivvalDummyKeyFile), filepath.Join(nodeDir, PrivvalDummyStateFile), )).Save() @@ -209,10 +210,11 @@ func MakeGenesis(testnet *e2e.Testnet) (types.GenesisDoc, error) { genesis.ConsensusParams.Evidence.MaxAgeNumBlocks = e2e.EvidenceAgeHeight genesis.ConsensusParams.Evidence.MaxAgeDuration = e2e.EvidenceAgeTime for validator, power := range testnet.Validators { + pubKey := validator.PrivvalKey.Public() genesis.Validators = append(genesis.Validators, types.GenesisValidator{ Name: validator.Name, - Address: validator.PrivvalKey.PubKey().Address(), - PubKey: validator.PrivvalKey.PubKey(), + Address: pubKey.Address(), + PubKey: pubKey, Power: power, }) } @@ -388,7 +390,8 @@ func MakeAppConfig(node *e2e.Node) ([]byte, error) { for height, validators := range node.Testnet.ValidatorUpdates { updateVals := map[string]int64{} for node, power := range validators { - updateVals[base64.StdEncoding.EncodeToString(node.PrivvalKey.PubKey().Bytes())] = power + key := node.PrivvalKey.Public() + updateVals[base64.StdEncoding.EncodeToString(key.Bytes())] = power } validatorUpdates[fmt.Sprintf("%v", height)] = updateVals } diff --git a/sei-tendermint/test/e2e/tests/validator_test.go b/sei-tendermint/test/e2e/tests/validator_test.go index 6d7e68c68d..faac2782e6 100644 --- a/sei-tendermint/test/e2e/tests/validator_test.go +++ b/sei-tendermint/test/e2e/tests/validator_test.go @@ -67,7 +67,7 @@ func TestValidator_Propose(t *testing.T) { if node.Mode != e2e.ModeValidator { return } - address := node.PrivvalKey.PubKey().Address() + address := node.PrivvalKey.Public().Address() valSchedule := newValidatorSchedule(*node.Testnet) expectCount := 0 @@ -100,7 +100,7 @@ func TestValidator_Sign(t *testing.T) { if node.Mode != e2e.ModeValidator { return } - address := node.PrivvalKey.PubKey().Address() + address := node.PrivvalKey.Public().Address() valSchedule := newValidatorSchedule(*node.Testnet) expectCount := 0 @@ -172,7 +172,7 @@ func (s *validatorSchedule) Increment(heights int64) error { func makeVals(valMap map[*e2e.Node]int64) []*types.Validator { vals := make([]*types.Validator, 0, len(valMap)) for node, power := range valMap { - vals = append(vals, types.NewValidator(node.PrivvalKey.PubKey(), power)) + vals = append(vals, types.NewValidator(node.PrivvalKey.Public(), power)) } return vals } diff --git a/sei-tendermint/test/fuzz/tests/p2p_secretconnection_test.go b/sei-tendermint/test/fuzz/tests/p2p_secretconnection_test.go index 65f268a7bf..7c7cb38ed8 100644 --- a/sei-tendermint/test/fuzz/tests/p2p_secretconnection_test.go +++ b/sei-tendermint/test/fuzz/tests/p2p_secretconnection_test.go @@ -84,22 +84,22 @@ func makeKVStoreConnPair() (fooConn, barConn kvstoreConn) { func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) { var ( fooConn, barConn = makeKVStoreConnPair() - fooPrvKey = ed25519.GenPrivKey() - fooPubKey = fooPrvKey.PubKey() - barPrvKey = ed25519.GenPrivKey() - barPubKey = barPrvKey.PubKey() + fooPrvKey = ed25519.GenerateSecretKey() + fooPubKey = fooPrvKey.Public() + barPrvKey = ed25519.GenerateSecretKey() + barPubKey = barPrvKey.Public() ) // Make connections from both sides in parallel. var trs, ok = async.Parallel( - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { fooSecConn, err = sc.MakeSecretConnection(fooConn, fooPrvKey) if err != nil { log.Printf("failed to establish SecretConnection for foo: %v", err) return nil, true, err } remotePubBytes := fooSecConn.RemotePubKey() - if !remotePubBytes.Equals(barPubKey) { + if remotePubBytes != barPubKey { err = fmt.Errorf("unexpected fooSecConn.RemotePubKey. Expected %v, got %v", barPubKey, fooSecConn.RemotePubKey()) log.Print(err) @@ -107,14 +107,14 @@ func makeSecretConnPair() (fooSecConn, barSecConn *sc.SecretConnection) { } return nil, false, nil }, - func(_ int) (val interface{}, abort bool, err error) { + func(_ int) (val any, abort bool, err error) { barSecConn, err = sc.MakeSecretConnection(barConn, barPrvKey) if barSecConn == nil { log.Printf("failed to establish SecretConnection for bar: %v", err) return nil, true, err } remotePubBytes := barSecConn.RemotePubKey() - if !remotePubBytes.Equals(fooPubKey) { + if remotePubBytes != fooPubKey { err = fmt.Errorf("unexpected barSecConn.RemotePubKey. Expected %v, got %v", fooPubKey, barSecConn.RemotePubKey()) log.Print(err) diff --git a/sei-tendermint/types/block.go b/sei-tendermint/types/block.go index a35db7bc2b..a7a43ec839 100644 --- a/sei-tendermint/types/block.go +++ b/sei-tendermint/types/block.go @@ -17,8 +17,8 @@ import ( "github.com/tendermint/tendermint/libs/bits" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmmath "github.com/tendermint/tendermint/libs/math" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "github.com/tendermint/tendermint/utils" "github.com/tendermint/tendermint/version" ) @@ -245,7 +245,10 @@ func (b *Block) ToReqBeginBlock(vals []*Validator) abci.RequestBeginBlock { SignedLastBlock: commitSig.BlockIDFlag != BlockIDFlagAbsent, }) } - abciEvidence := b.Evidence.ToABCI() + var byzantineValidators []abci.Evidence + for _, e := range b.Evidence.ToABCI() { + byzantineValidators = append(byzantineValidators, abci.Evidence(e)) + } return abci.RequestBeginBlock{ Hash: b.hash, Header: *tmHeader, @@ -253,9 +256,7 @@ func (b *Block) ToReqBeginBlock(vals []*Validator) abci.RequestBeginBlock { Round: b.LastCommit.Round, Votes: votes, }, - ByzantineValidators: utils.Map(abciEvidence, func(e abci.Misbehavior) abci.Evidence { - return abci.Evidence(e) - }), + ByzantineValidators: byzantineValidators, } } @@ -640,10 +641,11 @@ const ( // CommitSig is a part of the Vote included in a Commit. type CommitSig struct { - BlockIDFlag BlockIDFlag `json:"block_id_flag"` - ValidatorAddress Address `json:"validator_address"` - Timestamp time.Time `json:"timestamp"` - Signature []byte `json:"signature"` + BlockIDFlag BlockIDFlag `json:"block_id_flag"` + // WARNING: all fields below should be zeroed if BlockIDFlag == BlockIDFlagAbsent + ValidatorAddress Address `json:"validator_address"` + Timestamp time.Time `json:"timestamp"` + Signature utils.Option[crypto.Sig] `json:"signature"` } func MaxCommitBytes(valCount int) int64 { @@ -667,8 +669,12 @@ func NewCommitSigAbsent() CommitSig { // 3. block ID flag // 4. timestamp func (cs CommitSig) String() string { + var sigBytes []byte + if sig, ok := cs.Signature.Get(); ok { + sigBytes = sig.Bytes() + } return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}", - tmbytes.Fingerprint(cs.Signature), + tmbytes.Fingerprint(sigBytes), tmbytes.Fingerprint(cs.ValidatorAddress), cs.BlockIDFlag, CanonicalTime(cs.Timestamp)) @@ -709,7 +715,7 @@ func (cs CommitSig) ValidateBasic() error { if !cs.Timestamp.IsZero() { return errors.New("time is present") } - if len(cs.Signature) != 0 { + if cs.Signature.IsPresent() { return errors.New("signature is present") } default: @@ -719,13 +725,10 @@ func (cs CommitSig) ValidateBasic() error { len(cs.ValidatorAddress), ) } - // NOTE: Timestamp validation is subtle and handled elsewhere. - if len(cs.Signature) == 0 { + if !cs.Signature.IsPresent() { return errors.New("signature is missing") } - if len(cs.Signature) > MaxSignatureSize { - return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) - } + // NOTE: Timestamp validation is subtle and handled elsewhere. } return nil @@ -736,12 +739,15 @@ func (cs *CommitSig) ToProto() *tmproto.CommitSig { if cs == nil { return nil } - + var signature []byte + if sig, ok := cs.Signature.Get(); ok { + signature = sig.Bytes() + } return &tmproto.CommitSig{ BlockIdFlag: tmproto.BlockIDFlag(cs.BlockIDFlag), ValidatorAddress: cs.ValidatorAddress, Timestamp: cs.Timestamp, - Signature: cs.Signature, + Signature: signature, } } @@ -751,7 +757,16 @@ func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error { cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag) cs.ValidatorAddress = csp.ValidatorAddress cs.Timestamp = csp.Timestamp - cs.Signature = csp.Signature + + if len(csp.Signature) > 0 { + sig, err := crypto.SigFromBytes(csp.Signature) + if err != nil { + return fmt.Errorf("Signature: %w", err) + } + cs.Signature = utils.Some(sig) + } else { + cs.Signature = utils.None[crypto.Sig]() + } return cs.ValidateBasic() } diff --git a/sei-tendermint/types/block_test.go b/sei-tendermint/types/block_test.go index 5838182826..3d10be46f2 100644 --- a/sei-tendermint/types/block_test.go +++ b/sei-tendermint/types/block_test.go @@ -18,11 +18,13 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/bits" "github.com/tendermint/tendermint/libs/bytes" tmrand "github.com/tendermint/tendermint/libs/rand" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" "github.com/tendermint/tendermint/version" @@ -33,6 +35,8 @@ func TestMain(m *testing.M) { os.Exit(code) } +var testKey = ed25519.TestSecretKey([]byte("test")) + func TestBlockAddEvidence(t *testing.T) { ctx := t.Context() @@ -112,7 +116,6 @@ func TestBlockValidateBasic(t *testing.T) { }, true}, } for i, tc := range testCases { - i := i t.Run(tc.testName, func(t *testing.T) { block := MakeBlock(h, txs, commit, evList) block.ProposerAddress = valSet.GetProposer().Address @@ -279,7 +282,7 @@ func TestCommitHash(t *testing.T) { BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: crypto.AddressHash([]byte("validator1")), Timestamp: time.Now(), - Signature: crypto.CRandBytes(64), + Signature: utils.Some(testKey.Sign([]byte("data"))), } baseCommit := &Commit{ @@ -341,7 +344,7 @@ func TestCommitHash(t *testing.T) { BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: crypto.AddressHash([]byte("validator2")), // Different validator Timestamp: time.Now(), - Signature: crypto.CRandBytes(64), + Signature: utils.Some(testKey.Sign([]byte("other-data"))), } differentSigCommit := &Commit{ Height: 100, @@ -366,7 +369,7 @@ func TestCommitValidateBasic(t *testing.T) { expectErr bool }{ {"Random Commit", func(com *Commit) {}, false}, - {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false}, + {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = utils.Some(testKey.Sign([]byte("whatever"))) }, false}, {"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true}, {"Incorrect round", func(com *Commit) { com.Round = -100 }, true}, } @@ -377,7 +380,8 @@ func TestCommitValidateBasic(t *testing.T) { com := randCommit(ctx, t, time.Now()) tc.malleateCommit(com) - assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result") + err := com.ValidateBasic() + assert.Equal(t, tc.expectErr, err != nil, "Validate Basic had an unexpected result: %v", err) }) } } @@ -391,7 +395,7 @@ func TestMaxCommitBytes(t *testing.T) { BlockIDFlag: BlockIDFlagNil, ValidatorAddress: crypto.AddressHash([]byte("validator_address")), Timestamp: timestamp, - Signature: crypto.CRandBytes(MaxSignatureSize), + Signature: utils.Some(testKey.Sign([]byte("data"))), } pbSig := cs.ToProto() @@ -520,7 +524,7 @@ func TestMaxHeaderBytes(t *testing.T) { // Each supplementary character takes 4 bytes. // http://www.i18nguy.com/unicode/supplementary-test.html maxChainID := "" - for i := 0; i < MaxChainIDLen; i++ { + for range MaxChainIDLen { maxChainID += "𠜎" } @@ -639,7 +643,7 @@ func TestVoteSetToCommit(t *testing.T) { valSet, vals := randValidatorPrivValSet(ctx, t, 10, 1) voteSet := NewVoteSet("test_chain_id", 3, 1, tmproto.PrecommitType, valSet) - for i := 0; i < len(vals); i++ { + for i := range vals { pubKey, err := vals[i].GetPubKey(ctx) require.NoError(t, err) vote := &Vote{ @@ -652,9 +656,8 @@ func TestVoteSetToCommit(t *testing.T) { Timestamp: time.Now(), } v := vote.ToProto() - err = vals[i].SignVote(ctx, voteSet.ChainID(), v) - require.NoError(t, err) - vote.Signature = v.Signature + require.NoError(t, vals[i].SignVote(ctx, voteSet.ChainID(), v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) added, err := voteSet.AddVote(vote) require.NoError(t, err) require.True(t, added) @@ -918,7 +921,6 @@ func TestHeaderProto(t *testing.T) { } for _, tt := range tc { - tt := tt t.Run(tt.msg, func(t *testing.T) { pb := tt.h1.ToProto() h, err := HeaderFromProto(pb) @@ -1028,7 +1030,7 @@ func TestCommitSig_ValidateBasic(t *testing.T) { }, { "BlockIDFlagAbsent signatures present", - CommitSig{BlockIDFlag: BlockIDFlagAbsent, Signature: []byte{0xAA}}, + CommitSig{BlockIDFlag: BlockIDFlagAbsent, Signature: utils.Some(testKey.Sign([]byte{0xAA}))}, true, "signature is present", }, { @@ -1046,25 +1048,16 @@ func TestCommitSig_ValidateBasic(t *testing.T) { CommitSig{ BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, crypto.AddressSize), - Signature: make([]byte, 0), + Signature: utils.None[crypto.Sig](), }, true, "signature is missing", }, - { - "non-BlockIDFlagAbsent invalid signature (too large)", - CommitSig{ - BlockIDFlag: BlockIDFlagCommit, - ValidatorAddress: make([]byte, crypto.AddressSize), - Signature: make([]byte, MaxSignatureSize+1), - }, - true, "signature is too big", - }, { "non-BlockIDFlagAbsent valid", CommitSig{ BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, crypto.AddressSize), - Signature: make([]byte, MaxSignatureSize), + Signature: utils.Some(testKey.Sign([]byte("data"))), }, false, "", }, @@ -1399,7 +1392,7 @@ func TestCommit_ValidateBasic(t *testing.T) { { BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, crypto.AddressSize), - Signature: make([]byte, MaxSignatureSize+1), + Signature: utils.None[crypto.Sig](), }, }, }, @@ -1420,7 +1413,7 @@ func TestCommit_ValidateBasic(t *testing.T) { { BlockIDFlag: BlockIDFlagCommit, ValidatorAddress: make([]byte, crypto.AddressSize), - Signature: make([]byte, MaxSignatureSize), + Signature: utils.Some(testKey.Sign([]byte("data"))), }, }, }, diff --git a/sei-tendermint/types/evidence.go b/sei-tendermint/types/evidence.go index e0091a202b..68b203e611 100644 --- a/sei-tendermint/types/evidence.go +++ b/sei-tendermint/types/evidence.go @@ -17,6 +17,7 @@ import ( "github.com/tendermint/tendermint/internal/jsontypes" tmmath "github.com/tendermint/tendermint/libs/math" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -855,12 +856,23 @@ func NewMockDuplicateVoteEvidenceWithValidator(ctx context.Context, height int64 val := NewValidator(pubKey, 10) voteA := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vA := voteA.ToProto() - _ = pv.SignVote(ctx, chainID, vA) - voteA.Signature = vA.Signature + if err := pv.SignVote(ctx, chainID, vA); err != nil { + return nil, err + } + sig, err := crypto.SigFromBytes(vA.Signature) + if err != nil { + return nil, err + } + voteA.Signature = utils.Some(sig) + voteB := makeMockVote(height, 0, 0, pubKey.Address(), randBlockID(), time) vB := voteB.ToProto() _ = pv.SignVote(ctx, chainID, vB) - voteB.Signature = vB.Signature + sig, err = crypto.SigFromBytes(vB.Signature) + if err != nil { + return nil, err + } + voteB.Signature = utils.Some(sig) ev, err := NewDuplicateVoteEvidence(voteA, voteB, time, NewValidatorSet([]*Validator{val})) if err != nil { return nil, fmt.Errorf("constructing mock duplicate vote evidence: %w", err) diff --git a/sei-tendermint/types/evidence_test.go b/sei-tendermint/types/evidence_test.go index f4bbe93885..4ce9288251 100644 --- a/sei-tendermint/types/evidence_test.go +++ b/sei-tendermint/types/evidence_test.go @@ -14,6 +14,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/version" ) @@ -313,7 +314,7 @@ func makeVote( err = val.SignVote(ctx, chainID, vpb) require.NoError(t, err) - v.Signature = vpb.Signature + v.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(vpb.Signature))) return v } @@ -383,7 +384,8 @@ func TestEvidenceVectors(t *testing.T) { // Votes for duplicateEvidence val := NewMockPV() - val.PrivKey = ed25519.GenPrivKeyFromSecret([]byte("it's a secret")) // deterministic key + // WARNING: this key has to be stable, otherwise hashes break. + val.PrivKey = ed25519.TestSecretKey([]byte("it's a secret")) blockID := makeBlockID(crypto.Checksum([]byte("blockhash")), math.MaxInt32, crypto.Checksum([]byte("partshash"))) blockID2 := makeBlockID(crypto.Checksum([]byte("blockhash2")), math.MaxInt32, crypto.Checksum([]byte("partshash"))) const chainID = "mychain" diff --git a/sei-tendermint/types/genesis_test.go b/sei-tendermint/types/genesis_test.go index 7223581118..527b5d93b9 100644 --- a/sei-tendermint/types/genesis_test.go +++ b/sei-tendermint/types/genesis_test.go @@ -89,7 +89,7 @@ func TestBasicGenesisDoc(t *testing.T) { _, err := GenesisDocFromJSON(genDocBytes) assert.NoError(t, err, "expected no error for good genDoc json") - pubkey := ed25519.GenPrivKey().PubKey() + pubkey := ed25519.GenerateSecretKey().Public() // create a base gendoc from struct baseGenDoc := &GenesisDoc{ ChainID: "abc", @@ -165,7 +165,7 @@ func TestGenesisValidatorHash(t *testing.T) { } func randomGenesisDoc() *GenesisDoc { - pubkey := ed25519.GenPrivKey().PubKey() + pubkey := ed25519.GenerateSecretKey().Public() return &GenesisDoc{ GenesisTime: tmtime.Now(), ChainID: "abc", diff --git a/sei-tendermint/types/node_info_test.go b/sei-tendermint/types/node_info_test.go index 0fdbcc96a7..2bfb2fbcb4 100644 --- a/sei-tendermint/types/node_info_test.go +++ b/sei-tendermint/types/node_info_test.go @@ -101,7 +101,7 @@ func TestNodeInfoValidate(t *testing.T) { } func testNodeID() NodeID { - return NodeIDFromPubKey(ed25519.GenPrivKey().PubKey()) + return NodeIDFromPubKey(ed25519.GenerateSecretKey().Public()) } func testNodeInfo(t *testing.T, id NodeID, name string) NodeInfo { diff --git a/sei-tendermint/types/node_key.go b/sei-tendermint/types/node_key.go index 927e17065d..e930dfaf2b 100644 --- a/sei-tendermint/types/node_key.go +++ b/sei-tendermint/types/node_key.go @@ -53,7 +53,7 @@ func (nk *NodeKey) UnmarshalJSON(data []byte) error { // PubKey returns the peer's PubKey func (nk NodeKey) PubKey() crypto.PubKey { - return nk.PrivKey.PubKey() + return nk.PrivKey.Public() } // SaveAs persists the NodeKey to filePath. @@ -87,9 +87,9 @@ func LoadOrGenNodeKey(filePath string) (NodeKey, error) { // GenNodeKey generates a new node key. func GenNodeKey() NodeKey { - privKey := ed25519.GenPrivKey() + privKey := ed25519.GenerateSecretKey() return NodeKey{ - ID: NodeIDFromPubKey(privKey.PubKey()), + ID: NodeIDFromPubKey(privKey.Public()), PrivKey: privKey, } } diff --git a/sei-tendermint/types/params.go b/sei-tendermint/types/params.go index 978e1a0c86..8f0f572f85 100644 --- a/sei-tendermint/types/params.go +++ b/sei-tendermint/types/params.go @@ -26,7 +26,7 @@ const ( ) var ABCIPubKeyTypesToNames = map[string]string{ - ABCIPubKeyTypeEd25519: ed25519.PubKeyName, + ABCIPubKeyTypeEd25519: ed25519.PublicKeyName, } // ConsensusParams contains consensus critical parameters that determine the diff --git a/sei-tendermint/types/priv_validator.go b/sei-tendermint/types/priv_validator.go index 5a9b27cb63..fac6643bce 100644 --- a/sei-tendermint/types/priv_validator.go +++ b/sei-tendermint/types/priv_validator.go @@ -67,7 +67,7 @@ type MockPV struct { } func NewMockPV() MockPV { - return MockPV{ed25519.GenPrivKey(), false, false} + return MockPV{ed25519.GenerateSecretKey(), false, false} } // NewMockPVWithParams allows one to create a MockPV instance, but with finer @@ -79,7 +79,7 @@ func NewMockPVWithParams(privKey crypto.PrivKey, breakProposalSigning, breakVote // Implements PrivValidator. func (pv MockPV) GetPubKey(ctx context.Context) (crypto.PubKey, error) { - return pv.PrivKey.PubKey(), nil + return pv.PrivKey.Public(), nil } // Implements PrivValidator. @@ -90,11 +90,8 @@ func (pv MockPV) SignVote(ctx context.Context, chainID string, vote *tmproto.Vot } signBytes := VoteSignBytes(useChainID, vote) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - vote.Signature = sig + sig := pv.PrivKey.Sign(signBytes) + vote.Signature = sig.Bytes() return nil } @@ -106,11 +103,8 @@ func (pv MockPV) SignProposal(ctx context.Context, chainID string, proposal *tmp } signBytes := ProposalSignBytes(useChainID, proposal) - sig, err := pv.PrivKey.Sign(signBytes) - if err != nil { - return err - } - proposal.Signature = sig + sig := pv.PrivKey.Sign(signBytes) + proposal.Signature = sig.Bytes() return nil } @@ -143,7 +137,7 @@ var ErroringMockPVErr = errors.New("erroringMockPV always returns an error") // Implements PrivValidator. func (pv *ErroringMockPV) GetPubKey(ctx context.Context) (crypto.PubKey, error) { - return nil, ErroringMockPVErr + return crypto.PubKey{}, ErroringMockPVErr } // Implements PrivValidator. @@ -159,5 +153,5 @@ func (pv *ErroringMockPV) SignProposal(ctx context.Context, chainID string, prop // NewErroringMockPV returns a MockPV that fails on each signing request. Again, for testing only. func NewErroringMockPV() *ErroringMockPV { - return &ErroringMockPV{MockPV{ed25519.GenPrivKey(), false, false}} + return &ErroringMockPV{MockPV{ed25519.GenerateSecretKey(), false, false}} } diff --git a/sei-tendermint/types/proposal.go b/sei-tendermint/types/proposal.go index b8d4d27a05..d50aeeee13 100644 --- a/sei-tendermint/types/proposal.go +++ b/sei-tendermint/types/proposal.go @@ -6,6 +6,7 @@ import ( "math/bits" "time" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/libs/protoio" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmtime "github.com/tendermint/tendermint/libs/time" @@ -25,13 +26,13 @@ var ( // If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound. type Proposal struct { Type tmproto.SignedMsgType - Height int64 `json:"height,string"` - Round int32 `json:"round"` // there can not be greater than 2_147_483_647 rounds - POLRound int32 `json:"pol_round"` // -1 if null. - BlockID BlockID `json:"block_id"` - Timestamp time.Time `json:"timestamp"` - Signature []byte `json:"signature"` - TxKeys []TxKey `json:"tx_keys"` + Height int64 `json:"height,string"` + Round int32 `json:"round"` // there can not be greater than 2_147_483_647 rounds + POLRound int32 `json:"pol_round"` // -1 if null. + BlockID BlockID `json:"block_id"` + Timestamp time.Time `json:"timestamp"` + Signature crypto.Sig `json:"signature"` + TxKeys []TxKey `json:"tx_keys"` Header `json:"header"` LastCommit *Commit `json:"last_commit"` Evidence EvidenceList `json:"evidence"` @@ -79,14 +80,6 @@ func (p *Proposal) ValidateBasic() error { } // NOTE: Timestamp validation is subtle and handled elsewhere. - - if len(p.Signature) == 0 { - return errors.New("signature is missing") - } - - if len(p.Signature) > MaxSignatureSize { - return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) - } return nil } @@ -143,7 +136,7 @@ func (p *Proposal) String() string { p.Round, p.BlockID, p.POLRound, - tmbytes.Fingerprint(p.Signature), + tmbytes.Fingerprint(p.Signature.Bytes()), CanonicalTime(p.Timestamp)) } @@ -178,7 +171,7 @@ func (p *Proposal) ToProto() *tmproto.Proposal { pb.Round = p.Round pb.PolRound = p.POLRound pb.Timestamp = p.Timestamp - pb.Signature = p.Signature + pb.Signature = p.Signature.Bytes() txKeys := make([]*tmproto.TxKey, 0, len(p.TxKeys)) for _, txKey := range p.TxKeys { txKeys = append(txKeys, txKey.ToProto()) @@ -216,7 +209,11 @@ func ProposalFromProto(pp *tmproto.Proposal) (*Proposal, error) { p.Round = pp.Round p.POLRound = pp.PolRound p.Timestamp = pp.Timestamp - p.Signature = pp.Signature + sig, err := crypto.SigFromBytes(pp.Signature) + if err != nil { + return nil, fmt.Errorf("Signature: %w", err) + } + p.Signature = sig txKeys, err := TxKeysListFromProto(pp.TxKeys) if err != nil { return nil, err diff --git a/sei-tendermint/types/proposal_test.go b/sei-tendermint/types/proposal_test.go index 16f1ec9b8a..8a9c9bdfc2 100644 --- a/sei-tendermint/types/proposal_test.go +++ b/sei-tendermint/types/proposal_test.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/tendermint/internal/libs/protoio" tmrand "github.com/tendermint/tendermint/libs/rand" tmtime "github.com/tendermint/tendermint/libs/time" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -39,6 +40,7 @@ func generateHeader() Header { LastResultsHash: make([]byte, crypto.HashSize), } } + func getTestProposal(t testing.TB) *Proposal { t.Helper() @@ -88,13 +90,11 @@ func TestProposalVerifySignature(t *testing.T) { signBytes := ProposalSignBytes("test_chain_id", p) // sign it - err = privVal.SignProposal(ctx, "test_chain_id", p) - require.NoError(t, err) - prop.Signature = p.Signature + require.NoError(t, privVal.SignProposal(ctx, "test_chain_id", p)) + prop.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) // verify the same proposal - valid := pubKey.VerifySignature(signBytes, prop.Signature) - require.True(t, valid) + require.NoError(t, pubKey.Verify(signBytes, prop.Signature)) // serialize, deserialize and verify again.... newProp := new(tmproto.Proposal) @@ -112,29 +112,21 @@ func TestProposalVerifySignature(t *testing.T) { // verify the transmitted proposal newSignBytes := ProposalSignBytes("test_chain_id", pb) require.Equal(t, string(signBytes), string(newSignBytes)) - valid = pubKey.VerifySignature(newSignBytes, np.Signature) - require.True(t, valid) + require.NoError(t, pubKey.Verify(newSignBytes, np.Signature)) } func BenchmarkProposalWriteSignBytes(b *testing.B) { pbp := getTestProposal(b).ToProto() - - b.ResetTimer() - - for i := 0; i < b.N; i++ { + for b.Loop() { ProposalSignBytes("test_chain_id", pbp) } } func BenchmarkProposalSign(b *testing.B) { ctx := b.Context() - privVal := NewMockPV() - pbp := getTestProposal(b).ToProto() - b.ResetTimer() - - for i := 0; i < b.N; i++ { + for b.Loop() { err := privVal.SignProposal(ctx, "test_chain_id", pbp) if err != nil { b.Error(err) @@ -156,7 +148,7 @@ func BenchmarkProposalVerifySignature(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - pubKey.VerifySignature(ProposalSignBytes("test_chain_id", pbp), testProposal.Signature) + pubKey.Verify(ProposalSignBytes("test_chain_id", pbp), testProposal.Signature) } } @@ -176,12 +168,6 @@ func TestProposalValidateBasic(t *testing.T) { {"Invalid BlockId", func(p *Proposal) { p.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}} }, true}, - {"Invalid Signature", func(p *Proposal) { - p.Signature = make([]byte, 0) - }, true}, - {"Too big Signature", func(p *Proposal) { - p.Signature = make([]byte, MaxSignatureSize+1) - }, true}, } blockID := makeBlockID(crypto.Checksum([]byte("blockhash")), math.MaxInt32, crypto.Checksum([]byte("partshash"))) @@ -197,11 +183,11 @@ func TestProposalValidateBasic(t *testing.T) { blockID, tmtime.Now(), txKeys, generateHeader(), &Commit{}, EvidenceList{}, pubKey.Address()) p := prop.ToProto() - err = privVal.SignProposal(ctx, "test_chain_id", p) - prop.Signature = p.Signature - require.NoError(t, err) + require.NoError(t, privVal.SignProposal(ctx, "test_chain_id", p)) + prop.Signature = utils.OrPanic1(crypto.SigFromBytes(p.Signature)) tc.malleateProposal(prop) - assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") + err = prop.ValidateBasic() + assert.Equal(t, tc.expectErr, err != nil, "Validate Basic had an unexpected result: %v", err) }) } } @@ -209,7 +195,7 @@ func TestProposalValidateBasic(t *testing.T) { func TestProposalProtoBuf(t *testing.T) { var txKeys []TxKey proposal := NewProposal(1, 2, 3, makeBlockID([]byte("hash"), 2, []byte("part_set_hash")), tmtime.Now(), txKeys, generateHeader(), &Commit{Signatures: []CommitSig{}}, EvidenceList{}, crypto.Address("testaddr")) - proposal.Signature = []byte("sig") + proposal.Signature = testKey.Sign([]byte("sig")) proposal2 := NewProposal(1, 2, 3, BlockID{}, tmtime.Now(), txKeys, generateHeader(), &Commit{Signatures: []CommitSig{}}, EvidenceList{}, crypto.Address("testaddr")) testCases := []struct { diff --git a/sei-tendermint/types/protobuf.go b/sei-tendermint/types/protobuf.go index f82965fbf4..c59ccdee02 100644 --- a/sei-tendermint/types/protobuf.go +++ b/sei-tendermint/types/protobuf.go @@ -20,19 +20,13 @@ func (tm2pb) Validator(val *Validator) abci.Validator { } } -// XXX: panics on unknown pubkey type func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate { - pk, err := encoding.PubKeyToProto(val.PubKey) - if err != nil { - panic(err) - } return abci.ValidatorUpdate{ - PubKey: pk, + PubKey: encoding.PubKeyToProto(val.PubKey), Power: val.VotingPower, } } -// XXX: panics on nil or unknown pubkey type func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate { validators := make([]abci.ValidatorUpdate, vals.Size()) for i, val := range vals.Validators { diff --git a/sei-tendermint/types/protobuf_test.go b/sei-tendermint/types/protobuf_test.go index c482153c17..f931da0f69 100644 --- a/sei-tendermint/types/protobuf_test.go +++ b/sei-tendermint/types/protobuf_test.go @@ -13,14 +13,13 @@ import ( ) func TestABCIPubKey(t *testing.T) { - pkEd := ed25519.GenPrivKey().PubKey() + pkEd := ed25519.GenerateSecretKey().Public() err := testABCIPubKey(t, pkEd) assert.NoError(t, err) } func testABCIPubKey(t *testing.T, pk crypto.PubKey) error { - abciPubKey, err := encoding.PubKeyToProto(pk) - require.NoError(t, err) + abciPubKey := encoding.PubKeyToProto(pk) pk2, err := encoding.PubKeyFromProto(abciPubKey) require.NoError(t, err) require.Equal(t, pk, pk2) @@ -28,7 +27,7 @@ func testABCIPubKey(t *testing.T, pk crypto.PubKey) error { } func TestABCIValidators(t *testing.T) { - pkEd := ed25519.GenPrivKey().PubKey() + pkEd := ed25519.GenerateSecretKey().Public() // correct validator tmValExpected := NewValidator(pkEd, 10) @@ -53,7 +52,7 @@ func TestABCIValidators(t *testing.T) { } func TestABCIValidatorWithoutPubKey(t *testing.T) { - pkEd := ed25519.GenPrivKey().PubKey() + pkEd := ed25519.GenerateSecretKey().Public() abciVal := TM2PB.Validator(NewValidator(pkEd, 10)) diff --git a/sei-tendermint/types/signable.go b/sei-tendermint/types/signable.go deleted file mode 100644 index f1b71ca1b7..0000000000 --- a/sei-tendermint/types/signable.go +++ /dev/null @@ -1,12 +0,0 @@ -package types - -import ( - "github.com/tendermint/tendermint/crypto/ed25519" - tmmath "github.com/tendermint/tendermint/libs/math" -) - -var ( - // MaxSignatureSize is a maximum allowed signature size for the Proposal - // and Vote. - MaxSignatureSize = tmmath.MaxInt(ed25519.SignatureSize, 64) -) diff --git a/sei-tendermint/types/test_util.go b/sei-tendermint/types/test_util.go index e72e6ff4a7..53982cd510 100644 --- a/sei-tendermint/types/test_util.go +++ b/sei-tendermint/types/test_util.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -38,10 +40,13 @@ func MakeCommit(ctx context.Context, blockID BlockID, height int64, round int32, func signAddVote(ctx context.Context, privVal PrivValidator, vote *Vote, voteSet *VoteSet) (signed bool, err error) { v := vote.ToProto() - err = privVal.SignVote(ctx, voteSet.ChainID(), v) - if err != nil { + if err := privVal.SignVote(ctx, voteSet.ChainID(), v); err != nil { return false, err } - vote.Signature = v.Signature + sig, err := crypto.SigFromBytes(v.Signature) + if err != nil { + return false, fmt.Errorf("SigFromBytes(): %w", err) + } + vote.Signature = utils.Some(sig) return voteSet.AddVote(vote) } diff --git a/sei-tendermint/types/validation.go b/sei-tendermint/types/validation.go index adf1fcff31..f18389a72c 100644 --- a/sei-tendermint/types/validation.go +++ b/sei-tendermint/types/validation.go @@ -6,11 +6,12 @@ import ( "github.com/tendermint/tendermint/crypto" tmmath "github.com/tendermint/tendermint/libs/math" + "github.com/tendermint/tendermint/libs/utils" ) const batchVerifyThreshold = 2 -func shouldBatchVerify(vals *ValidatorSet, commit *Commit) bool { +func shouldBatchVerify(commit *Commit) bool { return len(commit.Signatures) >= batchVerifyThreshold } @@ -41,7 +42,7 @@ func VerifyCommit(chainID string, vals *ValidatorSet, blockID BlockID, count := func(c CommitSig) bool { return c.BlockIDFlag == BlockIDFlagCommit } // attempt to batch verify - if shouldBatchVerify(vals, commit) { + if shouldBatchVerify(commit) { return verifyCommitBatch(chainID, vals, commit, votingPowerNeeded, ignore, count, true, true) } @@ -74,7 +75,7 @@ func VerifyCommitLight(chainID string, vals *ValidatorSet, blockID BlockID, count := func(c CommitSig) bool { return true } // attempt to batch verify - if shouldBatchVerify(vals, commit) { + if shouldBatchVerify(commit) { return verifyCommitBatch(chainID, vals, commit, votingPowerNeeded, ignore, count, false, true) } @@ -120,7 +121,7 @@ func VerifyCommitLightTrusting(chainID string, vals *ValidatorSet, commit *Commi // attempt to batch verify commit. As the validator set doesn't necessarily // correspond with the validator set that signed the block we need to look // up by address rather than index. - if shouldBatchVerify(vals, commit) { + if shouldBatchVerify(commit) { return verifyCommitBatch(chainID, vals, commit, votingPowerNeeded, ignore, count, false, false) } @@ -205,9 +206,11 @@ func verifyCommitBatch( voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) // add the key, sig and message to the verifier - if err := bv.Add(val.PubKey, voteSignBytes, commitSig.Signature); err != nil { - return err + sig, ok := commitSig.Signature.Get() + if !ok { + return fmt.Errorf("missing signature at idx %v", idx) } + bv.Add(val.PubKey, voteSignBytes, sig) batchSigIdxs = append(batchSigIdxs, idx) // If this signature counts then add the voting power of the validator @@ -230,28 +233,14 @@ func verifyCommitBatch( } // attempt to verify the batch. - ok, validSigs := bv.Verify() - if ok { - // success - return nil - } - - // one or more of the signatures is invalid, find and return the first - // invalid signature. - for i, ok := range validSigs { - if !ok { - // go back from the batch index to the commit.Signatures index - idx := batchSigIdxs[i] - sig := commit.Signatures[idx] - return errBadSig{fmt.Errorf("wrong signature (#%d): %X", idx, sig)} - } + if err := bv.Verify(); err != nil { + err := utils.ErrorAs[crypto.ErrBadSig](err).OrPanic() + // go back from the batch index to the commit.Signatures index + idx := batchSigIdxs[err.Idx] + sig := commit.Signatures[idx] + return errBadSig{fmt.Errorf("wrong signature (#%d): %X", idx, sig)} } - - // execution reaching here is a bug, and one of the following has - // happened: - // * non-zero tallied voting power, empty batch (impossible?) - // * bv.Verify() returned `false, []bool{true, ..., true}` (BUG) - return fmt.Errorf("BUG: batch verification failed with no invalid signatures") + return nil } // Single Verification @@ -306,9 +295,12 @@ func verifyCommitSingle( } voteSignBytes = commit.VoteSignBytes(chainID, int32(idx)) - - if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { - return errBadSig{fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature)} + sig, ok := commitSig.Signature.Get() + if !ok { + return fmt.Errorf("missing signature at idx %v", idx) + } + if err := val.PubKey.Verify(voteSignBytes, sig); err != nil { + return errBadSig{fmt.Errorf("wrong signature (#%d): %v", idx, sig)} } // If this signature counts then add the voting power of the validator diff --git a/sei-tendermint/types/validation_test.go b/sei-tendermint/types/validation_test.go index 412c9a0788..adfb37e4f6 100644 --- a/sei-tendermint/types/validation_test.go +++ b/sei-tendermint/types/validation_test.go @@ -7,7 +7,9 @@ import ( "time" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" tmmath "github.com/tendermint/tendermint/libs/math" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -116,7 +118,7 @@ func TestValidatorSet_VerifyCommit_All(t *testing.T) { v := vote.ToProto() require.NoError(t, vals[vi%len(vals)].SignVote(ctx, tc.chainID, v)) - vote.Signature = v.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) sigs[vi] = vote.CommitSig() @@ -175,9 +177,8 @@ func TestValidatorSet_VerifyCommit_CheckAllSignatures(t *testing.T) { // malleate 4th signature vote := voteSet.GetByIndex(3) v := vote.ToProto() - err = vals[3].SignVote(ctx, "CentaurusA", v) - require.NoError(t, err) - vote.Signature = v.Signature + require.NoError(t, vals[3].SignVote(ctx, "CentaurusA", v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) commit.Signatures[3] = vote.CommitSig() err = valSet.VerifyCommit(chainID, blockID, h, commit) @@ -204,9 +205,8 @@ func TestValidatorSet_VerifyCommitLight_ReturnsAsSoonAsMajorityOfVotingPowerSign // malleate 4th signature (3 signatures are enough for 2/3+) vote := voteSet.GetByIndex(3) v := vote.ToProto() - err = vals[3].SignVote(ctx, "CentaurusA", v) - require.NoError(t, err) - vote.Signature = v.Signature + require.NoError(t, vals[3].SignVote(ctx, "CentaurusA", v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) commit.Signatures[3] = vote.CommitSig() err = valSet.VerifyCommitLight(chainID, blockID, h, commit) @@ -230,9 +230,8 @@ func TestValidatorSet_VerifyCommitLightTrusting_ReturnsAsSoonAsTrustLevelOfVotin // malleate 3rd signature (2 signatures are enough for 1/3+ trust level) vote := voteSet.GetByIndex(2) v := vote.ToProto() - err = vals[2].SignVote(ctx, "CentaurusA", v) - require.NoError(t, err) - vote.Signature = v.Signature + require.NoError(t, vals[2].SignVote(ctx, "CentaurusA", v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) commit.Signatures[2] = vote.CommitSig() err = valSet.VerifyCommitLightTrusting(chainID, commit, tmmath.Fraction{Numerator: 1, Denominator: 3}) diff --git a/sei-tendermint/types/validator.go b/sei-tendermint/types/validator.go index 43977cb643..6d16d74a56 100644 --- a/sei-tendermint/types/validator.go +++ b/sei-tendermint/types/validator.go @@ -38,13 +38,11 @@ func (v Validator) MarshalJSON() ([]byte, error) { VotingPower: v.VotingPower, ProposerPriority: v.ProposerPriority, } - if v.PubKey != nil { - pk, err := jsontypes.Marshal(v.PubKey) - if err != nil { - return nil, err - } - val.PubKey = pk + pk, err := jsontypes.Marshal(v.PubKey) + if err != nil { + return nil, err } + val.PubKey = pk return json.Marshal(val) } @@ -72,21 +70,21 @@ func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator { } } +var ErrNilValidator = errors.New("nil validator") +var ErrNegativeVotingPower = errors.New("validator has negative voting power") +var ErrBadAddressSize = errors.New("validator address has bad size") + // ValidateBasic performs basic validation. func (v *Validator) ValidateBasic() error { if v == nil { - return errors.New("nil validator") + return ErrNilValidator } - if v.PubKey == nil { - return errors.New("validator does not have a public key") - } - if v.VotingPower < 0 { - return errors.New("validator has negative voting power") + return ErrNegativeVotingPower } if len(v.Address) != crypto.AddressSize { - return fmt.Errorf("validator address is the wrong size: %v", v.Address) + return fmt.Errorf("%w: %v", ErrBadAddressSize, v.Address) } return nil @@ -154,11 +152,7 @@ func ValidatorListString(vals []*Validator) string { // as its redundant with the pubkey. This also excludes ProposerPriority // which changes every round. func (v *Validator) Bytes() []byte { - pk, err := encoding.PubKeyToProto(v.PubKey) - if err != nil { - panic(err) - } - + pk := encoding.PubKeyToProto(v.PubKey) pbv := tmproto.SimpleValidator{ PubKey: &pk, VotingPower: v.VotingPower, @@ -176,15 +170,9 @@ func (v *Validator) ToProto() (*tmproto.Validator, error) { if v == nil { return nil, errors.New("nil validator") } - - pk, err := encoding.PubKeyToProto(v.PubKey) - if err != nil { - return nil, err - } - return &tmproto.Validator{ Address: v.Address, - PubKey: pk, + PubKey: encoding.PubKeyToProto(v.PubKey), VotingPower: v.VotingPower, ProposerPriority: v.ProposerPriority, }, nil diff --git a/sei-tendermint/types/validator_set.go b/sei-tendermint/types/validator_set.go index 92b0cee17c..bc7dc6abaf 100644 --- a/sei-tendermint/types/validator_set.go +++ b/sei-tendermint/types/validator_set.go @@ -84,9 +84,11 @@ func NewValidatorSet(valz []*Validator) *ValidatorSet { return vals } +var ErrValidatorSetEmpty = errors.New("validator set is nil or empty") + func (vals *ValidatorSet) ValidateBasic() error { if vals.IsNilOrEmpty() { - return errors.New("validator set is nil or empty") + return ErrValidatorSetEmpty } for idx, val := range vals.Validators { @@ -96,7 +98,7 @@ func (vals *ValidatorSet) ValidateBasic() error { } if err := vals.Proposer.ValidateBasic(); err != nil { - return fmt.Errorf("proposer failed validate basic, error: %w", err) + return fmt.Errorf("Proposer: %w", err) } for _, val := range vals.Validators { diff --git a/sei-tendermint/types/validator_set_test.go b/sei-tendermint/types/validator_set_test.go index 1a72d41b7c..251885d983 100644 --- a/sei-tendermint/types/validator_set_test.go +++ b/sei-tendermint/types/validator_set_test.go @@ -3,6 +3,7 @@ package types import ( "bytes" "context" + "errors" "fmt" "math" "math/rand" @@ -18,7 +19,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" tmmath "github.com/tendermint/tendermint/libs/math" - tmrand "github.com/tendermint/tendermint/libs/rand" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -92,59 +93,50 @@ func TestValidatorSetValidateBasic(t *testing.T) { testCases := []struct { vals ValidatorSet - err bool - msg string + err utils.Option[error] }{ { vals: ValidatorSet{}, - err: true, - msg: "validator set is nil or empty", + err: utils.Some(ErrValidatorSetEmpty), }, { vals: ValidatorSet{ Validators: []*Validator{}, }, - err: true, - msg: "validator set is nil or empty", + err: utils.Some(ErrValidatorSetEmpty), }, { vals: ValidatorSet{ Validators: []*Validator{val}, }, - err: true, - msg: "proposer failed validate basic, error: nil validator", + err: utils.Some(ErrNilValidator), }, { vals: ValidatorSet{ Validators: []*Validator{badVal}, + Proposer: val, }, - err: true, - msg: "invalid validator #0: validator does not have a public key", + err: utils.Some(ErrBadAddressSize), }, { vals: ValidatorSet{ Validators: []*Validator{val}, Proposer: val, }, - err: false, - msg: "", }, { vals: ValidatorSet{ Validators: []*Validator{val}, Proposer: val2, }, - err: true, - msg: ErrProposerNotInVals.Error(), + err: utils.Some(ErrProposerNotInVals), }, } for _, tc := range testCases { err := tc.vals.ValidateBasic() - if tc.err { - if assert.Error(t, err) { - assert.Equal(t, tc.msg, err.Error()) - } + if wantErr, ok := tc.err.Get(); ok { + assert.True(t, errors.Is(err, wantErr)) } else { assert.NoError(t, err) } @@ -205,18 +197,16 @@ func TestIncrementProposerPriorityPositiveTimes(t *testing.T) { } func BenchmarkValidatorSetCopy(b *testing.B) { - b.StopTimer() vset := NewValidatorSet([]*Validator{}) - for i := 0; i < 1000; i++ { - privKey := ed25519.GenPrivKey() - pubKey := privKey.PubKey() + for range 1000 { + privKey := ed25519.GenerateSecretKey() + pubKey := privKey.Public() val := NewValidator(pubKey, 10) err := vset.UpdateWithChangeSet([]*Validator{val}) require.NoError(b, err) } - b.StartTimer() - for i := 0; i < b.N; i++ { + for b.Loop() { vset.Copy() } } @@ -230,7 +220,7 @@ func TestProposerSelection1(t *testing.T) { newValidator([]byte("baz"), 330), }) var proposers []string - for i := 0; i < 99; i++ { + for range 99 { val := vset.GetProposer() proposers = append(proposers, string(val.Address)) vset.IncrementProposerPriority(1) @@ -346,9 +336,9 @@ func TestProposerSelection3(t *testing.T) { }) proposerOrder := make([]*Validator, 4) - for i := 0; i < 4; i++ { + for i := range 4 { // need to give all validators to have keys - pk := ed25519.GenPrivKey().PubKey() + pk := ed25519.GenerateSecretKey().Public() vset.Validators[i].PubKey = pk proposerOrder[i] = vset.GetProposer() vset.IncrementProposerPriority(1) @@ -403,9 +393,7 @@ func newValidator(address []byte, power int64) *Validator { } func randPubKey() crypto.PubKey { - pubKey := make(ed25519.PubKey, ed25519.PubKeySize) - copy(pubKey, tmrand.Bytes(32)) - return ed25519.PubKey(tmrand.Bytes(32)) + return ed25519.GenerateSecretKey().Public() } func randModuloValidator(totalVotingPower int64) *Validator { @@ -434,7 +422,7 @@ func randValidator(ctx context.Context, randPower bool, minPower int64) (*Valida func randModuloValidatorSet(numValidators int) *ValidatorSet { validators := make([]*Validator, numValidators) totalVotingPower := int64(0) - for i := 0; i < numValidators; i++ { + for i := range numValidators { validators[i] = randModuloValidator(totalVotingPower) totalVotingPower += validators[i].VotingPower } @@ -836,7 +824,7 @@ func toTestValList(valList []*Validator) []testVal { func testValSet(nVals int, power int64) []testVal { vals := make([]testVal, nVals) - for i := 0; i < nVals; i++ { + for i := range nVals { vals[i] = testVal{fmt.Sprintf("v%d", i+1), power} } return vals @@ -1634,9 +1622,9 @@ func deterministicValidatorSet(ctx context.Context, t *testing.T) (*ValidatorSet t.Helper() - for i := 0; i < 10; i++ { - // val, privValidator := DeterministicValidator(ed25519.PrivKey([]byte(deterministicKeys[i]))) - val, privValidator := deterministicValidator(ctx, t, ed25519.GenPrivKeyFromSecret([]byte(fmt.Sprintf("key: %x", i)))) + for i := range 10 { + // WARNING: this key has to be stable, otherwise hashes break. + val, privValidator := deterministicValidator(ctx, t, ed25519.TestSecretKey(fmt.Appendf(nil, "key: %x", i))) valz[i] = val privValidators[i] = privValidator } diff --git a/sei-tendermint/types/validator_test.go b/sei-tendermint/types/validator_test.go index a0ff719a00..9a2b88cab9 100644 --- a/sei-tendermint/types/validator_test.go +++ b/sei-tendermint/types/validator_test.go @@ -2,12 +2,14 @@ package types import ( "context" + "errors" "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" ) func TestValidatorProtoBuf(t *testing.T) { @@ -51,55 +53,39 @@ func TestValidatorValidateBasic(t *testing.T) { pubKey, _ := priv.GetPubKey(ctx) testCases := []struct { val *Validator - err bool - msg string + err utils.Option[error] }{ { val: NewValidator(pubKey, 1), - err: false, - msg: "", }, { val: nil, - err: true, - msg: "nil validator", - }, - { - val: &Validator{ - PubKey: nil, - }, - err: true, - msg: "validator does not have a public key", + err: utils.Some(ErrNilValidator), }, { val: NewValidator(pubKey, -1), - err: true, - msg: "validator has negative voting power", + err: utils.Some(ErrNegativeVotingPower), }, { val: &Validator{ PubKey: pubKey, Address: nil, }, - err: true, - msg: "validator address is the wrong size: ", + err: utils.Some(ErrBadAddressSize), }, { val: &Validator{ PubKey: pubKey, Address: []byte{'a'}, }, - err: true, - msg: "validator address is the wrong size: 61", + err: utils.Some(ErrBadAddressSize), }, } for _, tc := range testCases { err := tc.val.ValidateBasic() - if tc.err { - if assert.Error(t, err) { - assert.Equal(t, tc.msg, err.Error()) - } + if wantErr, ok := tc.err.Get(); ok { + assert.True(t, errors.Is(err, wantErr)) } else { assert.NoError(t, err) } diff --git a/sei-tendermint/types/vote.go b/sei-tendermint/types/vote.go index 40f829182d..e9540184c1 100644 --- a/sei-tendermint/types/vote.go +++ b/sei-tendermint/types/vote.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/internal/libs/protoio" tmbytes "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -48,14 +49,14 @@ type Address = crypto.Address // Vote represents a prevote, precommit, or commit vote from validators for // consensus. type Vote struct { - Type tmproto.SignedMsgType `json:"type"` - Height int64 `json:"height,string"` - Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds - BlockID BlockID `json:"block_id"` // zero if vote is nil. - Timestamp time.Time `json:"timestamp"` - ValidatorAddress Address `json:"validator_address"` - ValidatorIndex int32 `json:"validator_index"` - Signature []byte `json:"signature"` + Type tmproto.SignedMsgType `json:"type"` + Height int64 `json:"height,string"` + Round int32 `json:"round"` // assume there will not be greater than 2_147_483_647 rounds + BlockID BlockID `json:"block_id"` // zero if vote is nil. + Timestamp time.Time `json:"timestamp"` + ValidatorAddress Address `json:"validator_address"` + ValidatorIndex int32 `json:"validator_index"` + Signature utils.Option[crypto.Sig] `json:"signature"` } // VoteFromProto attempts to convert the given serialization (Protobuf) type to @@ -67,7 +68,14 @@ func VoteFromProto(pv *tmproto.Vote) (*Vote, error) { if err != nil { return nil, err } - + signature := utils.None[crypto.Sig]() + if len(pv.Signature) > 0 { + sig, err := crypto.SigFromBytes(pv.Signature) + if err != nil { + return nil, fmt.Errorf("Signature: %w", err) + } + signature = utils.Some(sig) + } return &Vote{ Type: pv.Type, Height: pv.Height, @@ -76,7 +84,7 @@ func VoteFromProto(pv *tmproto.Vote) (*Vote, error) { Timestamp: pv.Timestamp, ValidatorAddress: pv.ValidatorAddress, ValidatorIndex: pv.ValidatorIndex, - Signature: pv.Signature, + Signature: signature, }, nil } @@ -154,6 +162,11 @@ func (vote *Vote) String() string { panic("Unknown vote type") } + var sigBytes []byte + if sig, ok := vote.Signature.Get(); ok { + sigBytes = sig.Bytes() + } + return fmt.Sprintf("Vote{index=%v:%X %v/%02d/%v(%v) %X %X @ %s}", vote.ValidatorIndex, vote.ValidatorAddress, @@ -162,7 +175,7 @@ func (vote *Vote) String() string { vote.Type, typeString, tmbytes.Fingerprint(vote.BlockID.Hash), - tmbytes.Fingerprint(vote.Signature), + tmbytes.Fingerprint(sigBytes), CanonicalTime(vote.Timestamp), ) } @@ -172,7 +185,11 @@ func (vote *Vote) verifyAndReturnProto(chainID string, pubKey crypto.PubKey) (*t return nil, ErrVoteInvalidValidatorAddress } v := vote.ToProto() - if !pubKey.VerifySignature(VoteSignBytes(chainID, v), vote.Signature) { + sig, ok := vote.Signature.Get() + if !ok { + return nil, ErrVoteInvalidSignature + } + if err := pubKey.Verify(VoteSignBytes(chainID, v), sig); err != nil { return nil, ErrVoteInvalidSignature } return v, nil @@ -223,13 +240,6 @@ func (vote *Vote) ValidateBasic() error { if vote.ValidatorIndex < 0 { return errors.New("negative ValidatorIndex") } - if len(vote.Signature) == 0 { - return errors.New("signature is missing") - } - - if len(vote.Signature) > MaxSignatureSize { - return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) - } return nil } @@ -240,6 +250,11 @@ func (vote *Vote) ToProto() *tmproto.Vote { return nil } + var signature []byte + if sig, ok := vote.Signature.Get(); ok { + signature = sig.Bytes() + } + return &tmproto.Vote{ Type: vote.Type, Height: vote.Height, @@ -248,7 +263,7 @@ func (vote *Vote) ToProto() *tmproto.Vote { Timestamp: vote.Timestamp, ValidatorAddress: vote.ValidatorAddress, ValidatorIndex: vote.ValidatorIndex, - Signature: vote.Signature, + Signature: signature, } } diff --git a/sei-tendermint/types/vote_set.go b/sei-tendermint/types/vote_set.go index d9171f0930..4b679dc83e 100644 --- a/sei-tendermint/types/vote_set.go +++ b/sei-tendermint/types/vote_set.go @@ -183,7 +183,7 @@ func (voteSet *VoteSet) addVote(vote *Vote) (added bool, err error) { // If we already know of this vote, return false. if existing, ok := voteSet.getVote(valIndex, blockKey); ok { - if bytes.Equal(existing.Signature, vote.Signature) { + if existing.Signature == vote.Signature { return false, nil // duplicate } return false, fmt.Errorf("existing vote: %v; new vote: %v: %w", existing, vote, ErrVoteNonDeterministicSignature) diff --git a/sei-tendermint/types/vote_test.go b/sei-tendermint/types/vote_test.go index 0fb8fe5389..feccb607cd 100644 --- a/sei-tendermint/types/vote_test.go +++ b/sei-tendermint/types/vote_test.go @@ -7,11 +7,12 @@ import ( "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/internal/libs/protoio" + "github.com/tendermint/tendermint/libs/utils" + "github.com/tendermint/tendermint/libs/utils/require" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -159,25 +160,20 @@ func TestVoteVerifySignature(t *testing.T) { signBytes := VoteSignBytes("test_chain_id", v) // sign it - err = privVal.SignVote(ctx, "test_chain_id", v) - require.NoError(t, err) + require.NoError(t, privVal.SignVote(ctx, "test_chain_id", v)) // verify the same vote - valid := pubkey.VerifySignature(VoteSignBytes("test_chain_id", v), v.Signature) - require.True(t, valid) + require.NoError(t, pubkey.Verify(VoteSignBytes("test_chain_id", v), utils.OrPanic1(crypto.SigFromBytes(v.Signature)))) // serialize, deserialize and verify again.... precommit := new(tmproto.Vote) - bs, err := proto.Marshal(v) - require.NoError(t, err) - err = proto.Unmarshal(bs, precommit) - require.NoError(t, err) + bs := utils.OrPanic1(proto.Marshal(v)) + require.NoError(t, proto.Unmarshal(bs, precommit)) // verify the transmitted vote newSignBytes := VoteSignBytes("test_chain_id", precommit) - require.Equal(t, string(signBytes), string(newSignBytes)) - valid = pubkey.VerifySignature(newSignBytes, precommit.Signature) - require.True(t, valid) + require.NoError(t, utils.TestDiff(signBytes, newSignBytes)) + require.NoError(t, pubkey.Verify(newSignBytes, utils.OrPanic1(crypto.SigFromBytes(precommit.Signature)))) } func TestIsVoteTypeValid(t *testing.T) { @@ -192,7 +188,6 @@ func TestIsVoteTypeValid(t *testing.T) { } for _, tt := range tc { - tt := tt t.Run(tt.name, func(st *testing.T) { if rs := IsVoteTypeValid(tt.in); rs != tt.out { t.Errorf("got unexpected Vote type. Expected:\n%v\nGot:\n%v", rs, tt.out) @@ -211,7 +206,7 @@ func TestVoteVerify(t *testing.T) { vote := examplePrevote(t) vote.ValidatorAddress = pubkey.Address() - err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey()) + err = vote.Verify("test_chain_id", ed25519.GenerateSecretKey().Public()) if assert.Error(t, err) { assert.Equal(t, ErrVoteInvalidValidatorAddress, err) } @@ -233,7 +228,7 @@ func signVote(ctx context.Context, t *testing.T, pv PrivValidator, chainID strin v := vote.ToProto() require.NoError(t, pv.SignVote(ctx, chainID, v)) - vote.Signature = v.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) } func TestValidVotes(t *testing.T) { @@ -268,8 +263,6 @@ func TestInvalidVotes(t *testing.T) { {"invalid block ID", func(v *Vote) { v.BlockID = BlockID{[]byte{1, 2, 3}, PartSetHeader{111, []byte("blockparts")}} }}, {"invalid address", func(v *Vote) { v.ValidatorAddress = make([]byte, 1) }}, {"invalid validator index", func(v *Vote) { v.ValidatorIndex = -1 }}, - {"invalid signature", func(v *Vote) { v.Signature = nil }}, - {"oversized signature", func(v *Vote) { v.Signature = make([]byte, MaxSignatureSize+1) }}, } for _, tc := range testCases { prevote := examplePrevote(t) @@ -290,9 +283,8 @@ func TestVoteProtobuf(t *testing.T) { privVal := NewMockPV() vote := examplePrecommit(t) v := vote.ToProto() - err := privVal.SignVote(ctx, "test_chain_id", v) - vote.Signature = v.Signature - require.NoError(t, err) + require.NoError(t, privVal.SignVote(ctx, "test_chain_id", v)) + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) testCases := []struct { msg string diff --git a/sei-wasmd/x/wasm/ibctesting/chain.go b/sei-wasmd/x/wasm/ibctesting/chain.go index e7da88a119..27c0162d45 100644 --- a/sei-wasmd/x/wasm/ibctesting/chain.go +++ b/sei-wasmd/x/wasm/ibctesting/chain.go @@ -36,6 +36,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/tmhash" + "github.com/tendermint/tendermint/libs/utils" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" tmversion "github.com/tendermint/tendermint/version" @@ -495,7 +496,7 @@ func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, v := vote.ToProto() err := privVal.SignVote(context.Background(), chainID, v) require.NoError(chain.t, err) - vote.Signature = v.Signature + vote.Signature = utils.Some(utils.OrPanic1(crypto.SigFromBytes(v.Signature))) _, err = voteSet.AddVote(vote) require.NoError(chain.t, err) } diff --git a/sei-wasmd/x/wasm/keeper/test_common.go b/sei-wasmd/x/wasm/keeper/test_common.go index 797d77e93d..2df530b9c0 100644 --- a/sei-wasmd/x/wasm/keeper/test_common.go +++ b/sei-wasmd/x/wasm/keeper/test_common.go @@ -721,8 +721,8 @@ func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { seed := make([]byte, 8) binary.BigEndian.PutUint64(seed, keyCounter) - key := ed25519.GenPrivKeyFromSecret(seed) - pub := key.PubKey() + key := ed25519.TestSecretKey(seed) + pub := key.Public() addr := sdk.AccAddress(pub.Address()) return key, pub, addr } diff --git a/sei-wasmd/x/wasm/module_test.go b/sei-wasmd/x/wasm/module_test.go index 654a948fd9..a332526b43 100644 --- a/sei-wasmd/x/wasm/module_test.go +++ b/sei-wasmd/x/wasm/module_test.go @@ -48,8 +48,8 @@ func setupTest(t *testing.T) testData { } func keyPubAddr() (crypto.PrivKey, crypto.PubKey, sdk.AccAddress) { - key := ed25519.GenPrivKey() - pub := key.PubKey() + key := ed25519.GenerateSecretKey() + pub := key.Public() addr := sdk.AccAddress(pub.Address()) return key, pub, addr } diff --git a/x/tokenfactory/types/msgs_test.go b/x/tokenfactory/types/msgs_test.go index 981c3f0424..a3b58dab82 100644 --- a/x/tokenfactory/types/msgs_test.go +++ b/x/tokenfactory/types/msgs_test.go @@ -16,7 +16,7 @@ import ( // TestMsgCreateDenom tests if valid/invalid create denom messages are properly validated/invalidated func TestMsgCreateDenom(t *testing.T) { // generate a private/public key pair and get the respective address - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() addr1 := sdk.AccAddress(pk1.Address()) // make a proper createDenom message @@ -80,7 +80,7 @@ func TestMsgCreateDenom(t *testing.T) { func TestMsgUpdateDenom(t *testing.T) { // generate a private/public key pair and get the respective address - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() addr1 := sdk.AccAddress(pk1.Address()) // make a proper createDenom message @@ -146,7 +146,7 @@ func TestMsgUpdateDenom(t *testing.T) { // TestMsgMint tests if valid/invalid create denom messages are properly validated/invalidated func TestMsgMint(t *testing.T) { // generate a private/public key pair and get the respective address - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() addr1 := sdk.AccAddress(pk1.Address()) // make a proper mint message @@ -219,7 +219,7 @@ func TestMsgMint(t *testing.T) { // TestMsgBurn tests if valid/invalid create denom messages are properly validated/invalidated func TestMsgBurn(t *testing.T) { // generate a private/public key pair and get the respective address - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() addr1 := sdk.AccAddress(pk1.Address()) // make a proper burn message @@ -289,9 +289,9 @@ func TestMsgBurn(t *testing.T) { // TestMsgChangeAdmin tests if valid/invalid create denom messages are properly validated/invalidated func TestMsgChangeAdmin(t *testing.T) { // generate a private/public key pair and get the respective address - pk1 := ed25519.GenPrivKey().PubKey() + pk1 := ed25519.GenerateSecretKey().Public() addr1 := sdk.AccAddress(pk1.Address()) - pk2 := ed25519.GenPrivKey().PubKey() + pk2 := ed25519.GenerateSecretKey().Public() addr2 := sdk.AccAddress(pk2.Address()) tokenFactoryDenom := fmt.Sprintf("factory/%s/bitcoin", addr1.String())