6
6
"time"
7
7
8
8
"github.com/fxamacker/cbor/v2"
9
- "github.com/onflow/crypto"
10
9
"github.com/stretchr/testify/assert"
11
10
"github.com/stretchr/testify/require"
12
11
"github.com/vmihailenco/msgpack/v4"
@@ -35,19 +34,7 @@ func TestHeaderFingerprint(t *testing.T) {
35
34
header .LastViewTC = helper .MakeTC ()
36
35
headerID := header .ID ()
37
36
data := header .Fingerprint ()
38
- var decoded struct {
39
- ChainID flow.ChainID
40
- ParentID flow.Identifier
41
- Height uint64
42
- PayloadHash flow.Identifier
43
- Timestamp uint64
44
- View uint64
45
- ParentView uint64
46
- ParentVoterIndices []byte
47
- ParentVoterSigData crypto.Signature
48
- ProposerID flow.Identifier
49
- LastViewTC interface {}
50
- }
37
+ var decoded flow.Body
51
38
rlp .NewMarshaler ().MustUnmarshal (data , & decoded )
52
39
decHeader := & flow.Header {
53
40
ChainID : decoded .ChainID ,
@@ -60,7 +47,7 @@ func TestHeaderFingerprint(t *testing.T) {
60
47
ParentVoterIndices : decoded .ParentVoterIndices ,
61
48
ParentVoterSigData : decoded .ParentVoterSigData ,
62
49
ProposerID : decoded .ProposerID ,
63
- ProposerSigData : header .ProposerSigData , // since this field is not encoded/decoded, just set it to the original value to pass test
50
+ ProposerSigData : decoded .ProposerSigData ,
64
51
LastViewTC : header .LastViewTC ,
65
52
}
66
53
decodedID := decHeader .ID ()
@@ -102,3 +89,11 @@ func TestNonUTCTimestampSameHashAsUTC(t *testing.T) {
102
89
checkedID := header .ID ()
103
90
assert .Equal (t , headerID , checkedID )
104
91
}
92
+
93
+ func TestHeaderMalleability (t * testing.T ) {
94
+ header := unittest .BlockHeaderFixture ()
95
+ // Require that LastViewTC (TimeoutCertificate) is not malleable, since its ID is incorporated in Body
96
+ unittest .RequireEntityNonMalleable (t , helper .MakeTC ())
97
+ // Body contains all data from the header, but with the timestamp converted to Unix time, and LastViewTC replaced with its ID
98
+ unittest .RequireEntityNonMalleable (t , header .Body ())
99
+ }
0 commit comments