Skip to content

Commit

Permalink
feat: tendermint headers compatibility (#505)
Browse files Browse the repository at this point in the history
  • Loading branch information
omritoptix authored Oct 19, 2023
1 parent ddcbc64 commit ec633de
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ proto/pb
.DS_Store
.vscode
.idea
.go-version
build
3 changes: 2 additions & 1 deletion block/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ import (
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/merkle"
"github.com/tendermint/tendermint/libs/pubsub"
"github.com/tendermint/tendermint/proxy"
tmtypes "github.com/tendermint/tendermint/types"

"github.com/tendermint/tendermint/proxy"

"github.com/dymensionxyz/dymint/config"
"github.com/dymensionxyz/dymint/da"
"github.com/dymensionxyz/dymint/log"
Expand Down
55 changes: 55 additions & 0 deletions block/produce.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
abciconv "github.com/dymensionxyz/dymint/conv/abci"
"github.com/dymensionxyz/dymint/settlement"
"github.com/dymensionxyz/dymint/types"
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
cmtproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
tmtime "github.com/tendermint/tendermint/types/time"
)

// waitForSync enforces the aggregator to be synced before it can produce blocks.
Expand Down Expand Up @@ -156,14 +160,29 @@ func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error {
if err != nil {
return err
}
proposerAddress, err := getAddress(m.proposerKey)
if err != nil {
return err
}
sign, err := m.proposerKey.Sign(abciHeaderBytes)
if err != nil {
return err
}
voteTimestamp := tmtime.Now()
tmSignature, err := m.createTMSignature(block, proposerAddress, voteTimestamp)
if err != nil {
return err
}
commit = &types.Commit{
Height: block.Header.Height,
HeaderHash: block.Header.Hash(),
Signatures: []types.Signature{sign},
TMSignature: tmtypes.CommitSig{
BlockIDFlag: 2,
ValidatorAddress: proposerAddress,
Timestamp: voteTimestamp,
Signature: tmSignature,
},
}

}
Expand All @@ -181,3 +200,39 @@ func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error {
rollappHeightGauge.Set(float64(newHeight))
return nil
}

func (m *Manager) createTMSignature(block *types.Block, proposerAddress []byte, voteTimestamp time.Time) ([]byte, error) {
headerHash := block.Header.Hash()
vote := tmtypes.Vote{
Type: cmtproto.PrecommitType,
Height: int64(block.Header.Height),
Round: 0,
Timestamp: voteTimestamp,
BlockID: tmtypes.BlockID{Hash: headerHash[:], PartSetHeader: tmtypes.PartSetHeader{
Total: 1,
Hash: headerHash[:],
}},
ValidatorAddress: proposerAddress,
ValidatorIndex: 0,
}
v := vote.ToProto()
// convert libp2p key to tm key
raw_key, _ := m.proposerKey.Raw()
tmprivkey := tmed25519.PrivKey(raw_key)
tmprivkey.PubKey().Bytes()
// Create a mock validator to sign the vote
tmvalidator := tmtypes.NewMockPVWithParams(tmprivkey, false, false)
err := tmvalidator.SignVote(m.lastState.ChainID, v)
if err != nil {
return nil, err
}
// Update the vote with the signature
vote.Signature = v.Signature
pubKey := tmprivkey.PubKey()
voteSignBytes := tmtypes.VoteSignBytes(m.lastState.ChainID, v)
if !pubKey.VerifySignature(voteSignBytes, vote.Signature) {
return nil, fmt.Errorf("wrong signature")
}
return vote.Signature, nil

}
1 change: 1 addition & 0 deletions block/testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func getManager(conf config.BlockManagerConfig, settlementlc settlement.LayerI,
if err != nil {
return nil, err
}

// Init the settlement layer mock
if settlementlc == nil {
settlementlc = slregistry.GetClient(slregistry.Mock)
Expand Down
30 changes: 18 additions & 12 deletions conv/abci/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,28 +121,34 @@ func ToABCIBlockMeta(block *types.Block) (*tmtypes.BlockMeta, error) {
// This function only converts fields that are available in Dymint commit.
// Other fields (especially ValidatorAddress and Timestamp of Signature) has to be filled by caller.
func ToABCICommit(commit *types.Commit, header *types.Header) *tmtypes.Commit {
headerHash := header.Hash()
tmCommit := tmtypes.Commit{
Height: int64(commit.Height),
Round: 0,
BlockID: tmtypes.BlockID{
Hash: commit.HeaderHash[:],
Hash: headerHash[:],
PartSetHeader: tmtypes.PartSetHeader{
Total: 1,
Hash: commit.HeaderHash[:],
Hash: headerHash[:],
},
},
}
for _, sig := range commit.Signatures {
commitSig := tmtypes.CommitSig{
BlockIDFlag: tmtypes.BlockIDFlagCommit,
Signature: sig,
// Check if TMSignature exists. if not use the previous dymint signature for backwards compatibility.
if len(commit.TMSignature.Signature) == 0 {
for _, sig := range commit.Signatures {
commitSig := tmtypes.CommitSig{
BlockIDFlag: tmtypes.BlockIDFlagCommit,
Signature: sig,
}
tmCommit.Signatures = append(tmCommit.Signatures, commitSig)
}
tmCommit.Signatures = append(tmCommit.Signatures, commitSig)
}
// This assumes that we have only one signature
if len(commit.Signatures) == 1 {
tmCommit.Signatures[0].ValidatorAddress = header.ProposerAddress
tmCommit.Signatures[0].Timestamp = time.Unix(0, int64(header.Time))
// This assumes that we have only one signature
if len(commit.Signatures) == 1 {
tmCommit.Signatures[0].ValidatorAddress = header.ProposerAddress
tmCommit.Signatures[0].Timestamp = time.Unix(0, int64(header.Time))
}
} else {
tmCommit.Signatures = append(tmCommit.Signatures, commit.TMSignature)
}

return &tmCommit
Expand Down
2 changes: 2 additions & 0 deletions proto/types/dymint/dymint.proto
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ syntax = "proto3";
package dymint;
option go_package = "github.com/dymensionxyz/dymint/types/pb/dymint";
import "types/tendermint/abci/types.proto";
import "types/tendermint/types/types.proto";

// Version captures the consensus rules for processing a block in the blockchain,
// including all blockchain data structures and the rules of the application's
Expand Down Expand Up @@ -63,6 +64,7 @@ message Commit {
bytes header_hash = 2;
// Note: most of the time this will be a single sinature
repeated bytes signatures = 3;
tendermint.types.CommitSig tm_signature = 4;
}

message Data {
Expand Down
5 changes: 4 additions & 1 deletion types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package types

import (
"encoding"

tmtypes "github.com/tendermint/tendermint/types"
)

// Header defines the structure of Dymint block header.
Expand Down Expand Up @@ -82,7 +84,8 @@ type Commit struct {
Height uint64
HeaderHash [32]byte
// TODO(omritoptix): Change from []Signature to Signature as it should be one signature per block
Signatures []Signature
Signatures []Signature
TMSignature tmtypes.CommitSig
}

// Signature represents signature of block creator.
Expand Down
Loading

0 comments on commit ec633de

Please sign in to comment.