From 55a8bd375f4b86743509822bf2778144c505c686 Mon Sep 17 00:00:00 2001 From: Daniel T <30197399+danwt@users.noreply.github.com> Date: Fri, 20 Dec 2024 14:51:18 +0000 Subject: [PATCH] fix(cons messages): include in header hash for fraud protection (#1288) --- block/executor.go | 2 + block/executor_test.go | 63 ++++++++ block/signature_test.go | 70 +++++++++ da/celestia/celestia_test.go | 3 +- da/da_test.go | 3 +- proto/types/dymint/dymint.proto | 4 + rpc/client/client_test.go | 9 +- testutil/types.go | 28 ++-- types/block.go | 6 + types/conv.go | 5 +- types/dym_header.go | 56 ++++++++ types/errors.go | 30 +++- types/pb/dymint/dymint.pb.go | 174 ++++++++++++++-------- types/serialization.go | 39 ++--- types/serialization_test.go | 21 +-- types/validation.go | 23 ++- types/validation_test.go | 246 ++++++++++++++++++-------------- 17 files changed, 565 insertions(+), 217 deletions(-) create mode 100644 block/signature_test.go create mode 100644 types/dym_header.go diff --git a/block/executor.go b/block/executor.go index f3a1421c5..ae04398d9 100644 --- a/block/executor.go +++ b/block/executor.go @@ -171,6 +171,8 @@ func (e *Executor) CreateBlock( }, LastCommit: *lastCommit, } + + block.Header.SetDymHeader(types.MakeDymHeader(block.Data.ConsensusMessages)) copy(block.Header.LastCommitHash[:], types.GetLastCommitHash(lastCommit, &block.Header)) copy(block.Header.DataHash[:], types.GetDataHash(block)) copy(block.Header.SequencerHash[:], state.GetProposerHash()) diff --git a/block/executor_test.go b/block/executor_test.go index c40e4af2b..369b38016 100644 --- a/block/executor_test.go +++ b/block/executor_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + pb "github.com/dymensionxyz/dymint/types/pb/dymint" "github.com/gogo/protobuf/proto" prototypes "github.com/gogo/protobuf/types" "github.com/golang/groupcache/testpb" @@ -86,8 +87,40 @@ func TestCreateBlock(t *testing.T) { err = mpool.CheckTx(make([]byte, 100), func(r *abci.Response) {}, mempool.TxInfo{}) require.NoError(err) block = executor.CreateBlock(3, &types.Commit{}, [32]byte{}, [32]byte(state.GetProposerHash()), state, maxBytes) + block.Data.ToProto() require.NotNil(block) assert.Len(block.Data.Txs, 2) + + // native -> proto -> binary -> proto -> native + var b1 = block + require.NoError(b1.ValidateBasic()) + b1p1 := b1.ToProto() + b1p1bz, err := b1p1.Marshal() + require.NoError(err) + var b1p2 pb.Block + err = proto.Unmarshal(b1p1bz, &b1p2) + require.NoError(err) + var b2 types.Block + err = b2.FromProto(&b1p2) + require.NoError(err) + require.NoError(b2.ValidateBasic()) + + // same + b1bz, err := b1.MarshalBinary() + require.NoError(err) + var b3 types.Block + err = b3.UnmarshalBinary(b1bz) + require.NoError(err) + require.NoError(b3.ValidateBasic()) + + // only to proto + require.NoError(b1.ValidateBasic()) + b1p3 := b1.ToProto() + var b4 types.Block + err = b4.FromProto(b1p3) + require.NoError(err) + require.NoError(b4.ValidateBasic()) + } func TestCreateBlockWithConsensusMessages(t *testing.T) { @@ -160,6 +193,36 @@ func TestCreateBlockWithConsensusMessages(t *testing.T) { assert.True(proto.Equal(anyMsg1, block.Data.ConsensusMessages[0])) assert.True(proto.Equal(anyMsg2, block.Data.ConsensusMessages[1])) + + // native -> proto -> binary -> proto -> native + var b1 = block + require.NoError(b1.ValidateBasic()) + b1p1 := b1.ToProto() + b1p1bz, err := b1p1.Marshal() + require.NoError(err) + var b1p2 pb.Block + err = proto.Unmarshal(b1p1bz, &b1p2) + require.NoError(err) + var b2 types.Block + err = b2.FromProto(&b1p2) + require.NoError(err) + require.NoError(b2.ValidateBasic()) + + // same + b1bz, err := b1.MarshalBinary() + require.NoError(err) + var b3 types.Block + err = b3.UnmarshalBinary(b1bz) + require.NoError(err) + require.NoError(b3.ValidateBasic()) + + // only to proto + require.NoError(b1.ValidateBasic()) + b1p3 := b1.ToProto() + var b4 types.Block + err = b4.FromProto(b1p3) + require.NoError(err) + require.NoError(b4.ValidateBasic()) } func TestApplyBlock(t *testing.T) { diff --git a/block/signature_test.go b/block/signature_test.go new file mode 100644 index 000000000..94346b491 --- /dev/null +++ b/block/signature_test.go @@ -0,0 +1,70 @@ +package block_test + +import ( + "context" + "testing" + + proto "github.com/gogo/protobuf/types" + + "github.com/dymensionxyz/dymint/block" + "github.com/dymensionxyz/dymint/p2p" + "github.com/dymensionxyz/dymint/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/proxy" +) + +// produce a block, mutate it, confirm the sig check fails +func TestProduceNewBlockMutation(t *testing.T) { + // Init app + app := testutil.GetAppMock(testutil.Commit, testutil.EndBlock) + commitHash := [32]byte{1} + app.On("Commit", mock.Anything).Return(abci.ResponseCommit{Data: commitHash[:]}) + app.On("EndBlock", mock.Anything).Return(abci.ResponseEndBlock{ + RollappParamUpdates: &abci.RollappParams{ + Da: "mock", + DrsVersion: 0, + }, + ConsensusParamUpdates: &abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxGas: 40000000, + MaxBytes: 500000, + }, + }, + }) + // Create proxy app + clientCreator := proxy.NewLocalClientCreator(app) + proxyApp := proxy.NewAppConns(clientCreator) + err := proxyApp.Start() + require.NoError(t, err) + // Init manager + manager, err := testutil.GetManager(testutil.GetManagerConfig(), nil, 1, 1, 0, proxyApp, nil) + require.NoError(t, err) + // Produce block + b, c, err := manager.ProduceApplyGossipBlock(context.Background(), block.ProduceBlockOptions{AllowEmpty: true}) + require.NoError(t, err) + // Validate state is updated with the commit hash + assert.Equal(t, uint64(1), manager.State.Height()) + assert.Equal(t, commitHash, manager.State.AppHash) + + err = b.ValidateBasic() + require.NoError(t, err) + + // TODO: better way to write test is to clone the block and commit and check a table of mutations + bd := p2p.BlockData{ + Block: *b, + Commit: *c, + } + err = bd.Validate(manager.State.GetProposerPubKey()) + require.NoError(t, err) + + b.Data.ConsensusMessages = []*proto.Any{{}} + bd = p2p.BlockData{ + Block: *b, + Commit: *c, + } + err = bd.Validate(manager.State.GetProposerPubKey()) + require.Error(t, err) +} diff --git a/da/celestia/celestia_test.go b/da/celestia/celestia_test.go index 34eab5c8d..01b24928b 100644 --- a/da/celestia/celestia_test.go +++ b/da/celestia/celestia_test.go @@ -319,7 +319,8 @@ func compareBatches(t *testing.T, b1, b2 *types.Batch) { func getRandomBlock(height uint64, nTxs int) *types.Block { block := &types.Block{ Header: types.Header{ - Height: height, + Height: height, + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: make(types.Txs, nTxs), diff --git a/da/da_test.go b/da/da_test.go index ac7f084da..e37492f0b 100644 --- a/da/da_test.go +++ b/da/da_test.go @@ -209,7 +209,8 @@ func doTestRetrieve(t *testing.T, dalc da.DataAvailabilityLayerClient) { func getRandomBlock(height uint64, nTxs int) *types.Block { block := &types.Block{ Header: types.Header{ - Height: height, + Height: height, + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: make(types.Txs, nTxs), diff --git a/proto/types/dymint/dymint.proto b/proto/types/dymint/dymint.proto index 54db50a7b..d99ef3100 100755 --- a/proto/types/dymint/dymint.proto +++ b/proto/types/dymint/dymint.proto @@ -63,6 +63,10 @@ message Header { // Chain ID the block belongs to string chain_id = 13; + + // The following fields are added on top of the normal TM header, for dymension purposes + // Note: LOSSY when converted to tendermint (squashed into a single hash) + bytes consensus_messages_hash = 15; } message Commit { diff --git a/rpc/client/client_test.go b/rpc/client/client_test.go index d963196d4..63b7904ab 100644 --- a/rpc/client/client_test.go +++ b/rpc/client/client_test.go @@ -374,7 +374,6 @@ func TestValidatedHeight(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - node.BlockManager.SettlementValidator.UpdateLastValidatedHeight(test.validatedHeight) node.BlockManager.LastSettlementHeight.Store(test.submittedHeight) @@ -389,7 +388,6 @@ func TestValidatedHeight(t *testing.T) { err = node.Stop() require.NoError(err) - } func TestGetCommit(t *testing.T) { @@ -929,9 +927,10 @@ func TestValidatorSetHandling(t *testing.T) { func getRandomBlock(height uint64, nTxs int) *types.Block { block := &types.Block{ Header: types.Header{ - Height: height, - Version: types.Version{Block: testutil.BlockVersion}, - ProposerAddress: getRandomBytes(20), + Height: height, + Version: types.Version{Block: testutil.BlockVersion}, + ProposerAddress: getRandomBytes(20), + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: make(types.Txs, nTxs), diff --git a/testutil/types.go b/testutil/types.go index 7f04ddd4d..409a7cb82 100644 --- a/testutil/types.go +++ b/testutil/types.go @@ -73,18 +73,19 @@ func generateBlock(height uint64, proposerHash []byte, lastHeaderHash [32]byte) Block: BlockVersion, App: AppVersion, }, - Height: height, - Time: 4567, - LastHeaderHash: lastHeaderHash, - LastCommitHash: h[0], - DataHash: h[1], - ConsensusHash: h[2], - AppHash: [32]byte{}, - LastResultsHash: GetEmptyLastResultsHash(), - ProposerAddress: []byte{4, 3, 2, 1}, - SequencerHash: [32]byte(proposerHash), - NextSequencersHash: [32]byte(proposerHash), - ChainID: "test-chain", + Height: height, + Time: 4567, + LastHeaderHash: lastHeaderHash, + LastCommitHash: h[0], + DataHash: h[1], + ConsensusHash: h[2], + AppHash: [32]byte{}, + LastResultsHash: GetEmptyLastResultsHash(), + ProposerAddress: []byte{4, 3, 2, 1}, + SequencerHash: [32]byte(proposerHash), + NextSequencersHash: [32]byte(proposerHash), + ChainID: "test-chain", + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: nil, @@ -388,7 +389,8 @@ func GetEmptyLastResultsHash() [32]byte { func GetRandomBlock(height uint64, nTxs int) *types.Block { block := &types.Block{ Header: types.Header{ - Height: height, + Height: height, + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: make(types.Txs, nTxs), diff --git a/types/block.go b/types/block.go index e6d2c1673..36fcf2ec7 100644 --- a/types/block.go +++ b/types/block.go @@ -43,6 +43,10 @@ type Header struct { // The Chain ID ChainID string + + // The following fields are added on top of the normal TM header, for dymension purposes + // Note: LOSSY when converted to tendermint (squashed into a single hash) + ConsensusMessagesHash [32]byte // must be the hash of the (merkle root) of the consensus messages } func (h Header) GetTimestamp() time.Time { @@ -124,6 +128,8 @@ func GetLastCommitHash(lastCommit *Commit, header *Header) []byte { } // GetDataHash returns the hash of the block data to be set in the block header. +// Doesn't include consensus messages because we want to avoid touching +// fundamental primitive and allow tx inclusion proofs. func GetDataHash(block *Block) []byte { abciData := tmtypes.Data{ Txs: ToABCIBlockDataTxs(&block.Data), diff --git a/types/conv.go b/types/conv.go index afbfc94a6..2a85b684a 100644 --- a/types/conv.go +++ b/types/conv.go @@ -3,11 +3,13 @@ package types import ( "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/proto/tendermint/version" + tmtypes "github.com/tendermint/tendermint/types" ) // ToABCIHeaderPB converts Dymint header to Header format defined in ABCI. // Caller should fill all the fields that are not available in Dymint header (like ChainID). +// WARNING: THIS IS A LOSSY CONVERSION func ToABCIHeaderPB(header *Header) types.Header { tmheader := ToABCIHeader(header) return *tmheader.ToProto() @@ -15,6 +17,7 @@ func ToABCIHeaderPB(header *Header) types.Header { // ToABCIHeader converts Dymint header to Header format defined in ABCI. // Caller should fill all the fields that are not available in Dymint header (like ChainID). +// WARNING: THIS IS A LOSSY CONVERSION func ToABCIHeader(header *Header) tmtypes.Header { return tmtypes.Header{ Version: version.Consensus{ @@ -37,7 +40,7 @@ func ToABCIHeader(header *Header) tmtypes.Header { ConsensusHash: header.ConsensusHash[:], AppHash: header.AppHash[:], LastResultsHash: header.LastResultsHash[:], - EvidenceHash: new(tmtypes.EvidenceData).Hash(), + EvidenceHash: header.DymHash(), // Overloaded, we don't need the evidence field because we don't use comet. ProposerAddress: header.ProposerAddress, ChainID: header.ChainID, } diff --git a/types/dym_header.go b/types/dym_header.go new file mode 100644 index 000000000..2d5a8165b --- /dev/null +++ b/types/dym_header.go @@ -0,0 +1,56 @@ +package types + +import ( + "fmt" + + proto "github.com/gogo/protobuf/types" + "github.com/tendermint/tendermint/crypto/merkle" + cmtbytes "github.com/tendermint/tendermint/libs/bytes" + _ "github.com/tendermint/tendermint/types" +) + +// a convenience struct to make computing easier +// persisted and over the wire types use a flat representation +type DymHeader struct { + ConsensusMessagesHash [32]byte +} + +func MakeDymHeader(consMessages []*proto.Any) DymHeader { + return DymHeader{ + ConsensusMessagesHash: ConsMessagesHash(consMessages), + } +} + +func (h DymHeader) Hash() cmtbytes.HexBytes { + // 32 bytes long + return merkle.HashFromByteSlices([][]byte{ + h.ConsensusMessagesHash[:], + // can be extended with other things if we need to later + }) +} + +func (h *Header) SetDymHeader(dh DymHeader) { + copy(h.ConsensusMessagesHash[:], dh.ConsensusMessagesHash[:]) +} + +func (h *Header) DymHash() cmtbytes.HexBytes { + ret := DymHeader{} + copy(ret.ConsensusMessagesHash[:], h.ConsensusMessagesHash[:]) + return ret.Hash() +} + +func ConsMessagesHash(msgs []*proto.Any) [32]byte { + bzz := make([][]byte, len(msgs)) + for i, msg := range msgs { + var err error + bzz[i], err = msg.Marshal() + if err != nil { + // Not obvious how to recover here. Shouldn't happen. + panic(fmt.Errorf("marshal consensus message: %w", err)) + } + } + merkleRoot := merkle.HashFromByteSlices(bzz) + ret := [32]byte{} + copy(ret[:], merkleRoot) // merkleRoot is already 32 bytes + return ret +} diff --git a/types/errors.go b/types/errors.go index 033c5bd80..3b689660b 100644 --- a/types/errors.go +++ b/types/errors.go @@ -19,6 +19,8 @@ var ( ErrEmptyBlock = errors.New("block has no transactions and is not allowed to be empty") ErrInvalidBlockHeight = errors.New("invalid block height") ErrInvalidHeaderDataHash = errors.New("header not matching block data") + ErrInvalidDymHeader = gerrc.ErrInvalidArgument.Wrap("dym header") + ErrInvalidDymHeaderHash = fmt.Errorf("hash mismatch: %w", ErrInvalidDymHeader) ErrMissingProposerPubKey = fmt.Errorf("missing proposer public key: %w", gerrc.ErrNotFound) ErrVersionMismatch = errors.New("version mismatch") ErrEmptyProposerAddress = errors.New("no proposer address") @@ -373,8 +375,7 @@ func NewErrInvalidHeaderDataHashFraud(block *Block) error { return &ErrInvalidHeaderDataHashFraud{ Expected: block.Header.DataHash, Actual: [32]byte(GetDataHash(block)), - - Header: block.Header, + Header: block.Header, } } @@ -390,6 +391,31 @@ func (e ErrInvalidHeaderDataHashFraud) Unwrap() error { return gerrc.ErrFault } +// when dym header on the block header is not correctly derived from block data +type ErrInvalidDymHeaderFraud struct { + *Block + base error +} + +func NewErrInvalidDymHeaderFraud(block *Block, err error) error { + return &ErrInvalidDymHeaderFraud{ + Block: block, + base: err, + } +} + +func (e ErrInvalidDymHeaderFraud) Error() string { + return fmt.Errorf( + "possible fraud, double check using correct DRS and block version: invalid dym header: height : %d: %w", + e.Header.Height, + e.Unwrap(), + ).Error() +} + +func (e ErrInvalidDymHeaderFraud) Unwrap() error { + return errors.Join(e.base, gerrc.ErrFault) +} + // ErrStateUpdateNumBlocksNotMatchingFraud represents an error where the number of blocks in the state update does not match the expected number. type ErrStateUpdateNumBlocksNotMatchingFraud struct { StateIndex uint64 diff --git a/types/pb/dymint/dymint.pb.go b/types/pb/dymint/dymint.pb.go index 5879a60c5..4d35e8e78 100644 --- a/types/pb/dymint/dymint.pb.go +++ b/types/pb/dymint/dymint.pb.go @@ -117,6 +117,9 @@ type Header struct { NextSequencerHash []byte `protobuf:"bytes,14,opt,name=next_sequencer_hash,json=nextSequencerHash,proto3" json:"next_sequencer_hash,omitempty"` // Chain ID the block belongs to ChainId string `protobuf:"bytes,13,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // The following fields are added on top of the normal TM header, for dymension purposes + // Note: LOSSY when converted to tendermint (squashed into a single hash) + ConsensusMessagesHash []byte `protobuf:"bytes,15,opt,name=consensus_messages_hash,json=consensusMessagesHash,proto3" json:"consensus_messages_hash,omitempty"` } func (m *Header) Reset() { *m = Header{} } @@ -251,6 +254,13 @@ func (m *Header) GetChainId() string { return "" } +func (m *Header) GetConsensusMessagesHash() []byte { + if m != nil { + return m.ConsensusMessagesHash + } + return nil +} + type Commit struct { Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` HeaderHash []byte `protobuf:"bytes,2,opt,name=header_hash,json=headerHash,proto3" json:"header_hash,omitempty"` @@ -696,65 +706,66 @@ func init() { func init() { proto.RegisterFile("types/dymint/dymint.proto", fileDescriptor_fe69c538ded4b87f) } var fileDescriptor_fe69c538ded4b87f = []byte{ - // 918 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x95, 0xcf, 0x6f, 0xdb, 0x36, - 0x14, 0xc7, 0xa3, 0xc4, 0xf1, 0x8f, 0x27, 0x27, 0x8d, 0xd9, 0xa0, 0x90, 0x5b, 0xcc, 0x71, 0x05, - 0xa4, 0x70, 0x07, 0x4c, 0x46, 0x3d, 0x0c, 0xdb, 0x69, 0x43, 0xd3, 0x15, 0x4b, 0x31, 0xec, 0x42, - 0x03, 0x3d, 0xec, 0x62, 0xd0, 0xd6, 0x9b, 0x24, 0xd4, 0xfa, 0x31, 0x91, 0x4e, 0xe3, 0x1d, 0xfb, - 0x17, 0xec, 0xbc, 0xdb, 0xfe, 0x9b, 0x9e, 0xb6, 0x1e, 0x77, 0x1a, 0x86, 0xe4, 0x1f, 0x19, 0xf8, - 0x48, 0xc9, 0x6a, 0xb7, 0x5e, 0x12, 0xf2, 0xfb, 0xfd, 0x90, 0x7c, 0x7e, 0x7c, 0x8f, 0x82, 0xa1, - 0xda, 0x16, 0x28, 0xa7, 0xe1, 0x36, 0x4d, 0x32, 0x65, 0xff, 0x05, 0x45, 0x99, 0xab, 0x9c, 0xb5, - 0xcd, 0xec, 0xfe, 0x69, 0x94, 0x47, 0x39, 0x49, 0x53, 0x3d, 0x32, 0xee, 0xfd, 0x87, 0x66, 0xa1, - 0xc2, 0x2c, 0xc4, 0x92, 0x16, 0x8b, 0xe5, 0x2a, 0x99, 0x92, 0x6a, 0x11, 0xff, 0x3f, 0x88, 0x15, - 0x1a, 0xcc, 0xa3, 0x8f, 0x30, 0x57, 0x62, 0x9d, 0x84, 0x42, 0xe5, 0xa5, 0xe5, 0x86, 0x51, 0x9e, - 0x47, 0x6b, 0x9c, 0xd2, 0x6c, 0xb9, 0xf9, 0x69, 0x2a, 0xb2, 0xad, 0xb1, 0xfc, 0x27, 0xd0, 0x79, - 0x89, 0xa5, 0x4c, 0xf2, 0x8c, 0x9d, 0xc2, 0xe1, 0x72, 0x9d, 0xaf, 0x5e, 0x79, 0xce, 0xd8, 0x99, - 0xb4, 0xb8, 0x99, 0xb0, 0x13, 0x38, 0x10, 0x45, 0xe1, 0xed, 0x93, 0xa6, 0x87, 0xfe, 0x9b, 0x16, - 0xb4, 0x2f, 0x51, 0x84, 0x58, 0xb2, 0xc7, 0xd0, 0xb9, 0x32, 0xab, 0x69, 0x91, 0x3b, 0xbb, 0x13, - 0xd8, 0x2c, 0xd8, 0x4d, 0x79, 0xe5, 0xb3, 0x73, 0xe8, 0x67, 0x22, 0x45, 0x59, 0x88, 0x15, 0x2e, - 0x92, 0x90, 0x36, 0xec, 0x5f, 0xec, 0x7b, 0x0e, 0x77, 0x6b, 0xfd, 0x45, 0xc8, 0xee, 0x41, 0x3b, - 0xc6, 0x24, 0x8a, 0x95, 0x77, 0x40, 0x27, 0xda, 0x19, 0x63, 0xd0, 0x52, 0x49, 0x8a, 0x5e, 0x6b, - 0xec, 0x4c, 0x0e, 0x38, 0x8d, 0xd9, 0x04, 0x4e, 0xd6, 0x42, 0xaa, 0x45, 0x4c, 0xc1, 0x2c, 0x62, - 0x21, 0x63, 0xef, 0x50, 0x6f, 0xcb, 0x8f, 0xb5, 0x6e, 0x62, 0xbc, 0x14, 0x32, 0xae, 0xc9, 0x55, - 0x9e, 0xa6, 0x89, 0x32, 0x64, 0x7b, 0x47, 0x3e, 0x23, 0x99, 0xc8, 0x07, 0xd0, 0x0b, 0x85, 0x12, - 0x06, 0xe9, 0x10, 0xd2, 0xd5, 0x02, 0x99, 0xe7, 0x70, 0xbc, 0xca, 0x33, 0x89, 0x99, 0xdc, 0x48, - 0x43, 0x74, 0x89, 0x38, 0xaa, 0x55, 0xc2, 0x86, 0xd0, 0x15, 0x45, 0x61, 0x80, 0x1e, 0x01, 0x1d, - 0x51, 0x14, 0x64, 0x7d, 0x0a, 0x03, 0x0a, 0xa4, 0x44, 0xb9, 0x59, 0x2b, 0xbb, 0x09, 0x10, 0x73, - 0x47, 0x1b, 0xdc, 0xe8, 0xc4, 0x3e, 0x86, 0x93, 0xa2, 0xcc, 0x8b, 0x5c, 0x62, 0xb9, 0x10, 0x61, - 0x58, 0xa2, 0x94, 0x9e, 0x6b, 0xd0, 0x4a, 0x7f, 0x6a, 0x64, 0x1d, 0x98, 0xc4, 0x9f, 0x37, 0x98, - 0xad, 0xaa, 0x3c, 0xf4, 0x4d, 0x60, 0xb5, 0x4a, 0x3b, 0x06, 0x70, 0x37, 0xc3, 0x6b, 0xb5, 0xf8, - 0x80, 0x3d, 0x26, 0x76, 0xa0, 0xad, 0xf9, 0x7b, 0xfc, 0x10, 0xba, 0xab, 0x58, 0x24, 0x99, 0xbe, - 0xaf, 0xa3, 0xb1, 0x33, 0xe9, 0xf1, 0x0e, 0xcd, 0x5f, 0x84, 0xfe, 0xef, 0x0e, 0xb4, 0x4d, 0xda, - 0x1a, 0x57, 0xe6, 0xbc, 0x77, 0x65, 0x67, 0xe0, 0x36, 0x6f, 0x86, 0x2e, 0x9c, 0x43, 0xbc, 0xbb, - 0x95, 0x11, 0x80, 0x4c, 0xa2, 0x4c, 0xa8, 0x4d, 0x89, 0xd2, 0x3b, 0x18, 0x1f, 0x68, 0x7f, 0xa7, - 0xb0, 0xaf, 0xa1, 0xaf, 0xd2, 0x45, 0x2d, 0xd0, 0xdd, 0xbb, 0xb3, 0x07, 0xc1, 0xae, 0xde, 0x03, - 0xd3, 0x0d, 0x26, 0x90, 0x79, 0x12, 0x71, 0x57, 0xa5, 0xf3, 0x8a, 0xf7, 0xff, 0x70, 0xa0, 0xf5, - 0xad, 0x50, 0x42, 0xd7, 0xb0, 0xba, 0x96, 0x9e, 0x43, 0x27, 0xe8, 0x21, 0xfb, 0x0a, 0xbc, 0x24, - 0x53, 0x58, 0xa6, 0x18, 0x26, 0x42, 0xe1, 0x42, 0x2a, 0xfd, 0xb7, 0xcc, 0x73, 0x25, 0xbd, 0x7d, - 0xc2, 0xee, 0x35, 0xfd, 0xb9, 0xb6, 0xb9, 0x76, 0xd9, 0x17, 0xd0, 0xc5, 0xab, 0x24, 0xd4, 0x49, - 0xa2, 0x90, 0xdd, 0xd9, 0xb0, 0x19, 0x90, 0xee, 0xe3, 0xe0, 0xb9, 0x05, 0x78, 0x8d, 0xb2, 0x67, - 0xc0, 0x76, 0xa5, 0x93, 0xa2, 0x94, 0x22, 0x42, 0xe9, 0xb5, 0x68, 0x83, 0xd3, 0xc0, 0xf4, 0x67, - 0x50, 0xf5, 0x67, 0xf0, 0x34, 0xdb, 0xf2, 0x41, 0xcd, 0xff, 0x60, 0x71, 0xff, 0x8d, 0x03, 0x87, - 0x17, 0xd4, 0x95, 0x8f, 0x74, 0xce, 0x75, 0x22, 0x6d, 0xdf, 0x1d, 0x57, 0x7d, 0x67, 0x8a, 0x9e, - 0x5b, 0x97, 0x8d, 0xa1, 0xa5, 0xab, 0x97, 0x92, 0xef, 0xce, 0xfa, 0x15, 0xa5, 0xb3, 0xc2, 0xc9, - 0x61, 0x53, 0x70, 0x1b, 0xad, 0x41, 0x5d, 0xd7, 0xd8, 0xce, 0x64, 0x96, 0xc3, 0xae, 0x4b, 0xfc, - 0xdf, 0x74, 0x10, 0x42, 0xad, 0x62, 0xf6, 0x10, 0xfa, 0x52, 0x89, 0x52, 0x37, 0x60, 0xe3, 0xfa, - 0x5d, 0xd2, 0x2e, 0x4d, 0x0d, 0x7c, 0x02, 0x80, 0x59, 0x58, 0x01, 0xe6, 0x11, 0xe9, 0x61, 0x16, - 0x5a, 0xfb, 0x1c, 0xda, 0xf4, 0xca, 0x48, 0x9b, 0xca, 0xa3, 0xea, 0x5c, 0xfa, 0x95, 0xdc, 0x9a, - 0x6c, 0x02, 0x1d, 0x13, 0x5e, 0x95, 0xb1, 0x0f, 0xe3, 0xab, 0x6c, 0xff, 0x4f, 0x07, 0x7a, 0x75, - 0x0d, 0xb3, 0xcf, 0x80, 0x49, 0x54, 0x6a, 0x8d, 0x29, 0x66, 0xaa, 0xee, 0x21, 0x87, 0x2a, 0x79, - 0xb0, 0x73, 0xaa, 0x2e, 0xfa, 0x06, 0x7a, 0xf5, 0xcb, 0x69, 0x33, 0xf6, 0x3f, 0xc5, 0xf6, 0xb2, - 0x42, 0x2e, 0x5a, 0x6f, 0xff, 0x3e, 0xdb, 0xe3, 0xbb, 0x35, 0xba, 0xe2, 0x4b, 0x7c, 0x2d, 0xca, - 0x90, 0xce, 0xa2, 0x5c, 0xf6, 0x38, 0x18, 0x49, 0x1f, 0xc2, 0x9e, 0xc0, 0xe9, 0xeb, 0x38, 0x51, - 0xb8, 0x4e, 0xa4, 0xc2, 0x70, 0x51, 0xe2, 0x5a, 0x6c, 0xb1, 0x34, 0xbf, 0xaa, 0xc7, 0xef, 0x36, - 0x3c, 0x6e, 0x2d, 0xff, 0x3b, 0xe8, 0xd7, 0x3f, 0x68, 0x8e, 0x8a, 0x7d, 0x09, 0x50, 0xb7, 0xaf, - 0x29, 0x69, 0x77, 0x36, 0xa8, 0xd2, 0x51, 0x93, 0x36, 0xb6, 0x06, 0xea, 0x9f, 0x41, 0xef, 0xf9, - 0x15, 0x66, 0xea, 0x7b, 0xdc, 0x4a, 0xfd, 0x9c, 0xbe, 0xc2, 0x6d, 0xd5, 0x12, 0x34, 0xbe, 0xb8, - 0x7c, 0x7b, 0x33, 0x72, 0xde, 0xdd, 0x8c, 0x9c, 0x7f, 0x6e, 0x46, 0xce, 0xaf, 0xb7, 0xa3, 0xbd, - 0x77, 0xb7, 0xa3, 0xbd, 0xbf, 0x6e, 0x47, 0x7b, 0x3f, 0x06, 0x51, 0xa2, 0xe2, 0xcd, 0x32, 0x58, - 0xe5, 0xa9, 0xfe, 0xca, 0x61, 0xa6, 0x5f, 0xf4, 0xeb, 0xed, 0x2f, 0xd5, 0x97, 0xcf, 0x7c, 0x75, - 0x8a, 0xa5, 0x9d, 0x2f, 0xdb, 0x54, 0xc8, 0x9f, 0xff, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x10, 0x0b, - 0x76, 0x49, 0x20, 0x07, 0x00, 0x00, + // 935 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x55, 0xcb, 0x6e, 0xdb, 0x46, + 0x14, 0x35, 0x6d, 0x59, 0x8f, 0x4b, 0xf9, 0xa1, 0x89, 0x9b, 0x52, 0x09, 0x2a, 0x2b, 0x04, 0x1c, + 0x28, 0x05, 0x4a, 0x21, 0x2a, 0xfa, 0x58, 0xb5, 0x88, 0xd3, 0xa0, 0x0e, 0x8a, 0x6e, 0x46, 0x40, + 0x16, 0xdd, 0x08, 0x23, 0xf1, 0x56, 0x24, 0x22, 0x3e, 0xca, 0x19, 0x39, 0x56, 0x97, 0xfd, 0x82, + 0xae, 0xbb, 0xeb, 0x6f, 0xf4, 0x0b, 0xb2, 0x6a, 0xb3, 0xec, 0xaa, 0x28, 0xec, 0x1f, 0x29, 0xe6, + 0xce, 0x90, 0x62, 0xe2, 0x66, 0x23, 0xcd, 0x9c, 0x73, 0x66, 0xe6, 0xf2, 0xcc, 0x3d, 0x24, 0xf4, + 0xd5, 0x26, 0x47, 0x39, 0x0e, 0x37, 0x49, 0x9c, 0x2a, 0xfb, 0x17, 0xe4, 0x45, 0xa6, 0x32, 0xd6, + 0x34, 0xb3, 0x7b, 0x27, 0xcb, 0x6c, 0x99, 0x11, 0x34, 0xd6, 0x23, 0xc3, 0xde, 0x7b, 0x60, 0x16, + 0x2a, 0x4c, 0x43, 0x2c, 0x68, 0xb1, 0x98, 0x2f, 0xe2, 0x31, 0xa1, 0x56, 0xe2, 0xdf, 0x92, 0x58, + 0xa0, 0xa6, 0x79, 0xf8, 0x1e, 0xcd, 0xa5, 0x58, 0xc5, 0xa1, 0x50, 0x59, 0x61, 0x75, 0xfd, 0x65, + 0x96, 0x2d, 0x57, 0x38, 0xa6, 0xd9, 0x7c, 0xfd, 0xe3, 0x58, 0xa4, 0x1b, 0x43, 0xf9, 0x8f, 0xa1, + 0xf5, 0x02, 0x0b, 0x19, 0x67, 0x29, 0x3b, 0x81, 0xfd, 0xf9, 0x2a, 0x5b, 0xbc, 0xf4, 0x9c, 0xa1, + 0x33, 0x6a, 0x70, 0x33, 0x61, 0xc7, 0xb0, 0x27, 0xf2, 0xdc, 0xdb, 0x25, 0x4c, 0x0f, 0xfd, 0x3f, + 0x1a, 0xd0, 0xbc, 0x40, 0x11, 0x62, 0xc1, 0x1e, 0x41, 0xeb, 0xd2, 0xac, 0xa6, 0x45, 0xee, 0xe4, + 0x28, 0xb0, 0x2e, 0xd8, 0x4d, 0x79, 0xc9, 0xb3, 0x33, 0xe8, 0xa6, 0x22, 0x41, 0x99, 0x8b, 0x05, + 0xce, 0xe2, 0x90, 0x36, 0xec, 0x9e, 0xef, 0x7a, 0x0e, 0x77, 0x2b, 0xfc, 0x79, 0xc8, 0xee, 0x42, + 0x33, 0xc2, 0x78, 0x19, 0x29, 0x6f, 0x8f, 0x4e, 0xb4, 0x33, 0xc6, 0xa0, 0xa1, 0xe2, 0x04, 0xbd, + 0xc6, 0xd0, 0x19, 0xed, 0x71, 0x1a, 0xb3, 0x11, 0x1c, 0xaf, 0x84, 0x54, 0xb3, 0x88, 0x8a, 0x99, + 0x45, 0x42, 0x46, 0xde, 0xbe, 0xde, 0x96, 0x1f, 0x6a, 0xdc, 0xd4, 0x78, 0x21, 0x64, 0x54, 0x29, + 0x17, 0x59, 0x92, 0xc4, 0xca, 0x28, 0x9b, 0x5b, 0xe5, 0x53, 0x82, 0x49, 0x79, 0x1f, 0x3a, 0xa1, + 0x50, 0xc2, 0x48, 0x5a, 0x24, 0x69, 0x6b, 0x80, 0xc8, 0x33, 0x38, 0x5c, 0x64, 0xa9, 0xc4, 0x54, + 0xae, 0xa5, 0x51, 0xb4, 0x49, 0x71, 0x50, 0xa1, 0x24, 0xeb, 0x43, 0x5b, 0xe4, 0xb9, 0x11, 0x74, + 0x48, 0xd0, 0x12, 0x79, 0x4e, 0xd4, 0xc7, 0xd0, 0xa3, 0x42, 0x0a, 0x94, 0xeb, 0x95, 0xb2, 0x9b, + 0x00, 0x69, 0x8e, 0x34, 0xc1, 0x0d, 0x4e, 0xda, 0x47, 0x70, 0x9c, 0x17, 0x59, 0x9e, 0x49, 0x2c, + 0x66, 0x22, 0x0c, 0x0b, 0x94, 0xd2, 0x73, 0x8d, 0xb4, 0xc4, 0x9f, 0x18, 0x58, 0x17, 0x26, 0xf1, + 0xa7, 0x35, 0xa6, 0x8b, 0xd2, 0x87, 0xae, 0x29, 0xac, 0x42, 0x69, 0xc7, 0x00, 0xee, 0xa4, 0x78, + 0xa5, 0x66, 0xef, 0x68, 0x0f, 0x49, 0xdb, 0xd3, 0xd4, 0xf4, 0x2d, 0x7d, 0x1f, 0xda, 0x8b, 0x48, + 0xc4, 0xa9, 0xbe, 0xaf, 0x83, 0xa1, 0x33, 0xea, 0xf0, 0x16, 0xcd, 0x9f, 0x87, 0xec, 0x73, 0xf8, + 0x70, 0x6b, 0x45, 0x82, 0x52, 0x8a, 0x25, 0xda, 0xc7, 0x39, 0xa2, 0xed, 0x3e, 0xa8, 0xe8, 0xef, + 0x2d, 0xab, 0xb7, 0xf4, 0x7f, 0x77, 0xa0, 0x69, 0xec, 0xae, 0x5d, 0xb5, 0xf3, 0xd6, 0x55, 0x9f, + 0x82, 0x5b, 0xbf, 0x51, 0x6a, 0x14, 0x0e, 0xd1, 0xf6, 0x36, 0x07, 0x00, 0x32, 0x5e, 0xa6, 0x42, + 0xad, 0x0b, 0x94, 0xde, 0xde, 0x70, 0x4f, 0xf3, 0x5b, 0x84, 0x7d, 0x05, 0x5d, 0x95, 0xcc, 0x2a, + 0x80, 0x7a, 0xc6, 0x9d, 0xdc, 0x0f, 0xb6, 0x39, 0x09, 0x4c, 0x8a, 0x4c, 0x21, 0xd3, 0x78, 0xc9, + 0x5d, 0x95, 0x4c, 0x4b, 0xbd, 0xff, 0xa7, 0x03, 0x8d, 0x6f, 0x84, 0x12, 0xba, 0xf7, 0xd5, 0x95, + 0xf4, 0x1c, 0x3a, 0x41, 0x0f, 0xd9, 0x97, 0xe0, 0xc5, 0xa9, 0xc2, 0x22, 0xc1, 0x30, 0x16, 0x0a, + 0x67, 0x52, 0xe9, 0xdf, 0x22, 0xcb, 0x94, 0xf4, 0x76, 0x49, 0x76, 0xb7, 0xce, 0x4f, 0x35, 0xcd, + 0x35, 0xcb, 0x3e, 0x83, 0x36, 0x5e, 0xc6, 0xa1, 0x36, 0x97, 0x4a, 0x76, 0x27, 0xfd, 0x7a, 0x41, + 0x3a, 0xff, 0xc1, 0x33, 0x2b, 0xe0, 0x95, 0x94, 0x3d, 0x05, 0x76, 0xdb, 0x67, 0xaf, 0x41, 0x1b, + 0x9c, 0x04, 0x26, 0xd7, 0x41, 0x99, 0xeb, 0xe0, 0x49, 0xba, 0xe1, 0xbd, 0x5b, 0xc6, 0xfb, 0xbf, + 0x38, 0xb0, 0x7f, 0x4e, 0x69, 0x7e, 0xa8, 0x3d, 0xd7, 0x46, 0xda, 0xbc, 0x1e, 0x96, 0x79, 0x35, + 0x61, 0xe1, 0x96, 0x65, 0x43, 0x68, 0xe8, 0xae, 0x27, 0xf3, 0xdd, 0x49, 0xb7, 0x54, 0x69, 0x57, + 0x38, 0x31, 0x6c, 0x0c, 0x6e, 0x2d, 0x52, 0x94, 0xd6, 0xda, 0x76, 0xc6, 0x59, 0x0e, 0xdb, 0x74, + 0xf9, 0xbf, 0xe9, 0x22, 0x84, 0x5a, 0x44, 0xec, 0x01, 0x74, 0xa5, 0x12, 0x85, 0x0e, 0x6e, 0xed, + 0xfa, 0x5d, 0xc2, 0x2e, 0x4c, 0x0f, 0x7c, 0x04, 0x80, 0x69, 0x58, 0x0a, 0xcc, 0xcb, 0xa7, 0x83, + 0x69, 0x68, 0xe9, 0x33, 0x68, 0xd2, 0xdb, 0x49, 0x5a, 0x2b, 0x0f, 0xca, 0x73, 0xe9, 0x29, 0xb9, + 0x25, 0xd9, 0x08, 0x5a, 0xa6, 0xbc, 0xd2, 0xb1, 0x77, 0xeb, 0x2b, 0x69, 0xff, 0x2f, 0x07, 0x3a, + 0x55, 0xef, 0xb3, 0x4f, 0x80, 0x49, 0x54, 0x6a, 0x85, 0x09, 0xa6, 0xaa, 0xca, 0x9e, 0x43, 0x09, + 0xe8, 0x6d, 0x99, 0x32, 0x7d, 0x5f, 0x43, 0xa7, 0x7a, 0xe3, 0x5a, 0xc7, 0xfe, 0xa7, 0xd9, 0x5e, + 0x94, 0x92, 0xf3, 0xc6, 0xeb, 0x7f, 0x4e, 0x77, 0xf8, 0x76, 0x8d, 0xee, 0xf8, 0x02, 0x5f, 0x89, + 0x22, 0xa4, 0xb3, 0xc8, 0xcb, 0x0e, 0x07, 0x03, 0xe9, 0x43, 0xd8, 0x63, 0x38, 0x79, 0x15, 0xc5, + 0x0a, 0x57, 0xb1, 0x54, 0x18, 0xce, 0x0a, 0x5c, 0x89, 0x0d, 0x16, 0xe6, 0xa9, 0x3a, 0xfc, 0x4e, + 0x8d, 0xe3, 0x96, 0xf2, 0xbf, 0x85, 0x6e, 0xf5, 0x40, 0x53, 0x54, 0xec, 0x0b, 0x80, 0x2a, 0xf6, + 0xa6, 0xa5, 0xdd, 0x49, 0xaf, 0xb4, 0xa3, 0x52, 0xda, 0xda, 0x6a, 0x52, 0xff, 0x14, 0x3a, 0xcf, + 0x2e, 0x31, 0x55, 0xdf, 0xe1, 0x46, 0xea, 0xd7, 0xf0, 0x4b, 0xdc, 0x94, 0x91, 0xa0, 0xf1, 0xf9, + 0xc5, 0xeb, 0xeb, 0x81, 0xf3, 0xe6, 0x7a, 0xe0, 0xfc, 0x7b, 0x3d, 0x70, 0x7e, 0xbd, 0x19, 0xec, + 0xbc, 0xb9, 0x19, 0xec, 0xfc, 0x7d, 0x33, 0xd8, 0xf9, 0x21, 0x58, 0xc6, 0x2a, 0x5a, 0xcf, 0x83, + 0x45, 0x96, 0xe8, 0xaf, 0x23, 0xa6, 0xfa, 0x4b, 0x70, 0xb5, 0xf9, 0xb9, 0xfc, 0x62, 0x9a, 0xaf, + 0x55, 0x3e, 0xb7, 0xf3, 0x79, 0x93, 0x1a, 0xf9, 0xd3, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x42, + 0x6a, 0x04, 0xdf, 0x58, 0x07, 0x00, 0x00, } func (m *Version) Marshal() (dAtA []byte, err error) { @@ -810,6 +821,13 @@ func (m *Header) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ConsensusMessagesHash) > 0 { + i -= len(m.ConsensusMessagesHash) + copy(dAtA[i:], m.ConsensusMessagesHash) + i = encodeVarintDymint(dAtA, i, uint64(len(m.ConsensusMessagesHash))) + i-- + dAtA[i] = 0x7a + } if len(m.NextSequencerHash) > 0 { i -= len(m.NextSequencerHash) copy(dAtA[i:], m.NextSequencerHash) @@ -1368,6 +1386,10 @@ func (m *Header) Size() (n int) { if l > 0 { n += 1 + l + sovDymint(uint64(l)) } + l = len(m.ConsensusMessagesHash) + if l > 0 { + n += 1 + l + sovDymint(uint64(l)) + } return n } @@ -2102,6 +2124,40 @@ func (m *Header) Unmarshal(dAtA []byte) error { m.NextSequencerHash = []byte{} } iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConsensusMessagesHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowDymint + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthDymint + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthDymint + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ConsensusMessagesHash = append(m.ConsensusMessagesHash[:0], dAtA[iNdEx:postIndex]...) + if m.ConsensusMessagesHash == nil { + m.ConsensusMessagesHash = []byte{} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipDymint(dAtA[iNdEx:]) diff --git a/types/serialization.go b/types/serialization.go index a4e79bb8e..be5d8f864 100644 --- a/types/serialization.go +++ b/types/serialization.go @@ -84,20 +84,21 @@ func (c *Commit) UnmarshalBinary(data []byte) error { // ToProto converts Header into protobuf representation and returns it. func (h *Header) ToProto() *pb.Header { return &pb.Header{ - Version: &pb.Version{Block: h.Version.Block, App: h.Version.App}, - NamespaceId: []byte{}, - Height: h.Height, - Time: h.Time, - LastHeaderHash: h.LastHeaderHash[:], - LastCommitHash: h.LastCommitHash[:], - DataHash: h.DataHash[:], - ConsensusHash: h.ConsensusHash[:], - AppHash: h.AppHash[:], - LastResultsHash: h.LastResultsHash[:], - ProposerAddress: h.ProposerAddress[:], - SequencerHash: h.SequencerHash[:], - NextSequencerHash: h.NextSequencersHash[:], - ChainId: h.ChainID, + Version: &pb.Version{Block: h.Version.Block, App: h.Version.App}, + NamespaceId: []byte{}, + Height: h.Height, + Time: h.Time, + LastHeaderHash: h.LastHeaderHash[:], + LastCommitHash: h.LastCommitHash[:], + DataHash: h.DataHash[:], + ConsensusHash: h.ConsensusHash[:], + AppHash: h.AppHash[:], + LastResultsHash: h.LastResultsHash[:], + ProposerAddress: h.ProposerAddress[:], + SequencerHash: h.SequencerHash[:], + NextSequencerHash: h.NextSequencersHash[:], + ChainId: h.ChainID, + ConsensusMessagesHash: h.ConsensusMessagesHash[:], } } @@ -130,13 +131,17 @@ func (h *Header) FromProto(other *pb.Header) error { return errors.New("invalid length of 'SequencerHash'") } if !safeCopy(h.NextSequencersHash[:], other.NextSequencerHash) { - return errors.New("invalid length of 'SequencersHash'") + return errors.New("invalid length of 'NextSequencersHash'") } - if len(other.ProposerAddress) > 0 { + if len(other.ProposerAddress) > 0 { // TODO: why if? h.ProposerAddress = make([]byte, len(other.ProposerAddress)) copy(h.ProposerAddress, other.ProposerAddress) } - + if 0 < len(other.ConsensusMessagesHash) { + if !safeCopy(h.ConsensusMessagesHash[:], other.ConsensusMessagesHash) { + return errors.New("invalid length of 'consensusMessagesHash'") + } + } return nil } diff --git a/types/serialization_test.go b/types/serialization_test.go index 2fe1f1f5a..a7a7fb8a5 100644 --- a/types/serialization_test.go +++ b/types/serialization_test.go @@ -48,16 +48,17 @@ func TestBlockSerializationRoundTrip(t *testing.T) { Block: 1, App: 2, }, - Height: 3, - Time: 4567, - LastHeaderHash: h[0], - LastCommitHash: h[1], - DataHash: h[2], - ConsensusHash: h[3], - AppHash: h[4], - LastResultsHash: h[5], - ProposerAddress: []byte{4, 3, 2, 1}, - NextSequencersHash: h[6], + Height: 3, + Time: 4567, + LastHeaderHash: h[0], + LastCommitHash: h[1], + DataHash: h[2], + ConsensusHash: h[3], + AppHash: h[4], + LastResultsHash: h[5], + ProposerAddress: []byte{4, 3, 2, 1}, + NextSequencersHash: h[6], + ConsensusMessagesHash: types.ConsMessagesHash(nil), }, Data: types.Data{ Txs: nil, diff --git a/types/validation.go b/types/validation.go index aa5bedae4..33354b225 100644 --- a/types/validation.go +++ b/types/validation.go @@ -25,22 +25,36 @@ func ValidateProposedTransition(state *State, block *Block, commit *Commit, prop func (b *Block) ValidateBasic() error { err := b.Header.ValidateBasic() if err != nil { - return err + return fmt.Errorf("header: %w", err) } err = b.Data.ValidateBasic() if err != nil { - return err + return fmt.Errorf("data: %w", err) } err = b.LastCommit.ValidateBasic() if err != nil { - return err + return fmt.Errorf("last commit: %w", err) } if b.Header.DataHash != [32]byte(GetDataHash(b)) { return ErrInvalidHeaderDataHash } + + if err := b.validateDymHeader(); err != nil { + return fmt.Errorf("dym header: %w", err) + } + + return nil +} + +func (b *Block) validateDymHeader() error { + exp := b.Header.DymHash() + got := MakeDymHeader(b.Data.ConsensusMessages).Hash() + if !bytes.Equal(exp, got) { + return ErrInvalidDymHeaderHash + } return nil } @@ -50,6 +64,9 @@ func (b *Block) ValidateWithState(state *State) error { if errors.Is(err, ErrInvalidHeaderDataHash) { return NewErrInvalidHeaderDataHashFraud(b) } + if errors.Is(err, ErrInvalidDymHeader) { + return NewErrInvalidDymHeaderFraud(b, err) + } return err } diff --git a/types/validation_test.go b/types/validation_test.go index b55860504..a9d412fd3 100644 --- a/types/validation_test.go +++ b/types/validation_test.go @@ -8,6 +8,7 @@ import ( "github.com/cometbft/cometbft/libs/math" "github.com/dymensionxyz/gerr-cosmos/gerrc" + proto "github.com/gogo/protobuf/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" @@ -36,21 +37,23 @@ func TestBlock_ValidateWithState(t *testing.T) { validState.LastBlockHeight.Store(9) validState.SetProposer(proposer) + // TODO: tests should be written to mutate valid block validBlock := &Block{ Header: Header{ Version: Version{ Block: 1, App: 1, }, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte{}, - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "chainID", - SequencerHash: [32]byte(proposerHash), + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte{}, + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + SequencerHash: [32]byte(proposerHash), + ConsensusMessagesHash: ConsMessagesHash(nil), }, Data: Data{}, LastCommit: Commit{}, @@ -81,14 +84,15 @@ func TestBlock_ValidateWithState(t *testing.T) { Block: 2, App: 1, }, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "chainID", + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -104,14 +108,15 @@ func TestBlock_ValidateWithState(t *testing.T) { Block: 1, App: 2, }, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "chainID", + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -123,13 +128,14 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "Invalid height", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 11, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), + Version: validBlock.Header.Version, + Height: 11, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -141,13 +147,14 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "Invalid AppHash", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{9, 9, 9}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{9, 9, 9}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -159,13 +166,14 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "Invalid LastResultsHash", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{9, 9, 9}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{9, 9, 9}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -177,13 +185,14 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "Future block time", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.Add(2 * TimeFraudMaxDrift).UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.Add(2 * TimeFraudMaxDrift).UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -195,12 +204,13 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "Invalid proposer address", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte{}, + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte{}, + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -212,14 +222,15 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "invalid last header hash", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), - LastHeaderHash: [32]byte{1, 2, 3}, + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + LastHeaderHash: [32]byte{1, 2, 3}, + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -231,15 +242,16 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "invalid chain ID", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "invalidChainID", + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "invalidChainID", + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -251,16 +263,17 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "invalid NextSequencersHash", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte(GetDataHash(validBlock)), - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "chainID", - NextSequencersHash: [32]byte{1, 2, 3}, + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte(GetDataHash(validBlock)), + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + NextSequencersHash: [32]byte{1, 2, 3}, + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -272,15 +285,16 @@ func TestBlock_ValidateWithState(t *testing.T) { name: "invalid header data hash", block: &Block{ Header: Header{ - Version: validBlock.Header.Version, - Height: 10, - Time: currentTime.UnixNano(), - AppHash: [32]byte{1, 2, 3}, - LastResultsHash: [32]byte{4, 5, 6}, - ProposerAddress: []byte("proposer"), - DataHash: [32]byte{1, 2, 3}, - LastHeaderHash: [32]byte{7, 8, 9}, - ChainID: "chainID", + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte{1, 2, 3}, + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + ConsensusMessagesHash: ConsMessagesHash(nil), }, }, state: validState, @@ -288,6 +302,27 @@ func TestBlock_ValidateWithState(t *testing.T) { expectedErrType: ErrInvalidHeaderDataHashFraud{}, isFraud: true, }, + { + name: "invalid dym header", + block: &Block{ + Header: Header{ + Version: validBlock.Header.Version, + Height: 10, + Time: currentTime.UnixNano(), + AppHash: [32]byte{1, 2, 3}, + LastResultsHash: [32]byte{4, 5, 6}, + ProposerAddress: []byte("proposer"), + DataHash: [32]byte{1, 2, 3}, + LastHeaderHash: [32]byte{7, 8, 9}, + ChainID: "chainID", + ConsensusMessagesHash: ConsMessagesHash([]*proto.Any{{}}), + }, + }, + state: validState, + wantErr: true, + expectedErrType: ErrInvalidDymHeaderFraud{}, + isFraud: true, + }, } for _, tt := range tests { @@ -327,16 +362,17 @@ func TestCommit_ValidateWithHeader(t *testing.T) { Block: 1, App: 1, }, - ChainID: "test", - Height: 1, - Time: time.Now().UTC().UnixNano(), - LastHeaderHash: [32]byte{}, - DataHash: [32]byte{}, - ConsensusHash: [32]byte{}, - AppHash: [32]byte{}, - LastResultsHash: [32]byte{}, - ProposerAddress: proposerKey.PubKey().Address(), - SequencerHash: [32]byte(proposerHash), + ChainID: "test", + Height: 1, + Time: time.Now().UTC().UnixNano(), + LastHeaderHash: [32]byte{}, + DataHash: [32]byte{}, + ConsensusHash: [32]byte{}, + AppHash: [32]byte{}, + LastResultsHash: [32]byte{}, + ProposerAddress: proposerKey.PubKey().Address(), + SequencerHash: [32]byte(proposerHash), + ConsensusMessagesHash: ConsMessagesHash(nil), }, }