diff --git a/abci/example/kvstore/helpers.go b/abci/example/kvstore/helpers.go index 7fd028560..91fe03d37 100644 --- a/abci/example/kvstore/helpers.go +++ b/abci/example/kvstore/helpers.go @@ -2,15 +2,14 @@ package kvstore import ( "fmt" - "os" - "github.com/line/ostracon/abci/types" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/composite" + "github.com/line/ostracon/crypto/ed25519" tmjson "github.com/line/ostracon/libs/json" tmos "github.com/line/ostracon/libs/os" tmrand "github.com/line/ostracon/libs/rand" "github.com/line/ostracon/privval" + "os" ) // LoadPrivValidatorKeyFile Load private key for use in an example or test. @@ -29,7 +28,7 @@ func LoadPrivValidatorKeyFile(keyFilePath string) (*privval.FilePVKey, error) { // GenDefaultPrivKey Generates a default private key for use in an example or test. func GenDefaultPrivKey() crypto.PrivKey { - return composite.GenPrivKey() + return ed25519.GenPrivKey() } // RandVal creates one random validator, with a key derived diff --git a/abci/example/kvstore/helpers_test.go b/abci/example/kvstore/helpers_test.go index 79aabb30e..94533a766 100644 --- a/abci/example/kvstore/helpers_test.go +++ b/abci/example/kvstore/helpers_test.go @@ -4,9 +4,10 @@ import ( "io/ioutil" "testing" - "github.com/line/ostracon/privval" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/line/ostracon/privval" ) func TestLoadPrivValidatorKeyFile(t *testing.T) { @@ -29,8 +30,7 @@ func TestLoadPrivValidatorKeyFile(t *testing.T) { require.Contains(t, err.Error(), "error reading") } - expected, err := privval.GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), privval.PrivKeyTypeEd25519) - require.Nil(t, err) + expected := privval.GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) expected.Save() diff --git a/abci/types/types.pb.go b/abci/types/types.pb.go index cc6635a2f..06189b0ce 100644 --- a/abci/types/types.pb.go +++ b/abci/types/types.pb.go @@ -2099,17 +2099,19 @@ func (m *ResponseBeginBlock) GetEvents() []Event { } type ResponseCheckTx struct { - Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` - Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` - Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` - GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` - GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` - Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` - Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` - Sender string `protobuf:"bytes,9,opt,name=sender,proto3" json:"sender,omitempty"` - Priority int64 `protobuf:"varint,10,opt,name=priority,proto3" json:"priority,omitempty"` - MempoolError string `protobuf:"bytes,11,opt,name=mempool_error,json=mempoolError,proto3" json:"mempool_error,omitempty"` + Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` + Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Log string `protobuf:"bytes,3,opt,name=log,proto3" json:"log,omitempty"` + Info string `protobuf:"bytes,4,opt,name=info,proto3" json:"info,omitempty"` + GasWanted int64 `protobuf:"varint,5,opt,name=gas_wanted,proto3" json:"gas_wanted,omitempty"` + GasUsed int64 `protobuf:"varint,6,opt,name=gas_used,proto3" json:"gas_used,omitempty"` + Events []Event `protobuf:"bytes,7,rep,name=events,proto3" json:"events,omitempty"` + Codespace string `protobuf:"bytes,8,opt,name=codespace,proto3" json:"codespace,omitempty"` + Sender string `protobuf:"bytes,9,opt,name=sender,proto3" json:"sender,omitempty"` + Priority int64 `protobuf:"varint,10,opt,name=priority,proto3" json:"priority,omitempty"` + // mempool_error is set by Ostracon. + // ABCI applictions creating a ResponseCheckTX should not set mempool_error. + MempoolError string `protobuf:"bytes,11,opt,name=mempool_error,json=mempoolError,proto3" json:"mempool_error,omitempty"` } func (m *ResponseCheckTx) Reset() { *m = ResponseCheckTx{} } diff --git a/cmd/ostracon/commands/gen_validator.go b/cmd/ostracon/commands/gen_validator.go index 96585565f..1114f33d2 100644 --- a/cmd/ostracon/commands/gen_validator.go +++ b/cmd/ostracon/commands/gen_validator.go @@ -19,13 +19,8 @@ var GenValidatorCmd = &cobra.Command{ Run: genValidator, } -func init() { - GenValidatorCmd.Flags().String("priv_key_type", config.PrivKeyType, - "Specify validator's private key type (ed25519 | composite)") -} - func genValidator(cmd *cobra.Command, args []string) { - pv, _ := privval.GenFilePV("", "", config.PrivKeyType) + pv := privval.GenFilePV("", "") jsbz, err := tmjson.Marshal(pv) if err != nil { panic(err) diff --git a/cmd/ostracon/commands/init.go b/cmd/ostracon/commands/init.go index 891a72195..8c1484dde 100644 --- a/cmd/ostracon/commands/init.go +++ b/cmd/ostracon/commands/init.go @@ -21,15 +21,9 @@ func NewInitCmd() *cobra.Command { RunE: initFiles, } - AddInitFlags(cmd) return cmd } -func AddInitFlags(cmd *cobra.Command) { - cmd.Flags().String("priv_key_type", config.PrivKeyType, - "Specify validator's private key type (ed25519 | composite)") -} - func initFiles(cmd *cobra.Command, args []string) error { return initFilesWithConfig(config) } @@ -38,21 +32,14 @@ func initFilesWithConfig(config *cfg.Config) error { // private validator privValKeyFile := config.PrivValidatorKeyFile() privValStateFile := config.PrivValidatorStateFile() - privKeyType := config.PrivValidatorKeyType() var pv *privval.FilePV if tmos.FileExists(privValKeyFile) { pv = privval.LoadFilePV(privValKeyFile, privValStateFile) logger.Info("Found private validator", "keyFile", privValKeyFile, "stateFile", privValStateFile) } else { - var err error - pv, err = privval.GenFilePV(privValKeyFile, privValStateFile, privKeyType) - if err != nil { - return err - } - if pv != nil { - pv.Save() - } + pv = privval.GenFilePV(privValKeyFile, privValStateFile) + pv.Save() logger.Info("Generated private validator", "keyFile", privValKeyFile, "stateFile", privValStateFile) } diff --git a/cmd/ostracon/commands/reset.go b/cmd/ostracon/commands/reset.go index 9e4cc1a0e..fcf81c5e6 100644 --- a/cmd/ostracon/commands/reset.go +++ b/cmd/ostracon/commands/reset.go @@ -40,10 +40,6 @@ var ResetStateCmd = &cobra.Command{ func init() { ResetAllCmd.Flags().BoolVar(&keepAddrBook, "keep-addr-book", false, "keep the address book intact") - ResetAllCmd.Flags().String("priv_key_type", config.PrivKeyType, - "Specify validator's private key type (ed25519 | composite)") - ResetPrivValidatorCmd.Flags().String("priv_key_type", config.PrivKeyType, - "Specify validator's private key type (ed25519 | composite)") } // ResetPrivValidatorCmd resets the private validator files. @@ -68,7 +64,6 @@ func resetAllCmd(cmd *cobra.Command, args []string) (err error) { config.P2P.AddrBookFile(), config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), - config.PrivValidatorKeyType(), logger, ) } @@ -81,13 +76,12 @@ func resetPrivValidator(cmd *cobra.Command, args []string) (err error) { return err } - return resetFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), - config.PrivValidatorKeyType(), logger) - + resetFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), logger) + return nil } // resetAll removes address book files plus all data, and resets the privValdiator data. -func resetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile, privKeyType string, logger log.Logger) error { +func resetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile string, logger log.Logger) error { if keepAddrBook { logger.Info("The address book remains intact") } else { @@ -105,7 +99,8 @@ func resetAll(dbDir, addrBookFile, privValKeyFile, privValStateFile, privKeyType } // recreate the dbDir since the privVal state needs to live there - return resetFilePV(privValKeyFile, privValStateFile, privKeyType, logger) + resetFilePV(privValKeyFile, privValStateFile, logger) + return nil } // resetState removes address book files plus all databases. @@ -162,7 +157,7 @@ func resetState(dbDir string, logger log.Logger) error { return nil } -func resetFilePV(privValKeyFile, privValStateFile, privKeyType string, logger log.Logger) error { +func resetFilePV(privValKeyFile, privValStateFile string, logger log.Logger) { if _, err := os.Stat(privValKeyFile); err == nil { pv := privval.LoadFilePVEmptyState(privValKeyFile, privValStateFile) pv.Reset() @@ -172,7 +167,7 @@ func resetFilePV(privValKeyFile, privValStateFile, privKeyType string, logger lo "stateFile", privValStateFile, ) } else { - pv, _ := privval.GenFilePV(privValKeyFile, privValStateFile, privKeyType) + pv := privval.GenFilePV(privValKeyFile, privValStateFile) pv.Save() logger.Info( "Generated private validator file", @@ -180,7 +175,6 @@ func resetFilePV(privValKeyFile, privValStateFile, privKeyType string, logger lo "stateFile", privValStateFile, ) } - return nil } func removeAddrBook(addrBookFile string, logger log.Logger) { diff --git a/cmd/ostracon/commands/reset_test.go b/cmd/ostracon/commands/reset_test.go index 0918745a7..fc3437eb6 100644 --- a/cmd/ostracon/commands/reset_test.go +++ b/cmd/ostracon/commands/reset_test.go @@ -48,7 +48,7 @@ func Test_ResetAll(t *testing.T) { pv.LastSignState.Height = 10 pv.Save() require.NoError(t, resetAll(config.DBDir(), config.P2P.AddrBookFile(), config.PrivValidatorKeyFile(), - config.PrivValidatorStateFile(), config.PrivKeyType, logger)) + config.PrivValidatorStateFile(), logger)) require.DirExists(t, config.DBDir()) require.NoFileExists(t, filepath.Join(config.DBDir(), "block.db")) require.NoFileExists(t, filepath.Join(config.DBDir(), "state.db")) diff --git a/cmd/ostracon/commands/testnet.go b/cmd/ostracon/commands/testnet.go index 8677a3fdd..7cc2e21fc 100644 --- a/cmd/ostracon/commands/testnet.go +++ b/cmd/ostracon/commands/testnet.go @@ -34,7 +34,6 @@ var ( hostnames []string p2pPort int randomMonikers bool - privKeyType string ) const ( @@ -75,8 +74,6 @@ func init() { "P2P Port") TestnetFilesCmd.Flags().BoolVar(&randomMonikers, "random-monikers", false, "randomize the moniker for each generated node") - TestnetFilesCmd.Flags().StringVar(&privKeyType, "priv-key-type", privval.PrivKeyTypeEd25519, - "specify validator's private key type (ed25519 | composite)") } // TestnetFilesCmd allows initialisation of files for an Ostracon testnet. @@ -139,7 +136,6 @@ func testnetFiles(cmd *cobra.Command, args []string) error { return err } - config.PrivKeyType = privKeyType if err := initFilesWithConfig(config); err != nil { return err } diff --git a/config/config.go b/config/config.go index 7217e567d..40bf5ae0f 100644 --- a/config/config.go +++ b/config/config.go @@ -8,8 +8,6 @@ import ( "os" "path/filepath" "time" - - "github.com/line/ostracon/privval" ) const ( @@ -244,9 +242,6 @@ type BaseConfig struct { //nolint: maligned // If true, query the ABCI app on connecting to a new peer // so the app can decide if we should keep the connection or not FilterPeers bool `mapstructure:"filter_peers"` // false - - // Specify validator's private key type - PrivKeyType string `mapstructure:"priv_key_type"` } // DefaultBaseConfig returns a default base configuration for an Ostracon node @@ -269,7 +264,6 @@ func DefaultBaseConfig() BaseConfig { FilterPeers: false, DBBackend: DefaultDBBackend, DBPath: "data", - PrivKeyType: privval.PrivKeyTypeEd25519, } } @@ -312,10 +306,6 @@ func (cfg BaseConfig) DBDir() string { return rootify(cfg.DBPath, cfg.RootDir) } -func (cfg BaseConfig) PrivValidatorKeyType() string { - return cfg.PrivKeyType -} - // ValidateBasic performs basic validation (checking param bounds, etc.) and // returns an error if any check fails. func (cfg BaseConfig) ValidateBasic() error { diff --git a/config/toml.go b/config/toml.go index c2e3dc900..5aabb89b5 100644 --- a/config/toml.go +++ b/config/toml.go @@ -620,8 +620,7 @@ var testGenesisFmt = `{ }, "validator": { "pub_key_types": [ - "ed25519", - "composite(bls12-381,ed25519)" + "ed25519" ] }, "version": {} diff --git a/consensus/aggregate_signature_test.go b/consensus/aggregate_signature_test.go deleted file mode 100644 index 3d96e4f28..000000000 --- a/consensus/aggregate_signature_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package consensus - -import ( - "crypto/ed25519" - "testing" - - "github.com/line/ostracon/crypto/bls" - - "github.com/stretchr/testify/require" - - "github.com/line/ostracon/libs/log" -) - -func startConsensusAndMakeBlocks(t *testing.T, nPeers, nVals, nValsWithComposite int) []*State { - css, _, _, cleanup := consensusNetWithPeers( - nVals, - nPeers, - t.Name(), - newMockTickerFunc(true), - newPersistentKVStoreWithPath, - nValsWithComposite) - - defer cleanup() - logger := log.TestingLogger() - - reactors, blocksSubs, eventBuses := startConsensusNet(t, css, nPeers) - defer stopConsensusNet(logger, reactors, eventBuses) - - // map of active validators - activeVals := make(map[string]struct{}) - for i := 0; i < nVals; i++ { - pubKey, err := css[i].privValidator.GetPubKey() - require.NoError(t, err) - activeVals[string(pubKey.Address())] = struct{}{} - } - - // wait till everyone makes block 1 - timeoutWaitGroup(t, nPeers, func(j int) { - <-blocksSubs[j].Out() - }, css) - - // wait till everyone makes block 2 - waitForAndValidateBlock(t, nPeers, activeVals, blocksSubs, css) - - return css -} - -func TestAggregateSignature(t *testing.T) { - const ( - nPeers = 4 - nVals = 4 - nValsWithComposite = 0 - ) - css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite) - for _, state := range css { - block := state.blockStore.LoadBlock(2) - - // validators are ed25519 only - for _, comsig := range block.LastCommit.Signatures { - require.EqualValues(t, ed25519.PrivateKeySize, len(comsig.Signature)) - } - require.EqualValues(t, nVals, len(block.LastCommit.Signatures)) - require.Nil(t, block.LastCommit.AggregatedSignature) - } -} - -func TestAggregateSignatureWithComposite(t *testing.T) { - const ( - nPeers = 4 - nVals = 4 - nValsWithComposite = 4 - ) - css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite) - - for _, state := range css { - block := state.blockStore.LoadBlock(2) - // validators are composite only - for _, comsig := range block.LastCommit.Signatures { - require.Nil(t, comsig.Signature) - } - require.EqualValues(t, nVals, len(block.LastCommit.Signatures)) - require.EqualValues(t, bls.SignatureSize, len(block.LastCommit.AggregatedSignature)) - } -} - -func TestAggregateSignatureWithMix(t *testing.T) { - const ( - nPeers = 4 - nVals = 4 - nValsWithComposite = 2 - expectedCntNotNilSig = nVals - nValsWithComposite - ) - css := startConsensusAndMakeBlocks(t, nPeers, nVals, nValsWithComposite) - - for _, state := range css { - block := state.blockStore.LoadBlock(2) - // composite and ed25519 validators - cnt := 0 - for _, comsig := range block.LastCommit.Signatures { - if comsig.Signature != nil { - cnt++ - } - } - // count the unaggregated sig - require.EqualValues(t, expectedCntNotNilSig, cnt) - // count the aggregated sig - require.EqualValues(t, nValsWithComposite, len(block.LastCommit.Signatures)-cnt) - } -} diff --git a/consensus/common_test.go b/consensus/common_test.go index e4f9977e6..86910c76d 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -472,8 +472,7 @@ func loadPrivValidator(config *cfg.Config) *privval.FilePV { privValidatorKeyFile := config.PrivValidatorKeyFile() ensureDir(filepath.Dir(privValidatorKeyFile), 0700) privValidatorStateFile := config.PrivValidatorStateFile() - privKeyType := config.PrivValidatorKeyType() - privValidator, _ := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile, privKeyType) + privValidator := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) privValidator.Reset() return privValidator } @@ -868,28 +867,6 @@ func randConsensusNet(nValidators int, testName string, tickerFunc func() Timeou } } -// nPeers = nValidators(ed25519 or composite) + nNotValidator -// (0 <= numOfComposite <= nValidators) -func consensusNetWithPeers( - nValidators, - nPeers int, - testName string, - tickerFunc func() TimeoutTicker, - appFunc func(string) abci.Application, - nValsWithComposite int, -) ([]*State, *types.GenesisDoc, *cfg.Config, cleanupFunc) { - genDoc, privVals := genesisDoc(nValidators, testMinPower, types.DefaultVoterParams(), nValsWithComposite) - - css, peer0Config, configRootDirs := createPeersAndValidators(nValidators, nPeers, testName, - genDoc, privVals, tickerFunc, appFunc) - - return css, genDoc, peer0Config, func() { - for _, dir := range configRootDirs { - os.RemoveAll(dir) - } - } -} - // nPeers = nValidators + nNotValidator func randConsensusNetWithPeers( nValidators, @@ -939,7 +916,7 @@ func createPeersAndValidators(nValidators, nPeers int, testName string, panic(err) } - privVal, _ = privval.GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), privval.PrivKeyTypeEd25519) + privVal = privval.GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) } app := appFunc(path.Join(config.DBDir(), fmt.Sprintf("%s_%d", testName, i))) @@ -970,41 +947,6 @@ func getSwitchIndex(switches []*p2p.Switch, peer p2p.Peer) int { //------------------------------------------------------------------------------- // genesis -func genesisDoc( - numValidators int, - minPower int64, - voterParams *types.VoterParams, - nValsWithComposite int, -) (*types.GenesisDoc, []types.PrivValidator) { - validators := make([]types.GenesisValidator, numValidators) - privValidators := make([]types.PrivValidator, numValidators) - var val *types.Validator - var privVal types.PrivValidator - for i := 0; i < nValsWithComposite; i++ { - val, privVal = createTestValidator(minPower, types.PrivKeyComposite) - validators[i] = types.GenesisValidator{ - PubKey: val.PubKey, - Power: val.VotingPower, - } - privValidators[i] = privVal - } - for i := nValsWithComposite; i < numValidators; i++ { - val, privVal = createTestValidator(minPower, types.PrivKeyEd25519) - validators[i] = types.GenesisValidator{ - PubKey: val.PubKey, - Power: val.VotingPower, - } - privValidators[i] = privVal - } - sort.Sort(types.PrivValidatorsByAddress(privValidators)) - - return &types.GenesisDoc{ - GenesisTime: tmtime.Now(), - ChainID: config.ChainID(), - Validators: validators, - VoterParams: voterParams, - }, privValidators -} func randGenesisDoc( numValidators int, @@ -1121,8 +1063,8 @@ func signDataIsEqual(v1 *types.Vote, v2 *tmproto.Vote) bool { //---------------------------------------- // Validator -func createTestValidator(minPower int64, keytype types.PrivKeyType) (*types.Validator, types.PrivValidator) { - privVal := types.NewMockPV(keytype) +func createTestValidator(minPower int64) (*types.Validator, types.PrivValidator) { + privVal := types.NewMockPV() votingPower := minPower votingPower += 100 diff --git a/consensus/msgs_test.go b/consensus/msgs_test.go index 7adfed9c9..7c975aac2 100644 --- a/consensus/msgs_test.go +++ b/consensus/msgs_test.go @@ -57,7 +57,7 @@ func TestMsgToProto(t *testing.T) { } pbProposal := proposal.ToProto() - pv := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + pv := types.NewMockPV() pk, err := pv.GetPubKey() require.NoError(t, err) val := types.NewValidator(pk, 100) diff --git a/consensus/reactor.go b/consensus/reactor.go index a337472b8..eeee480b3 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -702,11 +702,9 @@ OUTER_LOOP: // If peer is lagging by more than 1, send Commit. blockStoreBase := conR.conS.blockStore.Base() if blockStoreBase > 0 && prs.Height != 0 && rs.Height >= prs.Height+2 && prs.Height >= blockStoreBase { - // Load the seen commit for prs.Height, + // Load the block commit for prs.Height, // which contains precommit signatures for prs.Height. - // Originally the block commit was used, but with the addition of the BLS signature-aggregation, - // we use seen commit instead of the block commit because block commit has no individual signature. - if commit := conR.conS.blockStore.LoadSeenCommit(prs.Height); commit != nil { + if commit := conR.conS.blockStore.LoadBlockCommit(prs.Height); commit != nil { if ps.PickSendVote(commit) { logger.Debug("Picked Catchup commit to send", "height", prs.Height) continue OUTER_LOOP diff --git a/consensus/wal_generator.go b/consensus/wal_generator.go index 538581562..fced66777 100644 --- a/consensus/wal_generator.go +++ b/consensus/wal_generator.go @@ -40,11 +40,7 @@ func WALGenerateNBlocks(t *testing.T, wr io.Writer, numBlocks int) (err error) { // NOTE: we don't do handshake so need to set state.Version.Consensus.App directly. privValidatorKeyFile := config.PrivValidatorKeyFile() privValidatorStateFile := config.PrivValidatorStateFile() - privKeyType := config.PrivValidatorKeyType() - privValidator, err := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile, privKeyType) - if err != nil { - return fmt.Errorf("failed to load FilePV: %w", err) - } + privValidator := privval.LoadOrGenFilePV(privValidatorKeyFile, privValidatorStateFile) genDoc, err := types.GenesisDocFromFile(config.GenesisFile()) if err != nil { return fmt.Errorf("failed to read genesis file: %w", err) diff --git a/crypto/bls/bls.go b/crypto/bls/bls.go deleted file mode 100644 index 48ba34924..000000000 --- a/crypto/bls/bls.go +++ /dev/null @@ -1,233 +0,0 @@ -package bls - -import ( - "bytes" - "crypto/sha512" - "crypto/subtle" - "fmt" - - tmjson "github.com/line/ostracon/libs/json" - - "github.com/herumi/bls-eth-go-binary/bls" - - "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/tmhash" -) - -var _ crypto.PrivKey = PrivKey{} - -const ( - PrivKeyName = "ostracon/PrivKeyBLS12" - PubKeyName = "ostracon/PubKeyBLS12" - PrivKeySize = 32 - PubKeySize = 48 - SignatureSize = 96 - KeyType = "bls12-381" -) - -func init() { - tmjson.RegisterType(PubKey{}, PubKeyName) - tmjson.RegisterType(PrivKey{}, PrivKeyName) - - err := bls.Init(bls.BLS12_381) - if err != nil { - panic(fmt.Sprintf("ERROR: %s", err)) - } - err = bls.SetETHmode(bls.EthModeLatest) - if err != nil { - panic(fmt.Sprintf("ERROR: %s", err)) - } -} - -// PrivKey implements crypto.PrivKey. -type PrivKey [PrivKeySize]byte - -// AddSignature adds a BLS signature to the init. When the init is nil, then a new aggregate signature is built -// from specified signature. -func AddSignature(init []byte, signature []byte) (aggrSign []byte, err error) { - if init == nil { - blsSign := bls.Sign{} - init = blsSign.Serialize() - } else if len(init) != SignatureSize { - err = fmt.Errorf("invalid BLS signature: aggregated signature size %d is not valid size %d", - len(init), SignatureSize) - return - } - if len(signature) != SignatureSize { - err = fmt.Errorf("invalid BLS signature: signature size %d is not valid size %d", - len(signature), SignatureSize) - return - } - blsSign := bls.Sign{} - err = blsSign.Deserialize(signature) - if err != nil { - return - } - aggrBLSSign := bls.Sign{} - err = aggrBLSSign.Deserialize(init) - if err != nil { - return - } - aggrBLSSign.Add(&blsSign) - aggrSign = aggrBLSSign.Serialize() - return -} - -func VerifyAggregatedSignature(aggregatedSignature []byte, pubKeys []PubKey, msgs [][]byte) error { - if len(pubKeys) != len(msgs) { - return fmt.Errorf("the number of public keys %d doesn't match the one of messages %d", - len(pubKeys), len(msgs)) - } - if aggregatedSignature == nil { - if len(pubKeys) == 0 { - return nil - } - return fmt.Errorf( - "the aggregate signature was omitted, even though %d public keys were specified", len(pubKeys)) - } - aggrSign := bls.Sign{} - err := aggrSign.Deserialize(aggregatedSignature) - if err != nil { - return err - } - blsPubKeys := make([]bls.PublicKey, len(pubKeys)) - hashes := make([][]byte, len(msgs)) - for i := 0; i < len(pubKeys); i++ { - blsPubKeys[i] = bls.PublicKey{} - err = blsPubKeys[i].Deserialize(pubKeys[i][:]) - if err != nil { - return err - } - hash := sha512.Sum512_256(msgs[i]) - hashes[i] = hash[:] - } - if !aggrSign.VerifyAggregateHashes(blsPubKeys, hashes) { - return fmt.Errorf("failed to verify the aggregated hashes by %d public keys", len(blsPubKeys)) - } - return nil -} - -// GenPrivKey generates a new BLS12-381 private key. -func GenPrivKey() PrivKey { - sigKey := bls.SecretKey{} - sigKey.SetByCSPRNG() - sigKeyBinary := PrivKey{} - binary := sigKey.Serialize() - if len(binary) != PrivKeySize { - panic(fmt.Sprintf("unexpected BLS private key size: %d != %d", len(binary), PrivKeySize)) - } - copy(sigKeyBinary[:], binary) - return sigKeyBinary -} - -// Bytes marshals the privkey using amino encoding. -func (privKey PrivKey) Bytes() []byte { - return privKey[:] -} - -// Sign produces a signature on the provided message. -func (privKey PrivKey) Sign(msg []byte) ([]byte, error) { - if msg == nil { - panic("Nil specified as the message") - } - blsKey := bls.SecretKey{} - err := blsKey.Deserialize(privKey[:]) - if err != nil { - return nil, err - } - hash := sha512.Sum512_256(msg) - sign := blsKey.SignHash(hash[:]) - return sign.Serialize(), nil -} - -// VRFProve is not supported in BLS12. -func (privKey PrivKey) VRFProve(seed []byte) (crypto.Proof, error) { - return nil, fmt.Errorf("VRF prove is not supported by the BLS12") -} - -// PubKey gets the corresponding public key from the private key. -func (privKey PrivKey) PubKey() crypto.PubKey { - blsKey := bls.SecretKey{} - err := blsKey.Deserialize(privKey[:]) - if err != nil { - panic(fmt.Sprintf("Not a BLS12-381 private key: %X", privKey[:])) - } - pubKey := blsKey.GetPublicKey() - pubKeyBinary := PubKey{} - binary := pubKey.Serialize() - if len(binary) != PubKeySize { - panic(fmt.Sprintf("unexpected BLS public key size: %d != %d", len(binary), PubKeySize)) - } - copy(pubKeyBinary[:], binary) - return pubKeyBinary -} - -// Equals - you probably don't need to use this. -// Runs in constant time based on length of the keys. -func (privKey PrivKey) Equals(other crypto.PrivKey) bool { - if otherEd, ok := other.(PrivKey); ok { - return subtle.ConstantTimeCompare(privKey[:], otherEd[:]) == 1 - } - return false -} - -// Type returns information to identify the type of this key. -func (privKey PrivKey) Type() string { - return KeyType -} - -var _ crypto.PubKey = PubKey{} - -// PubKey implements crypto.PubKey for the BLS12-381 signature scheme. -type PubKey [PubKeySize]byte - -// Address is the SHA256-20 of the raw pubkey bytes. -func (pubKey PubKey) Address() crypto.Address { - return tmhash.SumTruncated(pubKey[:]) -} - -// Bytes marshals the PubKey using amino encoding. -func (pubKey PubKey) Bytes() []byte { - return pubKey[:] -} - -func (pubKey PubKey) VerifySignature(msg []byte, sig []byte) bool { - // make sure we use the same algorithm to sign - if len(sig) != SignatureSize { - return false - } - blsPubKey := bls.PublicKey{} - err := blsPubKey.Deserialize(pubKey[:]) - if err != nil { - return false - } - blsSign := bls.Sign{} - err = blsSign.Deserialize(sig) - if err != nil { - fmt.Printf("Signature Deserialize failed: %s", err) - return false - } - hash := sha512.Sum512_256(msg) - return blsSign.VerifyHash(&blsPubKey, hash[:]) -} - -// VRFVerify is not supported in BLS12. -func (pubKey PubKey) VRFVerify(proof crypto.Proof, seed []byte) (crypto.Output, error) { - return nil, fmt.Errorf("VRF verify is not supported by the BLS12") -} - -func (pubKey PubKey) String() string { - return fmt.Sprintf("PubKeyBLS12{%X}", pubKey[:]) -} - -func (pubKey PubKey) Equals(other crypto.PubKey) bool { - if otherEd, ok := other.(PubKey); ok { - return bytes.Equal(pubKey[:], otherEd[:]) - } - return false -} - -// Type returns information to identify the type of this key. -func (pubKey PubKey) Type() string { - return KeyType -} diff --git a/crypto/bls/bls_test.go b/crypto/bls/bls_test.go deleted file mode 100644 index 05ab9ad08..000000000 --- a/crypto/bls/bls_test.go +++ /dev/null @@ -1,373 +0,0 @@ -package bls_test - -import ( - "bytes" - "crypto/sha256" - "fmt" - "math/rand" - "reflect" - "testing" - "time" - - b "github.com/herumi/bls-eth-go-binary/bls" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" -) - -func TestBasicSignatureFunctions(t *testing.T) { - privateKey := b.SecretKey{} - privateKey.SetByCSPRNG() - publicKey := privateKey.GetPublicKey() - - duplicatedPrivateKey := b.SecretKey{} - err := duplicatedPrivateKey.Deserialize(privateKey.Serialize()) - if err != nil { - t.Fatalf("Private key deserialization failed.") - } - - if len(privateKey.Serialize()) != bls.PrivKeySize { - t.Fatalf("The constant size %d of the private key is different from the actual size %d.", - bls.PrivKeySize, len(privateKey.Serialize())) - } - - duplicatedPublicKey := b.PublicKey{} - err = duplicatedPublicKey.Deserialize(publicKey.Serialize()) - if err != nil { - t.Fatalf("Public key deserialization failed.") - } - - if len(publicKey.Serialize()) != bls.PubKeySize { - t.Fatalf("The constant size %d of the public key is different from the actual size %d.", - bls.PubKeySize, len(publicKey.Serialize())) - } - - duplicatedSignature := func(sig *b.Sign) *b.Sign { - duplicatedSign := b.Sign{} - err := duplicatedSign.Deserialize(sig.Serialize()) - if err != nil { - t.Fatalf("Signature deserialization failed.") - } - - if len(sig.Serialize()) != bls.SignatureSize { - t.Fatalf("The constant size %d of the signature is different from the actual size %d.", - bls.SignatureSize, len(sig.Serialize())) - } - return &duplicatedSign - } - - msg := []byte("hello, world") - for _, privKey := range []b.SecretKey{privateKey, duplicatedPrivateKey} { - for _, pubKey := range []*b.PublicKey{publicKey, &duplicatedPublicKey} { - signature := privKey.SignByte(msg) - if !signature.VerifyByte(pubKey, msg) { - t.Errorf("Signature verification failed.") - } - - if !duplicatedSignature(signature).VerifyByte(pubKey, msg) { - t.Errorf("Signature verification failed.") - } - - for i := 0; i < len(msg); i++ { - for j := 0; j < 8; j++ { - garbled := make([]byte, len(msg)) - copy(garbled, msg) - garbled[i] ^= 1 << (8 - j - 1) - if bytes.Equal(msg, garbled) { - t.Fatalf("Not a barbled message") - } - if signature.VerifyByte(pubKey, garbled) { - t.Errorf("Signature verification was successful against a garbled byte sequence.") - } - if duplicatedSignature(signature).VerifyByte(pubKey, garbled) { - t.Errorf("Signature verification was successful against a garbled byte sequence.") - } - } - } - } - } -} - -func TestSignatureAggregationAndVerify(t *testing.T) { - privKeys := make([]b.SecretKey, 25) - pubKeys := make([]b.PublicKey, len(privKeys)) - msgs := make([][]byte, len(privKeys)) - hash32s := make([][32]byte, len(privKeys)) - signatures := make([]b.Sign, len(privKeys)) - for i, privKey := range privKeys { - privKey.SetByCSPRNG() - pubKeys[i] = *privKey.GetPublicKey() - msgs[i] = []byte(fmt.Sprintf("hello, world #%d", i)) - hash32s[i] = sha256.Sum256(msgs[i]) - signatures[i] = *privKey.SignHash(hash32s[i][:]) - - // normal single-hash case - if !signatures[i].VerifyHash(&pubKeys[i], hash32s[i][:]) { - t.Fail() - } - - // in case where 1-bit of hash was garbled - garbledHash := make([]byte, len(msgs[i])) - copy(garbledHash, msgs[i]) - garbledHash[0] ^= 1 << 0 - if garbledHash[0] == msgs[i][0] || signatures[i].VerifyByte(&pubKeys[i], garbledHash) { - t.Fail() - } - - // Verification using an invalid public key - } - - // aggregation - multiSig := b.Sign{} - multiSig.Aggregate(signatures) - - // normal case - hashes := make([][]byte, len(privKeys)) - for i := 0; i < len(hashes); i++ { - hashes[i] = hash32s[i][:] - } - if !multiSig.VerifyAggregateHashes(pubKeys, hashes) { - t.Fatalf("failed to validate the aggregate signature of the hashed message") - } - - // in case where 1-bit of signature was garbled - multiSigBytes := multiSig.Serialize() - for i := range multiSigBytes { - for j := 0; j < 8; j++ { - garbledMultiSigBytes := make([]byte, len(multiSigBytes)) - copy(garbledMultiSigBytes, multiSigBytes) - garbledMultiSigBytes[i] ^= 1 << j - if garbledMultiSigBytes[i] == multiSigBytes[i] { - t.Fail() - } - garbledMultiSig := b.Sign{} - err := garbledMultiSig.Deserialize(garbledMultiSigBytes) - if err == nil { - // Note that in some cases Deserialize() fails - if garbledMultiSig.VerifyAggregateHashes(pubKeys, hashes) { - t.Errorf("successfully verified the redacted signature") - } - } - } - } - - // in case a public key used for verification is replaced - invalidPrivKey := b.SecretKey{} - invalidPrivKey.SetByCSPRNG() - invalidPubKeys := make([]b.PublicKey, len(pubKeys)) - copy(invalidPubKeys, pubKeys) - invalidPubKeys[len(invalidPubKeys)-1] = *invalidPrivKey.GetPublicKey() - if multiSig.VerifyAggregateHashes(invalidPubKeys, hashes) { - t.Fatalf("successfully verified that it contains a public key that was not involved in the signing") - } - - // in case a hash used for verification is replaced - invalidHashes := make([][]byte, len(hashes)) - copy(invalidHashes, hashes) - invalidHash := sha256.Sum256([]byte("hello, world #99")) - invalidHashes[len(invalidHashes)-1] = invalidHash[:] - if multiSig.VerifyAggregateHashes(pubKeys, invalidHashes) { - t.Fatalf("successfully verified that it contains a hash that was not involved in the signing") - } -} - -func generatePubKeysAndSigns(t *testing.T, size int) ([]bls.PubKey, [][]byte, [][]byte) { - pubKeys := make([]bls.PubKey, size) - msgs := make([][]byte, len(pubKeys)) - sigs := make([][]byte, len(pubKeys)) - for i := 0; i < len(pubKeys); i++ { - var err error - privKey := bls.GenPrivKey() - pubKeys[i] = blsPublicKey(t, privKey.PubKey()) - msgs[i] = []byte(fmt.Sprintf("hello, workd #%d", i)) - sigs[i], err = privKey.Sign(msgs[i]) - if err != nil { - t.Fatalf("fail to sign: %s", err) - } - if !pubKeys[i].VerifySignature(msgs[i], sigs[i]) { - t.Fatal("fail to verify signature") - } - } - return pubKeys, msgs, sigs -} - -func blsPublicKey(t *testing.T, pubKey crypto.PubKey) bls.PubKey { - blsPubKey, ok := pubKey.(bls.PubKey) - if !ok { - var keyType string - if t := reflect.TypeOf(pubKey); t.Kind() == reflect.Ptr { - keyType = "*" + t.Elem().Name() - } else { - keyType = t.Name() - } - t.Fatalf("specified public key is not for BLS: %s", keyType) - } - return blsPubKey -} - -func aggregateSignatures(init []byte, signatures [][]byte) (aggrSig []byte, err error) { - aggrSig = init - for _, sign := range signatures { - aggrSig, err = bls.AddSignature(aggrSig, sign) - if err != nil { - return - } - } - return -} - -func TestAggregatedSignature(t *testing.T) { - - // generate BLS signatures and public keys - pubKeys, msgs, sigs := generatePubKeysAndSigns(t, 25) - - // aggregate signatures - aggrSig, err := aggregateSignatures(nil, sigs) - if err != nil { - t.Errorf("fail to aggregate BLS signatures: %s", err) - } - if len(aggrSig) != bls.SignatureSize { - t.Errorf("inconpatible signature size: %d != %d", len(aggrSig), bls.SignatureSize) - } - - // validate the aggregated signature - if err := bls.VerifyAggregatedSignature(aggrSig, pubKeys, msgs); err != nil { - t.Errorf("fail to verify aggregated signature: %s", err) - } - - // validate with the public keys and messages pair in random order - t.Run("Doesn't Depend on the Order of PublicKey-Message Pairs", func(t *testing.T) { - shuffledPubKeys := make([]bls.PubKey, len(pubKeys)) - shuffledMsgs := make([][]byte, len(msgs)) - copy(shuffledPubKeys, pubKeys) - copy(shuffledMsgs, msgs) - rand.Seed(time.Now().UnixNano()) - rand.Shuffle(len(shuffledPubKeys), func(i, j int) { - shuffledPubKeys[i], shuffledPubKeys[j] = shuffledPubKeys[j], shuffledPubKeys[i] - shuffledMsgs[i], shuffledMsgs[j] = shuffledMsgs[j], shuffledMsgs[i] - }) - if err := bls.VerifyAggregatedSignature(aggrSig, shuffledPubKeys, shuffledMsgs); err != nil { - t.Errorf("fail to verify the aggregated signature with random order: %s", err) - } - }) - - // validate with the public keys in random order - t.Run("Incorrect Public Key Order", func(t *testing.T) { - shuffledPubKeys := make([]bls.PubKey, len(pubKeys)) - copy(shuffledPubKeys, pubKeys) - rand.Seed(time.Now().UnixNano()) - rand.Shuffle(len(shuffledPubKeys), func(i, j int) { - shuffledPubKeys[i], shuffledPubKeys[j] = shuffledPubKeys[j], shuffledPubKeys[i] - }) - if err := bls.VerifyAggregatedSignature(aggrSig, shuffledPubKeys, msgs); err == nil { - t.Error("successfully validated with public keys of different order") - } - }) - - // validate with the messages in random order - t.Run("Incorrect Message Order", func(t *testing.T) { - shuffledMsgs := make([][]byte, len(msgs)) - copy(shuffledMsgs, msgs) - rand.Seed(time.Now().UnixNano()) - rand.Shuffle(len(shuffledMsgs), func(i, j int) { - shuffledMsgs[i], shuffledMsgs[j] = shuffledMsgs[j], shuffledMsgs[i] - }) - if err := bls.VerifyAggregatedSignature(aggrSig, pubKeys, shuffledMsgs); err == nil { - t.Error("successfully validated with messages of different order") - } - }) - - // replace one public key with another and detect - t.Run("Replace One Public Key", func(t *testing.T) { - pubKey, _ := bls.GenPrivKey().PubKey().(bls.PubKey) - replacedPubKeys := make([]bls.PubKey, len(pubKeys)) - copy(replacedPubKeys, pubKeys) - replacedPubKeys[0] = pubKey - if err := bls.VerifyAggregatedSignature(aggrSig, replacedPubKeys, msgs); err == nil { - t.Error("verification with an invalid key was successful") - } - }) - - // replace one message with another and detect - t.Run("Replace One Message", func(t *testing.T) { - msg := []byte(fmt.Sprintf("hello, world #%d replaced", len(msgs))) - replacedMsgs := make([][]byte, len(msgs)) - copy(replacedMsgs, msgs) - replacedMsgs[0] = msg - if err := bls.VerifyAggregatedSignature(aggrSig, pubKeys, replacedMsgs); err == nil { - t.Error("verification with an invalid message was successful") - } - }) - - // add new signature to existing aggregated signature and verify - t.Run("Incremental Update", func(t *testing.T) { - msg := []byte(fmt.Sprintf("hello, world #%d", len(msgs))) - privKey := bls.GenPrivKey() - pubKey := privKey.PubKey() - sig, err := privKey.Sign(msg) - assert.Nilf(t, err, "%s", err) - newAggrSig, _ := aggregateSignatures(aggrSig, [][]byte{sig}) - newPubKeys := make([]bls.PubKey, len(pubKeys)) - copy(newPubKeys, pubKeys) - newPubKeys = append(newPubKeys, blsPublicKey(t, pubKey)) - newMsgs := make([][]byte, len(msgs)) - copy(newMsgs, msgs) - newMsgs = append(newMsgs, msg) - if err := bls.VerifyAggregatedSignature(newAggrSig, newPubKeys, newMsgs); err != nil { - t.Errorf("fail to verify the aggregate signature with the new signature: %s", err) - } - }) - - // nil is returned for nil and empty signature - nilSig, _ := aggregateSignatures(nil, [][]byte{}) - assert.Nil(t, nilSig) - - // a non-BLS signature contained - func() { - _, err = aggregateSignatures(nil, [][]byte{make([]byte, 0)}) - assert.NotNil(t, err) - }() -} - -func TestSignatureAggregation(t *testing.T) { - publicKeys := make([]b.PublicKey, 25) - aggregatedSignature := b.Sign{} - aggregatedPublicKey := b.PublicKey{} - msg := []byte("hello, world") - for i := 0; i < len(publicKeys); i++ { - privateKey := b.SecretKey{} - privateKey.SetByCSPRNG() - publicKeys[i] = *privateKey.GetPublicKey() - aggregatedSignature.Add(privateKey.SignByte(msg)) - aggregatedPublicKey.Add(&publicKeys[i]) - } - - if !aggregatedSignature.FastAggregateVerify(publicKeys, msg) { - t.Errorf("Aggregated signature verification failed.") - } - if !aggregatedSignature.VerifyByte(&aggregatedPublicKey, msg) { - t.Errorf("Aggregated signature verification failed.") - } -} - -func TestSignAndValidateBLS12(t *testing.T) { - privKey := bls.GenPrivKey() - pubKey := privKey.PubKey() - - msg := crypto.CRandBytes(128) - sig, err := privKey.Sign(msg) - require.Nil(t, err) - fmt.Printf("restoring signature: %x\n", sig) - - // 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)) -} diff --git a/crypto/composite/composite.go b/crypto/composite/composite.go deleted file mode 100644 index 845057ef0..000000000 --- a/crypto/composite/composite.go +++ /dev/null @@ -1,141 +0,0 @@ -package composite - -import ( - "bytes" - "fmt" - - tmjson "github.com/line/ostracon/libs/json" - "github.com/line/ostracon/libs/math" - - "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/ed25519" - "github.com/line/ostracon/crypto/tmhash" -) - -// composite.PubKey and composite.PrivKey are intended to allow public key algorithms to be selected for each function. - -const ( - PubKeyName = "ostracon/PubKeyComposite" - PrivKeyName = "ostracon/PrivKeyComposite" - - KeyType = "composite" - KeyTypeBlsWithEd25519 = KeyType + "(" + bls.KeyType + "," + ed25519.KeyType + ")" -) - -var MaxSignatureSize = math.MaxInt(ed25519.SignatureSize, bls.SignatureSize) - -func init() { - tmjson.RegisterType(PubKey{}, PubKeyName) - tmjson.RegisterType(PrivKey{}, PrivKeyName) -} - -type PubKey struct { - SignKey crypto.PubKey `json:"sign"` - VrfKey crypto.PubKey `json:"vrf"` -} - -func PubKeyFromBytes(bz []byte) PubKey { - if len(bz) != bls.PubKeySize+ed25519.PubKeySize { - panic(fmt.Sprintf("Wrong PubKey bytes size: %d", len(bz))) - } - sign := bls.PubKey{} - copy(sign[:], bz[:bls.PubKeySize]) - vrf := ed25519.PubKey(make([]byte, ed25519.PubKeySize)) - copy(vrf, bz[bls.PubKeySize:]) - return PubKey{SignKey: sign, VrfKey: vrf} -} - -func (pk PubKey) Identity() crypto.PubKey { - return pk.VrfKey -} - -func (pk PubKey) Address() crypto.Address { - return crypto.Address(tmhash.SumTruncated(pk.Bytes())) -} - -func (pk PubKey) Bytes() []byte { - bz := bytes.NewBuffer(pk.SignKey.Bytes()) - bz.Write(pk.VrfKey.Bytes()) - return bz.Bytes() -} - -func (pk PubKey) VerifySignature(msg []byte, sig []byte) bool { - return pk.SignKey.VerifySignature(msg, sig) -} - -// VRFVerify verifies that the given VRF Proof was generated from the seed by the owner of this public key. -func (pk PubKey) VRFVerify(proof crypto.Proof, seed []byte) (crypto.Output, error) { - return pk.VrfKey.VRFVerify(proof, seed) -} - -func (pk PubKey) Equals(key crypto.PubKey) bool { - other, ok := key.(PubKey) - return ok && pk.SignKey.Equals(other.SignKey) && pk.VrfKey.Equals(other.VrfKey) -} - -func (pk PubKey) Type() string { - return fmt.Sprintf("%s(%s,%s)", KeyType, pk.SignKey.Type(), pk.VrfKey.Type()) -} - -type PrivKey struct { - SignKey crypto.PrivKey `json:"sign"` - VrfKey crypto.PrivKey `json:"vrf"` -} - -func GenPrivKey() *PrivKey { - return NewPrivKeyComposite(bls.GenPrivKey(), ed25519.GenPrivKey()) -} - -func NewPrivKeyComposite(sign crypto.PrivKey, vrf crypto.PrivKey) *PrivKey { - return &PrivKey{SignKey: sign, VrfKey: vrf} -} - -// PrivKeyFromBytes depends on PrivKey.Bytes -// See PrivKey.Bytes -func PrivKeyFromBytes(bz []byte) *PrivKey { - if len(bz) != bls.PrivKeySize+ed25519.PrivateKeySize { - panic(fmt.Sprintf("Wrong PrivKey bytes size: %d", len(bz))) - } - sign := bls.PrivKey{} - copy(sign[:], bz[:bls.PrivKeySize]) - vrf := ed25519.PrivKey(make([]byte, ed25519.PrivateKeySize)) - copy(vrf, bz[bls.PrivKeySize:]) - return &PrivKey{SignKey: sign, VrfKey: vrf} -} - -func (sk PrivKey) Identity() crypto.PrivKey { - return sk.VrfKey -} - -func (sk PrivKey) Bytes() []byte { - bz := bytes.NewBuffer(sk.SignKey.Bytes()) - bz.Write(sk.VrfKey.Bytes()) - return bz.Bytes() -} - -func (sk PrivKey) Sign(msg []byte) ([]byte, error) { - return sk.SignKey.Sign(msg) -} - -// VRFProve generates a VRF Proof for given message to generate a verifiable random. -func (sk PrivKey) VRFProve(message []byte) (crypto.Proof, error) { - return sk.VrfKey.VRFProve(message) -} - -func (sk PrivKey) PubKey() crypto.PubKey { - return PubKey{sk.SignKey.PubKey(), sk.VrfKey.PubKey()} -} - -func (sk PrivKey) Equals(key crypto.PrivKey) bool { - switch other := key.(type) { - case *PrivKey: - return sk.SignKey.Equals(other.SignKey) && sk.VrfKey.Equals(other.VrfKey) - default: - return false - } -} - -func (sk PrivKey) Type() string { - return fmt.Sprintf("%s(%s,%s)", KeyType, sk.SignKey.Type(), sk.VrfKey.Type()) -} diff --git a/crypto/composite/composite_test.go b/crypto/composite/composite_test.go deleted file mode 100644 index 3abcac202..000000000 --- a/crypto/composite/composite_test.go +++ /dev/null @@ -1,292 +0,0 @@ -package composite_test - -import ( - "bytes" - "encoding/base64" - "encoding/hex" - "fmt" - "testing" - - "github.com/stretchr/testify/assert" - - tmjson "github.com/line/ostracon/libs/json" - - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" - "github.com/line/ostracon/crypto/ed25519" -) - -func TestGenPrivKey(t *testing.T) { - sk := composite.GenPrivKey() - sign := sk.SignKey - vrf := sk.VrfKey - compositeKey := composite.NewPrivKeyComposite(sign, vrf) - assert.Equal(t, sk, compositeKey) - bz := compositeKey.Bytes() - assert.Equal(t, sk, composite.PrivKeyFromBytes(bz)) -} - -func TestPrivKeyComposite_Bytes(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - compositeKey := composite.PrivKeyFromBytes(sk.Bytes()) - assert.Equal(t, sign, compositeKey.SignKey) - assert.Equal(t, vrf, compositeKey.VrfKey) - assert.Equal(t, sk, compositeKey) -} - -func TestPrivKeyComposite_Equals(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk1 := composite.NewPrivKeyComposite(sign, vrf) - if !sk1.Equals(sk1) { - t.Errorf("%v", sk1.SignKey.Equals(sk1.SignKey)) - t.Errorf("%v", sk1.VrfKey.Equals(sk1.VrfKey)) - t.Errorf("Identical key is evaluated as different: %v != %v", sk1, sk1) - } - sk2 := composite.NewPrivKeyComposite(sign, vrf) - if !sk1.Equals(sk2) || !sk2.Equals(sk1) { - t.Errorf("The same keys are evaluated as different") - } - sk3 := composite.NewPrivKeyComposite(ed25519.GenPrivKey(), bls.GenPrivKey()) - if sk1.Equals(sk3) || sk3.Equals(sk1) { - t.Errorf("The different keys are evaluated as the same") - } - if sk1.Equals(sign) || sk1.Equals(vrf) { - t.Errorf("The different kind of keys are evaluated as the same") - } -} - -func TestPrivKeyComposite_Identity(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - if !bytes.Equal(sk.Identity().Bytes(), vrf.Bytes()) { - t.Errorf("The identity key is not a vrf key") - } -} - -func TestPrivKeyComposite_PubKey(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey() - compositeKey := composite.PubKeyFromBytes(pk.Bytes()) - assert.Equal(t, sign.PubKey(), compositeKey.SignKey) - assert.Equal(t, vrf.PubKey(), compositeKey.VrfKey) - assert.Equal(t, pk, compositeKey) -} - -func TestPrivKeyComposite_Sign(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - msg := []byte("hello, world") - s1, err := sk.Sign(msg) - if err != nil { - t.Errorf("Fail to generate signature.") - } - s2, _ := sign.Sign(msg) - if !bytes.Equal(s1, s2) { - t.Errorf("The signature is not generated by sign key") - } -} - -func TestPrivKeyComposite_VRFProve(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - msg := []byte("hello, world") - p, err := sk.VRFProve(msg) - if err != nil { - t.Errorf("Fail to generate proof.") - } - _, err = sk.PubKey().VRFVerify(p, msg) - if err != nil { - t.Errorf("Fail to verify the vrf proof.") - } -} - -func TestPubKeyComposite_Address(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey().(composite.PubKey) - // check the byte-size is the same - if len(pk.Address().Bytes()) != len(vrf.PubKey().Address().Bytes()) { - t.Errorf("The address length is not compatible") - } -} - -func TestPubKeyComposite_Bytes(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey().(composite.PubKey) - compositeKey := composite.PubKeyFromBytes(pk.Bytes()) - assert.Equal(t, sign.PubKey(), compositeKey.SignKey) - assert.Equal(t, vrf.PubKey(), compositeKey.VrfKey) - assert.Equal(t, pk, compositeKey) -} - -func TestPubKeyComposite_Equals(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk1 := sk.PubKey().(composite.PubKey) - if !pk1.Equals(pk1) { - t.Errorf("Identical key is evaluated as different") - } - pk2 := sk.PubKey().(composite.PubKey) - if !pk1.Equals(pk2) || !pk2.Equals(pk1) { - t.Errorf("The same keys are evaluated as different") - } - sk3 := composite.NewPrivKeyComposite(ed25519.GenPrivKey(), bls.GenPrivKey()) - pk3 := sk3.PubKey().(composite.PubKey) - if pk1.Equals(pk3) || pk3.Equals(pk1) { - t.Errorf("The different keys are evaluated as the same") - } - if pk1.Equals(sign.PubKey()) || pk1.Equals(vrf.PubKey()) { - t.Errorf("The different kind of keys are evaluated as the same") - } -} - -func TestPubKeyComposite_Identity(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey().(composite.PubKey) - assert.Equal(t, vrf.PubKey(), pk.Identity()) -} - -func TestPubKeyComposite_VerifyBytes(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey().(composite.PubKey) - msg := []byte("hello, world") - s, err := sk.Sign(msg) - if err != nil { - t.Errorf("Fail to generate signature.") - } - if !pk.VerifySignature(msg, s) { - t.Errorf("Fail to verify signature.") - } - if pk.VerifySignature([]byte("brown fox"), s) { - t.Errorf("Signature validation for the different messages is successful.") - } -} - -func TestPubKeyComposite_VRFVerify(t *testing.T) { - sign := bls.GenPrivKey() - vrf := ed25519.GenPrivKey() - sk := composite.NewPrivKeyComposite(sign, vrf) - pk := sk.PubKey().(composite.PubKey) - msg := []byte("hello, world") - proof, err := sk.VRFProve(msg) - if err != nil { - t.Errorf("Fail to generage vrf proof.") - } - output1, err := pk.VRFVerify(proof, msg) - if err != nil { - t.Errorf("Fail to verify vrf proof.") - } - output2, _ := vrf.PubKey().VRFVerify(proof, msg) - if !bytes.Equal(output1, output2) { - t.Errorf("Output is different from the VRF key.") - } -} - -func TestEnvironmentalCompatibility(t *testing.T) { - t.Run("The same signature is generated from the same key binary for any runtime env", func(t *testing.T) { - privKeyJSON := fmt.Sprintf( - "{\"type\":\"%s\",\"value\":{"+ - "\"sign\":{\"type\":\"%s\",\"value\":\"%s\"},"+ - "\"vrf\":{\"type\":\"%s\",\"value\":\"%s\"}}}", - composite.PrivKeyName, - bls.PrivKeyName, "FXBs3F3g3FGyDY8P8ipK8t6jwFgJR/jvUnYwiKLWnYQ=", - ed25519.PrivKeyName, "IzLJPy6KFiEGbV7SvJAIUBzYbjOpgtdKU+RFsGWYknuTZdNPe6iQzthTvKj4ZU1rkLqXg6ofcej1/89NXexfww==") - compositePrivKey := composite.PrivKey{} - err := tmjson.Unmarshal([]byte(privKeyJSON), &compositePrivKey) - if err != nil { - t.Fatal(err) - } - - msg := []byte("hello, world") - actual, err := compositePrivKey.Sign(msg) - if err != nil { - t.Fatal(err) - } - expected, err := hex.DecodeString("880b6db7a1be536e1057b34552325dd4ae6acdab4aa833f196c9d7c6d10973c9bbfb4a" + - "7f6a482287698a26007be82047157e38c27f8994463b12788f7dde86a6057493543c7922141248845b4f63b4bcf207e4fc92b1d" + - "c4cff8d06d44e5d8109") - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(expected, actual) { - t.Logf("Expected Signature: %s (%d bytes)", hex.EncodeToString(expected), len(expected)) - t.Logf("Actual Signature: %s (%d bytes)", hex.EncodeToString(actual), len(actual)) - t.Errorf("Signatures generated from the same key and message are different than expected") - } - }) - - // https://github.com/line/ostracon/issues/121 - t.Run("A reproduction test of issue #121", func(t *testing.T) { - - // restore BLS private key from base64 string in priv_validator_key.json - blsPrivKey := bls.PrivKey{} - blsPrivKeyBytes, err := base64.StdEncoding.DecodeString("BpqODFajV6NnQhBfT8ERyvwyqPoZS664e1v35sfr76g=") - if err != nil { - t.Fatal(err) - } else if len(blsPrivKeyBytes) != bls.PrivKeySize { - t.Fatalf("fixed private key size: %d != %d", len(blsPrivKeyBytes), bls.PrivKeySize) - } - copy(blsPrivKey[:], blsPrivKeyBytes) - - // restore Ed25519 private key from base64 string in priv_validator_key.json - ed25519PrivKeyBytes, err := base64.StdEncoding.DecodeString("TGb5K4TbD1XdNd0HGEt7I6quhTJ2aSckgPLLBKs8hDUC" + - "4Wh8kfEmnRUeMYtR8V0UfNwQyTYqGupZeyIhJcV1TA==") - if err != nil { - t.Fatal(err) - } else if len(ed25519PrivKeyBytes) != ed25519.PrivateKeySize { - t.Fatalf("fixed private key size: %d != %d", len(ed25519PrivKeyBytes), ed25519.PrivateKeySize) - } - var ed25519PrivKey ed25519.PrivKey = ed25519PrivKeyBytes - - // compare addresses to assumed value - compositePrivKey := composite.NewPrivKeyComposite(blsPrivKey, ed25519PrivKey) - compositePubKey := compositePrivKey.PubKey() - address, err := hex.DecodeString("712988cd548e7c6858aa3e836e02e8f836cdb7a9") - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(address, compositePubKey.Address()) { - t.Errorf("addresses didn't match: %s", hex.EncodeToString(compositePubKey.Address())) - } - - // compare generated signature to assumed value - message, err := hex.DecodeString("44080111010000000000000022300A147A68265205CB115AE35A13515C423F1721E87BB" + - "412180A147A68265205CB115AE35A13515C423F1721E87BB410013205636861696E") - if err != nil { - t.Fatal(err) - } - signature, err := compositePrivKey.Sign(message) - if err != nil { - t.Fatal(err) - } - expectedSig, err := hex.DecodeString("a00a8a8143fff615e3df98e9b4a493b0ffc5cf1cee14c55d4c667c34651392331c4d" + - "5a1bf0a15d018262d61f74a59cc80775217b81363796e50aac7ce7542424a2eb84fbaf787f7a1c00229682ac4bb0a45f67cdf43f" + - "b21b091f25a0a8bd51ae") - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(expectedSig, signature) { - t.Logf("Address: %s", hex.EncodeToString(address)) - t.Logf("Message: %s (%d bytes)", hex.EncodeToString(message), len(message)) - t.Logf("Expected Signature: %s (%d bytes)", hex.EncodeToString(expectedSig), len(expectedSig)) - t.Logf("Actual Signature: %s (%d bytes)", hex.EncodeToString(signature), len(signature)) - t.Errorf("Different signatures are made for the same message with the same private key.") - } - }) -} diff --git a/crypto/ed25519/ed25519.go b/crypto/ed25519/ed25519.go index 4b8fe6803..2ad624b5d 100644 --- a/crypto/ed25519/ed25519.go +++ b/crypto/ed25519/ed25519.go @@ -26,7 +26,7 @@ const ( 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 + // SignatureSize 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 diff --git a/crypto/encoding/codec.go b/crypto/encoding/codec.go index 991cac0cb..333206eb0 100644 --- a/crypto/encoding/codec.go +++ b/crypto/encoding/codec.go @@ -4,8 +4,6 @@ import ( "fmt" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" "github.com/line/ostracon/crypto/ed25519" "github.com/line/ostracon/crypto/secp256k1" "github.com/line/ostracon/libs/json" @@ -16,37 +14,12 @@ func init() { json.RegisterType((*pc.PublicKey)(nil), "ostracon.crypto.PublicKey") json.RegisterType((*pc.PublicKey_Ed25519)(nil), "ostracon.crypto.PublicKey_Ed25519") json.RegisterType((*pc.PublicKey_Secp256K1)(nil), "ostracon.crypto.PublicKey_Secp256K1") - json.RegisterType((*pc.PublicKey_Composite)(nil), "ostracon.crypto.PublicKey_Composite") - json.RegisterType((*pc.PublicKey_Bls12)(nil), "ostracon.crypto.PublicKey_Bls12") } // PubKeyToProto takes crypto.PubKey and transforms it to a protobuf Pubkey func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) { var kp pc.PublicKey switch k := k.(type) { - case composite.PubKey: - sign, err := PubKeyToProto(k.SignKey) - if err != nil { - return kp, err - } - vrf, err := PubKeyToProto(k.VrfKey) - if err != nil { - return kp, err - } - kp = pc.PublicKey{ - Sum: &pc.PublicKey_Composite{ - Composite: &pc.CompositePublicKey{ - SignKey: &sign, - VrfKey: &vrf, - }, - }, - } - case bls.PubKey: - kp = pc.PublicKey{ - Sum: &pc.PublicKey_Bls12{ - Bls12: k[:], - }, - } case ed25519.PubKey: kp = pc.PublicKey{ Sum: &pc.PublicKey_Ed25519{ @@ -68,29 +41,6 @@ func PubKeyToProto(k crypto.PubKey) (pc.PublicKey, error) { // PubKeyFromProto takes a protobuf Pubkey and transforms it to a crypto.Pubkey func PubKeyFromProto(k *pc.PublicKey) (crypto.PubKey, error) { switch k := k.Sum.(type) { - case *pc.PublicKey_Composite: - var pk composite.PubKey - sign, err := PubKeyFromProto(k.Composite.SignKey) - if err != nil { - return pk, err - } - vrf, err := PubKeyFromProto(k.Composite.VrfKey) - if err != nil { - return pk, err - } - pk = composite.PubKey{ - SignKey: sign, - VrfKey: vrf, - } - return pk, nil - case *pc.PublicKey_Bls12: - if len(k.Bls12) != bls.PubKeySize { - return nil, fmt.Errorf("invalid size for PubKeyBls12. Got %d, expected %d", - len(k.Bls12), ed25519.PubKeySize) - } - pk := bls.PubKey{} - copy(pk[:], k.Bls12) - return pk, nil case *pc.PublicKey_Ed25519: if len(k.Ed25519) != ed25519.PubKeySize { return nil, fmt.Errorf("invalid size for PubKeyEd25519. Got %d, expected %d", diff --git a/crypto/encoding/codec_test.go b/crypto/encoding/codec_test.go index dd09e493f..3337e9bba 100644 --- a/crypto/encoding/codec_test.go +++ b/crypto/encoding/codec_test.go @@ -6,9 +6,6 @@ import ( "github.com/line/ostracon/crypto" "github.com/line/ostracon/crypto/ed25519" - - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" ) func testPubKeyFromToProto(t *testing.T, sk crypto.PrivKey) { @@ -31,6 +28,4 @@ func testPubKeyFromToProto(t *testing.T, sk crypto.PrivKey) { func TestPubKeyFromToProto(t *testing.T) { testPubKeyFromToProto(t, ed25519.GenPrivKey()) - testPubKeyFromToProto(t, bls.GenPrivKey()) - testPubKeyFromToProto(t, composite.NewPrivKeyComposite(bls.GenPrivKey(), ed25519.GenPrivKey())) } diff --git a/evidence/pool_test.go b/evidence/pool_test.go index 18cd4901d..c56b2a180 100644 --- a/evidence/pool_test.go +++ b/evidence/pool_test.go @@ -1,7 +1,6 @@ package evidence_test import ( - "fmt" "os" "testing" "time" @@ -13,9 +12,6 @@ import ( dbm "github.com/tendermint/tm-db" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" - "github.com/line/ostracon/crypto/ed25519" "github.com/line/ostracon/evidence" "github.com/line/ostracon/evidence/mocks" "github.com/line/ostracon/libs/log" @@ -90,17 +86,7 @@ func TestEvidencePoolBasic(t *testing.T) { next := pool.EvidenceFront() assert.Equal(t, ev, next.Value.(types.Evidence)) - var evidenceBytes int64 - switch keyType := voterSet.Voters[0].PubKey.(type) { - case ed25519.PubKey: - evidenceBytes = 375 - case bls.PubKey: - evidenceBytes = 439 - case composite.PubKey: - evidenceBytes = 439 - default: - assert.Fail(t, fmt.Sprintf("unknown public key: %s", keyType)) - } + var evidenceBytes int64 = 375 evs, size = pool.PendingEvidence(evidenceBytes) assert.Equal(t, 1, len(evs)) assert.Equal(t, evidenceBytes, size) // check that the size of the single evidence in bytes is correct @@ -115,7 +101,7 @@ func TestEvidencePoolBasic(t *testing.T) { // Tests inbound evidence for the right time and height func TestAddExpiredEvidence(t *testing.T) { var ( - val = types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val = types.NewMockPV() height = int64(30) stateStore = initializeValidatorState(val, height) evidenceDB = dbm.NewMemDB() @@ -272,10 +258,6 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { stateStore := &smmocks.Store{} stateStore.On("LoadValidators", height).Return(trusted.ValidatorSet, nil) stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature - stateStore.On("LoadVoters", height, state.VoterParams).Return( - trusted.ValidatorSet, ev.ConflictingBlock.VoterSet, state.VoterParams, mock.Anything, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", commonHeight, state.VoterParams).Return( trusted.ValidatorSet, ev.ConflictingBlock.VoterSet, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) @@ -324,7 +306,7 @@ func TestLightClientAttackEvidenceLifecycle(t *testing.T) { // pending evidence and continue to gossip it func TestRecoverPendingEvidence(t *testing.T) { height := int64(10) - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() evidenceDB := dbm.NewMemDB() stateStore := initializeValidatorState(val, height) state, err := stateStore.Load() @@ -457,7 +439,7 @@ func makeCommit(height int64, valAddr []byte) *types.Commit { } func defaultTestPool(height int64) (*evidence.Pool, types.MockPV) { - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() evidenceDB := dbm.NewMemDB() stateStore := initializeValidatorState(val, height) state, _ := stateStore.Load() diff --git a/evidence/reactor_test.go b/evidence/reactor_test.go index c67514c35..6e4f064e9 100644 --- a/evidence/reactor_test.go +++ b/evidence/reactor_test.go @@ -43,7 +43,7 @@ func TestReactorBroadcastEvidence(t *testing.T) { // create statedb for everyone stateDBs := make([]sm.Store, N) - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() // we need validators saved for heights at least as high as we have evidence for height := int64(numEvidence) + 10 for i := 0; i < N; i++ { @@ -73,7 +73,7 @@ func TestReactorBroadcastEvidence(t *testing.T) { func TestReactorSelectiveBroadcast(t *testing.T) { config := cfg.TestConfig() - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() height1 := int64(numEvidence) + 10 height2 := int64(numEvidence) / 2 @@ -116,7 +116,7 @@ func TestReactorSelectiveBroadcast(t *testing.T) { func TestReactorsGossipNoCommittedEvidence(t *testing.T) { config := cfg.TestConfig() - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() var height int64 = 10 // DB1 is ahead of DB2 @@ -195,7 +195,7 @@ func TestReactorBroadcastEvidenceMemoryLeak(t *testing.T) { blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return( &types.BlockMeta{Header: types.Header{Time: evidenceTime}}, ) - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types + val := types.NewMockPV() stateStore := initializeValidatorState(val, 1) pool, err := evidence.NewPool(evidenceDB, stateStore, blockStore) require.NoError(t, err) diff --git a/evidence/verify_test.go b/evidence/verify_test.go index be5e8b202..61496ae86 100644 --- a/evidence/verify_test.go +++ b/evidence/verify_test.go @@ -46,7 +46,7 @@ func TestVerifyLightClientAttack_Lunatic(t *testing.T) { // good pass -> no error err := evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) assert.NoError(t, err) @@ -89,7 +89,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { // good pass -> no error err := evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) assert.NoError(t, err) @@ -102,7 +102,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { amnesiaHeader.Commit.Round = 2 err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, amnesiaHeader, // illegal header common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) require.Error(t, err) require.Equal(t, "expected nil validators from an amnesia light client attack but got 1", err.Error()) @@ -113,7 +113,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { equivocationHeader.ProposerAddress = nil err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, equivocationHeader, // illegal header common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) require.Error(t, err) require.Equal(t, "expected 10 byzantine validators from evidence but got 1", err.Error()) @@ -123,7 +123,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { ev.ByzantineValidators = phantomVoterSet.Voters err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) require.Error(t, err) require.Contains(t, err.Error(), "evidence contained an unexpected byzantine validator address;") @@ -134,7 +134,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { ev.ByzantineValidators = phantomVoterSet.Voters err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) require.Error(t, err) require.Contains(t, err.Error(), "evidence contained unexpected byzantine validator voting power;") @@ -145,7 +145,7 @@ func TestVerifyLightClientAttack_validateABCIEvidence(t *testing.T) { ev.ByzantineValidators = phantomVoterSet.Voters err = evidence.VerifyLightClientAttack(ev, common.SignedHeader, trusted.SignedHeader, common.ValidatorSet, - ev.ConflictingBlock.VoterSet, // Should use correct VoterSet for bls.VerifyAggregatedSignature + ev.ConflictingBlock.VoterSet, defaultEvidenceTime.Add(2*time.Hour), 3*time.Hour, types.DefaultVoterParams()) require.Error(t, err) require.Contains(t, err.Error(), "evidence contained unexpected byzantine validator voting weight;") @@ -172,7 +172,6 @@ func TestVerify_LunaticAttackAgainstState(t *testing.T) { } stateStore := &smmocks.Store{} stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", commonHeight, state.VoterParams).Return( common.ValidatorSet, ev.ConflictingBlock.VoterSet, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) @@ -251,7 +250,6 @@ func TestVerify_ForwardLunaticAttack(t *testing.T) { stateStore := &smmocks.Store{} stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", commonHeight, state.VoterParams).Return( common.ValidatorSet, ev.ConflictingBlock.VoterSet, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) @@ -373,7 +371,6 @@ func TestVerifyLightClientAttack_Equivocation(t *testing.T) { } stateStore := &smmocks.Store{} stateStore.On("LoadValidators", int64(10)).Return(conflictingVals, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", int64(10), state.VoterParams).Return( conflictingVals, conflictingVoters, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) @@ -472,7 +469,6 @@ func TestVerifyLightClientAttack_Amnesia(t *testing.T) { } stateStore := &smmocks.Store{} stateStore.On("LoadValidators", int64(10)).Return(conflictingVals, nil) - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", int64(10), state.VoterParams).Return( conflictingVals, conflictingVoters, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) @@ -499,8 +495,8 @@ type voteData struct { } func TestVerifyDuplicateVoteEvidence(t *testing.T) { - val := types.NewMockPV(types.PrivKeyComposite) // TODO 🏺 need to test by all key types - val2 := types.NewMockPV(types.PrivKeyComposite) + val := types.NewMockPV() + val2 := types.NewMockPV() valSet := types.NewValidatorSet([]*types.Validator{val.ExtractIntoValidator(1)}) voterSet := types.ToVoterAll(valSet.Validators) @@ -570,7 +566,6 @@ func TestVerifyDuplicateVoteEvidence(t *testing.T) { VoterParams: types.DefaultVoterParams(), } stateStore := &smmocks.Store{} - // Should use correct VoterSet for bls.VerifyAggregatedSignature stateStore.On("LoadVoters", int64(10), state.VoterParams).Return( valSet, voterSet, state.VoterParams, state.LastProofHash, nil) stateStore.On("Load").Return(state, nil) diff --git a/node/node.go b/node/node.go index 5fa528c09..e47157de6 100644 --- a/node/node.go +++ b/node/node.go @@ -98,16 +98,9 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { return nil, fmt.Errorf("failed to load or gen node key %s: %w", config.NodeKeyFile(), err) } - privKey, err := privval.LoadOrGenFilePV( - config.PrivValidatorKeyFile(), - config.PrivValidatorStateFile(), - config.PrivValidatorKeyType()) - if err != nil { - return nil, fmt.Errorf("failed to create a private key: %s", err) - } - return NewNode( - config, - privKey, + pv := privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) + return NewNode(config, + pv, nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), diff --git a/node/node_test.go b/node/node_test.go index 41db99044..73111c68c 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -172,7 +172,7 @@ func TestNodeSetPrivValTCP(t *testing.T) { signerServer := privval.NewSignerServer( dialerEndpoint, config.ChainID(), - types.NewMockPV(types.PrivKeyEd25519), + types.NewMockPV(), ) go func() { @@ -218,7 +218,7 @@ func TestNodeSetPrivValIPC(t *testing.T) { pvsc := privval.NewSignerServer( dialerEndpoint, config.ChainID(), - types.NewMockPV(types.PrivKeyEd25519), + types.NewMockPV(), ) go func() { @@ -426,10 +426,8 @@ func TestNodeNewNodeCustomReactors(t *testing.T) { nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) require.NoError(t, err) - pvKey, _ := privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), - config.PrivValidatorKeyType()) n, err := NewNode(config, - pvKey, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), @@ -463,10 +461,8 @@ func TestNodeNewNodeTxIndexIndexer(t *testing.T) { nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) require.NoError(t, err) - pvKey, _ := privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), - config.PrivValidatorKeyType()) return NewNode(config, - pvKey, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), @@ -600,10 +596,8 @@ func TestNodeInvalidNodeInfoCustomReactors(t *testing.T) { nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) require.NoError(t, err) - pvKey, _ := privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile(), - config.PrivValidatorKeyType()) _, err = NewInvalidNode(config, - pvKey, + privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()), nodeKey, proxy.DefaultClientCreator(config.ProxyApp, config.ABCI, config.DBDir()), DefaultGenesisDocProviderFunc(config), diff --git a/privval/file.go b/privval/file.go index 87a51c5b1..b1a22e2aa 100644 --- a/privval/file.go +++ b/privval/file.go @@ -5,12 +5,8 @@ import ( "errors" "fmt" "os" - "strings" "time" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" - "github.com/gogo/protobuf/proto" "github.com/line/ostracon/crypto" @@ -33,11 +29,6 @@ const ( stepPrecommit int8 = 3 ) -const ( - PrivKeyTypeEd25519 string = "ed25519" - PrivKeyTypeComposite string = "composite" -) - // A vote is either stepPrevote or stepPrecommit. func voteToStep(vote *tmproto.Vote) int8 { switch vote.Type { @@ -178,17 +169,8 @@ func NewFilePV(privKey crypto.PrivKey, keyFilePath, stateFilePath string) *FileP // GenFilePV generates a new validator with randomly generated private key // and sets the filePaths, but does not call Save(). -func GenFilePV(keyFilePath, stateFilePath, privKeyType string) (filePV *FilePV, err error) { - var privKey crypto.PrivKey - switch strings.ToLower(privKeyType) { - case PrivKeyTypeEd25519: - privKey = ed25519.GenPrivKey() - case PrivKeyTypeComposite: - privKey = composite.NewPrivKeyComposite(bls.GenPrivKey(), ed25519.GenPrivKey()) - default: - return nil, fmt.Errorf("undefined private key type: %s", privKeyType) - } - return NewFilePV(privKey, keyFilePath, stateFilePath), nil +func GenFilePV(keyFilePath, stateFilePath string) *FilePV { + return NewFilePV(ed25519.GenPrivKey(), keyFilePath, stateFilePath) } // LoadFilePV loads a FilePV from the filePaths. The FilePV handles double @@ -244,17 +226,15 @@ func loadFilePV(keyFilePath, stateFilePath string, loadState bool) *FilePV { // LoadOrGenFilePV loads a FilePV from the given filePaths // or else generates a new one and saves it to the filePaths. -func LoadOrGenFilePV(keyFilePath, stateFilePath, privKeyType string) (pv *FilePV, err error) { +func LoadOrGenFilePV(keyFilePath, stateFilePath string) *FilePV { + var pv *FilePV if tmos.FileExists(keyFilePath) { pv = LoadFilePV(keyFilePath, stateFilePath) - err = nil } else { - pv, err = GenFilePV(keyFilePath, stateFilePath, privKeyType) - if pv != nil { - pv.Save() - } + pv = GenFilePV(keyFilePath, stateFilePath) + pv.Save() } - return pv, err + return pv } // GetAddress returns the address of the validator. diff --git a/privval/file_test.go b/privval/file_test.go index 95bf2082f..d3b31f8a6 100644 --- a/privval/file_test.go +++ b/privval/file_test.go @@ -5,43 +5,22 @@ import ( "fmt" "io/ioutil" "os" - "reflect" "testing" "time" - "github.com/line/ostracon/crypto" - tmjson "github.com/line/ostracon/libs/json" - - "github.com/line/ostracon/crypto/composite" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/line/ostracon/crypto" "github.com/line/ostracon/crypto/ed25519" "github.com/line/ostracon/crypto/tmhash" + tmjson "github.com/line/ostracon/libs/json" tmrand "github.com/line/ostracon/libs/rand" tmproto "github.com/line/ostracon/proto/ostracon/types" "github.com/line/ostracon/types" tmtime "github.com/line/ostracon/types/time" ) -var testingKeyTypes = []struct { - keyType string - privKey crypto.PrivKey - pubKey crypto.PubKey -}{ - { - keyType: PrivKeyTypeEd25519, - privKey: ed25519.GenPrivKey(), - pubKey: ed25519.PubKey{}, - }, - { - keyType: PrivKeyTypeComposite, - privKey: *composite.GenPrivKey(), - pubKey: composite.PubKey{}, - }, -} - var jsonKey = func(t *testing.T, addr crypto.Address, privKey crypto.PrivKey, pubKey crypto.PubKey) string { privKeyBytes, err := tmjson.MarshalIndent(privKey, " ", " ") assert.Nil(t, err) @@ -60,15 +39,9 @@ func TestGenFilePV(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) - require.EqualValues(t, reflect.TypeOf(testing.pubKey), reflect.TypeOf(privVal.Key.PubKey)) - } - - privValUndefinedPrivKeyType, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), "") - require.NotNil(t, err) - require.Nil(t, privValUndefinedPrivKeyType) + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + require.Nil(t, err) + require.Equal(t, ed25519.KeyType, privVal.Key.PubKey.Type()) } func TestGenLoadValidator(t *testing.T) { @@ -79,19 +52,15 @@ func TestGenLoadValidator(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) - - height := int64(100) - privVal.LastSignState.Height = height - privVal.Save() - addr := privVal.GetAddress() + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + height := int64(100) + privVal.LastSignState.Height = height + privVal.Save() + addr := privVal.GetAddress() - privVal = LoadFilePV(tempKeyFile.Name(), tempStateFile.Name()) - assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") - assert.Equal(height, privVal.LastSignState.Height, "expected privval.LastHeight to have been saved") - } + privVal = LoadFilePV(tempKeyFile.Name(), tempStateFile.Name()) + assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") + assert.Equal(height, privVal.LastSignState.Height, "expected privval.LastHeight to have been saved") } func TestResetValidator(t *testing.T) { @@ -100,31 +69,27 @@ func TestResetValidator(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + emptyState := FilePVLastSignState{filePath: tempStateFile.Name()} - emptyState := FilePVLastSignState{filePath: tempStateFile.Name()} + // new priv val has empty state + assert.Equal(t, privVal.LastSignState, emptyState) - // new priv val has empty state - assert.Equal(t, privVal.LastSignState, emptyState) + // test vote + height, round := int64(10), int32(1) + voteType := tmproto.PrevoteType + randBytes := tmrand.Bytes(tmhash.Size) + blockID := types.BlockID{Hash: randBytes, PartSetHeader: types.PartSetHeader{}} + vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) + err = privVal.SignVote("mychainid", vote.ToProto()) + assert.NoError(t, err, "expected no error signing vote") - // test vote - height, round := int64(10), int32(1) - voteType := tmproto.PrevoteType - randBytes := tmrand.Bytes(tmhash.Size) - blockID := types.BlockID{Hash: randBytes, PartSetHeader: types.PartSetHeader{}} - vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) - err = privVal.SignVote("mychainid", vote.ToProto()) - assert.NoError(t, err, "expected no error signing vote") - - // priv val after signing is not same as empty - assert.NotEqual(t, privVal.LastSignState, emptyState) + // priv val after signing is not same as empty + assert.NotEqual(t, privVal.LastSignState, emptyState) - // priv val after AcceptNewConnection is same as empty - privVal.Reset() - assert.Equal(t, privVal.LastSignState, emptyState) - } + // priv val after AcceptNewConnection is same as empty + privVal.Reset() + assert.Equal(t, privVal.LastSignState, emptyState) } func TestLoadOrGenValidator(t *testing.T) { @@ -135,25 +100,19 @@ func TestLoadOrGenValidator(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - tempKeyFilePath := tempKeyFile.Name() - if err := os.Remove(tempKeyFilePath); err != nil { - t.Error(err) - } - tempStateFilePath := tempStateFile.Name() - if err := os.Remove(tempStateFilePath); err != nil { - t.Error(err) - } - - privVal, err := LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath, testing.keyType) - require.Nil(t, err) - - addr := privVal.GetAddress() - privVal, err = LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath, testing.keyType) - require.Nil(t, err) - - assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same", "keyType", testing.keyType) + tempKeyFilePath := tempKeyFile.Name() + if err := os.Remove(tempKeyFilePath); err != nil { + t.Error(err) + } + tempStateFilePath := tempStateFile.Name() + if err := os.Remove(tempStateFilePath); err != nil { + t.Error(err) } + + privVal := LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath) + addr := privVal.GetAddress() + privVal = LoadOrGenFilePV(tempKeyFilePath, tempStateFilePath) + assert.Equal(addr, privVal.GetAddress(), "expected privval addr to be the same") } func TestUnmarshalValidatorState(t *testing.T) { @@ -184,28 +143,26 @@ func TestUnmarshalValidatorState(t *testing.T) { func TestUnmarshalValidatorKey(t *testing.T) { assert, require := assert.New(t), require.New(t) - for _, testing := range testingKeyTypes { - // create some fixed values - privKey := testing.privKey - pubKey := privKey.PubKey() - addr := pubKey.Address() + // create some fixed values + privKey := ed25519.GenPrivKey() + pubKey := privKey.PubKey() + addr := pubKey.Address() - serialized := jsonKey(t, addr, privKey, pubKey) + serialized := jsonKey(t, addr, privKey, pubKey) - val := FilePVKey{} - err := tmjson.Unmarshal([]byte(serialized), &val) - require.Nil(err, "%+v", err) + val := FilePVKey{} + err := tmjson.Unmarshal([]byte(serialized), &val) + require.Nil(err, "%+v", err) - // make sure the values match - assert.EqualValues(addr, val.Address) - assert.EqualValues(pubKey, val.PubKey) - assert.EqualValues(privKey, val.PrivKey) + // make sure the values match + assert.EqualValues(addr, val.Address) + assert.EqualValues(pubKey, val.PubKey) + assert.EqualValues(privKey, val.PrivKey) - // export it and make sure it is the same - out, err := tmjson.Marshal(val) - require.Nil(err, "%+v", err) - assert.JSONEq(serialized, string(out)) - } + // export it and make sure it is the same + out, err := tmjson.Marshal(val) + require.Nil(err, "%+v", err) + assert.JSONEq(serialized, string(out)) } func TestSignVote(t *testing.T) { @@ -216,52 +173,48 @@ func TestSignVote(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) - - randbytes := tmrand.Bytes(tmhash.Size) - randbytes2 := tmrand.Bytes(tmhash.Size) - - block1 := types.BlockID{Hash: randbytes, - PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} - block2 := types.BlockID{Hash: randbytes2, - PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} - - height, round := int64(10), int32(1) - voteType := tmproto.PrevoteType - - // sign a vote for first time - vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1) - v := vote.ToProto() - err = privVal.SignVote("mychainid", v) - assert.NoError(err, "expected no error signing vote") + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + randbytes := tmrand.Bytes(tmhash.Size) + randbytes2 := tmrand.Bytes(tmhash.Size) + + block1 := types.BlockID{Hash: randbytes, + PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} + block2 := types.BlockID{Hash: randbytes2, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} + + height, round := int64(10), int32(1) + voteType := tmproto.PrevoteType + + // sign a vote for first time + vote := newVote(privVal.Key.Address, 0, height, round, voteType, block1) + v := vote.ToProto() + err = privVal.SignVote("mychainid", v) + assert.NoError(err, "expected no error signing vote") + + // try to sign the same vote again; should be fine + err = privVal.SignVote("mychainid", v) + assert.NoError(err, "expected no error on signing same vote") + + // now try some bad votes + cases := []*types.Vote{ + newVote(privVal.Key.Address, 0, height, round-1, voteType, block1), // round regression + newVote(privVal.Key.Address, 0, height-1, round, voteType, block1), // height regression + newVote(privVal.Key.Address, 0, height-2, round+4, voteType, block1), // height regression and different round + newVote(privVal.Key.Address, 0, height, round, voteType, block2), // different block + } - // try to sign the same vote again; should be fine - err = privVal.SignVote("mychainid", v) - assert.NoError(err, "expected no error on signing same vote") - - // now try some bad votes - cases := []*types.Vote{ - newVote(privVal.Key.Address, 0, height, round-1, voteType, block1), // round regression - newVote(privVal.Key.Address, 0, height-1, round, voteType, block1), // height regression - newVote(privVal.Key.Address, 0, height-2, round+4, voteType, block1), // height regression and different round - newVote(privVal.Key.Address, 0, height, round, voteType, block2), // different block - } - - for _, c := range cases { - cpb := c.ToProto() - err = privVal.SignVote("mychainid", cpb) - assert.Error(err, "expected error on signing conflicting vote") - } - - // try signing a vote with a different time stamp - sig := vote.Signature - vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) - err = privVal.SignVote("mychainid", v) - assert.NoError(err) - assert.Equal(sig, vote.Signature) + for _, c := range cases { + cpb := c.ToProto() + err = privVal.SignVote("mychainid", cpb) + assert.Error(err, "expected error on signing conflicting vote") } + + // try signing a vote with a different time stamp + sig := vote.Signature + vote.Timestamp = vote.Timestamp.Add(time.Duration(1000)) + err = privVal.SignVote("mychainid", v) + assert.NoError(err) + assert.Equal(sig, vote.Signature) } func TestSignProposal(t *testing.T) { @@ -272,49 +225,45 @@ func TestSignProposal(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) - - randbytes := tmrand.Bytes(tmhash.Size) - randbytes2 := tmrand.Bytes(tmhash.Size) - - block1 := types.BlockID{Hash: randbytes, - PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} - block2 := types.BlockID{Hash: randbytes2, - PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} - height, round := int64(10), int32(1) + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + randbytes := tmrand.Bytes(tmhash.Size) + randbytes2 := tmrand.Bytes(tmhash.Size) + + block1 := types.BlockID{Hash: randbytes, + PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} + block2 := types.BlockID{Hash: randbytes2, + PartSetHeader: types.PartSetHeader{Total: 10, Hash: randbytes2}} + height, round := int64(10), int32(1) + + // sign a proposal for first time + proposal := newProposal(height, round, block1) + pbp := proposal.ToProto() + err = privVal.SignProposal("mychainid", pbp) + assert.NoError(err, "expected no error signing proposal") + + // try to sign the same proposal again; should be fine + err = privVal.SignProposal("mychainid", pbp) + assert.NoError(err, "expected no error on signing same proposal") + + // now try some bad Proposals + cases := []*types.Proposal{ + newProposal(height, round-1, block1), // round regression + newProposal(height-1, round, block1), // height regression + newProposal(height-2, round+4, block1), // height regression and different round + newProposal(height, round, block2), // different block + } - // sign a proposal for first time - proposal := newProposal(height, round, block1) - pbp := proposal.ToProto() - err = privVal.SignProposal("mychainid", pbp) - assert.NoError(err, "expected no error signing proposal") - - // try to sign the same proposal again; should be fine - err = privVal.SignProposal("mychainid", pbp) - assert.NoError(err, "expected no error on signing same proposal") - - // now try some bad Proposals - cases := []*types.Proposal{ - newProposal(height, round-1, block1), // round regression - newProposal(height-1, round, block1), // height regression - newProposal(height-2, round+4, block1), // height regression and different round - newProposal(height, round, block2), // different block - } - - for _, c := range cases { - err = privVal.SignProposal("mychainid", c.ToProto()) - assert.Error(err, "expected error on signing conflicting proposal") - } - - // try signing a proposal with a different time stamp - sig := proposal.Signature - proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) - err = privVal.SignProposal("mychainid", pbp) - assert.NoError(err) - assert.Equal(sig, proposal.Signature) + for _, c := range cases { + err = privVal.SignProposal("mychainid", c.ToProto()) + assert.Error(err, "expected error on signing conflicting proposal") } + + // try signing a proposal with a different time stamp + sig := proposal.Signature + proposal.Timestamp = proposal.Timestamp.Add(time.Duration(1000)) + err = privVal.SignProposal("mychainid", pbp) + assert.NoError(err) + assert.Equal(sig, proposal.Signature) } func TestGenerateVRFProof(t *testing.T) { @@ -323,21 +272,17 @@ func TestGenerateVRFProof(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + success := [][]byte{{}, {0x00}, make([]byte, 100)} + for _, msg := range success { + proof, err := privVal.GenerateVRFProof(msg) require.Nil(t, err) - - success := [][]byte{{}, {0x00}, make([]byte, 100)} - for _, msg := range success { - proof, err := privVal.GenerateVRFProof(msg) - require.Nil(t, err) - t.Log(" Message : ", hex.EncodeToString(msg), " -> ", hex.EncodeToString(proof[:])) - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - output, err := pubKey.VRFVerify(proof, msg) - require.Nil(t, err) - require.NotNil(t, output) - } + t.Log(" Message : ", hex.EncodeToString(msg), " -> ", hex.EncodeToString(proof[:])) + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + output, err := pubKey.VRFVerify(proof, msg) + require.Nil(t, err) + require.NotNil(t, output) } } @@ -347,61 +292,59 @@ func TestDifferByTimestamp(t *testing.T) { tempStateFile, err := ioutil.TempFile("", "priv_validator_state_") require.Nil(t, err) - for _, testing := range testingKeyTypes { - privVal, err := GenFilePV(tempKeyFile.Name(), tempStateFile.Name(), testing.keyType) - require.Nil(t, err) - randbytes := tmrand.Bytes(tmhash.Size) - block1 := types.BlockID{Hash: randbytes, PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} - height, round := int64(10), int32(1) - chainID := "mychainid" - - // test proposal - { - proposal := newProposal(height, round, block1) - pb := proposal.ToProto() - err := privVal.SignProposal(chainID, pb) - assert.NoError(t, err, "expected no error signing proposal") - signBytes := types.ProposalSignBytes(chainID, pb) - - sig := proposal.Signature - timeStamp := proposal.Timestamp - - // manipulate the timestamp. should get changed back - pb.Timestamp = pb.Timestamp.Add(time.Millisecond) - var emptySig []byte - proposal.Signature = emptySig - err = privVal.SignProposal("mychainid", pb) - assert.NoError(t, err, "expected no error on signing same proposal") - - assert.Equal(t, timeStamp, pb.Timestamp) - assert.Equal(t, signBytes, types.ProposalSignBytes(chainID, pb)) - assert.Equal(t, sig, proposal.Signature) - } - - // test vote - { - voteType := tmproto.PrevoteType - blockID := types.BlockID{Hash: randbytes, PartSetHeader: types.PartSetHeader{}} - vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) - v := vote.ToProto() - err := privVal.SignVote("mychainid", v) - assert.NoError(t, err, "expected no error signing vote") - - signBytes := types.VoteSignBytes(chainID, v) - sig := v.Signature - timeStamp := vote.Timestamp - - // manipulate the timestamp. should get changed back - v.Timestamp = v.Timestamp.Add(time.Millisecond) - var emptySig []byte - v.Signature = emptySig - err = privVal.SignVote("mychainid", v) - assert.NoError(t, err, "expected no error on signing same vote") - - assert.Equal(t, timeStamp, v.Timestamp) - assert.Equal(t, signBytes, types.VoteSignBytes(chainID, v)) - assert.Equal(t, sig, v.Signature) - } + privVal := GenFilePV(tempKeyFile.Name(), tempStateFile.Name()) + require.Nil(t, err) + randbytes := tmrand.Bytes(tmhash.Size) + block1 := types.BlockID{Hash: randbytes, PartSetHeader: types.PartSetHeader{Total: 5, Hash: randbytes}} + height, round := int64(10), int32(1) + chainID := "mychainid" + + // test proposal + { + proposal := newProposal(height, round, block1) + pb := proposal.ToProto() + err := privVal.SignProposal(chainID, pb) + assert.NoError(t, err, "expected no error signing proposal") + signBytes := types.ProposalSignBytes(chainID, pb) + + sig := proposal.Signature + timeStamp := proposal.Timestamp + + // manipulate the timestamp. should get changed back + pb.Timestamp = pb.Timestamp.Add(time.Millisecond) + var emptySig []byte + proposal.Signature = emptySig + err = privVal.SignProposal("mychainid", pb) + assert.NoError(t, err, "expected no error on signing same proposal") + + assert.Equal(t, timeStamp, pb.Timestamp) + assert.Equal(t, signBytes, types.ProposalSignBytes(chainID, pb)) + assert.Equal(t, sig, proposal.Signature) + } + + // test vote + { + voteType := tmproto.PrevoteType + blockID := types.BlockID{Hash: randbytes, PartSetHeader: types.PartSetHeader{}} + vote := newVote(privVal.Key.Address, 0, height, round, voteType, blockID) + v := vote.ToProto() + err := privVal.SignVote("mychainid", v) + assert.NoError(t, err, "expected no error signing vote") + + signBytes := types.VoteSignBytes(chainID, v) + sig := v.Signature + timeStamp := vote.Timestamp + + // manipulate the timestamp. should get changed back + v.Timestamp = v.Timestamp.Add(time.Millisecond) + var emptySig []byte + v.Signature = emptySig + err = privVal.SignVote("mychainid", v) + assert.NoError(t, err, "expected no error on signing same vote") + + assert.Equal(t, timeStamp, v.Timestamp) + assert.Equal(t, signBytes, types.VoteSignBytes(chainID, v)) + assert.Equal(t, sig, v.Signature) } } diff --git a/privval/signer_client_test.go b/privval/signer_client_test.go index 188a79e68..1aef3e020 100644 --- a/privval/signer_client_test.go +++ b/privval/signer_client_test.go @@ -430,7 +430,7 @@ func brokenHandler(privVal types.PrivValidator, request privvalproto.Message, } func TestSignerUnexpectedResponse(t *testing.T) { - for _, tc := range getSignerTestCases(t, types.NewMockPV(types.PrivKeyEd25519), false) { + for _, tc := range getSignerTestCases(t, types.NewMockPV(), false) { tc.signerServer.SetRequestHandler(brokenHandler) err := tc.signerServer.Start() if err != nil { diff --git a/privval/signer_listener_endpoint_test.go b/privval/signer_listener_endpoint_test.go index e72ffd5b9..9499d71ea 100644 --- a/privval/signer_listener_endpoint_test.go +++ b/privval/signer_listener_endpoint_test.go @@ -68,7 +68,7 @@ func TestSignerRemoteRetryTCPOnly(t *testing.T) { SignerDialerEndpointConnRetries(retries)(dialerEndpoint) chainID := tmrand.Str(12) - mockPV := types.NewMockPV(types.PrivKeyEd25519) + mockPV := types.NewMockPV() signerServer := NewSignerServer(dialerEndpoint, chainID, mockPV) err = signerServer.Start() @@ -92,7 +92,7 @@ func TestRetryConnToRemoteSigner(t *testing.T) { var ( logger = log.TestingLogger() chainID = tmrand.Str(12) - mockPV = types.NewMockPV(types.PrivKeyEd25519) + mockPV = types.NewMockPV() endpointIsOpenCh = make(chan struct{}) thisConnTimeout = testTimeoutReadWrite listenerEndpoint = newSignerListenerEndpoint(logger, tc.addr, thisConnTimeout) diff --git a/proto/ostracon/crypto/keys.pb.go b/proto/ostracon/crypto/keys.pb.go index 3d42cc643..7ecafbc7b 100644 --- a/proto/ostracon/crypto/keys.pb.go +++ b/proto/ostracon/crypto/keys.pb.go @@ -24,66 +24,11 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -// CompositePublicKey allows to use different public keys for different features -type CompositePublicKey struct { - SignKey *PublicKey `protobuf:"bytes,1,opt,name=sign_key,json=signKey,proto3" json:"sign_key,omitempty"` - VrfKey *PublicKey `protobuf:"bytes,2,opt,name=vrf_key,json=vrfKey,proto3" json:"vrf_key,omitempty"` -} - -func (m *CompositePublicKey) Reset() { *m = CompositePublicKey{} } -func (m *CompositePublicKey) String() string { return proto.CompactTextString(m) } -func (*CompositePublicKey) ProtoMessage() {} -func (*CompositePublicKey) Descriptor() ([]byte, []int) { - return fileDescriptor_fe45c29a2e63dfe7, []int{0} -} -func (m *CompositePublicKey) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *CompositePublicKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_CompositePublicKey.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *CompositePublicKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_CompositePublicKey.Merge(m, src) -} -func (m *CompositePublicKey) XXX_Size() int { - return m.Size() -} -func (m *CompositePublicKey) XXX_DiscardUnknown() { - xxx_messageInfo_CompositePublicKey.DiscardUnknown(m) -} - -var xxx_messageInfo_CompositePublicKey proto.InternalMessageInfo - -func (m *CompositePublicKey) GetSignKey() *PublicKey { - if m != nil { - return m.SignKey - } - return nil -} - -func (m *CompositePublicKey) GetVrfKey() *PublicKey { - if m != nil { - return m.VrfKey - } - return nil -} - // PublicKey defines the keys available for use with Ostracon Validators type PublicKey struct { // Types that are valid to be assigned to Sum: // *PublicKey_Ed25519 // *PublicKey_Secp256K1 - // *PublicKey_Composite - // *PublicKey_Bls12 Sum isPublicKey_Sum `protobuf_oneof:"sum"` } @@ -91,7 +36,7 @@ func (m *PublicKey) Reset() { *m = PublicKey{} } func (m *PublicKey) String() string { return proto.CompactTextString(m) } func (*PublicKey) ProtoMessage() {} func (*PublicKey) Descriptor() ([]byte, []int) { - return fileDescriptor_fe45c29a2e63dfe7, []int{1} + return fileDescriptor_fe45c29a2e63dfe7, []int{0} } func (m *PublicKey) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -134,17 +79,9 @@ type PublicKey_Ed25519 struct { type PublicKey_Secp256K1 struct { Secp256K1 []byte `protobuf:"bytes,2,opt,name=secp256k1,proto3,oneof" json:"secp256k1,omitempty"` } -type PublicKey_Composite struct { - Composite *CompositePublicKey `protobuf:"bytes,1000,opt,name=composite,proto3,oneof" json:"composite,omitempty"` -} -type PublicKey_Bls12 struct { - Bls12 []byte `protobuf:"bytes,1001,opt,name=bls12,proto3,oneof" json:"bls12,omitempty"` -} func (*PublicKey_Ed25519) isPublicKey_Sum() {} func (*PublicKey_Secp256K1) isPublicKey_Sum() {} -func (*PublicKey_Composite) isPublicKey_Sum() {} -func (*PublicKey_Bls12) isPublicKey_Sum() {} func (m *PublicKey) GetSum() isPublicKey_Sum { if m != nil { @@ -167,94 +104,37 @@ func (m *PublicKey) GetSecp256K1() []byte { return nil } -func (m *PublicKey) GetComposite() *CompositePublicKey { - if x, ok := m.GetSum().(*PublicKey_Composite); ok { - return x.Composite - } - return nil -} - -func (m *PublicKey) GetBls12() []byte { - if x, ok := m.GetSum().(*PublicKey_Bls12); ok { - return x.Bls12 - } - return nil -} - // XXX_OneofWrappers is for the internal use of the proto package. func (*PublicKey) XXX_OneofWrappers() []interface{} { return []interface{}{ (*PublicKey_Ed25519)(nil), (*PublicKey_Secp256K1)(nil), - (*PublicKey_Composite)(nil), - (*PublicKey_Bls12)(nil), } } func init() { - proto.RegisterType((*CompositePublicKey)(nil), "ostracon.crypto.CompositePublicKey") proto.RegisterType((*PublicKey)(nil), "ostracon.crypto.PublicKey") } func init() { proto.RegisterFile("ostracon/crypto/keys.proto", fileDescriptor_fe45c29a2e63dfe7) } var fileDescriptor_fe45c29a2e63dfe7 = []byte{ - // 305 bytes of a gzipped FileDescriptorProto + // 200 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x2f, 0x2e, 0x29, 0x4a, 0x4c, 0xce, 0xcf, 0xd3, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x87, 0xc9, 0xe9, 0x41, 0xe4, 0xa4, 0x44, 0xd2, - 0xf3, 0xd3, 0xf3, 0xc1, 0x72, 0xfa, 0x20, 0x16, 0x44, 0x99, 0x52, 0x17, 0x23, 0x97, 0x90, 0x73, - 0x7e, 0x6e, 0x41, 0x7e, 0x71, 0x66, 0x49, 0x6a, 0x40, 0x69, 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, - 0xa5, 0x90, 0x29, 0x17, 0x47, 0x71, 0x66, 0x7a, 0x5e, 0x7c, 0x76, 0x6a, 0xa5, 0x04, 0xa3, 0x02, - 0xa3, 0x06, 0xb7, 0x91, 0x94, 0x1e, 0x9a, 0x81, 0x7a, 0x70, 0xd5, 0x41, 0xec, 0x20, 0xb5, 0x20, - 0x6d, 0xc6, 0x5c, 0xec, 0x65, 0x45, 0x69, 0x60, 0x5d, 0x4c, 0x04, 0x75, 0xb1, 0x95, 0x15, 0xa5, - 0x79, 0xa7, 0x56, 0x5a, 0x71, 0xbc, 0x58, 0x20, 0xcf, 0xf8, 0x62, 0xa1, 0x3c, 0xa3, 0xd2, 0x76, - 0x46, 0x2e, 0x4e, 0x84, 0x1b, 0xa4, 0xb8, 0xd8, 0x53, 0x53, 0x8c, 0x4c, 0x4d, 0x0d, 0x2d, 0xc1, - 0x4e, 0xe0, 0xf1, 0x60, 0x08, 0x82, 0x09, 0x08, 0xc9, 0x71, 0x71, 0x16, 0xa7, 0x26, 0x17, 0x18, - 0x99, 0x9a, 0x65, 0x1b, 0x82, 0xad, 0x02, 0xc9, 0x22, 0x84, 0x84, 0x5c, 0xb8, 0x38, 0x93, 0x61, - 0xbe, 0x92, 0x78, 0xc1, 0x0e, 0x76, 0x8b, 0x32, 0x86, 0x5b, 0x30, 0x3d, 0x0e, 0x32, 0x05, 0xae, - 0x51, 0x48, 0x9c, 0x8b, 0x35, 0x29, 0xa7, 0xd8, 0xd0, 0x48, 0xe2, 0x25, 0x3b, 0xd4, 0x0a, 0x08, - 0x1f, 0xe1, 0x64, 0x27, 0x56, 0x2e, 0xe6, 0xe2, 0xd2, 0x5c, 0x27, 0x8f, 0x13, 0x8f, 0xe4, 0x18, - 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, - 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, - 0xcf, 0xd5, 0xcf, 0xc9, 0xcc, 0x4b, 0xd5, 0x87, 0xc7, 0x19, 0x24, 0x2e, 0xd0, 0xa2, 0x30, 0x89, - 0x0d, 0x2c, 0x6c, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xa8, 0x75, 0xf4, 0xa6, 0xdc, 0x01, 0x00, - 0x00, + 0xf3, 0xd3, 0xf3, 0xc1, 0x72, 0xfa, 0x20, 0x16, 0x44, 0x99, 0x52, 0x04, 0x17, 0x67, 0x40, 0x69, + 0x52, 0x4e, 0x66, 0xb2, 0x77, 0x6a, 0xa5, 0x90, 0x14, 0x17, 0x7b, 0x6a, 0x8a, 0x91, 0xa9, 0xa9, + 0xa1, 0xa5, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x8f, 0x07, 0x43, 0x10, 0x4c, 0x40, 0x48, 0x8e, 0x8b, + 0xb3, 0x38, 0x35, 0xb9, 0xc0, 0xc8, 0xd4, 0x2c, 0xdb, 0x50, 0x82, 0x09, 0x2a, 0x8b, 0x10, 0xb2, + 0xe2, 0x78, 0xb1, 0x40, 0x9e, 0xf1, 0xc5, 0x42, 0x79, 0x46, 0x27, 0x56, 0x2e, 0xe6, 0xe2, 0xd2, + 0x5c, 0x27, 0x8f, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, + 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0xd2, 0x4b, 0xcf, + 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xc9, 0xcc, 0x4b, 0xd5, 0x87, 0x7b, + 0x03, 0xe2, 0x3c, 0x34, 0x5f, 0x25, 0xb1, 0x81, 0x85, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, + 0x75, 0xfb, 0x97, 0xf1, 0xef, 0x00, 0x00, 0x00, } -func (this *CompositePublicKey) Compare(that interface{}) int { - if that == nil { - if this == nil { - return 0 - } - return 1 - } - - that1, ok := that.(*CompositePublicKey) - if !ok { - that2, ok := that.(CompositePublicKey) - if ok { - that1 = &that2 - } else { - return 1 - } - } - if that1 == nil { - if this == nil { - return 0 - } - return 1 - } else if this == nil { - return -1 - } - if c := this.SignKey.Compare(that1.SignKey); c != 0 { - return c - } - if c := this.VrfKey.Compare(that1.VrfKey); c != 0 { - return c - } - return 0 -} func (this *PublicKey) Compare(that interface{}) int { if that == nil { if this == nil { @@ -293,10 +173,6 @@ func (this *PublicKey) Compare(that interface{}) int { thisType = 0 case *PublicKey_Secp256K1: thisType = 1 - case *PublicKey_Composite: - thisType = 2 - case *PublicKey_Bls12: - thisType = 3 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.Sum)) } @@ -306,10 +182,6 @@ func (this *PublicKey) Compare(that interface{}) int { that1Type = 0 case *PublicKey_Secp256K1: that1Type = 1 - case *PublicKey_Composite: - that1Type = 2 - case *PublicKey_Bls12: - that1Type = 3 default: panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.Sum)) } @@ -385,93 +257,6 @@ func (this *PublicKey_Secp256K1) Compare(that interface{}) int { } return 0 } -func (this *PublicKey_Composite) Compare(that interface{}) int { - if that == nil { - if this == nil { - return 0 - } - return 1 - } - - that1, ok := that.(*PublicKey_Composite) - if !ok { - that2, ok := that.(PublicKey_Composite) - if ok { - that1 = &that2 - } else { - return 1 - } - } - if that1 == nil { - if this == nil { - return 0 - } - return 1 - } else if this == nil { - return -1 - } - if c := this.Composite.Compare(that1.Composite); c != 0 { - return c - } - return 0 -} -func (this *PublicKey_Bls12) Compare(that interface{}) int { - if that == nil { - if this == nil { - return 0 - } - return 1 - } - - that1, ok := that.(*PublicKey_Bls12) - if !ok { - that2, ok := that.(PublicKey_Bls12) - if ok { - that1 = &that2 - } else { - return 1 - } - } - if that1 == nil { - if this == nil { - return 0 - } - return 1 - } else if this == nil { - return -1 - } - if c := bytes.Compare(this.Bls12, that1.Bls12); c != 0 { - return c - } - return 0 -} -func (this *CompositePublicKey) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*CompositePublicKey) - if !ok { - that2, ok := that.(CompositePublicKey) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if !this.SignKey.Equal(that1.SignKey) { - return false - } - if !this.VrfKey.Equal(that1.VrfKey) { - return false - } - return true -} func (this *PublicKey) Equal(that interface{}) bool { if that == nil { return this == nil @@ -550,101 +335,6 @@ func (this *PublicKey_Secp256K1) Equal(that interface{}) bool { } return true } -func (this *PublicKey_Composite) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*PublicKey_Composite) - if !ok { - that2, ok := that.(PublicKey_Composite) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if !this.Composite.Equal(that1.Composite) { - return false - } - return true -} -func (this *PublicKey_Bls12) Equal(that interface{}) bool { - if that == nil { - return this == nil - } - - that1, ok := that.(*PublicKey_Bls12) - if !ok { - that2, ok := that.(PublicKey_Bls12) - if ok { - that1 = &that2 - } else { - return false - } - } - if that1 == nil { - return this == nil - } else if this == nil { - return false - } - if !bytes.Equal(this.Bls12, that1.Bls12) { - return false - } - return true -} -func (m *CompositePublicKey) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *CompositePublicKey) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *CompositePublicKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.VrfKey != nil { - { - size, err := m.VrfKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintKeys(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - if m.SignKey != nil { - { - size, err := m.SignKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintKeys(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - func (m *PublicKey) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -709,47 +399,6 @@ func (m *PublicKey_Secp256K1) MarshalToSizedBuffer(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } -func (m *PublicKey_Composite) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PublicKey_Composite) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - if m.Composite != nil { - { - size, err := m.Composite.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintKeys(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x3e - i-- - dAtA[i] = 0xc2 - } - return len(dAtA) - i, nil -} -func (m *PublicKey_Bls12) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *PublicKey_Bls12) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - if m.Bls12 != nil { - i -= len(m.Bls12) - copy(dAtA[i:], m.Bls12) - i = encodeVarintKeys(dAtA, i, uint64(len(m.Bls12))) - i-- - dAtA[i] = 0x3e - i-- - dAtA[i] = 0xca - } - return len(dAtA) - i, nil -} func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { offset -= sovKeys(v) base := offset @@ -761,23 +410,6 @@ func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *CompositePublicKey) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.SignKey != nil { - l = m.SignKey.Size() - n += 1 + l + sovKeys(uint64(l)) - } - if m.VrfKey != nil { - l = m.VrfKey.Size() - n += 1 + l + sovKeys(uint64(l)) - } - return n -} - func (m *PublicKey) Size() (n int) { if m == nil { return 0 @@ -814,30 +446,6 @@ func (m *PublicKey_Secp256K1) Size() (n int) { } return n } -func (m *PublicKey_Composite) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Composite != nil { - l = m.Composite.Size() - n += 2 + l + sovKeys(uint64(l)) - } - return n -} -func (m *PublicKey_Bls12) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Bls12 != nil { - l = len(m.Bls12) - n += 2 + l + sovKeys(uint64(l)) - } - return n -} func sovKeys(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 @@ -845,128 +453,6 @@ func sovKeys(x uint64) (n int) { func sozKeys(x uint64) (n int) { return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *CompositePublicKey) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowKeys - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: CompositePublicKey: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: CompositePublicKey: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field SignKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowKeys - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthKeys - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthKeys - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.SignKey == nil { - m.SignKey = &PublicKey{} - } - if err := m.SignKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field VrfKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowKeys - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthKeys - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthKeys - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.VrfKey == nil { - m.VrfKey = &PublicKey{} - } - if err := m.VrfKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipKeys(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthKeys - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *PublicKey) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -1062,74 +548,6 @@ func (m *PublicKey) Unmarshal(dAtA []byte) error { copy(v, dAtA[iNdEx:postIndex]) m.Sum = &PublicKey_Secp256K1{v} iNdEx = postIndex - case 1000: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Composite", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowKeys - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthKeys - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthKeys - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - v := &CompositePublicKey{} - if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - m.Sum = &PublicKey_Composite{v} - iNdEx = postIndex - case 1001: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Bls12", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowKeys - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthKeys - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthKeys - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - v := make([]byte, postIndex-iNdEx) - copy(v, dAtA[iNdEx:postIndex]) - m.Sum = &PublicKey_Bls12{v} - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipKeys(dAtA[iNdEx:]) diff --git a/proto/ostracon/crypto/keys.proto b/proto/ostracon/crypto/keys.proto index c32cfcbec..c375549cb 100644 --- a/proto/ostracon/crypto/keys.proto +++ b/proto/ostracon/crypto/keys.proto @@ -5,15 +5,6 @@ option go_package = "github.com/line/ostracon/proto/ostracon/crypto"; import "gogoproto/gogo.proto"; -// CompositePublicKey allows to use different public keys for different features -message CompositePublicKey { - option (gogoproto.compare) = true; - option (gogoproto.equal) = true; - - PublicKey sign_key = 1; - PublicKey vrf_key = 2; -} - // PublicKey defines the keys available for use with Ostracon Validators message PublicKey { option (gogoproto.compare) = true; @@ -22,9 +13,5 @@ message PublicKey { oneof sum { bytes ed25519 = 1; bytes secp256k1 = 2; - - // *** Ostracon Extended Fields *** - CompositePublicKey composite = 1000; - bytes bls12 = 1001; } } diff --git a/rpc/client/evidence_test.go b/rpc/client/evidence_test.go index b980f8e32..e0a8c204f 100644 --- a/rpc/client/evidence_test.go +++ b/rpc/client/evidence_test.go @@ -6,13 +6,12 @@ import ( "testing" "time" - "github.com/line/ostracon/abci/example/kvstore" - "github.com/line/ostracon/crypto/ed25519" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/line/ostracon/abci/example/kvstore" abci "github.com/line/ostracon/abci/types" + "github.com/line/ostracon/crypto/ed25519" cryptoenc "github.com/line/ostracon/crypto/encoding" "github.com/line/ostracon/crypto/tmhash" tmrand "github.com/line/ostracon/libs/rand" @@ -123,14 +122,9 @@ func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { var ( config = rpctest.GetConfig() chainID = config.ChainID() - pv, err = privval.LoadOrGenFilePV( - config.PrivValidatorKeyFile(), - config.PrivValidatorStateFile(), - privval.PrivKeyTypeEd25519, - ) + pv = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) ) - require.NoError(t, err) for i, c := range GetClients() { correct, fakes := makeEvidences(t, pv, chainID) t.Logf("client %d", i) diff --git a/rpc/test/helpers.go b/rpc/test/helpers.go index 9037ac64b..88391dea8 100644 --- a/rpc/test/helpers.go +++ b/rpc/test/helpers.go @@ -9,9 +9,8 @@ import ( "time" abci "github.com/line/ostracon/abci/types" - "github.com/line/ostracon/libs/log" - cfg "github.com/line/ostracon/config" + "github.com/line/ostracon/libs/log" tmnet "github.com/line/ostracon/libs/net" nm "github.com/line/ostracon/node" "github.com/line/ostracon/p2p" @@ -161,8 +160,7 @@ func NewOstracon(app abci.Application, opts *Options) *nm.Node { } pvKeyFile := config.PrivValidatorKeyFile() pvKeyStateFile := config.PrivValidatorStateFile() - pvKeyType := config.PrivValidatorKeyType() - pv, _ := privval.LoadOrGenFilePV(pvKeyFile, pvKeyStateFile, pvKeyType) + pv := privval.LoadOrGenFilePV(pvKeyFile, pvKeyStateFile) papp := proxy.NewLocalClientCreator(app) nodeKey, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()) if err != nil { diff --git a/state/execution.go b/state/execution.go index e7ab02e38..2839801a6 100644 --- a/state/execution.go +++ b/state/execution.go @@ -5,10 +5,8 @@ import ( "fmt" "time" - "github.com/line/ostracon/crypto" - canonictime "github.com/line/ostracon/types/time" - abci "github.com/line/ostracon/abci/types" + "github.com/line/ostracon/crypto" cryptoenc "github.com/line/ostracon/crypto/encoding" "github.com/line/ostracon/crypto/vrf" "github.com/line/ostracon/libs/fail" @@ -18,6 +16,7 @@ import ( tmproto "github.com/line/ostracon/proto/ostracon/types" "github.com/line/ostracon/proxy" "github.com/line/ostracon/types" + canonictime "github.com/line/ostracon/types/time" ) //----------------------------------------------------------------------------- @@ -131,10 +130,10 @@ func (blockExec *BlockExecutor) CreateProposalBlock( maxBytes := state.ConsensusParams.Block.MaxBytes maxGas := state.ConsensusParams.Block.MaxGas - evidence, _ := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) + evidence, evSize := blockExec.evpool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes) // Fetch a limited amount of valid txs - maxDataBytes := types.MaxDataBytes(maxBytes, commit, evidence) + maxDataBytes := types.MaxDataBytes(maxBytes, evSize, state.Voters.Size()) txs := blockExec.mempool.ReapMaxBytesMaxGasMaxTxs(maxDataBytes, maxGas, maxTxs) diff --git a/state/state_test.go b/state/state_test.go index 532eab7f9..74e444c85 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -446,7 +446,7 @@ func TestProposerFrequency(t *testing.T) { // make sure votePower > 0 votePower := int64(tmrand.Int()%maxPower) + 1 totalVotePower += votePower - privVal := types.NewMockPV(types.PrivKeyEd25519) + privVal := types.NewMockPV() pubKey, err := privVal.GetPubKey() require.NoError(t, err) val := types.NewValidator(pubKey, votePower) diff --git a/state/tx_filter_test.go b/state/tx_filter_test.go index b4b79bfc7..4f10b7379 100644 --- a/state/tx_filter_test.go +++ b/state/tx_filter_test.go @@ -26,8 +26,8 @@ func TestTxFilter(t *testing.T) { tx types.Tx isErr bool }{ - {types.Tx(tmrand.Bytes(2112 - vrf.ProofSize)), false}, - {types.Tx(tmrand.Bytes(2113 - vrf.ProofSize)), true}, + {types.Tx(tmrand.Bytes(2145 - vrf.ProofSize)), false}, + {types.Tx(tmrand.Bytes(2146 - vrf.ProofSize)), true}, {types.Tx(tmrand.Bytes(3000)), true}, } diff --git a/state/validation_test.go b/state/validation_test.go index cde483c3d..fd3ff3c3e 100644 --- a/state/validation_test.go +++ b/state/validation_test.go @@ -112,7 +112,7 @@ func TestValidateBlockCommit(t *testing.T) { ) lastCommit := types.NewCommit(0, 0, types.BlockID{}, nil) wrongSigsCommit := types.NewCommit(1, 0, types.BlockID{}, nil) - badPrivVal := types.NewMockPV(types.PrivKeyEd25519) + badPrivVal := types.NewMockPV() for height := int64(1); height < validationTestsStopHeight; height++ { proposerAddr := state.Validators.SelectProposer([]byte{}, height, 0).Address diff --git a/test/e2e/node/main.go b/test/e2e/node/main.go index 98abd0bd2..c5dcf9a95 100644 --- a/test/e2e/node/main.go +++ b/test/e2e/node/main.go @@ -122,11 +122,7 @@ func startNode(cfg *Config) error { return fmt.Errorf("failed to setup config: %w", err) } - privVal, err := privval.LoadOrGenFilePV( - tmcfg.PrivValidatorKeyFile(), - tmcfg.PrivValidatorStateFile(), - privval.PrivKeyTypeEd25519, - ) + privVal := privval.LoadOrGenFilePV(tmcfg.PrivValidatorKeyFile(), tmcfg.PrivValidatorStateFile()) if err != nil { return fmt.Errorf("failed to load/generate FilePV%w", err) } diff --git a/tools/tm-signer-harness/internal/test_harness_test.go b/tools/tm-signer-harness/internal/test_harness_test.go index 61ad16567..05537e299 100644 --- a/tools/tm-signer-harness/internal/test_harness_test.go +++ b/tools/tm-signer-harness/internal/test_harness_test.go @@ -52,8 +52,7 @@ const ( }, "validator": { "pub_key_types": [ - "ed25519", - "composite(bls12-381,ed25519)" + "ed25519" ] } }, diff --git a/types/block.go b/types/block.go index fdaedaa52..3e65c205d 100644 --- a/types/block.go +++ b/types/block.go @@ -4,17 +4,14 @@ import ( "bytes" "errors" "fmt" + "github.com/line/ostracon/crypto/ed25519" "strings" "time" - "golang.org/x/crypto/ed25519" - "github.com/gogo/protobuf/proto" gogotypes "github.com/gogo/protobuf/types" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" "github.com/line/ostracon/crypto/merkle" "github.com/line/ostracon/crypto/tmhash" "github.com/line/ostracon/crypto/vrf" @@ -304,15 +301,11 @@ func BlockFromProto(bp *tmproto.Block) (*Block, error) { // MaxDataBytes returns the maximum size of block's data. // // XXX: Panics on negative result. -func MaxDataBytes(maxBytes int64, commit *Commit, evidences []Evidence) int64 { - evidenceBytes := int64(0) - for _, ev := range evidences { - evidenceBytes += MaxEvidenceBytes(ev) - } +func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 { maxDataBytes := maxBytes - MaxOverheadForBlock - MaxHeaderBytes - - commit.MaxCommitBytes() - + MaxCommitBytes(valsCount) - evidenceBytes if maxDataBytes < 0 { @@ -332,14 +325,10 @@ func MaxDataBytes(maxBytes int64, commit *Commit, evidences []Evidence) int64 { // // XXX: Panics on negative result. func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 { - signsBytes := make([]int, valsCount) - for i := range signsBytes { - signsBytes[i] = composite.MaxSignatureSize - } maxDataBytes := maxBytes - MaxOverheadForBlock - MaxHeaderBytes - - MaxCommitBytes(signsBytes, 0) + MaxCommitBytes(valsCount) if maxDataBytes < 0 { panic(fmt.Sprintf( @@ -662,24 +651,19 @@ const ( // MaxCommitOverheadBytes is max size of commit without any commitSigs -> 82 for BlockID, 8 for Height, 4 for Round. // NOTE: 🏺This size is for the ProtocolBuffers representation of Commit without CommitSig. Therefore, it includes // the overhead of ProtocolBuffers in addition to the above number. -const MaxCommitOverheadBytes int64 = (1 + 9) + // Height - (1 + 5) + // Round - (1 + 76 + 1) // BlockID - -// MaxCommitSigBytes is made up of 64 or 96 bytes for the signature, 20 bytes for the address, -// 1 byte for the flag and 17 bytes for the timestamp. -// NOTE: 🏺This size is for the ProtocolBuffers representation of CommitSig. Therefore, it includes the overhead of -// ProtocolBuffers in addition to the above number. -// var MaxCommitSigBytes = (int64(composite.MaxSignatureSize) + 2) + (20 + 2) + (1 + 1) + (17 + 2) -func MaxCommitSigBytes(signBytes int) int64 { - var size int64 = (1 + 1) + // BlockIDFlag +const ( + MaxCommitOverheadBytes int64 = (1 + 9) + // Height + (1 + 5) + // Round + (1 + 76 + 1) // BlockID + // MaxCommitSigBytes sig size is made up of 64 bytes for the signature, 20 bytes for the address, + // 1 byte for the flag and 14 bytes for the timestamp + // NOTE: 🏺This size is for the ProtocolBuffers representation of CommitSig. Therefore, it includes the overhead of + // ProtocolBuffers in addition to the above number. + MaxCommitSigBytes int64 = (1 + 1) + // BlockIDFlag (1 + 20 + 1) + // ValidatorAddress - (1 + 17 + 1) // Timestamp - if signBytes > 0 { - size += 1 + int64(signBytes) + 1 // Signature - } - return size -} + (1 + 17 + 1) + // Timestamp + (1 + ed25519.SignatureSize + 1) // Signature +) // CommitSig is a part of the Vote included in a Commit. type CommitSig struct { @@ -709,31 +693,10 @@ func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) Commi } } -func MaxCommitBytes(sigSizes []int, aggrSigSize int) int64 { +func MaxCommitBytes(valCount int) int64 { // From the repeated commit sig field - var size = MaxCommitOverheadBytes // Height + Round + BlockID - for _, sigSize := range sigSizes { - var protoEncodingOverhead int64 = 1 - switch sigSize { - case 0: - protoEncodingOverhead++ - case ed25519.SignatureSize: - protoEncodingOverhead++ - case bls.SignatureSize: - protoEncodingOverhead += 2 - default: - panic(fmt.Sprintf("unexpected signature size: %d bytes", sigSize)) - } - size += MaxCommitSigBytes(sigSize) + protoEncodingOverhead - } - if aggrSigSize > 0 { - size += 2 + int64(aggrSigSize) + 1 - } - return size -} - -func (cs CommitSig) MaxCommitSigBytes() int64 { - return MaxCommitSigBytes(len(cs.Signature)) + var protoEncodingOverhead int64 = 2 + return MaxCommitOverheadBytes + ((MaxCommitSigBytes + protoEncodingOverhead) * int64(valCount)) } // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other @@ -814,9 +777,11 @@ func (cs CommitSig) ValidateBasic() error { ) } // NOTE: Timestamp validation is subtle and handled elsewhere. - // NOTE: Signature may be nil if it is aggregated and is handled elsewhere. - if cs.Signature != nil && len(cs.Signature) > MaxSignatureSize { - return fmt.Errorf("signature is too big %d (max: %d)", len(cs.Signature), MaxSignatureSize) + if len(cs.Signature) == 0 { + return errors.New("signature is missing") + } + if len(cs.Signature) > MaxSignatureSize { + return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize) } } @@ -863,8 +828,6 @@ type Commit struct { BlockID BlockID `json:"block_id"` Signatures []CommitSig `json:"signatures"` - AggregatedSignature []byte `json:"aggregated_signature"` - // Memoized in first call to corresponding method. // NOTE: can't memoize in constructor because constructor isn't used for // unmarshaling. @@ -890,80 +853,23 @@ const ( CommitAggrSigOverhead = 2 ) -func (commit *Commit) MaxCommitBytes() int64 { - sigSizes := make([]int, len(commit.Signatures)) - for i := range sigSizes { - sigSizes[i] = len(commit.Signatures[i].Signature) - } - return MaxCommitBytes(sigSizes, len(commit.AggregatedSignature)) -} - // CommitToVoteSet constructs a VoteSet from the Commit and validator set. // Panics if signatures from the commit can't be added to the voteset. // Inverse of VoteSet.MakeCommit(). func CommitToVoteSet(chainID string, commit *Commit, voters *VoterSet) *VoteSet { voteSet := NewVoteSet(chainID, commit.Height, commit.Round, tmproto.PrecommitType, voters) - blsPubKeys := make([]bls.PubKey, 0, len(commit.Signatures)) - msgs := make([][]byte, 0, len(commit.Signatures)) for idx, commitSig := range commit.Signatures { if commitSig.Absent() { continue // OK, some precommits can be missing. } - vote := commit.GetVote(int32(idx)) - if vote.Signature != nil { - added, err := voteSet.AddVote(vote) - if !added || err != nil { - panic(fmt.Sprintf("Failed to reconstruct LastCommit from Votes: %v", err)) - } - } else { - added, err := voteSet.AddAggregatedVote(vote) - if !added || err != nil { - panic(fmt.Sprintf("Failed to reconstruct LastCommit from AggregatedVotes : %v", err)) - } - // Ensure that signer is a validator. - addr, voter := voters.GetByIndex(vote.ValidatorIndex) - if voter == nil || addr == nil { - panic(fmt.Sprintf("Cannot find voter %d in voterSet of size %d", vote.ValidatorIndex, voters.Size())) - } - msg := VoteSignBytes(chainID, vote.ToProto()) - blsPubKey := GetSignatureKey(voter.PubKey) - if blsPubKey == nil { - panic(fmt.Errorf("signature %d has been omitted, even though it is not a BLS key", idx)) - } - blsPubKeys = append(blsPubKeys, *blsPubKey) - msgs = append(msgs, msg) - } - } - if commit.AggregatedSignature != nil { - err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, msgs) - if err != nil { - panic(fmt.Sprintf("Failed to VerifyAggregatedSignature : %v", err)) + added, err := voteSet.AddVote(commit.GetVote(int32(idx))) + if !added || err != nil { + panic(fmt.Sprintf("Failedd to reconstruct LastCommit: %v", err)) } } return voteSet } -func (commit *Commit) AggregateSignatures() { - if commit.AggregatedSignature != nil { - panic("The commit is already aggregated") - } - var err error - for i := 0; i < len(commit.Signatures); i++ { - if !commit.Signatures[i].Absent() && len(commit.Signatures[i].Signature) == bls.SignatureSize { - if commit.AggregatedSignature == nil { - commit.AggregatedSignature = commit.Signatures[i].Signature - } else { - commit.AggregatedSignature, err = bls.AddSignature(commit.AggregatedSignature, - commit.Signatures[i].Signature) - if err != nil { - panic(fmt.Sprintf("fail to aggregate signature: %s\n", err)) - } - } - commit.Signatures[i].Signature = nil - } - } -} - // GetVote converts the CommitSig for the given valIdx to a Vote. // Returns nil if the precommit at valIdx is nil. // Panics if valIdx >= commit.Size(). @@ -1067,27 +973,10 @@ func (commit *Commit) ValidateBasic() error { if len(commit.Signatures) == 0 { return errors.New("no signatures in commit") } - omittedSignatures := 0 for i, commitSig := range commit.Signatures { if err := commitSig.ValidateBasic(); err != nil { return fmt.Errorf("wrong CommitSig #%d: %v", i, err) } - if !commitSig.Absent() && commitSig.Signature == nil { - omittedSignatures++ - } - } - switch { - case commit.AggregatedSignature == nil: - if omittedSignatures > 0 { - return fmt.Errorf("%d erased signatures are present, but no aggregate signature exist in commit", - omittedSignatures) - } - case omittedSignatures == 0: - return fmt.Errorf("erased signatures are not present, but aggregated signature exist in commit: %x", - commit.AggregatedSignature) - case len(commit.AggregatedSignature) > MaxSignatureSize: - return fmt.Errorf("signature is too big %d (max: %d)", - len(commit.AggregatedSignature), MaxSignatureSize) } } return nil @@ -1099,7 +988,7 @@ func (commit *Commit) Hash() tmbytes.HexBytes { return nil } if commit.hash == nil { - bs := make([][]byte, len(commit.Signatures)+1) + bs := make([][]byte, len(commit.Signatures)) for i, commitSig := range commit.Signatures { pbcs := commitSig.ToProto() bz, err := pbcs.Marshal() @@ -1109,7 +998,6 @@ func (commit *Commit) Hash() tmbytes.HexBytes { bs[i] = bz } - bs[len(bs)-1] = commit.AggregatedSignature commit.hash = merkle.HashFromByteSlices(bs) } return commit.hash @@ -1128,14 +1016,12 @@ func (commit *Commit) StringIndented(indent string) string { %s Height: %d %s Round: %d %s BlockID: %v -%s AggregatedSignature: %X %s Signatures: %s %v %s}#%v`, indent, commit.Height, indent, commit.Round, indent, commit.BlockID, - indent, tmbytes.Fingerprint(commit.AggregatedSignature), indent, indent, strings.Join(commitSigStrings, "\n"+indent+" "), indent, commit.hash) @@ -1158,48 +1044,9 @@ func (commit *Commit) ToProto() *tmproto.Commit { c.Round = commit.Round c.BlockID = commit.BlockID.ToProto() - c.AggregatedSignature = commit.AggregatedSignature return c } -// VerifySignatures validates the signatures in this commit. -func (commit *Commit) VerifySignatures(chainID string, vals []*Validator) error { - blsPubKeys := make([]bls.PubKey, 0, len(commit.Signatures)) - messages := make([][]byte, 0, len(commit.Signatures)) - for idx, commitSig := range commit.Signatures { - if commitSig.Absent() { - continue // OK, some signatures can be absent. - } - - // Validate signature. - if val := vals[idx]; val != nil { - voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) - if commitSig.Signature != nil { - if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { - return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) - } - } else { - blsPubKey := GetSignatureKey(val.PubKey) - if blsPubKey == nil { - return fmt.Errorf("signature %d has been omitted, even though it is not a BLS key", idx) - } - blsPubKeys = append(blsPubKeys, *blsPubKey) - messages = append(messages, voteSignBytes) - } - } else if commitSig.Signature == nil { - // 🏺 In the case of using signature aggregation, if one or more public keys are missing, signature - // verifications of other valid public keys will also fail. - return fmt.Errorf("the public key to verify the signature of commit was missing: %X", - commitSig.ValidatorAddress) - } - } - - if err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, messages); err != nil { - return fmt.Errorf("wrong aggregated signature: %X; %s", commit.AggregatedSignature, err) - } - return nil -} - // FromProto sets a protobuf Commit to the given pointer. // It returns an error if the commit is invalid. func CommitFromProto(cp *tmproto.Commit) (*Commit, error) { @@ -1227,7 +1074,6 @@ func CommitFromProto(cp *tmproto.Commit) (*Commit, error) { commit.Height = cp.Height commit.Round = cp.Round commit.BlockID = *bi - commit.AggregatedSignature = cp.AggregatedSignature return commit, commit.ValidateBasic() } @@ -1494,19 +1340,3 @@ func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) { return blockID, blockID.ValidateBasic() } - -// GetSignatureKey is a utility function for referencing a specified public key as a BLS key for signature. -// If the key is not BLS, return nil -func GetSignatureKey(pubKey crypto.PubKey) *bls.PubKey { - for { - if compPubKey, ok := pubKey.(composite.PubKey); ok { - pubKey = compPubKey.SignKey - } else { - break - } - } - if blsPubKey, ok := pubKey.(bls.PubKey); ok { - return &blsPubKey - } - return nil -} diff --git a/types/block_test.go b/types/block_test.go index 7caba5826..7daedc454 100644 --- a/types/block_test.go +++ b/types/block_test.go @@ -5,7 +5,6 @@ import ( // number generator here and we can run the tests a bit faster "crypto/rand" "encoding/hex" - "fmt" "math" "os" "reflect" @@ -19,9 +18,6 @@ import ( gogotypes "github.com/gogo/protobuf/types" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" - "github.com/line/ostracon/crypto/ed25519" "github.com/line/ostracon/crypto/merkle" "github.com/line/ostracon/crypto/tmhash" "github.com/line/ostracon/crypto/vrf" @@ -264,63 +260,6 @@ func TestNilDataHashDoesntCrash(t *testing.T) { assert.Equal(t, emptyBytes, []byte(new(Data).Hash())) } -func TestNewCommit(t *testing.T) { - blockID := BlockID{ - Hash: []byte{}, - PartSetHeader: PartSetHeader{ - Total: 0, - Hash: []byte{}, - }, - } - privKeys := [...]crypto.PrivKey{ - bls.GenPrivKey(), - composite.GenPrivKey(), - ed25519.GenPrivKey(), - bls.GenPrivKey(), - } - msgs := make([][]byte, len(privKeys)) - signs := make([][]byte, len(privKeys)) - pubKeys := make([]crypto.PubKey, len(privKeys)) - commitSigs := make([]CommitSig, len(privKeys)) - for i := 0; i < len(privKeys); i++ { - msgs[i] = []byte(fmt.Sprintf("hello, world %d", i)) - signs[i], _ = privKeys[i].Sign(msgs[i]) - pubKeys[i] = privKeys[i].PubKey() - commitSigs[i] = NewCommitSigForBlock(signs[i], pubKeys[i].Address(), time.Now()) - assert.Equal(t, signs[i], commitSigs[i].Signature) - } - commit := NewCommit(0, 1, blockID, commitSigs) - - assert.Equal(t, int64(0), commit.Height) - assert.Equal(t, int32(1), commit.Round) - assert.Equal(t, blockID, commit.BlockID) - assert.Equal(t, len(commitSigs), len(commit.Signatures)) - assert.Nil(t, commit.AggregatedSignature) - assert.NotNil(t, commit.Signatures[0].Signature) - assert.NotNil(t, commit.Signatures[1].Signature) - assert.NotNil(t, commit.Signatures[2].Signature) - assert.NotNil(t, commit.Signatures[3].Signature) - assert.True(t, pubKeys[2].VerifySignature(msgs[2], commit.Signatures[2].Signature)) - - blsPubKeys := []bls.PubKey{ - *GetSignatureKey(pubKeys[0]), - *GetSignatureKey(pubKeys[1]), - *GetSignatureKey(pubKeys[3]), - } - blsSigMsgs := [][]byte{msgs[0], msgs[1], msgs[3]} - func() { - aggrSig, err := bls.AddSignature(nil, signs[0]) - assert.Nil(t, err) - aggrSig, err = bls.AddSignature(aggrSig, signs[1]) - assert.Nil(t, err) - aggrSig, err = bls.AddSignature(aggrSig, signs[3]) - assert.Nil(t, err) - err = bls.VerifyAggregatedSignature(aggrSig, blsPubKeys, blsSigMsgs) - assert.Nil(t, err) - assert.Nil(t, commit.AggregatedSignature) - }() -} - func TestCommit(t *testing.T) { lastID := makeBlockIDRandom() h := int64(3) @@ -338,12 +277,8 @@ func TestCommit(t *testing.T) { require.NotNil(t, commit.BitArray()) assert.Equal(t, bits.NewBitArray(10).Size(), commit.BitArray().Size()) - if len(voteSet.GetByIndex(0).Signature) != bls.SignatureSize { - assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) - } else { - assert.NotNil(t, commit.AggregatedSignature) - isEqualVoteWithoutSignature(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) - } + assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) + assert.True(t, commit.IsCommit()) } func TestCommitValidateBasic(t *testing.T) { @@ -381,7 +316,7 @@ func TestMaxCommitBytes(t *testing.T) { pbSig := cs.ToProto() // test that a single commit sig doesn't exceed max commit sig bytes - assert.EqualValues(t, MaxCommitSigBytes(len(cs.Signature)), int64(pbSig.Size())) + assert.EqualValues(t, MaxCommitSigBytes, int64(pbSig.Size())) // check size with a single commit commit := &Commit{ @@ -399,91 +334,16 @@ func TestMaxCommitBytes(t *testing.T) { pb := commit.ToProto() - assert.EqualValues(t, MaxCommitBytes([]int{len(commit.Signatures[0].Signature)}, 0), int64(pb.Size())) - assert.EqualValues(t, commit.MaxCommitBytes(), int64(pb.Size())) + assert.EqualValues(t, MaxCommitBytes(1), int64(pb.Size())) // check the upper bound of the commit size - sigsBytes := make([]int, MaxVotesCount) - sigsBytes[0] = len(commit.Signatures[0].Signature) for i := 1; i < MaxVotesCount; i++ { commit.Signatures = append(commit.Signatures, cs) - sigsBytes[i] = len(commit.Signatures[i].Signature) } pb = commit.ToProto() - assert.EqualValues(t, MaxCommitBytes(sigsBytes, 0), int64(pb.Size())) - assert.EqualValues(t, commit.MaxCommitBytes(), int64(pb.Size())) - - pv1 := NewMockPV(PrivKeyEd25519) - pv2 := NewMockPV(PrivKeyComposite) - pv3 := NewMockPV(PrivKeyComposite) - - pub1, _ := pv1.GetPubKey() - pub2, _ := pv2.GetPubKey() - pub3, _ := pv3.GetPubKey() - - blockID := BlockID{tmrand.Bytes(tmhash.Size), - PartSetHeader{math.MaxUint32, tmrand.Bytes(tmhash.Size)}} - - chainID := "mychain2" - - vote1 := &Vote{ - ValidatorAddress: pub1.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - Signature: tmrand.Bytes(MaxSignatureSize), - } - pbVote1 := vote1.ToProto() - assert.NoError(t, pv1.SignVote(chainID, pbVote1)) - - vote2 := &Vote{ - ValidatorAddress: pub2.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - Signature: tmrand.Bytes(MaxSignatureSize), - } - pbVote2 := vote2.ToProto() - assert.NoError(t, pv2.SignVote(chainID, pbVote2)) - - vote3 := &Vote{ - ValidatorAddress: pub2.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - Signature: tmrand.Bytes(MaxSignatureSize), - } - pbVote3 := vote3.ToProto() - // does not sign vote3 - - commitSig := make([]CommitSig, 3) - commitSig[0] = NewCommitSigForBlock(pbVote1.Signature, pub1.Address(), timestamp) - commitSig[1] = NewCommitSigForBlock(pbVote2.Signature, pub2.Address(), timestamp) - commitSig[2] = NewCommitSigForBlock(pbVote3.Signature, pub3.Address(), timestamp) - - commit = NewCommit(math.MaxInt64, math.MaxInt32, blockID, commitSig) - commit.AggregatedSignature = tmrand.Bytes(bls.SignatureSize) - - protoBlockID := blockID.ToProto() - bz1, err1 := protoBlockID.Marshal() - assert.NoError(t, err1) - bz2, err2 := commit.ToProto().Marshal() - assert.NoError(t, err2) - assert.Equal(t, len(bz1), protoBlockID.Size()) - assert.Equal(t, len(bz2), commit.ToProto().Size()) - assert.Equal(t, CommitBlockIDMaxLen, protoBlockID.Size()) - assert.Equal(t, commit.MaxCommitBytes(), int64(commit.ToProto().Size())) + assert.EqualValues(t, MaxCommitBytes(MaxVotesCount), int64(pb.Size())) } func TestCommitHash(t *testing.T) { @@ -494,11 +354,11 @@ func TestCommitHash(t *testing.T) { t.Run("without any signatures", func(t *testing.T) { commit := &Commit{ - hash: nil, - Signatures: nil, - AggregatedSignature: nil, + hash: nil, + Signatures: nil, } - expected, _ := hex.DecodeString("6E340B9CFFB37A989CA544E6BB780A2C78901D3FB33738768511A30617AFA01D") + expected := []byte{0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, + 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55} assert.Equal(t, expected, commit.Hash().Bytes()) }) @@ -512,19 +372,14 @@ func TestCommitHash(t *testing.T) { NewCommitSigAbsent(), NewCommitSigForBlock(signature, address, tm), }, - AggregatedSignature: nil, } - expected, _ := hex.DecodeString("5EF6A2B65D0585177BD139364D23D9680A7387C2BFEE845F3F4AAF043FEBC555") - assert.Equal(t, expected, commit.Hash().Bytes()) - - commit.hash = nil - commit.AggregatedSignature = []byte{0, 0, 0, 0} - expected, _ = hex.DecodeString("3D9CD0C08000318B48DB77B1E2F974AD8F6AF32B922F571BB5BAB922D4443B65") + expected := []byte{0xf9, 0x3c, 0x17, 0x4b, 0x5c, 0x27, 0x56, 0xef, 0x81, 0x7a, 0x43, 0x83, 0x63, 0x15, 0x60, + 0x84, 0xc1, 0x3d, 0x6, 0x10, 0xfd, 0x94, 0xb9, 0x5d, 0xb0, 0x46, 0xbb, 0x11, 0x1d, 0x6c, 0x65, 0x2a} assert.Equal(t, expected, commit.Hash().Bytes()) commit.hash = nil - commit.AggregatedSignature = []byte{0, 1, 2, 3} - expected, _ = hex.DecodeString("F8960CFC0FFE82E323FD0484BA715589618AFCCF852731BDE6C9964F95DFC800") + expected = []byte{0xf9, 0x3c, 0x17, 0x4b, 0x5c, 0x27, 0x56, 0xef, 0x81, 0x7a, 0x43, 0x83, 0x63, 0x15, 0x60, + 0x84, 0xc1, 0x3d, 0x6, 0x10, 0xfd, 0x94, 0xb9, 0x5d, 0xb0, 0x46, 0xbb, 0x11, 0x1d, 0x6c, 0x65, 0x2a} assert.Equal(t, expected, commit.Hash().Bytes()) }) } @@ -800,231 +655,37 @@ func hexBytesFromString(s string) bytes.HexBytes { return bytes.HexBytes(b) } -func TestCommitSigNumOfBytes(t *testing.T) { - pv1 := NewMockPV(PrivKeyEd25519) - pv2 := NewMockPV(PrivKeyComposite) - pv3 := NewMockPV(PrivKeyBLS) - - pub1, _ := pv1.GetPubKey() - pub2, _ := pv2.GetPubKey() - pub3, _ := pv3.GetPubKey() - - blockID := BlockID{tmrand.Bytes(tmhash.Size), - PartSetHeader{math.MaxInt32, tmrand.Bytes(tmhash.Size)}} - chainID := "mychain1" - timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) - - vote1 := &Vote{ - ValidatorAddress: pub1.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - pbVote1 := vote1.ToProto() - assert.NoError(t, pv1.SignVote(chainID, pbVote1)) - - vote2 := &Vote{ - ValidatorAddress: pub2.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - pbVote2 := vote2.ToProto() - assert.NoError(t, pv2.SignVote(chainID, pbVote2)) - - vote3 := &Vote{ - ValidatorAddress: pub3.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - pbVote3 := vote3.ToProto() - assert.NoError(t, pv3.SignVote(chainID, pbVote3)) - - commitSig1 := NewCommitSigForBlock(pbVote1.Signature, pub1.Address(), timestamp) - commitSig2 := NewCommitSigForBlock(pbVote2.Signature, pub2.Address(), timestamp) - commitSig3 := NewCommitSigForBlock(pbVote3.Signature, pub3.Address(), timestamp) - aggregatedCommitSig := NewCommitSigForBlock(nil, pub2.Address(), timestamp) - - b1, err1 := commitSig1.ToProto().Marshal() - assert.NoError(t, err1) - assert.Equal(t, int64(len(b1)), commitSig1.MaxCommitSigBytes()) - - b2, err2 := commitSig2.ToProto().Marshal() - assert.NoError(t, err2) - assert.Equal(t, int64(len(b2)), commitSig2.MaxCommitSigBytes()) - - b3, err3 := commitSig3.ToProto().Marshal() - assert.NoError(t, err3) - assert.Equal(t, int64(len(b3)), commitSig3.MaxCommitSigBytes()) - - b4, err4 := aggregatedCommitSig.ToProto().Marshal() - assert.NoError(t, err4) - assert.Equal(t, int64(len(b4)), aggregatedCommitSig.MaxCommitSigBytes()) -} - -func TestMaxCommitBytesMany(t *testing.T) { - commitCount := 100 - commitSig := make([]CommitSig, commitCount) - blockID := BlockID{tmrand.Bytes(tmhash.Size), - PartSetHeader{math.MaxInt32, tmrand.Bytes(tmhash.Size)}} - - chainID := "mychain3" - timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) - - for i := 0; i < commitCount; i++ { - pv := NewMockPV(PrivKeyEd25519) - pub, _ := pv.GetPubKey() - vote := &Vote{ - ValidatorAddress: pub.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - assert.NoError(t, pv.SignVote(chainID, vote.ToProto())) - commitSig[i] = NewCommitSigForBlock(vote.Signature, pub.Address(), timestamp) - } - commit := NewCommit(math.MaxInt64, math.MaxInt32, blockID, commitSig) - bz, err := commit.ToProto().Marshal() - assert.NoError(t, err) - assert.Equal(t, commit.MaxCommitBytes(), int64(len(bz))) -} - -func TestMaxCommitBytesAggregated(t *testing.T) { - commitCount := 100 - commitSig := make([]CommitSig, commitCount) - blockID := BlockID{tmrand.Bytes(tmhash.Size), - PartSetHeader{math.MaxInt32, tmrand.Bytes(tmhash.Size)}} - - timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) - - for i := 0; i < commitCount; i++ { - pv := NewMockPV(PrivKeyComposite) - pub, _ := pv.GetPubKey() - vote := &Vote{ - ValidatorAddress: pub.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - // do not sign - commitSig[i] = NewCommitSigForBlock(vote.Signature, pub.Address(), timestamp) - } - commit := NewCommit(math.MaxInt64, math.MaxInt32, blockID, commitSig) - commit.AggregatedSignature = tmrand.Bytes(bls.SignatureSize) - - bz, err := commit.ToProto().Marshal() - assert.NoError(t, err) - assert.Equal(t, commit.MaxCommitBytes(), int64(len(bz))) -} - -func TestMaxCommitBytesMixed(t *testing.T) { - commitCount := 100 - commitSig := make([]CommitSig, commitCount) - blockID := BlockID{tmrand.Bytes(tmhash.Size), - PartSetHeader{math.MaxInt32, tmrand.Bytes(tmhash.Size)}} - - chainID := "mychain4" - timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) - - for i := 0; i < commitCount; i++ { - keyType := RandomKeyType() - pv := NewMockPV(keyType) - pub, _ := pv.GetPubKey() - vote := &Vote{ - ValidatorAddress: pub.Address(), - ValidatorIndex: math.MaxInt32, - Height: math.MaxInt64, - Round: math.MaxInt32, - Timestamp: timestamp, - Type: tmproto.PrecommitType, - BlockID: blockID, - } - // sign only if key type is ed25519 - if keyType == PrivKeyEd25519 { - assert.NoError(t, pv.SignVote(chainID, vote.ToProto())) - } - commitSig[i] = NewCommitSigForBlock(vote.Signature, pub.Address(), timestamp) - } - commit := NewCommit(math.MaxInt64, math.MaxInt32, blockID, commitSig) - commit.AggregatedSignature = tmrand.Bytes(bls.SignatureSize) - - bz, err := commit.ToProto().Marshal() - assert.NoError(t, err) - assert.Equal(t, commit.MaxCommitBytes(), int64(len(bz))) -} - func TestBlockMaxDataBytes(t *testing.T) { - pv1 := NewMockPV(PrivKeyEd25519) - pv2 := NewMockPV(PrivKeyComposite) - pv3 := NewMockPV(PrivKeyBLS) - - pub1, _ := pv1.GetPubKey() - pub2, _ := pv2.GetPubKey() - pub3, _ := pv3.GetPubKey() - - val := make([]*Validator, 3) - val[0] = newValidator(pub1.Address(), 100) - val[1] = newValidator(pub2.Address(), 200) - val[2] = newValidator(pub3.Address(), 300) - valSet := NewValidatorSet(val) - blockID := makeBlockIDRandom() - chainID := "mychain5" - vote1, _ := MakeVote(1, blockID, valSet, pv1, chainID, tmtime.Now()) - vote2, _ := MakeVote(1, blockID, valSet, pv2, chainID, tmtime.Now()) - vote3, _ := MakeVote(1, blockID, valSet, pv3, chainID, tmtime.Now()) - vote4, _ := MakeVote(1, makeBlockIDRandom(), valSet, pv3, chainID, tmtime.Now()) - - commitSig := make([]CommitSig, 3) - commitSig[0] = NewCommitSigForBlock(vote1.Signature, pub1.Address(), tmtime.Now()) - commitSig[1] = NewCommitSigForBlock(vote2.Signature, pub2.Address(), tmtime.Now()) - commitSig[2] = NewCommitSigForBlock(vote3.Signature, pub3.Address(), tmtime.Now()) - - commit := NewCommit(1, 0, blockID, commitSig) - dupEv := NewDuplicateVoteEvidence(vote3, vote4, defaultVoteTime, ToVoterAll(val)) - testCases := []struct { - maxBytes int64 - commit *Commit - evidence []Evidence - panics bool - result int64 + maxBytes int64 + valsCount int + evidenceBytes int64 + panics bool + result int64 }{ - 0: {-10, commit, []Evidence{dupEv}, true, 0}, - 1: {10, commit, []Evidence{dupEv}, true, 0}, - 2: {1701 + int64(vrf.ProofSize), commit, []Evidence{dupEv}, true, 0}, - 3: {1702 + int64(vrf.ProofSize), commit, []Evidence{dupEv}, false, 0}, - 4: {1703 + int64(vrf.ProofSize), commit, []Evidence{dupEv}, false, 1}, + 0: {-10, 1, 0, true, 0}, + 1: {10, 1, 0, true, 0}, + 2: {886 + int64(vrf.ProofSize), 1, 0, true, 0}, + 3: {887 + int64(vrf.ProofSize), 1, 0, false, 0}, + 4: {888 + int64(vrf.ProofSize), 1, 0, false, 1}, + 5: {997 + int64(vrf.ProofSize), 2, 0, true, 0}, + 6: {998 + int64(vrf.ProofSize), 2, 0, false, 0}, + 7: {999 + int64(vrf.ProofSize), 2, 0, false, 1}, + 8: {1097 + int64(vrf.ProofSize), 2, 100, true, 0}, + 9: {1098 + int64(vrf.ProofSize), 2, 100, false, 0}, + 10: {1099 + int64(vrf.ProofSize), 2, 100, false, 1}, } for i, tc := range testCases { tc := tc if tc.panics { assert.Panics(t, func() { - MaxDataBytes(tc.maxBytes, tc.commit, tc.evidence) + MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount) }, "#%v", i) } else { - assert.NotPanics(t, func() { - MaxDataBytes(tc.maxBytes, tc.commit, tc.evidence) - }, "#%v", i) assert.Equal(t, tc.result, - MaxDataBytes(tc.maxBytes, tc.commit, tc.evidence), + MaxDataBytes(tc.maxBytes, tc.evidenceBytes, tc.valsCount), "#%v", i) } } @@ -1039,9 +700,12 @@ func TestBlockMaxDataBytesNoEvidence(t *testing.T) { }{ 0: {-10, 1, true, 0}, 1: {10, 1, true, 0}, - 2: {919 + int64(vrf.ProofSize), 1, true, 0}, - 3: {920 + int64(vrf.ProofSize), 1, false, 0}, - 4: {921 + int64(vrf.ProofSize), 1, false, 1}, + 2: {886 + int64(vrf.ProofSize), 1, true, 0}, + 3: {887 + int64(vrf.ProofSize), 1, false, 0}, + 4: {888 + int64(vrf.ProofSize), 1, false, 1}, + 5: {997 + int64(vrf.ProofSize), 2, true, 0}, + 6: {998 + int64(vrf.ProofSize), 2, false, 0}, + 7: {999 + int64(vrf.ProofSize), 2, false, 1}, } for i, tc := range testCases { @@ -1081,56 +745,14 @@ func TestCommitToVoteSet(t *testing.T) { // This is the vote created from `MakeCommit` vote3 := commit.GetVote(i) - if len(vote1.Signature) != bls.SignatureSize { - vote1bz, err := vote1.ToProto().Marshal() - require.NoError(t, err) - vote2bz, err := vote2.ToProto().Marshal() - require.NoError(t, err) - vote3bz, err := vote3.ToProto().Marshal() - require.NoError(t, err) - assert.Equal(t, vote1bz, vote2bz) - assert.Equal(t, vote1bz, vote3bz) - } else { - vote2bz, err := vote2.ToProto().Marshal() - require.NoError(t, err) - vote3bz, err := vote3.ToProto().Marshal() - require.NoError(t, err) - assert.Equal(t, vote2bz, vote3bz) - assert.NotNil(t, commit.AggregatedSignature) - assert.Nil(t, vote2.Signature) - assert.Nil(t, vote3.Signature) - isEqualVoteWithoutSignature(t, vote1, vote2) - isEqualVoteWithoutSignature(t, vote1, vote3) - } - } -} - -func TestMakeCommitPanicByAggregatedCommitAndVoteSet(t *testing.T) { - lastID := makeBlockIDRandom() - h := int64(3) - - voteSet, _, voterSet, vals := randVoteSet(h-1, 1, tmproto.PrecommitType, 10, 1) - commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) - assert.NoError(t, err) - - chainID := voteSet.ChainID() - voteSet2 := CommitToVoteSet(chainID, commit, voterSet) - - // panic test - defer func() { - err := recover() - if err != nil { - wantStr := "This signature of commitSig is already aggregated: commitSig: <" - gotStr := fmt.Sprintf("%v", err) - isPanic := strings.Contains(gotStr, wantStr) - assert.True(t, isPanic) - } else { - t.Log("Not aggregated") - } - }() - if commit.AggregatedSignature != nil { - voteSet2.MakeCommit() - assert.Fail(t, "Don't reach here") + vote1bz, err := vote1.ToProto().Marshal() + require.NoError(t, err) + vote2bz, err := vote2.ToProto().Marshal() + require.NoError(t, err) + vote3bz, err := vote3.ToProto().Marshal() + require.NoError(t, err) + assert.Equal(t, vote1bz, vote2bz) + assert.Equal(t, vote1bz, vote3bz) } } diff --git a/types/evidence.go b/types/evidence.go index 3239d6cf6..84bbe9f18 100644 --- a/types/evidence.go +++ b/types/evidence.go @@ -20,12 +20,12 @@ import ( func MaxEvidenceBytes(ev Evidence) int64 { switch ev := ev.(type) { case *DuplicateVoteEvidence: - return (1 + MaxVoteBytes(len(ev.VoteA.Signature)) + 2) + // VoteA - (1 + MaxVoteBytes(len(ev.VoteB.Signature)) + 2) + // VoteB + return (1 + MaxVoteBytes + 2) + // VoteA + (1 + MaxVoteBytes + 2) + // VoteB (1 + 9) + // TotalVotingPower (1 + 9) + // ValidatorPower - //(1 + 9) + // VotingWeight is not include - (1 + 17 + 1) // Timestamp + (1 + 17 + 1) + // Timestamp + (2 + 9) // VotingWeight is not include case *LightClientAttackEvidence: // FIXME 🏺 need this? return 0 @@ -576,7 +576,7 @@ func (err *ErrEvidenceOverflow) Error() string { // assumes the round to be 0 and the validator index to be 0 func NewMockDuplicateVoteEvidence(height int64, time time.Time, chainID string) *DuplicateVoteEvidence { - val := NewMockPV(PrivKeyEd25519) + val := NewMockPV() return NewMockDuplicateVoteEvidenceWithValidator(height, time, val, chainID) } diff --git a/types/evidence_test.go b/types/evidence_test.go index 7ae396bde..aa241b432 100644 --- a/types/evidence_test.go +++ b/types/evidence_test.go @@ -19,14 +19,12 @@ import ( var defaultVoteTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC) func TestEvidenceList(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - ev := randomDuplicatedVoteEvidence(kt, t) - evl := EvidenceList([]Evidence{ev}) + ev := randomDuplicatedVoteEvidence(t) + evl := EvidenceList([]Evidence{ev}) - assert.NotNil(t, evl.Hash()) - assert.True(t, evl.Has(ev)) - assert.False(t, evl.Has(&DuplicateVoteEvidence{})) - }) + assert.NotNil(t, evl.Hash()) + assert.True(t, evl.Has(ev)) + assert.False(t, evl.Has(&DuplicateVoteEvidence{})) } func TestMaxEvidenceBytes(t *testing.T) { @@ -34,30 +32,29 @@ func TestMaxEvidenceBytes(t *testing.T) { // year int, month Month, day, hour, min, sec, nsec int, loc *Location timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - val := NewMockPV(kt) - randomPartHash := tmrand.Bytes(int(tmrand.Uint32() % 1000)) - randomHash1 := tmrand.Bytes(int(tmrand.Uint32() % 1000)) - randomHash2 := tmrand.Bytes(int(tmrand.Uint32() % 1000)) - blockID := makeBlockID(tmhash.Sum(randomHash1), math.MaxUint32, tmhash.Sum(randomPartHash)) - blockID2 := makeBlockID(tmhash.Sum(randomHash2), math.MaxUint32, tmhash.Sum(randomPartHash)) - const chainID = "mychain" - ev := &DuplicateVoteEvidence{ - TotalVotingPower: math.MaxInt64, - ValidatorPower: math.MaxInt64, - Timestamp: timestamp, - VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 32, blockID, timestamp), - VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 32, blockID2, timestamp), - } + val := NewMockPV() + randomPartHash := tmrand.Bytes(int(tmrand.Uint32() % 1000)) + randomHash1 := tmrand.Bytes(int(tmrand.Uint32() % 1000)) + randomHash2 := tmrand.Bytes(int(tmrand.Uint32() % 1000)) + blockID := makeBlockID(tmhash.Sum(randomHash1), math.MaxUint32, tmhash.Sum(randomPartHash)) + blockID2 := makeBlockID(tmhash.Sum(randomHash2), math.MaxUint32, tmhash.Sum(randomPartHash)) + const chainID = "mychain" + ev := &DuplicateVoteEvidence{ + VoteA: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 32, blockID, timestamp), + VoteB: makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 32, blockID2, timestamp), + TotalVotingPower: math.MaxInt64, + ValidatorPower: math.MaxInt64, + VotingWeight: math.MaxInt64, + Timestamp: timestamp, + } - bz, err := ev.ToProto().Marshal() - require.NoError(t, err) - assert.EqualValues(t, MaxEvidenceBytes(ev), len(bz)) - }) + bz, err := ev.ToProto().Marshal() + require.NoError(t, err) + assert.EqualValues(t, MaxEvidenceBytes(ev), len(bz)) } -func randomDuplicatedVoteEvidence(keyType PrivKeyType, t *testing.T) *DuplicateVoteEvidence { - val := NewMockPV(keyType) +func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence { + val := NewMockPV() blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) const chainID = "mychain" @@ -77,53 +74,49 @@ func TestDuplicateVoteEvidence(t *testing.T) { assert.NotNil(t, ev.String()) assert.Equal(t, ev.Height(), height) - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - ev := randomDuplicatedVoteEvidence(kt, t) - assert.Equal(t, ev.Hash(), tmhash.Sum(ev.Bytes())) - assert.NotNil(t, ev.String()) - }) + ev = randomDuplicatedVoteEvidence(t) + assert.Equal(t, ev.Hash(), tmhash.Sum(ev.Bytes())) + assert.NotNil(t, ev.String()) } func TestDuplicateVoteEvidenceValidation(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - val := NewMockPV(kt) - blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - const chainID = "mychain" + val := NewMockPV() + blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + const chainID = "mychain" - testCases := []struct { - testName string - malleateEvidence func(*DuplicateVoteEvidence) - expectErr bool - }{ - {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false}, - {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true}, - {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true}, - {"Nil votes", func(ev *DuplicateVoteEvidence) { - ev.VoteA = nil - ev.VoteB = nil - }, true}, - {"Invalid vote type", func(ev *DuplicateVoteEvidence) { - ev.VoteA = makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0, blockID2, defaultVoteTime) - }, true}, - {"Invalid vote order", func(ev *DuplicateVoteEvidence) { - swap := ev.VoteA.Copy() - ev.VoteA = ev.VoteB.Copy() - ev.VoteB = swap - }, true}, - } - for _, tc := range testCases { - tc := tc - t.Run(tc.testName, func(t *testing.T) { - vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime) - vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime) - voterSet := WrapValidatorsToVoterSet([]*Validator{val.ExtractIntoValidator(10)}) - ev := NewDuplicateVoteEvidence(vote1, vote2, defaultVoteTime, voterSet) - tc.malleateEvidence(ev) - assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result") - }) - } - }) + testCases := []struct { + testName string + malleateEvidence func(*DuplicateVoteEvidence) + expectErr bool + }{ + {"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false}, + {"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true}, + {"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true}, + {"Nil votes", func(ev *DuplicateVoteEvidence) { + ev.VoteA = nil + ev.VoteB = nil + }, true}, + {"Invalid vote type", func(ev *DuplicateVoteEvidence) { + ev.VoteA = makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0, blockID2, defaultVoteTime) + }, true}, + {"Invalid vote order", func(ev *DuplicateVoteEvidence) { + swap := ev.VoteA.Copy() + ev.VoteA = ev.VoteB.Copy() + ev.VoteB = swap + }, true}, + } + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + vote1 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID, defaultVoteTime) + vote2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, math.MaxInt32, 0x02, blockID2, defaultVoteTime) + voterSet := WrapValidatorsToVoterSet([]*Validator{val.ExtractIntoValidator(10)}) + ev := NewDuplicateVoteEvidence(vote1, vote2, defaultVoteTime, voterSet) + tc.malleateEvidence(ev) + assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result") + }) + } } func TestLightClientAttackEvidenceBasic(t *testing.T) { @@ -318,60 +311,58 @@ func makeHeaderRandom() *Header { } func TestEvidenceProto(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - // -------- Votes -------- - val := NewMockPV(kt) - blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - const chainID = "mychain" - v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime) - v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, defaultVoteTime) + // -------- Votes -------- + val := NewMockPV() + blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + const chainID = "mychain" + v := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 1, 0x01, blockID, defaultVoteTime) + v2 := makeVote(t, val, chainID, math.MaxInt32, math.MaxInt64, 2, 0x01, blockID2, defaultVoteTime) - // -------- SignedHeaders -------- - const height int64 = 37 + // -------- SignedHeaders -------- + const height int64 = 37 - var ( - header1 = makeHeaderRandom() - header2 = makeHeaderRandom() - ) + var ( + header1 = makeHeaderRandom() + header2 = makeHeaderRandom() + ) - header1.Height = height - header1.LastBlockID = blockID - header1.ChainID = chainID + header1.Height = height + header1.LastBlockID = blockID + header1.ChainID = chainID - header2.Height = height - header2.LastBlockID = blockID - header2.ChainID = chainID + header2.Height = height + header2.LastBlockID = blockID + header2.ChainID = chainID - tests := []struct { - testName string - evidence Evidence - toProtoErr bool - fromProtoErr bool - }{ - {"nil fail", nil, true, true}, - {"DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, false, true}, - {"DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true}, - {"DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true}, - {"DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.testName, func(t *testing.T) { - pb, err := EvidenceToProto(tt.evidence) - if tt.toProtoErr { - assert.Error(t, err, tt.testName) - return - } - assert.NoError(t, err, tt.testName) + tests := []struct { + testName string + evidence Evidence + toProtoErr bool + fromProtoErr bool + }{ + {"nil fail", nil, true, true}, + {"DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, false, true}, + {"DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, false, true}, + {"DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, false, true}, + {"DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v}, false, false}, + } + for _, tt := range tests { + tt := tt + t.Run(tt.testName, func(t *testing.T) { + pb, err := EvidenceToProto(tt.evidence) + if tt.toProtoErr { + assert.Error(t, err, tt.testName) + return + } + assert.NoError(t, err, tt.testName) - evi, err := EvidenceFromProto(pb) - if tt.fromProtoErr { - assert.Error(t, err, tt.testName) - return - } - require.Equal(t, tt.evidence, evi, tt.testName) - }) - } - }) + evi, err := EvidenceFromProto(pb) + if tt.fromProtoErr { + assert.Error(t, err, tt.testName) + return + } + require.Equal(t, tt.evidence, evi, tt.testName) + }) + } } diff --git a/types/params.go b/types/params.go index 6aac0dfba..4c00eda6a 100644 --- a/types/params.go +++ b/types/params.go @@ -61,10 +61,10 @@ func DefaultEvidenceParams() tmproto.EvidenceParams { } // DefaultValidatorParams returns a default ValidatorParams, which allows -// only key type generated by the default init command. +// only ed25519 pubkeys. func DefaultValidatorParams() tmproto.ValidatorParams { return tmproto.ValidatorParams{ - PubKeyTypes: []string{ABCIPubKeyTypeEd25519, ABCIPubKeyTypeBls12WithEd25519}, + PubKeyTypes: []string{ABCIPubKeyTypeEd25519}, } } diff --git a/types/priv_validator.go b/types/priv_validator.go index 7cf2724a7..56c021491 100644 --- a/types/priv_validator.go +++ b/types/priv_validator.go @@ -5,11 +5,7 @@ import ( "errors" "fmt" - "github.com/line/ostracon/libs/rand" - "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" "github.com/line/ostracon/crypto/ed25519" tmproto "github.com/line/ostracon/proto/ostracon/types" ) @@ -59,37 +55,8 @@ type MockPV struct { breakVoteSigning bool } -type PrivKeyType int - -const ( - PrivKeyEd25519 PrivKeyType = iota - PrivKeyComposite - PrivKeyBLS -) - -func NewMockPV(keyType PrivKeyType) MockPV { - switch keyType { - case PrivKeyEd25519: - return MockPV{ed25519.GenPrivKey(), false, false} - case PrivKeyComposite: - return MockPV{composite.GenPrivKey(), false, false} - case PrivKeyBLS: - return MockPV{bls.GenPrivKey(), false, false} - default: - panic(fmt.Sprintf("known pv key type: %d", keyType)) - } -} - -func PrivKeyTypeByPubKey(pubKey crypto.PubKey) PrivKeyType { - switch pubKey.(type) { - case ed25519.PubKey: - return PrivKeyEd25519 - case composite.PubKey: - return PrivKeyComposite - case bls.PubKey: - return PrivKeyBLS - } - panic(fmt.Sprintf("unknown public key type: %v", pubKey)) +func NewMockPV() MockPV { + return MockPV{ed25519.GenPrivKey(), false, false} } // NewMockPVWithParams allows one to create a MockPV instance, but with finer @@ -183,17 +150,3 @@ func (pv *ErroringMockPV) SignProposal(chainID string, proposal *tmproto.Proposa func NewErroringMockPV() *ErroringMockPV { return &ErroringMockPV{MockPV{ed25519.GenPrivKey(), false, false}} } - -// ======================================== - -// RandomKeyType for testing -func RandomKeyType() PrivKeyType { - r := rand.Uint32() % 2 - switch r { - case 0: - return PrivKeyEd25519 - case 1: - return PrivKeyComposite - } - return PrivKeyEd25519 -} diff --git a/types/priv_validator_test.go b/types/priv_validator_test.go deleted file mode 100644 index c2dbe2077..000000000 --- a/types/priv_validator_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package types - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func forAllPrivKeyTypes(t *testing.T, exec func(t *testing.T, name string, keyType PrivKeyType)) { - keyNameAndTypes := []struct { - name string - keyType PrivKeyType - }{ - {name: "ed25512", keyType: PrivKeyEd25519}, - {name: "composite", keyType: PrivKeyComposite}, - {name: "bls", keyType: PrivKeyBLS}} - for _, knt := range keyNameAndTypes { - name := knt.name // pin; to avoid "Using the variable on range scope knt in function literal (scopelint)" - keyType := knt.keyType - t.Run(name, func(t *testing.T) { - exec(t, name, keyType) - }) - } -} - -func TestPvKeyTypeByAddress(t *testing.T) { - for i := 0; i < 1000; i++ { - keyType := RandomKeyType() - pv := NewMockPV(keyType) - pubKey, _ := pv.GetPubKey() - assert.True(t, keyType == PrivKeyTypeByPubKey(pubKey)) - } -} diff --git a/types/proposal_test.go b/types/proposal_test.go index b202178b2..e6d55e193 100644 --- a/types/proposal_test.go +++ b/types/proposal_test.go @@ -55,50 +55,43 @@ func TestProposalString(t *testing.T) { } func TestProposalVerifySignature(t *testing.T) { - keyTypeCases := []PrivKeyType{ - PrivKeyEd25519, - PrivKeyComposite, - PrivKeyBLS, - } - for _, kt := range keyTypeCases { - privVal := NewMockPV(kt) - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - - prop := NewProposal( - 4, 2, 2, - BlockID{tmrand.Bytes(tmhash.Size), PartSetHeader{777, tmrand.Bytes(tmhash.Size)}}) - p := prop.ToProto() - signBytes := ProposalSignBytes("test_chain_id", p) - - // sign it - err = privVal.SignProposal("test_chain_id", p) - require.NoError(t, err) - prop.Signature = p.Signature - - // verify the same proposal - valid := pubKey.VerifySignature(signBytes, prop.Signature) - require.True(t, valid) - - // serialize, deserialize and verify again.... - newProp := new(tmproto.Proposal) - pb := prop.ToProto() - - bs, err := proto.Marshal(pb) - require.NoError(t, err) - - err = proto.Unmarshal(bs, newProp) - require.NoError(t, err) - - np, err := ProposalFromProto(newProp) - require.NoError(t, err) - - // 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) - } + privVal := NewMockPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + + prop := NewProposal( + 4, 2, 2, + BlockID{tmrand.Bytes(tmhash.Size), PartSetHeader{777, tmrand.Bytes(tmhash.Size)}}) + p := prop.ToProto() + signBytes := ProposalSignBytes("test_chain_id", p) + + // sign it + err = privVal.SignProposal("test_chain_id", p) + require.NoError(t, err) + prop.Signature = p.Signature + + // verify the same proposal + valid := pubKey.VerifySignature(signBytes, prop.Signature) + require.True(t, valid) + + // serialize, deserialize and verify again.... + newProp := new(tmproto.Proposal) + pb := prop.ToProto() + + bs, err := proto.Marshal(pb) + require.NoError(t, err) + + err = proto.Unmarshal(bs, newProp) + require.NoError(t, err) + + np, err := ProposalFromProto(newProp) + require.NoError(t, err) + + // 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) } func BenchmarkProposalWriteSignBytes(b *testing.B) { @@ -108,19 +101,11 @@ func BenchmarkProposalWriteSignBytes(b *testing.B) { } func BenchmarkProposalSignEd25519(b *testing.B) { - benchmarkProposalSign(b, PrivKeyEd25519) + benchmarkProposalSign(b) } -func BenchmarkProposalSignComposite(b *testing.B) { - benchmarkProposalSign(b, PrivKeyComposite) -} - -func BenchmarkProposalSignBLS(b *testing.B) { - benchmarkProposalSign(b, PrivKeyBLS) -} - -func benchmarkProposalSign(b *testing.B, keyType PrivKeyType) { - privVal := NewMockPV(keyType) +func benchmarkProposalSign(b *testing.B) { + privVal := NewMockPV() for i := 0; i < b.N; i++ { err := privVal.SignProposal("test_chain_id", pbp) if err != nil { @@ -130,19 +115,11 @@ func benchmarkProposalSign(b *testing.B, keyType PrivKeyType) { } func BenchmarkProposalVerifySignatureEd25519(b *testing.B) { - benchmarkProposalVerifySignature(b, PrivKeyEd25519) -} - -func BenchmarkProposalVerifySignatureComposite(b *testing.B) { - benchmarkProposalVerifySignature(b, PrivKeyComposite) -} - -func BenchmarkProposalVerifySignatureBLS(b *testing.B) { - benchmarkProposalVerifySignature(b, PrivKeyBLS) + benchmarkProposalVerifySignature(b) } -func benchmarkProposalVerifySignature(b *testing.B, keyType PrivKeyType) { - privVal := NewMockPV(keyType) +func benchmarkProposalVerifySignature(b *testing.B) { + privVal := NewMockPV() err := privVal.SignProposal("test_chain_id", pbp) require.NoError(b, err) pubKey, err := privVal.GetPubKey() @@ -155,49 +132,43 @@ func benchmarkProposalVerifySignature(b *testing.B, keyType PrivKeyType) { } func TestProposalValidateBasic(t *testing.T) { - keyTypeCases := []PrivKeyType{ - PrivKeyEd25519, - PrivKeyComposite, - PrivKeyBLS, + + privVal := NewMockPV() + testCases := []struct { + testName string + malleateProposal func(*Proposal) + expectErr bool + }{ + {"Good Proposal", func(p *Proposal) {}, false}, + {"Invalid Type", func(p *Proposal) { p.Type = tmproto.PrecommitType }, true}, + {"Invalid Height", func(p *Proposal) { p.Height = -1 }, true}, + {"Invalid Round", func(p *Proposal) { p.Round = -1 }, true}, + {"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true}, + {"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}, } - for _, kt := range keyTypeCases { - privVal := NewMockPV(kt) - testCases := []struct { - testName string - malleateProposal func(*Proposal) - expectErr bool - }{ - {"Good Proposal", func(p *Proposal) {}, false}, - {"Invalid Type", func(p *Proposal) { p.Type = tmproto.PrecommitType }, true}, - {"Invalid Height", func(p *Proposal) { p.Height = -1 }, true}, - {"Invalid Round", func(p *Proposal) { p.Round = -1 }, true}, - {"Invalid POLRound", func(p *Proposal) { p.POLRound = -2 }, true}, - {"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(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) - - for _, tc := range testCases { - tc := tc - t.Run(tc.testName, func(t *testing.T) { - prop := NewProposal( - 4, 2, 2, - blockID) - p := prop.ToProto() - err := privVal.SignProposal("test_chain_id", p) - prop.Signature = p.Signature - require.NoError(t, err) - tc.malleateProposal(prop) - assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") - }) - } + blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt32, tmhash.Sum([]byte("partshash"))) + + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + prop := NewProposal( + 4, 2, 2, + blockID) + p := prop.ToProto() + err := privVal.SignProposal("test_chain_id", p) + prop.Signature = p.Signature + require.NoError(t, err) + tc.malleateProposal(prop) + assert.Equal(t, tc.expectErr, prop.ValidateBasic() != nil, "Validate Basic had an unexpected result") + }) } } diff --git a/types/protobuf.go b/types/protobuf.go index c75e68314..986865b8f 100644 --- a/types/protobuf.go +++ b/types/protobuf.go @@ -3,8 +3,6 @@ package types import ( abci "github.com/line/ostracon/abci/types" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" "github.com/line/ostracon/crypto/ed25519" cryptoenc "github.com/line/ostracon/crypto/encoding" "github.com/line/ostracon/crypto/secp256k1" @@ -15,19 +13,15 @@ import ( // Use strings to distinguish types in ABCI messages const ( - ABCIPubKeyTypeBls12WithEd25519 = composite.KeyTypeBlsWithEd25519 - ABCIPubKeyTypeEd25519 = ed25519.KeyType - ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType - ABCIPubKeyTypeBls12 = bls.KeyType + ABCIPubKeyTypeEd25519 = ed25519.KeyType + ABCIPubKeyTypeSecp256k1 = secp256k1.KeyType ) // TODO: Make non-global by allowing for registration of more pubkey types var ABCIPubKeyTypesToNames = map[string]string{ - ABCIPubKeyTypeBls12WithEd25519: composite.PubKeyName, - ABCIPubKeyTypeEd25519: ed25519.PubKeyName, - ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, - ABCIPubKeyTypeBls12: bls.PubKeyName, + ABCIPubKeyTypeEd25519: ed25519.PubKeyName, + ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyName, } //------------------------------------------------------- diff --git a/types/protobuf_test.go b/types/protobuf_test.go index 0a830653f..67fc6dcad 100644 --- a/types/protobuf_test.go +++ b/types/protobuf_test.go @@ -8,30 +8,24 @@ import ( "github.com/golang/protobuf/proto" // nolint: staticcheck // still used by gogoproto "github.com/tendermint/go-amino" - "github.com/line/ostracon/proto/ostracon/version" - "github.com/line/ostracon/types/time" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" abci "github.com/line/ostracon/abci/types" "github.com/line/ostracon/crypto" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" "github.com/line/ostracon/crypto/ed25519" cryptoenc "github.com/line/ostracon/crypto/encoding" + "github.com/line/ostracon/proto/ostracon/version" + "github.com/line/ostracon/types/time" ) func TestABCIPubKey(t *testing.T) { pkEd := ed25519.GenPrivKey().PubKey() pkSecp := secp256k1.GenPrivKey().PubKey() - pkComposite := composite.NewPrivKeyComposite(bls.GenPrivKey(), ed25519.GenPrivKey()).PubKey() err := testABCIPubKey(t, pkEd, ABCIPubKeyTypeEd25519) assert.NoError(t, err) err = testABCIPubKey(t, pkSecp, ABCIPubKeyTypeSecp256k1) assert.NoError(t, err) - err = testABCIPubKey(t, pkComposite, ABCIPubKeyTypeBls12WithEd25519) - assert.NoError(t, err) } func testABCIPubKey(t *testing.T, pk crypto.PubKey, typeStr string) error { @@ -134,23 +128,21 @@ func TestABCIHeader(t *testing.T) { } func TestABCIEvidence(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - val := NewMockPV(kt) - blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) - blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) - const chainID = "mychain" - now := time.Now() - ev := &DuplicateVoteEvidence{ - VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID, now), - VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, now), - TotalVotingPower: int64(100), - ValidatorPower: int64(10), - Timestamp: now, - } - for _, abciEv := range ev.ABCI() { - assert.Equal(t, "DUPLICATE_VOTE", abciEv.Type.String()) - } - }) + val := NewMockPV() + blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) + blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) + const chainID = "mychain" + now := time.Now() + ev := &DuplicateVoteEvidence{ + VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID, now), + VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2, now), + TotalVotingPower: int64(100), + ValidatorPower: int64(10), + Timestamp: now, + } + for _, abciEv := range ev.ABCI() { + assert.Equal(t, "DUPLICATE_VOTE", abciEv.Type.String()) + } } type pubKeyEddie struct{} diff --git a/types/signable.go b/types/signable.go index 5292e9de6..9cb7b1e3a 100644 --- a/types/signable.go +++ b/types/signable.go @@ -1,7 +1,6 @@ package types import ( - "github.com/line/ostracon/crypto/bls" "github.com/line/ostracon/crypto/ed25519" tmmath "github.com/line/ostracon/libs/math" ) @@ -10,7 +9,7 @@ var ( // MaxSignatureSize is a maximum allowed signature size for the Proposal // and Vote. // XXX: secp256k1 does not have Size nor MaxSize defined. - MaxSignatureSize = tmmath.MaxInt(tmmath.MaxInt(ed25519.SignatureSize, bls.SignatureSize), 64) + MaxSignatureSize = tmmath.MaxInt(ed25519.SignatureSize, 64) ) // Signable is an interface for all signable things. diff --git a/types/validator.go b/types/validator.go index 7ca4841c0..3ad644353 100644 --- a/types/validator.go +++ b/types/validator.go @@ -188,11 +188,7 @@ func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) { // RandValidator returns a randomized validator, useful for testing. // UNSTABLE func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) { - return RandValidatorForPrivKey(RandomKeyType(), randPower, minPower) -} - -func RandValidatorForPrivKey(keyType PrivKeyType, randPower bool, minPower int64) (*Validator, PrivValidator) { - privVal := NewMockPV(keyType) + privVal := NewMockPV() votingPower := minPower if randPower { votingPower += int64(tmrand.Uint32()) diff --git a/types/validator_set_test.go b/types/validator_set_test.go index 7cf0cb6f0..3eab4672b 100644 --- a/types/validator_set_test.go +++ b/types/validator_set_test.go @@ -414,21 +414,21 @@ func randValidatorSet(numValidators int) *ValidatorSet { return NewValidatorSet(validators) } -func randValidatorWithMinMax(keyType PrivKeyType, min, max int64) (*Validator, PrivValidator) { - privVal := NewMockPV(keyType) +func randValidatorWithMinMax(min, max int64) (*Validator, PrivValidator) { + privVal := NewMockPV() pubKey, _ := privVal.GetPubKey() val := NewValidator(pubKey, min+int64(tmrand.Uint64()%uint64(1+max-min))) val.ProposerPriority = min + tmrand.Int64()%max return val, privVal } -func randValidatorSetWithMinMax(keyType PrivKeyType, numValidators int, min, max int64) (*ValidatorSet, +func randValidatorSetWithMinMax(numValidators int, min, max int64) (*ValidatorSet, map[string]PrivValidator) { validators := make([]*Validator, numValidators) privMap := make(map[string]PrivValidator) var privVal PrivValidator for i := 0; i < numValidators; i++ { - validators[i], privVal = randValidatorWithMinMax(keyType, min, max) + validators[i], privVal = randValidatorWithMinMax(min, max) privMap[validators[i].Address.String()] = privVal } return NewValidatorSet(validators), privMap @@ -1326,7 +1326,7 @@ func TestNewValidatorSetFromExistingValidators(t *testing.T) { size := 5 vals := make([]*Validator, size) for i := 0; i < size; i++ { - pv := NewMockPV(PrivKeyComposite) // TODO 🏺 need to test by all key types + pv := NewMockPV() vals[i] = pv.ExtractIntoValidator(int64(i + 1)) } valSet := NewValidatorSet(vals) diff --git a/types/validator_test.go b/types/validator_test.go index 510d748bd..5eb2ed7bf 100644 --- a/types/validator_test.go +++ b/types/validator_test.go @@ -39,7 +39,7 @@ func TestValidatorProtoBuf(t *testing.T) { } func TestValidatorValidateBasic(t *testing.T) { - priv := NewMockPV(PrivKeyComposite) // TODO 🏺 need to test by all key types + priv := NewMockPV() pubKey, _ := priv.GetPubKey() testCases := []struct { val *Validator diff --git a/types/vote.go b/types/vote.go index 2adc39dde..52defe9cc 100644 --- a/types/vote.go +++ b/types/vote.go @@ -6,10 +6,8 @@ import ( "fmt" "time" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/ed25519" - "github.com/line/ostracon/crypto" + "github.com/line/ostracon/crypto/ed25519" tmbytes "github.com/line/ostracon/libs/bytes" "github.com/line/ostracon/libs/protoio" tmproto "github.com/line/ostracon/proto/ostracon/types" @@ -61,26 +59,14 @@ type Vote struct { Signature []byte `json:"signature"` } -func MaxVoteBytes(signSize int) int64 { - size := (1 + 1) + // Type - (1 + 9) + // Height - (1 + 5) + // Round - (1 + 76 + 1) + // BlockID - (1 + 17 + 1) + // Timestamp - (1 + 20 + 1) + // ValidatorAddress - (1 + 5) // ValidatorIndex - switch signSize { // Signature - case 0: - /* */ - case ed25519.SignatureSize: - fallthrough - case bls.SignatureSize: - size += 1 + signSize + 1 - default: - panic(fmt.Sprintf("unsupported signature size: %d", signSize)) - } - return int64(size) -} +const MaxVoteBytes int64 = (1 + 1) + // Type + (1 + 9) + // Height + (1 + 5) + // Round + (1 + 76 + 1) + // BlockID + (1 + 17 + 1) + // Timestamp + (1 + 20 + 1) + // ValidatorAddress + (1 + 5) + // ValidatorIndex + (1 + ed25519.SignatureSize + 1) // Signature // CommitSig converts the Vote to a CommitSig. func (vote *Vote) CommitSig() CommitSig { diff --git a/types/vote_set.go b/types/vote_set.go index 1cff55806..fb482331b 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -665,7 +665,6 @@ func (voteSet *VoteSet) MakeCommit() *Commit { commitSigs[i] = commitSig } newCommit := NewCommit(voteSet.GetHeight(), voteSet.GetRound(), *voteSet.maj23, commitSigs) - newCommit.AggregateSignatures() return newCommit } diff --git a/types/vote_set_test.go b/types/vote_set_test.go index 07d903c69..d47779b76 100644 --- a/types/vote_set_test.go +++ b/types/vote_set_test.go @@ -6,10 +6,6 @@ import ( "sort" "testing" - "github.com/line/ostracon/crypto/bls" - "github.com/line/ostracon/crypto/composite" - "github.com/line/ostracon/crypto/ed25519" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -606,50 +602,4 @@ func TestVoteSet_MakeCommit(t *testing.T) { if err := commit.ValidateBasic(); err != nil { t.Errorf("error in Commit.ValidateBasic(): %v", err) } - - // Signature aggregation - t.Run("SignatureAggregation", func(t *testing.T) { - privKeys := [...]crypto.PrivKey{ - bls.GenPrivKey(), - composite.GenPrivKey(), - ed25519.GenPrivKey(), - bls.GenPrivKey(), - } - voteSet, _, _, privValidators := randVoteSetForPrivKeys(height, round, tmproto.PrecommitType, privKeys[:], 1) - for i := range privKeys { - pubKey, err := privValidators[i].GetPubKey() - if err != nil { - t.Fatal(err) - } - addr := pubKey.Address() - vote := withValidator(voteProto, addr, int32(i)) - fmt.Printf("*** %v - %v\n", vote.ValidatorAddress, addr) - if _, err := signAddVote(privValidators[i], vote, voteSet); err != nil { - t.Error(err) - } - } - - commit := voteSet.MakeCommit() - - assert.Equal(t, height, commit.Height) - assert.Equal(t, round, commit.Round) - assert.NotNil(t, commit.AggregatedSignature) - // The order of commit.Signatures is sorted by address. - for i := range commit.Signatures { - idx := 0 - for { - if bytes.Equal(privKeys[idx].PubKey().Address(), commit.Signatures[i].ValidatorAddress) { - break - } - idx++ - } - if _, ok := privKeys[idx].(ed25519.PrivKey); ok { - assert.NotNil(t, commit.Signatures[i].Signature) - } else if _, ok := privKeys[idx].(bls.PrivKey); ok { - assert.Nil(t, commit.Signatures[i].Signature) - } else if _, ok := privKeys[idx].(composite.PrivKey); ok { - assert.Nil(t, commit.Signatures[i].Signature) - } - } - }) } diff --git a/types/vote_test.go b/types/vote_test.go index 3166a02af..3644e81a7 100644 --- a/types/vote_test.go +++ b/types/vote_test.go @@ -158,36 +158,34 @@ func TestVoteProposalNotEq(t *testing.T) { } func TestVoteVerifySignature(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - privVal := NewMockPV(kt) - pubkey, err := privVal.GetPubKey() - require.NoError(t, err) - - vote := examplePrecommit() - v := vote.ToProto() - signBytes := VoteSignBytes("test_chain_id", v) - - // sign it - err = privVal.SignVote("test_chain_id", v) - require.NoError(t, err) - - // verify the same vote - valid := pubkey.VerifySignature(VoteSignBytes("test_chain_id", v), v.Signature) - require.True(t, valid) - - // 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) - - // 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) - }) + privVal := NewMockPV() + pubkey, err := privVal.GetPubKey() + require.NoError(t, err) + + vote := examplePrecommit() + v := vote.ToProto() + signBytes := VoteSignBytes("test_chain_id", v) + + // sign it + err = privVal.SignVote("test_chain_id", v) + require.NoError(t, err) + + // verify the same vote + valid := pubkey.VerifySignature(VoteSignBytes("test_chain_id", v), v.Signature) + require.True(t, valid) + + // 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) + + // 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) } func TestIsVoteTypeValid(t *testing.T) { @@ -212,24 +210,22 @@ func TestIsVoteTypeValid(t *testing.T) { } func TestVoteVerify(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - privVal := NewMockPV(kt) - pubkey, err := privVal.GetPubKey() - require.NoError(t, err) + privVal := NewMockPV() + pubkey, err := privVal.GetPubKey() + require.NoError(t, err) - vote := examplePrevote() - vote.ValidatorAddress = pubkey.Address() + vote := examplePrevote() + vote.ValidatorAddress = pubkey.Address() - err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey()) - if assert.Error(t, err) { - assert.Equal(t, ErrVoteInvalidValidatorAddress, err) - } + err = vote.Verify("test_chain_id", ed25519.GenPrivKey().PubKey()) + if assert.Error(t, err) { + assert.Equal(t, ErrVoteInvalidValidatorAddress, err) + } - err = vote.Verify("test_chain_id", pubkey) - if assert.Error(t, err) { - assert.Equal(t, ErrVoteInvalidSignature, err) - } - }) + err = vote.Verify("test_chain_id", pubkey) + if assert.Error(t, err) { + assert.Equal(t, ErrVoteInvalidSignature, err) + } } func TestMaxVoteBytes(t *testing.T) { @@ -252,16 +248,14 @@ func TestMaxVoteBytes(t *testing.T) { }, } - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - privVal := NewMockPV(kt) - pbVote := vote.ToProto() - err := privVal.SignVote("test_chain_id", pbVote) - require.NoError(t, err) + privVal := NewMockPV() + pbVote := vote.ToProto() + err := privVal.SignVote("test_chain_id", pbVote) + require.NoError(t, err) - bz, err := pbVote.Marshal() - require.NoError(t, err) - assert.Equal(t, MaxVoteBytes(len(pbVote.Signature)), int64(len(bz))) - }) + bz, err := pbVote.Marshal() + require.NoError(t, err) + assert.Equal(t, MaxVoteBytes, int64(len(bz))) } func TestVoteString(t *testing.T) { @@ -295,51 +289,47 @@ func TestVoteValidateBasic(t *testing.T) { {"Invalid Signature", func(v *Vote) { v.Signature = nil }, true}, {"Too big Signature", func(v *Vote) { v.Signature = make([]byte, MaxSignatureSize+1) }, true}, } - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - privVal := NewMockPV(kt) - for _, tc := range testCases { - tc := tc - t.Run(tc.testName, func(t *testing.T) { - vote := examplePrecommit() - v := vote.ToProto() - err := privVal.SignVote("test_chain_id", v) - vote.Signature = v.Signature - require.NoError(t, err) - tc.malleateVote(vote) - assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result") - }) - } - }) + privVal := NewMockPV() + for _, tc := range testCases { + tc := tc + t.Run(tc.testName, func(t *testing.T) { + vote := examplePrecommit() + v := vote.ToProto() + err := privVal.SignVote("test_chain_id", v) + vote.Signature = v.Signature + require.NoError(t, err) + tc.malleateVote(vote) + assert.Equal(t, tc.expectErr, vote.ValidateBasic() != nil, "Validate Basic had an unexpected result") + }) + } } func TestVoteProtobuf(t *testing.T) { - forAllPrivKeyTypes(t, func(t *testing.T, name string, kt PrivKeyType) { - privVal := NewMockPV(kt) - vote := examplePrecommit() - v := vote.ToProto() - err := privVal.SignVote("test_chain_id", v) - vote.Signature = v.Signature - require.NoError(t, err) - - testCases := []struct { - msg string - v1 *Vote - expPass bool - }{ - {"success", vote, true}, - {"fail vote validate basic", &Vote{}, false}, - {"failure nil", nil, false}, - } - for _, tc := range testCases { - protoProposal := tc.v1.ToProto() - - v, err := VoteFromProto(protoProposal) - if tc.expPass { - require.NoError(t, err) - require.Equal(t, tc.v1, v, tc.msg) - } else { - require.Error(t, err) - } + privVal := NewMockPV() + vote := examplePrecommit() + v := vote.ToProto() + err := privVal.SignVote("test_chain_id", v) + vote.Signature = v.Signature + require.NoError(t, err) + + testCases := []struct { + msg string + v1 *Vote + expPass bool + }{ + {"success", vote, true}, + {"fail vote validate basic", &Vote{}, false}, + {"failure nil", nil, false}, + } + for _, tc := range testCases { + protoProposal := tc.v1.ToProto() + + v, err := VoteFromProto(protoProposal) + if tc.expPass { + require.NoError(t, err) + require.Equal(t, tc.v1, v, tc.msg) + } else { + require.Error(t, err) } - }) + } } diff --git a/types/voter_set.go b/types/voter_set.go index 5b05d8ba5..270e97e2a 100644 --- a/types/voter_set.go +++ b/types/voter_set.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" - "github.com/line/ostracon/crypto/bls" "github.com/line/ostracon/crypto/merkle" "github.com/line/ostracon/crypto/tmhash" tmmath "github.com/line/ostracon/libs/math" @@ -173,8 +172,6 @@ func (voters *VoterSet) VerifyCommit(chainID string, blockID BlockID, height int talliedVotingWeight := int64(0) requiredVotingWeight := voters.TotalVotingWeight() * 2 / 3 // FIXME: 🏺 arithmetic overflow - blsPubKeys := make([]bls.PubKey, 0, len(commit.Signatures)) - messages := make([][]byte, 0, len(commit.Signatures)) for idx, commitSig := range commit.Signatures { if commitSig.Absent() { continue // OK, some signatures can be absent. @@ -186,29 +183,20 @@ func (voters *VoterSet) VerifyCommit(chainID string, blockID BlockID, height int // Validate signature. voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) - verifiedVotingWeight, unverifiedVotingWeight, err := verifySignatureOrCollectBlsPubKeysAndGetVotingWeight( - idx, commitSig, voter, voteSignBytes, &blsPubKeys, &messages) - if err != nil { - return err + if !voter.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { + return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) } // Good! if commitSig.ForBlock() { - talliedVotingWeight += verifiedVotingWeight + unverifiedVotingWeight + talliedVotingWeight += voter.VotingWeight } - // else { // It's OK. We include stray signatures (~votes for nil) to measure // voter availability. // } } - // Validate aggregate signature - if err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, messages); err != nil { - return fmt.Errorf("wrong aggregated signature: %X; %s", commit.AggregatedSignature, err) - } - - // add voting weight for BLS batch verification and return without error if trust-level of the signatures are verified if got, needed := talliedVotingWeight, requiredVotingWeight; got <= needed { return ErrNotEnoughVotingWeightSigned{Got: got, Needed: needed} } @@ -243,10 +231,7 @@ func (voters *VoterSet) VerifyCommitLight(chainID string, blockID BlockID, } talliedVotingWeight := int64(0) - talliedUnverifiedVotingWeight := int64(0) requiredVotingWeight := voters.TotalVotingWeight() * 2 / 3 // FIXME: 🏺 arithmetic overflow - blsPubKeys := make([]bls.PubKey, 0, len(commit.Signatures)) - messages := make([][]byte, 0, len(commit.Signatures)) for idx, commitSig := range commit.Signatures { // No need to verify absent or nil votes. if !commitSig.ForBlock() { @@ -263,14 +248,11 @@ func (voters *VoterSet) VerifyCommitLight(chainID string, blockID BlockID, // Validate signature. voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) - verifiedVotingWeight, unverifiedVotingWeight, err := verifySignatureOrCollectBlsPubKeysAndGetVotingWeight( - idx, commitSig, voter, voteSignBytes, &blsPubKeys, &messages) - if err != nil { - return err + if !voter.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { + return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) } - talliedVotingWeight += verifiedVotingWeight - talliedUnverifiedVotingWeight += unverifiedVotingWeight + talliedVotingWeight += voter.VotingWeight // return as soon as +2/3 of the signatures are verified by individual verification if talliedVotingWeight > requiredVotingWeight { @@ -278,16 +260,6 @@ func (voters *VoterSet) VerifyCommitLight(chainID string, blockID BlockID, } } - // Validate aggregate signature - if err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, messages); err != nil { - return fmt.Errorf("wrong aggregated signature: %X; %s", commit.AggregatedSignature, err) - } - // add voting weight for BLS batch verification and return without error if +2/3 of the signatures are verified - talliedVotingWeight += talliedUnverifiedVotingWeight - if talliedVotingWeight > requiredVotingWeight { - return nil - } - return ErrNotEnoughVotingWeightSigned{Got: talliedVotingWeight, Needed: requiredVotingWeight} } @@ -306,9 +278,8 @@ func (voters *VoterSet) VerifyCommitLightTrusting(chainID string, commit *Commit } var ( - talliedVotingWeight int64 - talliedUnverifiedVotingWeight int64 - seenVoters = make(map[int32]int, len(commit.Signatures)) // voter index -> commit index + talliedVotingWeight int64 + seenVoters = make(map[int32]int, len(commit.Signatures)) // voter index -> commit index ) // Safely calculate voting weight needed. @@ -319,8 +290,6 @@ func (voters *VoterSet) VerifyCommitLightTrusting(chainID string, commit *Commit } requiredVotingWeight := totalVotingWeightMulByNumerator / int64(trustLevel.Denominator) - blsPubKeys := make([]bls.PubKey, 0, len(commit.Signatures)) - messages := make([][]byte, 0, len(commit.Signatures)) for idx, commitSig := range commit.Signatures { // No need to verify absent or nil votes. if !commitSig.ForBlock() { @@ -341,14 +310,11 @@ func (voters *VoterSet) VerifyCommitLightTrusting(chainID string, commit *Commit // Verify Signature voteSignBytes := commit.VoteSignBytes(chainID, int32(idx)) - verifiedVotingWeight, unverifiedVotingWeight, err := verifySignatureOrCollectBlsPubKeysAndGetVotingWeight( - idx, commitSig, voter, voteSignBytes, &blsPubKeys, &messages) - if err != nil { - return err + if !voter.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { + return fmt.Errorf("wrong signature (#%d): %X", idx, commitSig.Signature) } - talliedVotingWeight += verifiedVotingWeight - talliedUnverifiedVotingWeight += unverifiedVotingWeight + talliedVotingWeight += voter.VotingWeight if talliedVotingWeight > requiredVotingWeight { return nil @@ -356,48 +322,9 @@ func (voters *VoterSet) VerifyCommitLightTrusting(chainID string, commit *Commit } } - // Validate aggregate signature - if err := bls.VerifyAggregatedSignature(commit.AggregatedSignature, blsPubKeys, messages); err != nil { - return fmt.Errorf("wrong aggregated signature: %X; %s", commit.AggregatedSignature, err) - } - // add voting weight for BLS batch verification and return without error if trust-level of the signatures are verified - talliedVotingWeight += talliedUnverifiedVotingWeight - if talliedVotingWeight > requiredVotingWeight { - return nil - } - return ErrNotEnoughVotingWeightSigned{Got: talliedVotingWeight, Needed: requiredVotingWeight} } -func verifySignatureOrCollectBlsPubKeysAndGetVotingWeight( - idx int, commitSig CommitSig, val *Validator, voteSignBytes []byte, - blsPubKeys *[]bls.PubKey, messages *[][]byte) (int64, int64, error) { - verifiedVotingWeight := int64(0) - unverifiedVotingWeight := int64(0) - if commitSig.Signature != nil { - if !val.PubKey.VerifySignature(voteSignBytes, commitSig.Signature) { - return verifiedVotingWeight, unverifiedVotingWeight, fmt.Errorf( - "wrong signature (#%d): %X", - idx, - commitSig.Signature, - ) - } - verifiedVotingWeight = val.VotingWeight - } else { - blsPubKey := GetSignatureKey(val.PubKey) - if blsPubKey == nil { - return verifiedVotingWeight, unverifiedVotingWeight, fmt.Errorf( - "signature %d has been omitted, even though it is not a BLS key", - idx, - ) - } - *blsPubKeys = append(*blsPubKeys, *blsPubKey) - *messages = append(*messages, voteSignBytes) - unverifiedVotingWeight = val.VotingWeight - } - return verifiedVotingWeight, unverifiedVotingWeight, nil -} - // ToProto converts VoterSet to protobuf func (voters *VoterSet) ToProto() (*tmproto.VoterSet, error) { if voters.IsNilOrEmpty() { diff --git a/types/voter_set_test.go b/types/voter_set_test.go index 7482965c4..4371716bd 100644 --- a/types/voter_set_test.go +++ b/types/voter_set_test.go @@ -408,7 +408,7 @@ func BenchmarkSelectVoterReasonableVotingPower(b *testing.B) { } func findLargestVotingPowerGap(b *testing.B, loopCount int, minMaxRate int, maxVoters int) { - valSet, privMap := randValidatorSetWithMinMax(PrivKeyEd25519, 30, 100, 100*int64(minMaxRate)) + valSet, privMap := randValidatorSetWithMinMax(30, 100, 100*int64(minMaxRate)) genDoc := &GenesisDoc{ GenesisTime: tmtime.Now(), ChainID: "ostracon-test", @@ -457,7 +457,7 @@ func BenchmarkSelectVoterMaxVarious(b *testing.B) { b.Logf("<<< min: 100, max: %d >>>", 100*minMaxRate) for validators := 16; validators <= 256; validators *= 4 { for voters := 1; voters <= validators; voters += 10 { - valSet, _ := randValidatorSetWithMinMax(PrivKeyEd25519, validators, 100, 100*int64(minMaxRate)) + valSet, _ := randValidatorSetWithMinMax(validators, 100, 100*int64(minMaxRate)) voterSet := SelectVoter(valSet, []byte{byte(hash)}, &VoterParams{int32(voters), 20}) if voterSet.Size() < voters { b.Logf("Cannot elect voters up to MaxVoters: validators=%d, MaxVoters=%d, actual voters=%d",