diff --git a/model/flow/payload.go b/model/flow/payload.go index d2c97dc5698..5e95ffd6c97 100644 --- a/model/flow/payload.go +++ b/model/flow/payload.go @@ -45,6 +45,26 @@ func NewPayload(untrusted UntrustedPayload) (*Payload, error) { if untrusted.ProtocolStateID == ZeroID { return nil, fmt.Errorf("ProtocolStateID must not be zero") } + for i, g := range untrusted.Guarantees { + if g == nil { + return nil, fmt.Errorf("guarantee at index %d is nil", i) + } + } + for i, s := range untrusted.Seals { + if s == nil { + return nil, fmt.Errorf("seal at index %d is nil", i) + } + } + for i, r := range untrusted.Receipts { + if r == nil { + return nil, fmt.Errorf("receipt at index %d is nil", i) + } + } + for i, r := range untrusted.Results { + if r == nil { + return nil, fmt.Errorf("result at index %d is nil", i) + } + } return &Payload{ Guarantees: untrusted.Guarantees, diff --git a/model/flow/payload_test.go b/model/flow/payload_test.go index c4a1f267648..c4ef10897c6 100644 --- a/model/flow/payload_test.go +++ b/model/flow/payload_test.go @@ -65,15 +65,6 @@ func TestPayloadEncodingMsgpack(t *testing.T) { } // TestNewPayload verifies the behavior of the NewPayload constructor. -// It ensures proper handling of both valid and invalid untrusted input fields. -// -// Test Cases: -// -// 1. Valid input: -// - Verifies that a properly populated UntrustedPayload results in a valid Payload. -// -// 2. Valid input with zero ProtocolStateID: -// - Ensures that an error is returned when ProtocolStateID is flow.ZeroID. func TestNewPayload(t *testing.T) { t.Run("valid input", func(t *testing.T) { payload := unittest.PayloadFixture( @@ -85,7 +76,7 @@ func TestNewPayload(t *testing.T) { require.NotNil(t, res) }) - t.Run("valid input with zero ProtocolStateID", func(t *testing.T) { + t.Run("zero ProtocolStateID rejected", func(t *testing.T) { payload := unittest.PayloadFixture() payload.ProtocolStateID = flow.ZeroID @@ -94,4 +85,52 @@ func TestNewPayload(t *testing.T) { require.Nil(t, res) require.Contains(t, err.Error(), "ProtocolStateID must not be zero") }) + + t.Run("nil Guarantee element rejected", func(t *testing.T) { + untrusted := flow.UntrustedPayload(unittest.PayloadFixture( + unittest.WithProtocolStateID(unittest.IdentifierFixture()), + )) + untrusted.Guarantees = []*flow.CollectionGuarantee{nil} + + res, err := flow.NewPayload(untrusted) + require.Error(t, err) + require.Nil(t, res) + require.Contains(t, err.Error(), "guarantee at index 0 is nil") + }) + + t.Run("nil Seal element rejected", func(t *testing.T) { + untrusted := flow.UntrustedPayload(unittest.PayloadFixture( + unittest.WithProtocolStateID(unittest.IdentifierFixture()), + )) + untrusted.Seals = []*flow.Seal{nil} + + res, err := flow.NewPayload(untrusted) + require.Error(t, err) + require.Nil(t, res) + require.Contains(t, err.Error(), "seal at index 0 is nil") + }) + + t.Run("nil Receipt element rejected", func(t *testing.T) { + untrusted := flow.UntrustedPayload(unittest.PayloadFixture( + unittest.WithProtocolStateID(unittest.IdentifierFixture()), + )) + untrusted.Receipts = flow.ExecutionReceiptStubList{nil} + + res, err := flow.NewPayload(untrusted) + require.Error(t, err) + require.Nil(t, res) + require.Contains(t, err.Error(), "receipt at index 0 is nil") + }) + + t.Run("nil Result element rejected", func(t *testing.T) { + untrusted := flow.UntrustedPayload(unittest.PayloadFixture( + unittest.WithProtocolStateID(unittest.IdentifierFixture()), + )) + untrusted.Results = flow.ExecutionResultList{nil} + + res, err := flow.NewPayload(untrusted) + require.Error(t, err) + require.Nil(t, res) + require.Contains(t, err.Error(), "result at index 0 is nil") + }) }