diff --git a/proto/tendermint/statesync/message_test.go b/proto/tendermint/statesync/message_test.go index 192e17c6d..dcf089130 100644 --- a/proto/tendermint/statesync/message_test.go +++ b/proto/tendermint/statesync/message_test.go @@ -1,6 +1,7 @@ package statesync_test import ( + "encoding/hex" "testing" proto "github.com/gogo/protobuf/proto" @@ -12,69 +13,103 @@ import ( func TestValidateMsg(t *testing.T) { testcases := map[string]struct { - msg proto.Message - valid bool + msg proto.Message + validMsg bool + valid bool }{ - "nil": {nil, false}, - "unrelated": {&tmproto.Block{}, false}, + "nil": {nil, false, false}, + "unrelated": {&tmproto.Block{}, false, false}, - "ChunkRequest valid": {&ssproto.ChunkRequest{Height: 1, Format: 1, Index: 1}, true}, - "ChunkRequest 0 height": {&ssproto.ChunkRequest{Height: 0, Format: 1, Index: 1}, false}, - "ChunkRequest 0 format": {&ssproto.ChunkRequest{Height: 1, Format: 0, Index: 1}, true}, - "ChunkRequest 0 chunk": {&ssproto.ChunkRequest{Height: 1, Format: 1, Index: 0}, true}, + "ChunkRequest valid": {&ssproto.ChunkRequest{Height: 1, Format: 1, Index: 1}, true, true}, + "ChunkRequest 0 height": {&ssproto.ChunkRequest{Height: 0, Format: 1, Index: 1}, true, false}, + "ChunkRequest 0 format": {&ssproto.ChunkRequest{Height: 1, Format: 0, Index: 1}, true, true}, + "ChunkRequest 0 chunk": {&ssproto.ChunkRequest{Height: 1, Format: 1, Index: 0}, true, true}, "ChunkResponse valid": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{1}}, - true}, + true, + true, + }, "ChunkResponse 0 height": { &ssproto.ChunkResponse{Height: 0, Format: 1, Index: 1, Chunk: []byte{1}}, - false}, + true, + false, + }, "ChunkResponse 0 format": { &ssproto.ChunkResponse{Height: 1, Format: 0, Index: 1, Chunk: []byte{1}}, - true}, + true, + true, + }, "ChunkResponse 0 chunk": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 0, Chunk: []byte{1}}, - true}, + true, + true, + }, "ChunkResponse empty body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: []byte{}}, - true}, + true, + true, + }, "ChunkResponse nil body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Chunk: nil}, - false}, + true, + false, + }, "ChunkResponse missing": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true}, - true}, + true, + true, + }, "ChunkResponse missing with empty": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true, Chunk: []byte{}}, - true}, + true, + true, + }, "ChunkResponse missing with body": { &ssproto.ChunkResponse{Height: 1, Format: 1, Index: 1, Missing: true, Chunk: []byte{1}}, - false}, + true, + false, + }, - "SnapshotsRequest valid": {&ssproto.SnapshotsRequest{}, true}, + "SnapshotsRequest valid": {&ssproto.SnapshotsRequest{}, true, true}, "SnapshotsResponse valid": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Chunks: 2, Hash: []byte{1}}, - true}, + true, + true, + }, "SnapshotsResponse 0 height": { &ssproto.SnapshotsResponse{Height: 0, Format: 1, Chunks: 2, Hash: []byte{1}}, - false}, + true, + false, + }, "SnapshotsResponse 0 format": { &ssproto.SnapshotsResponse{Height: 1, Format: 0, Chunks: 2, Hash: []byte{1}}, - true}, + true, + true, + }, "SnapshotsResponse 0 chunks": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Hash: []byte{1}}, - false}, + true, + false, + }, "SnapshotsResponse no hash": { &ssproto.SnapshotsResponse{Height: 1, Format: 1, Chunks: 2, Hash: []byte{}}, - false}, + true, + false, + }, } for name, tc := range testcases { tc := tc t.Run(name, func(t *testing.T) { msg := new(ssproto.Message) - _ = msg.Wrap(tc.msg) + + if tc.validMsg { + require.NoError(t, msg.Wrap(tc.msg)) + } else { + require.Error(t, msg.Wrap(tc.msg)) + } if tc.valid { require.NoError(t, msg.Validate()) @@ -84,3 +119,58 @@ func TestValidateMsg(t *testing.T) { }) } } + +func TestStateSyncVectors(t *testing.T) { + testCases := []struct { + testName string + msg proto.Message + expBytes string + }{ + { + "SnapshotsRequest", + &ssproto.SnapshotsRequest{}, + "0a00", + }, + { + "SnapshotsResponse", + &ssproto.SnapshotsResponse{ + Height: 1, + Format: 2, + Chunks: 3, + Hash: []byte("chuck hash"), + Metadata: []byte("snapshot metadata"), + }, + "1225080110021803220a636875636b20686173682a11736e617073686f74206d65746164617461", + }, + { + "ChunkRequest", + &ssproto.ChunkRequest{ + Height: 1, + Format: 2, + Index: 3, + }, + "1a06080110021803", + }, + { + "ChunkResponse", + &ssproto.ChunkResponse{ + Height: 1, + Format: 2, + Index: 3, + Chunk: []byte("it's a chunk"), + }, + "2214080110021803220c697427732061206368756e6b", + }, + } + + for _, tc := range testCases { + tc := tc + + msg := new(ssproto.Message) + require.NoError(t, msg.Wrap(tc.msg)) + + bz, err := msg.Marshal() + require.NoError(t, err) + require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName) + } +} diff --git a/statesync/messages.go b/statesync/messages.go deleted file mode 100644 index 7d556aa09..000000000 --- a/statesync/messages.go +++ /dev/null @@ -1,16 +0,0 @@ -package statesync - -import ( - "github.com/tendermint/tendermint/p2p" - ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" -) - -const ( - // snapshotMsgSize is the maximum size of a snapshotResponseMessage - snapshotMsgSize = int(4e6) - // chunkMsgSize is the maximum size of a chunkResponseMessage - chunkMsgSize = int(16e6) -) - -// assert Wrapper interface implementation of the state sync proto message type. -var _ p2p.Wrapper = (*ssproto.Message)(nil) diff --git a/statesync/messages_test.go b/statesync/messages_test.go deleted file mode 100644 index 0cc0a795b..000000000 --- a/statesync/messages_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package statesync - -import ( - "encoding/hex" - "testing" - - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/require" - - ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" -) - -//nolint:lll // ignore line length -func TestStateSyncVectors(t *testing.T) { - testCases := []struct { - testName string - msg proto.Message - expBytes string - }{ - {"SnapshotsRequest", &ssproto.SnapshotsRequest{}, "0a00"}, - {"SnapshotsResponse", &ssproto.SnapshotsResponse{Height: 1, Format: 2, Chunks: 3, Hash: []byte("chuck hash"), Metadata: []byte("snapshot metadata")}, "1225080110021803220a636875636b20686173682a11736e617073686f74206d65746164617461"}, - {"ChunkRequest", &ssproto.ChunkRequest{Height: 1, Format: 2, Index: 3}, "1a06080110021803"}, - {"ChunkResponse", &ssproto.ChunkResponse{Height: 1, Format: 2, Index: 3, Chunk: []byte("it's a chunk")}, "2214080110021803220c697427732061206368756e6b"}, - } - - for _, tc := range testCases { - tc := tc - - msg := new(ssproto.Message) - require.NoError(t, msg.Wrap(tc.msg)) - - bz, err := msg.Marshal() - require.NoError(t, err) - require.Equal(t, tc.expBytes, hex.EncodeToString(bz), tc.testName) - } -} diff --git a/statesync/reactor.go b/statesync/reactor.go index 1af831e21..b4dd0934c 100644 --- a/statesync/reactor.go +++ b/statesync/reactor.go @@ -20,6 +20,7 @@ import ( var ( _ service.Service = (*Reactor)(nil) + _ p2p.Wrapper = (*ssproto.Message)(nil) // ChannelShims contains a map of ChannelDescriptorShim objects, where each // object wraps a reference to a legacy p2p ChannelDescriptor and the corresponding @@ -59,6 +60,12 @@ const ( // recentSnapshots is the number of recent snapshots to send and receive per peer. recentSnapshots = 10 + + // snapshotMsgSize is the maximum size of a snapshotResponseMessage + snapshotMsgSize = int(4e6) + + // chunkMsgSize is the maximum size of a chunkResponseMessage + chunkMsgSize = int(16e6) ) // Reactor handles state sync, both restoring snapshots for the local node and serving snapshots