Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Enable secp256r1 #8786

Merged
merged 11 commits into from
Mar 4, 2021
2 changes: 1 addition & 1 deletion crypto/keys/secp256r1/keys.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 3 additions & 19 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
- [Output](#cosmos.bank.v1beta1.Output)
- [Params](#cosmos.bank.v1beta1.Params)
- [SendEnabled](#cosmos.bank.v1beta1.SendEnabled)
- [Supply](#cosmos.bank.v1beta1.Supply)

- [cosmos/bank/v1beta1/genesis.proto](#cosmos/bank/v1beta1/genesis.proto)
- [Balance](#cosmos.bank.v1beta1.Balance)
Expand Down Expand Up @@ -1774,22 +1773,6 @@ sendable).




<a name="cosmos.bank.v1beta1.Supply"></a>

### Supply
Supply represents a struct that passively keeps track of the total supply
amounts in the network.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | |





<!-- end messages -->

<!-- end enums -->
Expand Down Expand Up @@ -3159,7 +3142,7 @@ PubKey defines a secp256r1 ECDSA public key.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62. |
| `key` | [bytes](#bytes) | | Point on secp256r1 curve in a compressed representation as specified in section 4.3.6 of ANSI X9.62: https://webstore.ansi.org/standards/ascx9/ansix9621998 |



Expand Down Expand Up @@ -8228,7 +8211,7 @@ upgrade.
| `title` | [string](#string) | | |
| `description` | [string](#string) | | |
| `plan` | [cosmos.upgrade.v1beta1.Plan](#cosmos.upgrade.v1beta1.Plan) | | |
| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | An UpgradedClientState must be provided to perform an IBC breaking upgrade. This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connected chains can verify that the new upgraded client is valid by verifying a proof of the intended new client state on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades. |
| `upgraded_client_state` | [google.protobuf.Any](#google.protobuf.Any) | | An UpgradedClientState must be provided to perform an IBC breaking upgrade. This will make the chain commit to the correct upgraded (self) client state before the upgrade occurs, so that connecting chains can verify that the new upgraded client is valid by verifying a proof on the previous version of the chain. This will allow IBC connections to persist smoothly across planned chain upgrades |



Expand Down Expand Up @@ -10945,3 +10928,4 @@ that implements Misbehaviour interface expected by ICS-02
| <a name="bool" /> bool | | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass |
| <a name="string" /> string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| <a name="bytes" /> bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |

11 changes: 11 additions & 0 deletions testutil/testdata/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"encoding/json"

"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
)

// KeyTestPubAddr generates a new secp256k1 keypair.
Expand All @@ -16,6 +18,15 @@ func KeyTestPubAddr() (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress)
return key, pub, addr
}

// KeyTestPubAddr generates a new secp256r1 keypair.
func KeyTestPubAddrSecp256R1(require *require.Assertions) (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) {
key, err := secp256r1.GenPrivKey()
require.NoError(err)
pub := key.PubKey()
addr := sdk.AccAddress(pub.Address())
return key, pub, addr
}

// NewTestFeeAmount is a test fee amount.
func NewTestFeeAmount() sdk.Coins {
return sdk.NewCoins(sdk.NewInt64Coin("atom", 150))
Expand Down
5 changes: 5 additions & 0 deletions x/auth/ante/sigverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -368,6 +369,10 @@ func DefaultSigVerificationGasConsumer(
meter.ConsumeGas(params.SigVerifyCostSecp256k1, "ante verify: secp256k1")
return nil

case *secp256r1.PubKey:
meter.ConsumeGas(params.SigVerifyCostSecp256r1(), "ante verify: secp256r1")
return nil

case multisig.PubKey:
multisignature, ok := sig.Data.(*signing.MultiSignatureData)
if !ok {
Expand Down
42 changes: 42 additions & 0 deletions x/auth/ante/sigverify_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ante_test

import (
"testing"

"github.com/stretchr/testify/require"
tmcrypto "github.com/tendermint/tendermint/crypto"

"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
)

// This benchmark is used to asses the ante.Secp256k1ToR1GasFactor value
func BenchmarkSig(b *testing.B) {
require := require.New(b)
msg := tmcrypto.CRandBytes(1000)

skK := secp256k1.GenPrivKey()
pkK := skK.PubKey()
skR, _ := secp256r1.GenPrivKey()
pkR := skR.PubKey()

sigK, err := skK.Sign(msg)
require.NoError(err)
sigR, err := skR.Sign(msg)
require.NoError(err)
b.ResetTimer()

b.Run("secp256k1", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ok := pkK.VerifySignature(msg, sigK)
require.True(ok)
}
})

b.Run("secp256r1", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ok := pkR.VerifySignature(msg, sigR)
require.True(ok)
}
})
}
31 changes: 17 additions & 14 deletions x/auth/ante/sigverify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/simapp"
Expand All @@ -21,12 +22,13 @@ import (

func (suite *AnteTestSuite) TestSetPubKey() {
suite.SetupTest(true) // setup
require := suite.Require()
suite.txBuilder = suite.clientCtx.TxConfig.NewTxBuilder()

// keys and addresses
priv1, pub1, addr1 := testdata.KeyTestPubAddr()
priv2, pub2, addr2 := testdata.KeyTestPubAddr()
priv3, pub3, addr3 := testdata.KeyTestPubAddr()
priv3, pub3, addr3 := testdata.KeyTestPubAddrSecp256R1(require)

addrs := []sdk.AccAddress{addr1, addr2, addr3}
pubs := []cryptotypes.PubKey{pub1, pub2, pub3}
Expand All @@ -35,32 +37,30 @@ func (suite *AnteTestSuite) TestSetPubKey() {
// set accounts and create msg for each address
for i, addr := range addrs {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr)
suite.Require().NoError(acc.SetAccountNumber(uint64(i)))
require.NoError(acc.SetAccountNumber(uint64(i)))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
msgs[i] = testdata.NewTestMsg(addr)
}
suite.Require().NoError(suite.txBuilder.SetMsgs(msgs...))

feeAmount := testdata.NewTestFeeAmount()
gasLimit := testdata.NewTestGasLimit()
suite.txBuilder.SetFeeAmount(feeAmount)
suite.txBuilder.SetGasLimit(gasLimit)
require.NoError(suite.txBuilder.SetMsgs(msgs...))
suite.txBuilder.SetFeeAmount(testdata.NewTestFeeAmount())
suite.txBuilder.SetGasLimit(testdata.NewTestGasLimit())

privs, accNums, accSeqs := []cryptotypes.PrivKey{priv1, priv2, priv3}, []uint64{0, 1, 2}, []uint64{0, 0, 0}
tx, err := suite.CreateTestTx(privs, accNums, accSeqs, suite.ctx.ChainID())
suite.Require().NoError(err)
require.NoError(err)

spkd := ante.NewSetPubKeyDecorator(suite.app.AccountKeeper)
antehandler := sdk.ChainAnteDecorators(spkd)

ctx, err := antehandler(suite.ctx, tx, false)
suite.Require().Nil(err)
require.NoError(err)

// Require that all accounts have pubkey set after Decorator runs
for i, addr := range addrs {
pk, err := suite.app.AccountKeeper.GetPubKey(ctx, addr)
suite.Require().Nil(err, "Error on retrieving pubkey from account")
suite.Require().Equal(pubs[i], pk, "Pubkey retrieved from account is unexpected")
require.NoError(err, "Error on retrieving pubkey from account")
require.True(pubs[i].Equals(pk),
"Wrong Pubkey retrieved from AccountKeeper, idx=%d\nexpected=%s\n got=%s", i, pubs[i], pk)
}
}

Expand All @@ -69,6 +69,8 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
msg := []byte{1, 2, 3, 4}
cdc := simapp.MakeTestEncodingConfig().Amino

p := types.DefaultParams()
skR1, _ := secp256r1.GenPrivKey()
pkSet1, sigSet1 := generatePubKeysAndSignatures(5, msg, false)
multisigKey1 := kmultisig.NewLegacyAminoPubKey(2, pkSet1)
multisignature1 := multisig.NewMultisig(len(pkSet1))
Expand All @@ -93,8 +95,9 @@ func (suite *AnteTestSuite) TestConsumeSignatureVerificationGas() {
gasConsumed uint64
shouldErr bool
}{
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostED25519, true},
{"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, types.DefaultSigVerifyCostSecp256k1, false},
{"PubKeyEd25519", args{sdk.NewInfiniteGasMeter(), nil, ed25519.GenPrivKey().PubKey(), params}, p.SigVerifyCostED25519, true},
{"PubKeySecp256k1", args{sdk.NewInfiniteGasMeter(), nil, secp256k1.GenPrivKey().PubKey(), params}, p.SigVerifyCostSecp256k1, false},
{"PubKeySecp256r1", args{sdk.NewInfiniteGasMeter(), nil, skR1.PubKey(), params}, p.SigVerifyCostSecp256r1(), false},
{"Multisig", args{sdk.NewInfiniteGasMeter(), multisignature1, multisigKey1, params}, expectedCost1, false},
{"unknown key", args{sdk.NewInfiniteGasMeter(), nil, nil, params}, 0, true},
}
Expand Down
12 changes: 12 additions & 0 deletions x/auth/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ func DefaultParams() Params {
}
}

// SigVerifyCostSecp256r1 returns gas fee of secp256r1 signature verification.
// Set by benchmarking current implementation:
// BenchmarkSig/secp256k1 4334 277167 ns/op 4128 B/op 79 allocs/op
// BenchmarkSig/secp256r1 10000 108769 ns/op 1672 B/op 33 allocs/op
// Based on the results above the factor would be 2x. However we propose to discount it and
// use 1.2x because we are comparing a highly optimized cgo implementation of secp256k1 to
// a go stdlib secp256r1. In other benchmark we found that ported secp256k1 to stdlib based
// implementation wold be 20x slower.
func (p Params) SigVerifyCostSecp256r1() uint64 {
return p.SigVerifyCostSecp256k1 * 12 / 10 // 120%
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss the fee adjustment in #8515


// String implements the stringer interface.
func (p Params) String() string {
out, _ := yaml.Marshal(p)
Expand Down