Skip to content

Commit

Permalink
feat: add bls signature verification
Browse files Browse the repository at this point in the history
  • Loading branch information
j75689 committed Jul 7, 2023
1 parent ef98eb2 commit 66487db
Show file tree
Hide file tree
Showing 28 changed files with 835 additions and 334 deletions.
567 changes: 357 additions & 210 deletions api/cosmos/staking/v1beta1/tx.pulsar.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions client/keys/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ The pass backend requires GnuPG: https://gnupg.org/
RenameKeyCommand(),
ParseKeyStringCommand(),
MigrateCommand(),
SignMsgKeysCmd(),
VerifySignatureCmd(),
)

cmd.PersistentFlags().String(flags.FlagHome, defaultNodeHome, "The application home directory")
Expand Down
2 changes: 1 addition & 1 deletion client/keys/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ func TestCommands(t *testing.T) {
assert.Assert(t, rootCommands != nil)

// Commands are registered
assert.Equal(t, 11, len(rootCommands.Commands()))
assert.Equal(t, 13, len(rootCommands.Commands()))
}
106 changes: 106 additions & 0 deletions client/keys/sign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package keys

import (
"encoding/hex"
"errors"

"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/spf13/cobra"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
)

// SignMsgKeysCmd returns the Cobra Command for signing messages with the private key of a given name.
func SignMsgKeysCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "sign [message]",
Short: "Sign message",
Long: "Return a signature from their associated name and address private key.",
RunE: runSignMsgCmd,
}

cmd.Flags().String(flags.FlagFrom, "", "Name or address of private key with which to sign")
return cmd
}

func runSignMsgCmd(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("invalid number of arguments")
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

_, name, _, err := client.GetFromFields(clientCtx, clientCtx.Keyring, clientCtx.From)
if err != nil {
return err
}

msg, err := hex.DecodeString(args[0])
if err != nil {
return err
}
sig, _, err := clientCtx.Keyring.Sign(name, tmhash.Sum(msg))
if err != nil {
return err
}

cmd.Println(hex.EncodeToString(sig))
return nil
}

// VerifySignatureCmd returns the Cobra Command for verifying signatures with a given public key and message.
func VerifySignatureCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "verify [message] [signature]",
Short: "Verify signature",
Long: "Verify signature with public key and message",
RunE: runVerifySignatureCmd,
}

cmd.Flags().String(flags.FlagFrom, "", "Name or address of private key with which to sign")
return cmd
}

func runVerifySignatureCmd(cmd *cobra.Command, args []string) error {
if len(args) != 2 {
return errors.New("invalid number of arguments")
}

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

_, name, _, err := client.GetFromFields(clientCtx, clientCtx.Keyring, clientCtx.From)
if err != nil {
return err
}
record, err := clientCtx.Keyring.Key(name)
if err != nil {
return err
}

priv, err := record.ExtractPrivKey()
if err != nil {
return nil
}

msg, err := hex.DecodeString(args[0])
if err != nil {
return nil
}
signature, err := hex.DecodeString(args[1])
if err != nil {
return nil
}
if priv.PubKey().VerifySignature(tmhash.Sum(msg), signature) {
cmd.Println("Signature verify successfully")
} else {
cmd.Println("Signature verify failed")
}
return nil
}
5 changes: 5 additions & 0 deletions crypto/keyring/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ func (k *Record) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
return nil
}

// ExtractPrivKey returns the priv key
func (k *Record) ExtractPrivKey() (cryptotypes.PrivKey, error) {
return extractPrivKeyFromRecord(k)
}

