-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(lib/parachain): Implement request and response message for /req_…
…available_data/1 protocol (#3368) - Added AvailableDataFetchingRequest and AvailableDataFetchingResponse types. - Implemented 'network.Message' interface in AvailableDataFetchingRequest and 'network.ResponseMessage' interface in AvailableDataFetchingResponse as they will be passed into this function as req and res.
- Loading branch information
1 parent
b2f9595
commit 26269b9
Showing
2 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package parachain | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/pkg/scale" | ||
) | ||
|
||
// AvailableDataFetchingRequest represents a request to retrieve all available data for a specific candidate. | ||
type AvailableDataFetchingRequest struct { | ||
// Hash of the candidate for which the available data is requested. | ||
CandidateHash CandidateHash | ||
} | ||
|
||
// Encode returns the SCALE encoding of the AvailableDataFetchingRequest | ||
func (a AvailableDataFetchingRequest) Encode() ([]byte, error) { | ||
return scale.Marshal(a) | ||
} | ||
|
||
// AvailableDataFetchingResponse represents the possible responses to an available data fetching request. | ||
type AvailableDataFetchingResponse scale.VaryingDataType | ||
|
||
// NewAvailableDataFetchingResponse returns a new available data fetching response varying data type | ||
func NewAvailableDataFetchingResponse() AvailableDataFetchingResponse { | ||
vdt := scale.MustNewVaryingDataType(AvailableData{}, NoSuchData{}) | ||
return AvailableDataFetchingResponse(vdt) | ||
} | ||
|
||
// Set will set a value using the underlying varying data type | ||
func (a *AvailableDataFetchingResponse) Set(val scale.VaryingDataTypeValue) (err error) { | ||
vdt := scale.VaryingDataType(*a) | ||
err = vdt.Set(val) | ||
if err != nil { | ||
return | ||
} | ||
*a = AvailableDataFetchingResponse(vdt) | ||
return | ||
} | ||
|
||
// Value returns the value from the underlying varying data type | ||
func (a *AvailableDataFetchingResponse) Value() (val scale.VaryingDataTypeValue, err error) { | ||
vdt := scale.VaryingDataType(*a) | ||
return vdt.Value() | ||
} | ||
|
||
// AvailableData represents the data that is kept available for each candidate included in the relay chain. | ||
type AvailableData struct { | ||
// The Proof-of-Validation (PoV) of the candidate | ||
PoV Pov `scale:"1"` | ||
|
||
// The persisted validation data needed for approval checks | ||
ValidationData PersistedValidationData `scale:"2"` | ||
} | ||
|
||
// Pov represents a Proof-of-Validity block (PoV block) or a parachain block. | ||
// It contains the necessary data for the parachain specific state transition logic. | ||
type Pov struct { | ||
BlockData BlockData `scale:"1"` | ||
} | ||
|
||
// BlockData represents parachain block data. | ||
// It contains everything required to validate para-block, may contain block and witness data. | ||
type BlockData []byte | ||
|
||
// Index returns the index of varying data type | ||
func (AvailableData) Index() uint { | ||
return 0 | ||
} | ||
|
||
// PersistedValidationData provides information about how to create the inputs for the validation | ||
// of a candidate by calling the Runtime. | ||
// This information is derived from the parachain state and will vary from parachain to parachain, | ||
// although some of the fields may be the same for every parachain. | ||
type PersistedValidationData struct { | ||
// The parent head-data | ||
ParentHead headData `scale:"1"` | ||
|
||
// The relay-chain block number this is in the context of | ||
RelayParentNumber BlockNumber `scale:"2"` | ||
|
||
// The relay-chain block storage root this is in the context of | ||
RelayParentStorageRoot common.Hash `scale:"3"` | ||
|
||
// The maximum legal size of a POV block, in bytes | ||
MaxPovSize uint32 `scale:"4"` | ||
} | ||
|
||
// NoSuchData indicates that the requested data was not found. | ||
type NoSuchData struct{} | ||
|
||
// Index returns the index of varying data type | ||
func (NoSuchData) Index() uint { | ||
return 1 | ||
} | ||
|
||
// Encode returns the SCALE encoding of the AvailableDataFetchingResponse | ||
func (a *AvailableDataFetchingResponse) Encode() ([]byte, error) { | ||
return scale.Marshal(*a) | ||
} | ||
|
||
// Decode returns the SCALE decoding of the AvailableDataFetchingResponse. | ||
func (a *AvailableDataFetchingResponse) Decode(in []byte) (err error) { | ||
return scale.Unmarshal(in, a) | ||
} | ||
|
||
// String formats a AvailableDataFetchingResponse as a string | ||
func (p *AvailableDataFetchingResponse) String() string { | ||
if p == nil { | ||
return "AvailableDataFetchingResponse=nil" | ||
} | ||
|
||
v, _ := p.Value() | ||
availableData, ok := v.(AvailableData) | ||
if !ok { | ||
return "AvailableDataFetchingResponse=NoSuchData" | ||
} | ||
return fmt.Sprintf("AvailableDataFetchingResponse AvailableData=%+v", availableData) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package parachain | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/pkg/scale" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEncodeAvailableDataFetchingRequest(t *testing.T) { | ||
availableDataFetchingRequest := AvailableDataFetchingRequest{ | ||
CandidateHash: CandidateHash{ | ||
common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"), | ||
}, | ||
} | ||
|
||
actualEncode, err := availableDataFetchingRequest.Encode() | ||
require.NoError(t, err) | ||
|
||
expextedEncode := common.MustHexToBytes("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19") | ||
require.Equal(t, expextedEncode, actualEncode) | ||
} | ||
|
||
func TestAvailableDataFetchingResponse(t *testing.T) { | ||
t.Parallel() | ||
|
||
testHash := common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19") | ||
testBytes := testHash.ToBytes() | ||
availableData := AvailableData{ | ||
PoV: Pov{BlockData: testBytes}, | ||
ValidationData: PersistedValidationData{ | ||
ParentHead: testBytes, | ||
RelayParentNumber: BlockNumber(4), | ||
RelayParentStorageRoot: testHash, | ||
MaxPovSize: 6, | ||
}, | ||
} | ||
|
||
testCases := []struct { | ||
name string | ||
value scale.VaryingDataTypeValue | ||
encodeValue []byte | ||
}{ | ||
{ | ||
name: "AvailableData", | ||
value: availableData, | ||
encodeValue: common.MustHexToBytes("0x0080677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1980677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1904000000677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1906000000"), //nolint:lll | ||
}, | ||
{ | ||
name: "NoSuchData", | ||
value: NoSuchData{}, | ||
encodeValue: []byte{1}, | ||
}, | ||
} | ||
|
||
for _, c := range testCases { | ||
c := c | ||
t.Run(c.name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
t.Run("encode", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
availableDataFetchingResponse := NewAvailableDataFetchingResponse() | ||
err := availableDataFetchingResponse.Set(c.value) | ||
require.NoError(t, err) | ||
|
||
actualEncode, err := availableDataFetchingResponse.Encode() | ||
require.NoError(t, err) | ||
|
||
require.Equal(t, c.encodeValue, actualEncode) | ||
}) | ||
|
||
t.Run("decode", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
availableDataFetchingResponse := NewAvailableDataFetchingResponse() | ||
err := availableDataFetchingResponse.Decode(c.encodeValue) | ||
require.NoError(t, err) | ||
|
||
actualData, err := availableDataFetchingResponse.Value() | ||
require.NoError(t, err) | ||
|
||
require.EqualValues(t, c.value, actualData) | ||
}) | ||
|
||
}) | ||
} | ||
} |