11package finalizer
22
33import (
4+ "bytes"
45 "encoding/binary"
56 "testing"
67
8+ "github.com/ethereum/go-ethereum/crypto"
79 "github.com/stretchr/testify/require"
10+
11+ "github.com/flare-foundation/flare-system-client/client/protocol"
12+ "github.com/flare-foundation/go-flare-common/pkg/payload"
813)
914
10- func TestFromSignedPayloadEmpty (t * testing.T ) {
11- cases := []struct {
15+ const (
16+ type0PayloadLen = 1 + 38 + 65 // typeID + message + signature
17+ type1PayloadLen = 1 + 65 // typeID + signature
18+ )
19+
20+ func TestFromSignedPayload (t * testing.T ) {
21+ message := bytes .Repeat ([]byte {0xAB }, 38 )
22+ signature := bytes .Repeat ([]byte {0xCD }, 65 )
23+
24+ type0Payload := append (append ([]byte {0x00 }, message ... ), signature ... )
25+ type1Payload := append ([]byte {0x01 }, signature ... )
26+
27+ tests := []struct {
1228 name string
13- payload []byte
29+ msg payloadMessage
30+ wantErr bool
31+ check func (t * testing.T , s * submitSignaturesPayload )
1432 }{
15- {"nil" , nil },
16- {"empty" , []byte {}},
33+ {
34+ name : "nil payload" ,
35+ msg : payloadMessage {payload : nil },
36+ wantErr : true ,
37+ },
38+ {
39+ name : "empty payload" ,
40+ msg : payloadMessage {payload : []byte {}},
41+ wantErr : true ,
42+ },
43+ {
44+ name : "type 0 only type byte" ,
45+ msg : payloadMessage {payload : []byte {0x00 }},
46+ wantErr : true ,
47+ },
48+ {
49+ name : "type 0 one byte short" ,
50+ msg : payloadMessage {payload : type0Payload [:type0PayloadLen - 1 ]},
51+ wantErr : true ,
52+ },
53+ {
54+ name : "type 1 one byte short" ,
55+ msg : payloadMessage {payload : type1Payload [:type1PayloadLen - 1 ]},
56+ wantErr : true ,
57+ },
58+ {
59+ name : "invalid typeID 2" ,
60+ msg : payloadMessage {payload : append ([]byte {0x02 }, signature ... )},
61+ wantErr : true ,
62+ },
63+ {
64+ name : "invalid typeID 0xFF" ,
65+ msg : payloadMessage {payload : append ([]byte {0xFF }, signature ... )},
66+ wantErr : true ,
67+ },
68+ {
69+ name : "type 0 exact length" ,
70+ msg : payloadMessage {
71+ protocolID : 7 ,
72+ votingRoundID : 42 ,
73+ payload : type0Payload ,
74+ },
75+ check : func (t * testing.T , s * submitSignaturesPayload ) {
76+ t .Helper ()
77+ require .Equal (t , uint8 (7 ), s .protocolID )
78+ require .Equal (t , uint32 (42 ), s .votingRoundID )
79+ require .Equal (t , uint8 (0 ), s .typeID )
80+ require .Equal (t , message , []byte (s .message ))
81+ require .Equal (t , signature , s .signature )
82+ require .Equal (t , - 1 , s .voterIndex )
83+ },
84+ },
85+ {
86+ name : "type 1 exact length" ,
87+ msg : payloadMessage {
88+ protocolID : 9 ,
89+ votingRoundID : 1234 ,
90+ payload : type1Payload ,
91+ },
92+ check : func (t * testing.T , s * submitSignaturesPayload ) {
93+ t .Helper ()
94+ require .Equal (t , uint8 (9 ), s .protocolID )
95+ require .Equal (t , uint32 (1234 ), s .votingRoundID )
96+ require .Equal (t , uint8 (1 ), s .typeID )
97+ require .Nil (t , s .message )
98+ require .Equal (t , signature , s .signature )
99+ require .Equal (t , - 1 , s .voterIndex )
100+ },
101+ },
102+ {
103+ name : "type 0 with trailing bytes" ,
104+ msg : payloadMessage {
105+ protocolID : 3 ,
106+ votingRoundID : 99 ,
107+ payload : append (append ([]byte {}, type0Payload ... ), 0xAA , 0xBB , 0xCC ),
108+ },
109+ check : func (t * testing.T , s * submitSignaturesPayload ) {
110+ t .Helper ()
111+ require .Equal (t , message , []byte (s .message ))
112+ require .Equal (t , signature , s .signature )
113+ require .Len (t , s .signature , 65 )
114+ require .Len (t , s .message , 38 )
115+ },
116+ },
117+ {
118+ name : "type 1 with trailing bytes" ,
119+ msg : payloadMessage {
120+ protocolID : 3 ,
121+ votingRoundID : 99 ,
122+ payload : append (append ([]byte {}, type1Payload ... ), 0xAA , 0xBB ),
123+ },
124+ check : func (t * testing.T , s * submitSignaturesPayload ) {
125+ t .Helper ()
126+ require .Nil (t , s .message )
127+ require .Equal (t , signature , s .signature )
128+ require .Len (t , s .signature , 65 )
129+ },
130+ },
17131 }
18- for _ , tc := range cases {
132+
133+ for _ , tc := range tests {
19134 t .Run (tc .name , func (t * testing.T ) {
20135 var s submitSignaturesPayload
21- err := s .FromSignedPayload (payloadMessage {payload : tc .payload })
22- require .Error (t , err )
136+ err := s .FromSignedPayload (tc .msg )
137+ if tc .wantErr {
138+ require .Error (t , err )
139+ return
140+ }
141+ require .NoError (t , err )
142+ tc .check (t , & s )
23143 })
24144 }
25145}
26146
27- func TestExtractPayloadsZeroLengthDoesNotPanic (t * testing.T ) {
147+ // TestRoundTripWithEncodePayload generates a tx-style input with protocol.EncodePayload
148+ // for both protocol types, parses it back through ExtractPayloads and FromSignedPayload,
149+ // and confirms the round trip preserves protocolID, votingRoundID, typeID, and message.
150+ func TestRoundTripWithEncodePayload (t * testing.T ) {
151+ privateKey , err := crypto .HexToECDSA (testPrivateKeyHex )
152+ require .NoError (t , err )
153+
154+ const votingRound int64 = 1234
155+
156+ type0Message := bytes .Repeat ([]byte {0x11 }, 38 )
157+ type1Message := bytes .Repeat ([]byte {0x22 }, 16 )
158+
159+ cases := []struct {
160+ protocolID uint8
161+ protocolType uint8
162+ data []byte
163+ }{
164+ {protocolID : 1 , protocolType : 0 , data : type0Message },
165+ {protocolID : 5 , protocolType : 1 , data : type1Message },
166+ }
167+
168+ buf := new (bytes.Buffer )
169+ buf .Write ([]byte {0xde , 0xad , 0xbe , 0xef }) // function selector
170+
171+ for _ , c := range cases {
172+ resp := & protocol.SubProtocolResponse {
173+ Status : payload .Ok ,
174+ Data : c .data ,
175+ }
176+ err := protocol .EncodePayload (buf , votingRound , resp , c .protocolID , c .protocolType , privateKey )
177+ require .NoError (t , err )
178+ }
179+
180+ payloads , err := ExtractPayloads (buf .Bytes ())
181+ require .NoError (t , err )
182+ require .Len (t , payloads , len (cases ))
183+
184+ for i , c := range cases {
185+ var s submitSignaturesPayload
186+ require .NoError (t , s .FromSignedPayload (payloads [i ]))
187+ require .Equal (t , c .protocolID , s .protocolID )
188+ require .Equal (t , uint32 (votingRound ), s .votingRoundID )
189+ require .Equal (t , c .protocolType , s .typeID )
190+ require .Len (t , s .signature , 65 )
191+ require .Equal (t , - 1 , s .voterIndex )
192+ if c .protocolType == 0 {
193+ require .Equal (t , c .data , []byte (s .message ))
194+ } else {
195+ require .Nil (t , s .message )
196+ }
197+ }
198+ }
199+
200+ // TestExtractPayloadsZeroLength confirms ExtractPayloads accepts a header with
201+ // length=0 and that FromSignedPayload rejects the resulting empty payload
202+ // rather than panicking.
203+ func TestExtractPayloadsZeroLength (t * testing.T ) {
28204 // 4-byte selector + 1-byte protocol + 4-byte votingRound + 2-byte length=0
29205 data := make ([]byte , 4 + 1 + 4 + 2 )
30206 binary .BigEndian .PutUint32 (data [5 :9 ], 1 )
@@ -35,6 +211,5 @@ func TestExtractPayloadsZeroLengthDoesNotPanic(t *testing.T) {
35211 require .Len (t , payloads , 1 )
36212
37213 var s submitSignaturesPayload
38- err = s .FromSignedPayload (payloads [0 ])
39- require .Error (t , err )
214+ require .Error (t , s .FromSignedPayload (payloads [0 ]))
40215}
0 commit comments