sort FromExtWitness input to sanitize it

This commit is contained in:
Guillaume Ballet 2026-05-21 17:57:01 +02:00
parent 40dc49e8bc
commit d82790a19a
2 changed files with 10 additions and 18 deletions

View file

@ -58,9 +58,11 @@ func (w *Witness) FromExtWitness(ext *ExtWitness) error {
return errors.New("witness must contain at least one header")
}
w.Headers = slices.Clone(ext.Headers)
if headersAscending(w.Headers) {
slices.Reverse(w.Headers)
}
// don't trust the input and sort headers in reverse order
// this is only useful for calling `Root`
slices.SortFunc(w.Headers, func(a, b *types.Header) int {
return b.Number.Cmp(a.Number)
})
w.Codes = make(map[string]struct{}, len(ext.Codes))
for _, code := range ext.Codes {
@ -73,20 +75,6 @@ func (w *Witness) FromExtWitness(ext *ExtWitness) error {
return nil
}
// headersAscending reports whether headers are in the external witness order,
// oldest ancestor first and parent last. The internal witness keeps headers in
// the opposite order so Root can retrieve the parent root from Headers[0].
func headersAscending(headers []*types.Header) bool {
if len(headers) < 2 {
return false
}
first, last := headers[0], headers[len(headers)-1]
if first == nil || last == nil || first.Number == nil || last.Number == nil {
return false
}
return first.Number.Cmp(last.Number) < 0
}
// EncodeRLP serializes a witness as RLP.
func (w *Witness) EncodeRLP(wr io.Writer) error {
return rlp.Encode(wr, w.ToExtWitness())

View file

@ -65,7 +65,11 @@ func TestWitnessFromExtWitnessNormalizesHeaderOrder(t *testing.T) {
headers: []*types.Header{testHeader(1), testHeader(2), testHeader(3)},
},
{
name: "legacy internal ordered",
name: "not ordered",
headers: []*types.Header{testHeader(2), testHeader(3), testHeader(1)},
},
{
name: "internal ordered",
headers: []*types.Header{testHeader(3), testHeader(2), testHeader(1)},
},
}