func extractPrivKeyFromRecord(k *Record) (cryptotypes.PrivKey, error) {
rl := k.GetLocal()
if rl == nil {
Expand Down
6 changes: 5 additions & 1 deletion crypto/keys/eth/ethsecp256k1/pubkey.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ func (pubKey *PubKey) VerifySignature(msg, sig []byte) bool {
sig = sig[:len(sig)-1]
}

if len(msg) != crypto.DigestLength {
msg = crypto.Keccak256Hash(msg).Bytes()
}

// the signature needs to be in [R || S] format when provided to VerifySignature
return crypto.VerifySignature(pubKey.Key, crypto.Keccak256Hash(msg).Bytes(), sig)
return crypto.VerifySignature(pubKey.Key, msg, sig)
}
4 changes: 3 additions & 1 deletion proto/cosmos/staking/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ message MsgCreateValidator {
string relayer_address = 9 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string challenger_address = 10 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string bls_key = 11;
string bls_proof = 12;
}

// MsgCreateValidatorResponse defines the Msg/CreateValidator response type.
Expand Down Expand Up @@ -98,7 +99,8 @@ message MsgEditValidator {

string relayer_address = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string challenger_address = 6 [(cosmos_proto.scalar) = "cosmos.AddressString"];
string bls_key = 7; // The BLS pubkey for the authorized relayer/challenger
string bls_key = 7; // The BLS pubkey for the authorized relayer/challenger
string bls_proof = 8;
}

// MsgEditValidatorResponse defines the Msg/EditValidator response type.
Expand Down
5 changes: 4 additions & 1 deletion simapp/simd/cmd/testnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"path/filepath"

tmconfig "github.com/cometbft/cometbft/config"
"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/cometbft/cometbft/types"
tmtime "github.com/cometbft/cometbft/types/time"
"github.com/prysmaticlabs/prysm/crypto/bls"
Expand Down Expand Up @@ -302,14 +303,16 @@ func initTestnetFiles(
valTokens := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction)
blsSecretKey, _ := bls.RandKey()
blsPk := hex.EncodeToString(blsSecretKey.PublicKey().Marshal())
blsProofBuf := blsSecretKey.Sign(tmhash.Sum(blsSecretKey.PublicKey().Marshal()))
blsProof := hex.EncodeToString(blsProofBuf.Marshal())
createValMsg, err := stakingtypes.NewMsgCreateValidator(
sdk.AccAddress(addr),
valPubKeys[i],
sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.OneDec()),
sdk.OneInt(),
addr, addr, addr, addr, blsPk,
addr, addr, addr, addr, blsPk, blsProof,
)
if err != nil {
return err
Expand Down
6 changes: 4 additions & 2 deletions testutil/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

dbm "github.com/cometbft/cometbft-db"
"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/cometbft/cometbft/node"
tmclient "github.com/cometbft/cometbft/rpc/client"
"github.com/prysmaticlabs/prysm/crypto/bls"
Expand Down Expand Up @@ -498,15 +499,16 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
return nil, err
}
blsPubKey := hex.EncodeToString(blsSecretKey.PublicKey().Marshal())

