From edbc71d2cd4edc198aaeeb2a89b9c8ea66aac23b Mon Sep 17 00:00:00 2001 From: Oleg Kovalov Date: Wed, 29 May 2024 20:20:45 +0200 Subject: [PATCH] feat: require non-zero headers for Verify (#184) * docs: document trusted header in Verify * stricted verification * Update verify.go Co-authored-by: Hlib Kanunnikov --------- Co-authored-by: Hlib Kanunnikov --- headertest/verify_test.go | 27 ++++++++++++++++++++++++++- verify.go | 6 +++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/headertest/verify_test.go b/headertest/verify_test.go index 2774c056..35456991 100644 --- a/headertest/verify_test.go +++ b/headertest/verify_test.go @@ -14,6 +14,7 @@ import ( func TestVerify(t *testing.T) { suite := NewTestSuite(t) trusted := suite.GenDummyHeaders(1)[0] + var zero *DummyHeader next := func() *DummyHeader { next := *suite.NextHeader() @@ -21,11 +22,13 @@ func TestVerify(t *testing.T) { } tests := []struct { + trusted *DummyHeader prepare func() *DummyHeader err error soft bool }{ { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.VerifyFailure = true @@ -34,6 +37,7 @@ func TestVerify(t *testing.T) { err: ErrDummyVerify, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.VerifyFailure = true @@ -43,17 +47,20 @@ func TestVerify(t *testing.T) { soft: true, // soft because non-adjacent }, { + trusted: trusted, prepare: func() *DummyHeader { return next() }, }, { + trusted: trusted, prepare: func() *DummyHeader { return nil }, err: header.ErrZeroHeader, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.Chainid = "gtmb" @@ -62,6 +69,7 @@ func TestVerify(t *testing.T) { err: header.ErrWrongChainID, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.Timestamp = untrusted.Timestamp.Truncate(time.Minute * 10) @@ -70,6 +78,7 @@ func TestVerify(t *testing.T) { err: header.ErrUnorderedTime, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.Timestamp = untrusted.Timestamp.Add(time.Minute) @@ -78,6 +87,7 @@ func TestVerify(t *testing.T) { err: header.ErrFromFuture, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.HeightI = trusted.Height() @@ -86,6 +96,7 @@ func TestVerify(t *testing.T) { err: header.ErrKnownHeader, }, { + trusted: trusted, prepare: func() *DummyHeader { untrusted := next() untrusted.HeightI += 100000 @@ -93,11 +104,25 @@ func TestVerify(t *testing.T) { }, err: header.ErrHeightFromFuture, }, + { + trusted: trusted, + prepare: func() *DummyHeader { + return zero + }, + err: header.ErrZeroHeader, + }, + { + trusted: zero, + prepare: func() *DummyHeader { + return next() + }, + err: header.ErrZeroHeader, + }, } for i, test := range tests { t.Run(strconv.Itoa(i), func(t *testing.T) { - err := header.Verify(trusted, test.prepare(), 0) + err := header.Verify(test.trusted, test.prepare(), 0) if test.err != nil { var verErr *header.VerifyError assert.ErrorAs(t, err, &verErr) diff --git a/verify.go b/verify.go index 0c1f3e9e..72888ef8 100644 --- a/verify.go +++ b/verify.go @@ -11,8 +11,9 @@ import ( const DefaultHeightThreshold uint64 = 80000 // ~ 14 days of 15 second headers // Verify verifies untrusted Header against trusted following general Header checks and -// custom user-specific checks defined in Header.Verify +// custom user-specific checks defined in Header.Verify. // +// Given headers must be non-zero // If heightThreshold is zero, uses DefaultHeightThreshold. // Always returns VerifyError. func Verify[H Header[H]](trstd, untrstd H, heightThreshold uint64) error { @@ -50,6 +51,9 @@ func verify[H Header[H]](trstd, untrstd H, heightThreshold uint64) error { heightThreshold = DefaultHeightThreshold } + if trstd.IsZero() { + return ErrZeroHeader + } if untrstd.IsZero() { return ErrZeroHeader }