11package transaction
22
33import (
4+ "encoding/hex"
45 "math/big"
56 "strings"
67 "testing"
78
89 "github.com/ethereum/go-ethereum/common"
10+ "github.com/ethereum/go-ethereum/rlp"
911 "github.com/google/go-cmp/cmp"
1012 "github.com/stretchr/testify/assert"
1113 "github.com/tempoxyz/tempo-go/pkg/signer"
@@ -331,45 +333,84 @@ func TestDecodeAccessList(t *testing.T) {
331333}
332334
333335func TestDecodeSignature (t * testing.T ) {
336+ big33Bytes := new (big.Int ).Lsh (big .NewInt (1 ), 256 )
337+ max32Bytes := new (big.Int ).Sub (new (big.Int ).Lsh (big .NewInt (1 ), 256 ), big .NewInt (1 ))
338+
334339 tests := []struct {
335- name string
336- input []interface {}
337- want * signer.Signature
338- wantErr bool
340+ name string
341+ r []byte
342+ s []byte
343+ yParity byte
344+ want * signer.Signature
345+ wantErr bool
346+ wantErrStr string
339347 }{
340348 {
341- name : "valid signature" ,
342- input : []interface {}{
343- []byte {0 },
344- big .NewInt (12345 ).Bytes (),
345- big .NewInt (67890 ).Bytes (),
346- },
347- want : signer .NewSignature (big .NewInt (12345 ), big .NewInt (67890 ), 0 ),
349+ name : "valid signature" ,
350+ r : big .NewInt (12345 ).Bytes (),
351+ s : big .NewInt (67890 ).Bytes (),
352+ yParity : 0 ,
353+ want : signer .NewSignature (big .NewInt (12345 ), big .NewInt (67890 ), 0 ),
348354 },
349355 {
350- name : "signature with yParity = 1" ,
351- input : []interface {}{
352- []byte {1 },
353- big .NewInt (12345 ).Bytes (),
354- big .NewInt (67890 ).Bytes (),
355- },
356- want : signer .NewSignature (big .NewInt (12345 ), big .NewInt (67890 ), 1 ),
356+ name : "signature with yParity = 1" ,
357+ r : big .NewInt (12345 ).Bytes (),
358+ s : big .NewInt (67890 ).Bytes (),
359+ yParity : 1 ,
360+ want : signer .NewSignature (big .NewInt (12345 ), big .NewInt (67890 ), 1 ),
357361 },
358362 {
359- name : "invalid - wrong length" ,
360- input : []interface {}{
361- []byte {0 },
362- big .NewInt (12345 ).Bytes (),
363- },
364- wantErr : true ,
363+ name : "empty R and S" ,
364+ r : []byte {},
365+ s : []byte {},
366+ yParity : 0 ,
367+ want : signer .NewSignature (big .NewInt (0 ), big .NewInt (0 ), 0 ),
368+ },
369+ {
370+ name : "max valid size (32 bytes)" ,
371+ r : max32Bytes .Bytes (),
372+ s : max32Bytes .Bytes (),
373+ yParity : 0 ,
374+ want : signer .NewSignature (max32Bytes , max32Bytes , 0 ),
375+ },
376+ {
377+ name : "oversized R (33 bytes)" ,
378+ r : big33Bytes .Bytes (),
379+ s : big .NewInt (1 ).Bytes (),
380+ yParity : 0 ,
381+ wantErr : true ,
382+ wantErrStr : "r exceeds maximum size" ,
383+ },
384+ {
385+ name : "oversized S (33 bytes)" ,
386+ r : big .NewInt (1 ).Bytes (),
387+ s : big33Bytes .Bytes (),
388+ yParity : 0 ,
389+ wantErr : true ,
390+ wantErrStr : "s exceeds maximum size" ,
391+ },
392+ {
393+ name : "oversized R and S" ,
394+ r : big33Bytes .Bytes (),
395+ s : big33Bytes .Bytes (),
396+ yParity : 0 ,
397+ wantErr : true ,
398+ wantErrStr : "r exceeds maximum size" ,
365399 },
366400 }
367401
368402 for _ , tt := range tests {
369403 t .Run (tt .name , func (t * testing.T ) {
370- got , err := decodeSignature (tt .input )
404+ input := []interface {}{
405+ []byte {tt .yParity },
406+ tt .r ,
407+ tt .s ,
408+ }
409+ got , err := decodeSignature (input )
371410 if tt .wantErr {
372411 assert .Error (t , err )
412+ assert .Nil (t , got )
413+ assert .Contains (t , err .Error (), tt .wantErrStr )
373414 return
374415 }
375416 assert .NoError (t , err )
@@ -380,6 +421,16 @@ func TestDecodeSignature(t *testing.T) {
380421 }
381422}
382423
424+ func TestDecodeSignature_InvalidTupleLength (t * testing.T ) {
425+ input := []interface {}{
426+ []byte {0 },
427+ big .NewInt (12345 ).Bytes (),
428+ }
429+ got , err := decodeSignature (input )
430+ assert .Error (t , err )
431+ assert .Nil (t , got )
432+ }
433+
383434func TestRoundtrip (t * testing.T ) {
384435 tests := []struct {
385436 name string
@@ -568,6 +619,69 @@ func TestRoundtripWithOptions(t *testing.T) {
568619 })
569620}
570621
622+ func TestDeserialize_OversizedSignature (t * testing.T ) {
623+ big33Bytes := new (big.Int ).Lsh (big .NewInt (1 ), 256 ) // 33 bytes
624+
625+ tests := []struct {
626+ name string
627+ r []byte
628+ s []byte
629+ wantErrStr string
630+ }{
631+ {
632+ name : "oversized R in fee payer signature" ,
633+ r : big33Bytes .Bytes (),
634+ s : big .NewInt (1 ).Bytes (),
635+ wantErrStr : "r exceeds maximum size" ,
636+ },
637+ {
638+ name : "oversized S in fee payer signature" ,
639+ r : big .NewInt (1 ).Bytes (),
640+ s : big33Bytes .Bytes (),
641+ wantErrStr : "s exceeds maximum size" ,
642+ },
643+ }
644+
645+ for _ , tt := range tests {
646+ t .Run (tt .name , func (t * testing.T ) {
647+ rlpList := []interface {}{
648+ big .NewInt (42424 ).Bytes (), // chainId
649+ big .NewInt (1000000 ).Bytes (), // maxPriorityFeePerGas
650+ big .NewInt (2000000 ).Bytes (), // maxFeePerGas
651+ big .NewInt (21000 ).Bytes (), // gas
652+ []interface {}{ // calls
653+ []interface {}{
654+ common .HexToAddress ("0x1234567890123456789012345678901234567890" ).Bytes (),
655+ big .NewInt (1000000 ).Bytes (),
656+ []byte {},
657+ },
658+ },
659+ []interface {}{}, // accessList
660+ []byte {}, // nonceKey
661+ big .NewInt (1 ).Bytes (), // nonce
662+ []byte {}, // validBefore
663+ []byte {}, // validAfter
664+ []byte {}, // feeToken
665+ []interface {}{ // fee payer signature
666+ []byte {0 },
667+ tt .r ,
668+ tt .s ,
669+ },
670+ []interface {}{}, // authorizationList
671+ }
672+
673+ rlpBytes , err := rlp .EncodeToBytes (rlpList )
674+ assert .NoError (t , err )
675+
676+ serialized := "0x76" + hex .EncodeToString (rlpBytes )
677+
678+ _ , err = Deserialize (serialized )
679+ assert .Error (t , err )
680+ assert .Contains (t , err .Error (), tt .wantErrStr )
681+ })
682+ }
683+ }
684+
571685// Helper functions
572686
573687func hexToBigInt (s string ) * big.Int {
0 commit comments