blsProofBuf := blsSecretKey.Sign(tmhash.Sum(blsSecretKey.PublicKey().Marshal()))
blsProof := hex.EncodeToString(blsProofBuf.Marshal())
createValMsg, err := stakingtypes.NewMsgCreateValidator(
addr,
valPubKeys[i],
sdk.NewCoin(cfg.BondDenom, cfg.BondedTokens),
stakingtypes.NewDescription(nodeDirName, "", "", "", ""),
stakingtypes.NewCommissionRates(commission, math.LegacyOneDec(), math.LegacyOneDec()),
math.OneInt(),
addr, addr, addr, addr, blsPubKey,
addr, addr, addr, addr, blsPubKey, blsProof,
)
if err != nil {
return nil, err
Expand Down
14 changes: 14 additions & 0 deletions testutil/sims/address_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/eth/ethsecp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -144,6 +145,19 @@ func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey {
return publicKeys
}

// CreateTestAccounts returns number of PubKey, PrivKey
func CreateTestAccounts(num int) ([]cryptotypes.PubKey, []cryptotypes.PrivKey) {
var publicKeys = make([]cryptotypes.PubKey, 0, num)
var privateKeys = make([]cryptotypes.PrivKey, 0, num)
for i := 0; i < num; i++ {
privKey, _ := ethsecp256k1.GenPrivKey()
publicKeys = append(publicKeys, privKey.PubKey())
privateKeys = append(privateKeys, privKey)
}

return publicKeys, privateKeys
}

// NewPubKeyFromHex returns a PubKey from a hex string.
func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) {
pkBytes, err := hex.DecodeString(pk)
Expand Down
5 changes: 3 additions & 2 deletions types/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ const (
EthAddressLength = 20

// BLSPubKeyLength defines a valid BLS Public key length
BLSPubKeyLength = 48
BLSEmptyPubKey = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dead"
BLSPubKeyLength = 48
BLSSignatureLength = 96
BLSEmptyPubKey = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dead"
)

// cache variables
Expand Down
11 changes: 9 additions & 2 deletions x/genutil/client/cli/gentx.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"

tmtypes "github.com/cometbft/cometbft/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/pkg/errors"
"github.com/spf13/cobra"

Expand All @@ -33,9 +34,9 @@ func GenTxCmd(mbm module.BasicManager, txEncCfg client.TxEncodingConfig, genBalI
fsCreateValidator, defaultsDesc := cli.CreateValidatorMsgFlagSet(ipDefault)

cmd := &cobra.Command{
Use: "gentx [key_name] [amount] [validator] [relayer] [challenger] [blskey]",
Use: "gentx [key_name] [amount] [validator] [relayer] [challenger] [blskey] [blsProof]",
Short: "Generate a genesis tx carrying a self delegation",
Args: cobra.ExactArgs(6),
Args: cobra.ExactArgs(7),
Long: fmt.Sprintf(`Generate a genesis transaction that creates a validator with a self-delegation,
that is signed by the key in the Keyring referenced by a given name. A node ID and Bech32 consensus
pubkey may optionally be provided. If they are omitted, they will be retrieved from the priv_validator.json
Expand All @@ -47,6 +48,7 @@ $ %s gentx my-key-name 1000000stake \
0x6D967dc83b625603c963713eABd5B43A281E595e \
0xcdd393723f1Af81faa3F3c87B51dAB72B6c68154 \
ac1e598ae0ccbeeaafa31bc6faefa85c2ae3138699cac79169cd718f1a38445201454ec092a86f200e08a15266bdc6e9 \
b68b819c2d431bd8ea800326bbcd91bbbbec5404b8f456b23c87de368c7f48507e7be120f32354ebf3df38c2b5808cebd4c07254f0b4626007c6d46fc05b260901 \
--home=/path/to/home/dir --keyring-backend=os --chain-id=greenfield_9000-1 \
--moniker="myvalidator" \
--commission-max-change-rate=0.01 \
Expand Down Expand Up @@ -172,12 +174,17 @@ $ %s gentx my-key-name 1000000stake \
if len(blsPk) != 2*sdk.BLSPubKeyLength {
return fmt.Errorf("invalid bls pubkey")
}
blsProof := args[6]
if len(blsProof) != 2*ethcrypto.SignatureLength {
return fmt.Errorf("invalid bls proof")
}

createValCfg.Validator = validator
createValCfg.Delegator = addr
createValCfg.Relayer = relayer
createValCfg.Challenger = challenger
createValCfg.BlsKey = blsPk
createValCfg.BLSProof = blsProof

// create a 'create-validator' message
txBldr, msg, err := cli.BuildCreateValidatorMsg(clientCtx, createValCfg, txFactory, true)
Expand Down
7 changes: 5 additions & 2 deletions x/genutil/gentx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/tmhash"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil"
genutiltestutil "github.com/cosmos/cosmos-sdk/x/genutil/testutil"
Expand Down Expand Up @@ -67,17 +68,19 @@ func (suite *GenTxTestSuite) SetupTest() {
one := math.OneInt()
blsSecretKey, _ := bls.RandKey()
blsPk := hex.EncodeToString(blsSecretKey.PublicKey().Marshal())
blsProofBuf := blsSecretKey.Sign(tmhash.Sum(blsSecretKey.PublicKey().Marshal()))
blsProof := hex.EncodeToString(blsProofBuf.Marshal())
suite.msg1, err = stakingtypes.NewMsgCreateValidator(
sdk.AccAddress(pk1.Address()), pk1,
amount, desc, comm, one,
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()),
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()), blsPk)
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()), blsPk, blsProof)
suite.NoError(err)
suite.msg2, err = stakingtypes.NewMsgCreateValidator(
sdk.AccAddress(pk2.Address()), pk1,
amount, desc, comm, one,
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk2.Address()),
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk1.Address()), blsPk)
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk1.Address()), blsPk, blsProof)
suite.NoError(err)
}

Expand Down
9 changes: 7 additions & 2 deletions x/genutil/types/genesis_state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"testing"

"github.com/cometbft/cometbft/crypto/tmhash"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -43,20 +44,24 @@ func TestValidateGenesisMultipleMessages(t *testing.T) {

blsSecretKey1, _ := bls.RandKey()
blsPk1 := hex.EncodeToString(blsSecretKey1.PublicKey().Marshal())
blsProofBuf := blsSecretKey1.Sign(tmhash.Sum(blsSecretKey1.PublicKey().Marshal()))
blsProof1 := hex.EncodeToString(blsProofBuf.Marshal())
msg1, err := stakingtypes.NewMsgCreateValidator(
sdk.AccAddress(pk1.Address()), pk1,
sdk.NewInt64Coin(sdk.DefaultBondDenom, 50), desc, comm, sdk.OneInt(),
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()),
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()), blsPk1)
sdk.AccAddress(pk1.Address()), sdk.AccAddress(pk1.Address()), blsPk1, blsProof1)
require.NoError(t, err)

blsSecretKey2, _ := bls.RandKey()
blsPk2 := hex.EncodeToString(blsSecretKey2.PublicKey().Marshal())
blsProofBuf = blsSecretKey2.Sign(tmhash.Sum(blsSecretKey2.PublicKey().Marshal()))
blsProof2 := hex.EncodeToString(blsProofBuf.Marshal())
msg2, err := stakingtypes.NewMsgCreateValidator(
sdk.AccAddress(pk2.Address()), pk2,
sdk.NewInt64Coin(sdk.DefaultBondDenom, 50), desc, comm, sdk.OneInt(),
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk2.Address()),
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk2.Address()), blsPk2)
sdk.AccAddress(pk2.Address()), sdk.AccAddress(pk2.Address()), blsPk2, blsProof2)
require.NoError(t, err)

txConfig := moduletestutil.MakeTestEncodingConfig(staking.AppModuleBasic{}, genutil.AppModuleBasic{}).TxConfig
Expand Down
5 changes: 4 additions & 1 deletion x/gov/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

abci "github.com/cometbft/cometbft/abci/types"
"github.com/cometbft/cometbft/crypto/tmhash"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -393,11 +394,13 @@ func createValidators(t *testing.T, stakingMsgSvr stakingtypes.MsgServer, ctx sd
valTokens := sdk.TokensFromConsensusPower(powerAmt[i], sdk.DefaultPowerReduction)
blsSecretKey, _ := bls.RandKey()
blsPk := hex.EncodeToString(blsSecretKey.PublicKey().Marshal())
blsProofBuf := blsSecretKey.Sign(tmhash.Sum(blsSecretKey.PublicKey().Marshal()))
blsProof := hex.EncodeToString(blsProofBuf.Marshal())
valCreateMsg, err := stakingtypes.NewMsgCreateValidator(
addrs[i], pubkeys[i], sdk.NewCoin(sdk.DefaultBondDenom, valTokens),
TestDescription, TestCommissionRates, sdk.OneInt(),
addrs[i], addrs[i],
addrs[i], addrs[i], blsPk)
addrs[i], addrs[i], blsPk, blsProof)
require.NoError(t, err)
res, err := stakingMsgSvr.CreateValidator(sdk.WrapSDKContext(ctx), valCreateMsg)
require.NoError(t, err)
Expand Down
Loading

0 comments on commit 66487db

Please sign in to comment.