Skip to content

Commit

Permalink
Added signed header verification (cosmos#1026)
Browse files Browse the repository at this point in the history
<!--
Please read and fill out this form before submitting your PR.

Please make sure you have reviewed our contributors guide before
submitting your
first PR.
-->

## Overview
Resolves: cosmos#1027, Resolves: cosmos#1048
<!-- 
Please provide an explanation of the PR, including the appropriate
context,
background, goal, and rationale. If there is an issue with this
information,
please provide a tl;dr and link the issue. 
-->

## Checklist

<!-- 
Please complete the checklist to ensure that the PR is ready to be
reviewed.

IMPORTANT:
PRs should be left in Draft until the below checklist is completed.
-->

- [x] New and updated code has appropriate documentation
- [x] New and updated code has new and/or updated testing
- [x] Required CI checks are passing
- [x] Visual proof for any user facing features like CLI or
documentation updates
- [x] Linked issues closed with keywords
  • Loading branch information
Manav-Aggarwal authored Jul 3, 2023
1 parent 4c951e4 commit dd5e371
Show file tree
Hide file tree
Showing 15 changed files with 377 additions and 227 deletions.
18 changes: 3 additions & 15 deletions block/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
tmtypes "github.com/tendermint/tendermint/types"

Expand All @@ -29,9 +28,9 @@ func TestInitialState(t *testing.T) {
ChainID: "state id",
InitialHeight: 123,
LastBlockHeight: 128,
LastValidators: getRandomValidatorSet(),
Validators: getRandomValidatorSet(),
NextValidators: getRandomValidatorSet(),
LastValidators: types.GetRandomValidatorSet(),
Validators: types.GetRandomValidatorSet(),
NextValidators: types.GetRandomValidatorSet(),
}

ctx := context.Background()
Expand Down Expand Up @@ -97,14 +96,3 @@ func getMockDALC(logger log.Logger) da.DataAvailabilityLayerClient {
_ = dalc.Start()
return dalc
}

// copied from store_test.go
func getRandomValidatorSet() *tmtypes.ValidatorSet {
pubKey := ed25519.GenPrivKey().PubKey()
return &tmtypes.ValidatorSet{
Proposer: &tmtypes.Validator{PubKey: pubKey, Address: pubKey.Address()},
Validators: []*tmtypes.Validator{
{PubKey: pubKey, Address: pubKey.Address()},
},
}
}
25 changes: 1 addition & 24 deletions conv/abci/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func ToABCIBlock(block *types.Block) (*tmtypes.Block, error) {
if err != nil {
return nil, err
}
abciCommit := ToABCICommit(&block.SignedHeader.Commit, block.SignedHeader.Header.BaseHeader.Height, block.SignedHeader.Hash())
abciCommit := block.SignedHeader.Commit.ToABCICommit(int64(block.SignedHeader.Header.BaseHeader.Height), block.SignedHeader.Hash())
// This assumes that we have only one signature
if len(abciCommit.Signatures) == 1 {
abciCommit.Signatures[0].ValidatorAddress = block.SignedHeader.Header.ProposerAddress
Expand Down Expand Up @@ -112,26 +112,3 @@ func ToABCIBlockMeta(block *types.Block) (*tmtypes.BlockMeta, error) {
NumTxs: len(tmblock.Txs),
}, nil
}

// ToABCICommit converts Rollkit commit into commit format defined by ABCI.
// This function only converts fields that are available in Rollkit commit.
// Other fields (especially ValidatorAddress and Timestamp of Signature) has to be filled by caller.
func ToABCICommit(commit *types.Commit, height uint64, hash types.Hash) *tmtypes.Commit {
tmCommit := tmtypes.Commit{
Height: int64(height),
Round: 0,
BlockID: tmtypes.BlockID{
Hash: tmbytes.HexBytes(hash),
PartSetHeader: tmtypes.PartSetHeader{},
},
}
for _, sig := range commit.Signatures {
commitSig := tmtypes.CommitSig{
BlockIDFlag: tmtypes.BlockIDFlagCommit,
Signature: sig,
}
tmCommit.Signatures = append(tmCommit.Signatures, commitSig)
}

return &tmCommit
}
18 changes: 3 additions & 15 deletions da/test/da_test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package test

import (
"fmt"
"math/rand"
"net"
"os"
"strconv"
Expand All @@ -20,17 +19,6 @@ import (

const mockDaBlockTime = 100 * time.Millisecond

func getRandomTx() types.Tx {
size := rand.Int()%100 + 100 //nolint:gosec
return types.Tx(getRandomBytes(size))
}

func getRandomBytes(n int) []byte {
data := make([]byte, n)
_, _ = rand.Read(data) //nolint:gosec
return data
}

// copy-pasted from store/store_test.go
func getRandomBlock(height uint64, nTxs int) *types.Block {
block := &types.Block{
Expand All @@ -48,11 +36,11 @@ func getRandomBlock(height uint64, nTxs int) *types.Block {
},
},
}
block.SignedHeader.Header.AppHash = getRandomBytes(32)
block.SignedHeader.Header.AppHash = types.GetRandomBytes(32)

for i := 0; i < nTxs; i++ {
block.Data.Txs[i] = getRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = getRandomBytes(32)
block.Data.Txs[i] = types.GetRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = types.GetRandomBytes(32)
}

// TODO(tzdybal): see https://github.com/rollkit/rollkit/issues/143
Expand Down
2 changes: 1 addition & 1 deletion node/full_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ func (c *FullClient) Commit(ctx context.Context, height *int64) (*ctypes.ResultC
if err != nil {
return nil, err
}
commit := abciconv.ToABCICommit(com, heightValue, b.SignedHeader.Hash())
commit := com.ToABCICommit(int64(heightValue), b.SignedHeader.Hash())
block, err := abciconv.ToABCIBlock(b)
if err != nil {
return nil, err
Expand Down
33 changes: 5 additions & 28 deletions node/full_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
crand "crypto/rand"
"fmt"
"math/rand"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -45,20 +44,9 @@ var expectedInfo = abci.ResponseInfo{

var mockTxProcessingTime = 10 * time.Millisecond

// TODO: accept argument for number of validators / proposer index
func getRandomValidatorSet() *tmtypes.ValidatorSet {
pubKey := ed25519.GenPrivKey().PubKey()
return &tmtypes.ValidatorSet{
Proposer: &tmtypes.Validator{PubKey: pubKey, Address: pubKey.Address()},
Validators: []*tmtypes.Validator{
{PubKey: pubKey, Address: pubKey.Address()},
},
}
}

// copy-pasted from store/store_test.go
func getRandomBlock(height uint64, nTxs int) *types.Block {
return getRandomBlockWithProposer(height, nTxs, getRandomBytes(20))
return getRandomBlockWithProposer(height, nTxs, types.GetRandomBytes(20))
}

func getRandomBlockWithProposer(height uint64, nTxs int, proposerAddr []byte) *types.Block {
Expand All @@ -79,11 +67,11 @@ func getRandomBlockWithProposer(height uint64, nTxs int, proposerAddr []byte) *t
},
},
}
block.SignedHeader.Header.AppHash = getRandomBytes(32)
block.SignedHeader.Header.AppHash = types.GetRandomBytes(32)

for i := 0; i < nTxs; i++ {
block.Data.Txs[i] = getRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = getRandomBytes(32)
block.Data.Txs[i] = types.GetRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = types.GetRandomBytes(32)
}

// TODO(tzdybal): see https://github.com/rollkit/rollkit/issues/143
Expand All @@ -100,22 +88,11 @@ func getRandomBlockWithProposer(height uint64, nTxs int, proposerAddr []byte) *t
copy(lastCommitHash, tmprotoLC.Hash().Bytes())
block.SignedHeader.Header.LastCommitHash = lastCommitHash

block.SignedHeader.Validators = getRandomValidatorSet()
block.SignedHeader.Validators = types.GetRandomValidatorSet()

return block
}

func getRandomTx() types.Tx {
size := rand.Int()%100 + 100 //nolint:gosec
return types.Tx(getRandomBytes(size))
}

func getRandomBytes(n int) []byte {
data := make([]byte, n)
_, _ = crand.Read(data)
return data
}

func getBlockMeta(rpc *FullClient, n int64) *tmtypes.BlockMeta {
b, err := rpc.node.Store.LoadBlock(uint64(n))
if err != nil {
Expand Down
11 changes: 1 addition & 10 deletions state/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func (e *BlockExecutor) CreateBlock(height uint64, lastCommit *types.Commit, las
// Evidence: types.EvidenceData{Evidence: nil},
},
}
block.SignedHeader.Header.LastCommitHash = e.getLastCommitHash(lastCommit, &block.SignedHeader.Header)
block.SignedHeader.Header.LastCommitHash = lastCommit.GetCommitHash(&block.SignedHeader.Header, e.proposerAddress)
block.SignedHeader.Header.LastHeaderHash = lastHeaderHash
block.SignedHeader.Header.AggregatorsHash = state.Validators.Hash()

Expand Down Expand Up @@ -475,15 +475,6 @@ func (e *BlockExecutor) generateFraudProof(beginBlockRequest *abci.RequestBeginB
return resp.FraudProof, nil
}

func (e *BlockExecutor) getLastCommitHash(lastCommit *types.Commit, header *types.Header) []byte {
lastABCICommit := abciconv.ToABCICommit(lastCommit, header.BaseHeader.Height, header.Hash())
if len(lastCommit.Signatures) == 1 {
lastABCICommit.Signatures[0].ValidatorAddress = e.proposerAddress
lastABCICommit.Signatures[0].Timestamp = header.Time()
}
return lastABCICommit.Hash()
}

func (e *BlockExecutor) publishEvents(resp *tmstate.ABCIResponses, block *types.Block, state types.State) error {
if e.eventBus == nil {
return nil
Expand Down
4 changes: 2 additions & 2 deletions store/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func TestStoreLoad(t *testing.T) {
for _, block := range c.blocks {
commit := &types.Commit{}
block.SignedHeader.Commit = *lastCommit
block.SignedHeader.Validators = getRandomValidatorSet()
block.SignedHeader.Validators = types.GetRandomValidatorSet()
err := bstore.SaveBlock(block, commit)
require.NoError(err)
lastCommit = commit
Expand All @@ -127,7 +127,7 @@ func TestRestart(t *testing.T) {

assert := assert.New(t)

validatorSet := getRandomValidatorSet()
validatorSet := types.GetRandomValidatorSet()

ctx := context.Background()
kv, _ := NewDefaultInMemoryKVStore()
Expand Down
31 changes: 2 additions & 29 deletions store/test_helpers.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package store

import (
"math/rand"

"github.com/tendermint/tendermint/crypto/ed25519"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/rollkit/rollkit/types"
)

Expand All @@ -27,31 +22,9 @@ func getRandomBlock(height uint64, nTxs int) *types.Block {
}

for i := 0; i < nTxs; i++ {
block.Data.Txs[i] = getRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = getRandomBytes(32)
block.Data.Txs[i] = types.GetRandomTx()
block.Data.IntermediateStateRoots.RawRootsList[i] = types.GetRandomBytes(32)
}

return block
}

func getRandomTx() types.Tx {
size := rand.Int()%100 + 100 //nolint:gosec
return types.Tx(getRandomBytes(size))
}

func getRandomBytes(n int) []byte {
data := make([]byte, n)
_, _ = rand.Read(data) //nolint:gosec
return data
}

// TODO(tzdybal): extract to some common place
func getRandomValidatorSet() *tmtypes.ValidatorSet {
pubKey := ed25519.GenPrivKey().PubKey()
return &tmtypes.ValidatorSet{
Proposer: &tmtypes.Validator{PubKey: pubKey, Address: pubKey.Address()},
Validators: []*tmtypes.Validator{
{PubKey: pubKey, Address: pubKey.Address()},
},
}
}
63 changes: 63 additions & 0 deletions types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package types

import (
"encoding"
"errors"

"fmt"
"time"

tmbytes "github.com/tendermint/tendermint/libs/bytes"

"github.com/celestiaorg/go-header"
tmtypes "github.com/tendermint/tendermint/types"
)
Expand Down Expand Up @@ -65,6 +69,65 @@ type IntermediateStateRoots struct {
RawRootsList [][]byte
}

// ToABCICommit converts Rollkit commit into commit format defined by ABCI.
// This function only converts fields that are available in Rollkit commit.
// Other fields (especially ValidatorAddress and Timestamp of Signature) has to be filled by caller.
func (c *Commit) ToABCICommit(height int64, hash Hash) *tmtypes.Commit {
tmCommit := tmtypes.Commit{
Height: height,
Round: 0,
BlockID: tmtypes.BlockID{
Hash: tmbytes.HexBytes(hash),
PartSetHeader: tmtypes.PartSetHeader{},
},
Signatures: make([]tmtypes.CommitSig, len(c.Signatures)),
}
for i, sig := range c.Signatures {
commitSig := tmtypes.CommitSig{
BlockIDFlag: tmtypes.BlockIDFlagCommit,
Signature: sig,
}
tmCommit.Signatures[i] = commitSig
}

return &tmCommit
}

func (c *Commit) GetCommitHash(header *Header, proposerAddress []byte) []byte {
lastABCICommit := c.ToABCICommit(header.Height(), header.Hash())
// Rollkit does not support a multi signature scheme so there can only be one signature
if len(c.Signatures) == 1 {
lastABCICommit.Signatures[0].ValidatorAddress = proposerAddress
lastABCICommit.Signatures[0].Timestamp = header.Time()
}
return lastABCICommit.Hash()
}

// ValidateBasic performs basic validation of block data.
// Actually it's a placeholder, because nothing is checked.
func (d *Data) ValidateBasic() error {
return nil
}

// ValidateBasic performs basic validation of a commit.
func (c *Commit) ValidateBasic() error {
if len(c.Signatures) == 0 {
return errors.New("no signatures")
}
return nil
}

// ValidateBasic performs basic validation of a block.
func (b *Block) ValidateBasic() error {
if err := b.SignedHeader.ValidateBasic(); err != nil {
return err
}
if err := b.Data.ValidateBasic(); err != nil {
return err
}
return nil
}

func (b *Block) New() header.Header {
return new(Block)
}
Expand Down
10 changes: 10 additions & 0 deletions types/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package types

import (
"encoding"
"errors"
"fmt"
"time"

Expand Down Expand Up @@ -145,6 +146,15 @@ func verifyNewHeaderAndVals(trusted, untrusted *Header) error {
return nil
}

// ValidateBasic performs basic validation of a header.
func (h *Header) ValidateBasic() error {
if len(h.ProposerAddress) == 0 {
return errors.New("no proposer address")
}

return nil
}

var _ header.Header = &Header{}
var _ encoding.BinaryMarshaler = &Header{}
var _ encoding.BinaryUnmarshaler = &Header{}
Loading

0 comments on commit dd5e371

Please sign in to comment.