Skip to content

Commit

Permalink
manager: use validator set from state (cosmos#814)
Browse files Browse the repository at this point in the history
This PR changes the signed header to use validator set from last state.

Tests needed to be updated to use at least one validator (because
`ValidateBasic` now fails if there's nil validators). Since they need to
be able to handle multiple validators anyway, we're passing 2 validators
for now.

Fixes cosmos#812
  • Loading branch information
tuxcanfly authored Mar 28, 2023
1 parent d450698 commit 6a8b5d8
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 50 deletions.
15 changes: 1 addition & 14 deletions block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/libp2p/go-libp2p/core/crypto"
abci "github.com/tendermint/tendermint/abci/types"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/proxy"
tmtypes "github.com/tendermint/tendermint/types"
Expand Down Expand Up @@ -494,19 +493,7 @@ func (m *Manager) publishBlock(ctx context.Context) error {
// set the commit to current block's signed header
block.SignedHeader.Commit = *commit

// set the validator set using the signer's public key
// TODO(ganesh): need to hook into a module that selects signers
pubKeyRaw, err := m.proposerKey.GetPublic().Raw()
if err != nil {
return err
}
pubKey := ed25519.PubKey(pubKeyRaw)
proposer := &tmtypes.Validator{Address: pubKey.Address(), PubKey: pubKey}
// TODO: read staking query to construct validators
block.SignedHeader.Validators = &tmtypes.ValidatorSet{
Validators: []*tmtypes.Validator{proposer},
Proposer: proposer,
}
block.SignedHeader.Validators = m.lastState.Validators

// SaveBlock commits the DB tx
err = m.store.SaveBlock(block, commit)
Expand Down
40 changes: 28 additions & 12 deletions node/full_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/tendermint/tendermint/version"

"github.com/rollkit/rollkit/config"
"github.com/rollkit/rollkit/conv"
abciconv "github.com/rollkit/rollkit/conv/abci"
"github.com/rollkit/rollkit/mocks"
"github.com/rollkit/rollkit/types"
Expand All @@ -53,6 +54,21 @@ func getRandomValidatorSet() *tmtypes.ValidatorSet {
}
}

// TODO: use n and return n validators
func getGenesisValidatorSetWithSigner(n int) ([]tmtypes.GenesisValidator, crypto.PrivKey) {
validatorKey := ed25519.GenPrivKey()
nodeKey := &p2p.NodeKey{
PrivKey: validatorKey,
}
signingKey, _ := conv.GetNodeKey(nodeKey)
pubKey := validatorKey.PubKey()

genesisValidators := []tmtypes.GenesisValidator{
{Address: pubKey.Address(), PubKey: pubKey, Power: int64(100), Name: "gen #1"},
}
return genesisValidators, signingKey
}

func TestConnectionGetter(t *testing.T) {
assert := assert.New(t)

Expand Down Expand Up @@ -410,15 +426,7 @@ func TestTx(t *testing.T) {
mockApp := &mocks.Application{}
mockApp.On("InitChain", mock.Anything).Return(abci.ResponseInitChain{})
key, _, _ := crypto.GenerateEd25519Key(crand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(crand.Reader)

vKeys := make([]tmcrypto.PrivKey, 4)
genesisValidators := make([]tmtypes.GenesisValidator, len(vKeys))
for i := 0; i < len(vKeys); i++ {
vKeys[i] = ed25519.GenPrivKey()
genesisValidators[i] = tmtypes.GenesisValidator{Address: vKeys[i].PubKey().Address(), PubKey: vKeys[i].PubKey(), Power: int64(i + 100), Name: fmt.Sprintf("genesis validator #%d", i)}
}

genesisValidators, signingKey := getGenesisValidatorSetWithSigner(1)
node, err := newFullNode(context.Background(), config.NodeConfig{
DALayer: "mock",
Aggregator: true,
Expand Down Expand Up @@ -640,6 +648,9 @@ func TestBlockchainInfo(t *testing.T) {
}

func TestValidatorSetHandling(t *testing.T) {
// handle multiple sequencers
t.Skip()

assert := assert.New(t)
require := require.New(t)
app := &mocks.Application{}
Expand All @@ -651,14 +662,18 @@ func TestValidatorSetHandling(t *testing.T) {
app.On("GenerateFraudProof", mock.Anything).Return(abci.ResponseGenerateFraudProof{})

key, _, _ := crypto.GenerateEd25519Key(crand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(crand.Reader)

vKeys := make([]tmcrypto.PrivKey, 4)
genesisValidators := make([]tmtypes.GenesisValidator, len(vKeys))
for i := 0; i < len(vKeys); i++ {
vKeys[i] = ed25519.GenPrivKey()
genesisValidators[i] = tmtypes.GenesisValidator{Address: vKeys[i].PubKey().Address(), PubKey: vKeys[i].PubKey(), Power: int64(i + 100), Name: "one"}
genesisValidators[i] = tmtypes.GenesisValidator{Address: vKeys[i].PubKey().Address(), PubKey: vKeys[i].PubKey(), Power: int64(i + 100), Name: fmt.Sprintf("gen #%d", i)}
}

nodeKey := &p2p.NodeKey{
PrivKey: vKeys[0],
}
signingKey, _ := conv.GetNodeKey(nodeKey)

pbValKey, err := encoding.PubKeyToProto(vKeys[0].PubKey())
require.NoError(err)
Expand Down Expand Up @@ -1072,7 +1087,7 @@ func TestFutureGenesisTime(t *testing.T) {
mockApp.On("DeliverTx", mock.Anything).Return(abci.ResponseDeliverTx{})
mockApp.On("CheckTx", mock.Anything).Return(abci.ResponseCheckTx{})
key, _, _ := crypto.GenerateEd25519Key(crand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(crand.Reader)
genesisValidators, signingKey := getGenesisValidatorSetWithSigner(1)
genesisTime := time.Now().Local().Add(time.Second * time.Duration(1))
node, err := newFullNode(context.Background(), config.NodeConfig{
DALayer: "mock",
Expand All @@ -1086,6 +1101,7 @@ func TestFutureGenesisTime(t *testing.T) {
ChainID: "test",
InitialHeight: 1,
GenesisTime: genesisTime,
Validators: genesisValidators,
},
log.TestingLogger())
require.NoError(err)
Expand Down
14 changes: 6 additions & 8 deletions node/full_node_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,13 @@ func TestAggregatorMode(t *testing.T) {
app.On("GetAppHash", mock.Anything).Return(abci.ResponseGetAppHash{})

key, _, _ := crypto.GenerateEd25519Key(rand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(rand.Reader)
anotherKey, _, _ := crypto.GenerateEd25519Key(rand.Reader)

genesisValidators, signingKey := getGenesisValidatorSetWithSigner(1)
blockManagerConfig := config.BlockManagerConfig{
BlockTime: 1 * time.Second,
NamespaceID: types.NamespaceID{1, 2, 3, 4, 5, 6, 7, 8},
}
node, err := newFullNode(context.Background(), config.NodeConfig{DALayer: "mock", Aggregator: true, BlockManagerConfig: blockManagerConfig}, key, signingKey, abcicli.NewLocalClient(nil, app), &tmtypes.GenesisDoc{ChainID: "test"}, log.TestingLogger())
node, err := newFullNode(context.Background(), config.NodeConfig{DALayer: "mock", Aggregator: true, BlockManagerConfig: blockManagerConfig}, key, signingKey, abcicli.NewLocalClient(nil, app), &tmtypes.GenesisDoc{ChainID: "test", Validators: genesisValidators}, log.TestingLogger())
require.NoError(err)
require.NotNil(node)

Expand Down Expand Up @@ -147,8 +146,7 @@ func TestLazyAggregator(t *testing.T) {
app.On("GetAppHash", mock.Anything).Return(abci.ResponseGetAppHash{})

key, _, _ := crypto.GenerateEd25519Key(rand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(rand.Reader)

genesisValidators, signingKey := getGenesisValidatorSetWithSigner(1)
blockManagerConfig := config.BlockManagerConfig{
BlockTime: 1 * time.Second,
NamespaceID: types.NamespaceID{1, 2, 3, 4, 5, 6, 7, 8},
Expand All @@ -159,7 +157,7 @@ func TestLazyAggregator(t *testing.T) {
Aggregator: true,
BlockManagerConfig: blockManagerConfig,
LazyAggregator: true,
}, key, signingKey, abcicli.NewLocalClient(nil, app), &tmtypes.GenesisDoc{ChainID: "test"}, log.TestingLogger())
}, key, signingKey, abcicli.NewLocalClient(nil, app), &tmtypes.GenesisDoc{ChainID: "test", Validators: genesisValidators}, log.TestingLogger())
assert.False(node.IsRunning())
assert.NoError(err)
err = node.Start()
Expand Down Expand Up @@ -536,7 +534,7 @@ func createNode(ctx context.Context, n int, isMalicious bool, aggregator bool, d
ctx = context.Background()
}

signingKey, _, _ := crypto.GenerateEd25519Key(rand.Reader)
genesisValidators, signingKey := getGenesisValidatorSetWithSigner(1)
node, err := newFullNode(
ctx,
config.NodeConfig{
Expand All @@ -548,7 +546,7 @@ func createNode(ctx context.Context, n int, isMalicious bool, aggregator bool, d
keys[n],
signingKey,
abcicli.NewLocalClient(nil, app),
&tmtypes.GenesisDoc{ChainID: "test"},
&tmtypes.GenesisDoc{ChainID: "test", Validators: genesisValidators},
log.TestingLogger().With("node", n))
require.NoError(err)
require.NotNil(node)
Expand Down
18 changes: 15 additions & 3 deletions rpc/json/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ import (
"github.com/libp2p/go-libp2p/core/crypto"
abciclient "github.com/tendermint/tendermint/abci/client"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/p2p"
rpcclient "github.com/tendermint/tendermint/rpc/client"
"github.com/tendermint/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/rollkit/rollkit/config"
"github.com/rollkit/rollkit/conv"
"github.com/rollkit/rollkit/mocks"
"github.com/rollkit/rollkit/node"
)
Expand Down Expand Up @@ -291,8 +294,17 @@ func getRPC(t *testing.T) (*mocks.Application, rpcclient.Client) {
LastBlockAppHash: nil,
})
key, _, _ := crypto.GenerateEd25519Key(rand.Reader)
signingKey, _, _ := crypto.GenerateEd25519Key(rand.Reader)
n, err := node.NewNode(context.Background(), config.NodeConfig{Aggregator: true, DALayer: "mock", BlockManagerConfig: config.BlockManagerConfig{BlockTime: 1 * time.Second}, Light: false}, key, signingKey, abciclient.NewLocalClient(nil, app), &types.GenesisDoc{ChainID: "test"}, log.TestingLogger())
validatorKey := ed25519.GenPrivKey()
nodeKey := &p2p.NodeKey{
PrivKey: validatorKey,
}
signingKey, _ := conv.GetNodeKey(nodeKey)
pubKey := validatorKey.PubKey()

genesisValidators := []tmtypes.GenesisValidator{
{Address: pubKey.Address(), PubKey: pubKey, Power: int64(100), Name: "gen #1"},
}
n, err := node.NewNode(context.Background(), config.NodeConfig{Aggregator: true, DALayer: "mock", BlockManagerConfig: config.BlockManagerConfig{BlockTime: 1 * time.Second}, Light: false}, key, signingKey, abciclient.NewLocalClient(nil, app), &tmtypes.GenesisDoc{ChainID: "test", Validators: genesisValidators}, log.TestingLogger())
require.NoError(err)
require.NotNil(n)

Expand Down
25 changes: 12 additions & 13 deletions types/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,20 @@ func (h *SignedHeader) ValidateBasic() error {
return err
}

// Make sure there are as many signatures as validators
if len(h.Commit.Signatures) != len(h.Validators.Validators) {
return errors.New("number of signatures and keys don't match")
// Make sure there is exactly one signature
if len(h.Commit.Signatures) != 1 {
return errors.New("expected exactly one signature")
}

for i, val := range h.Validators.Validators {
sig := h.Commit.Signatures[i]
var pubKey ed25519.PubKey = val.PubKey.Bytes()
msg, err := h.Header.MarshalBinary()
if err != nil {
return errors.New("signature verification failed, unable to marshal header")
}
if !pubKey.VerifySignature(msg, sig) {
return errors.New("signature verification failed")
}
signature := h.Commit.Signatures[0]
proposer := h.Validators.GetProposer()
var pubKey ed25519.PubKey = proposer.PubKey.Bytes()
msg, err := h.Header.MarshalBinary()
if err != nil {
return errors.New("signature verification failed, unable to marshal header")
}
if !pubKey.VerifySignature(msg, signature) {
return errors.New("signature verification failed")
}

return nil
Expand Down

0 comments on commit 6a8b5d8

Please sign in to comment.