-
Notifications
You must be signed in to change notification settings - Fork 116
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_…
…chunk/1 protocol (#3362) - Added `ChunkFetchingRequest` and `ChunkFetchingResponse` types. - implemented network.Message interface in `ChunkFetchingRequest` and 'network.ResponseMessage' interface in `ChunkFetchingResponse`
- Loading branch information
1 parent
bed63fa
commit 6de96d7
Showing
2 changed files
with
176 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,93 @@ | ||
package parachain | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/ChainSafe/gossamer/pkg/scale" | ||
) | ||
|
||
// ChunkFetchingRequest represents a request to retrieve chunks of a parachain candidate | ||
type ChunkFetchingRequest struct { | ||
// Hash of candidate we want a chunk for. | ||
CandidateHash CandidateHash `scale:"1"` | ||
|
||
// The index of the chunk to fetch. | ||
Index ValidatorIndex `scale:"2"` | ||
} | ||
|
||
// Encode returns the SCALE encoding of the ChunkFetchingRequest | ||
func (c ChunkFetchingRequest) Encode() ([]byte, error) { | ||
return scale.Marshal(c) | ||
} | ||
|
||
// ChunkFetchingResponse represents the response for a requested erasure chunk | ||
type ChunkFetchingResponse scale.VaryingDataType | ||
|
||
// NewChunkFetchingResponse returns a new chunk fetching response varying data type | ||
func NewChunkFetchingResponse() ChunkFetchingResponse { | ||
vdt := scale.MustNewVaryingDataType(ChunkResponse{}, NoSuchChunk{}) | ||
return ChunkFetchingResponse(vdt) | ||
} | ||
|
||
// Set will set a value using the underlying varying data type | ||
func (c *ChunkFetchingResponse) Set(val scale.VaryingDataTypeValue) (err error) { | ||
vdt := scale.VaryingDataType(*c) | ||
err = vdt.Set(val) | ||
if err != nil { | ||
return | ||
} | ||
*c = ChunkFetchingResponse(vdt) | ||
return | ||
} | ||
|
||
// Value returns the value from the underlying varying data type | ||
func (c *ChunkFetchingResponse) Value() (val scale.VaryingDataTypeValue, err error) { | ||
vdt := scale.VaryingDataType(*c) | ||
return vdt.Value() | ||
} | ||
|
||
// ChunkResponse represents the requested chunk data | ||
type ChunkResponse struct { | ||
// The erasure-encoded chunk of data belonging to the candidate block | ||
Chunk []byte `scale:"1"` | ||
|
||
// Proof for this chunk's branch in the Merkle tree | ||
Proof [][]byte `scale:"2"` | ||
} | ||
|
||
// Index returns the index of varying data type | ||
func (ChunkResponse) Index() uint { | ||
return 0 | ||
} | ||
|
||
// NoSuchChunk indicates that the requested chunk was not found | ||
type NoSuchChunk struct{} | ||
|
||
// Index returns the index of varying data type | ||
func (NoSuchChunk) Index() uint { | ||
return 1 | ||
} | ||
|
||
// Encode returns the SCALE encoding of the ChunkFetchingResponse | ||
func (c *ChunkFetchingResponse) Encode() ([]byte, error) { | ||
return scale.Marshal(*c) | ||
} | ||
|
||
// Decode returns the SCALE decoding of the ChunkFetchingResponse. | ||
func (c *ChunkFetchingResponse) Decode(in []byte) (err error) { | ||
return scale.Unmarshal(in, c) | ||
} | ||
|
||
// String formats a ChunkFetchingResponse as a string | ||
func (c *ChunkFetchingResponse) String() string { | ||
if c == nil { | ||
return "ChunkFetchingResponse=nil" | ||
} | ||
|
||
v, _ := c.Value() | ||
chunkRes, ok := v.(ChunkResponse) | ||
if !ok { | ||
return "ChunkFetchingResponse=NoSuchChunk" | ||
} | ||
return fmt.Sprintf("ChunkFetchingResponse ChunkResponse=%+v", chunkRes) | ||
} |
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,83 @@ | ||
package parachain | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/ChainSafe/gossamer/lib/common" | ||
"github.com/ChainSafe/gossamer/pkg/scale" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEncodeChunkFetchingRequest(t *testing.T) { | ||
chunkFetchingRequest := ChunkFetchingRequest{ | ||
CandidateHash: CandidateHash{ | ||
common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"), | ||
}, | ||
Index: ValidatorIndex(8), | ||
} | ||
|
||
actualEncode, err := chunkFetchingRequest.Encode() | ||
require.NoError(t, err) | ||
|
||
expextedEncode := common.MustHexToBytes("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1908000000") | ||
require.Equal(t, expextedEncode, actualEncode) | ||
} | ||
|
||
func TestChunkFetchingResponse(t *testing.T) { | ||
t.Parallel() | ||
|
||
testBytes := common.MustHexToBytes("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19") | ||
testCases := []struct { | ||
name string | ||
value scale.VaryingDataTypeValue | ||
encodeValue []byte | ||
}{ | ||
{ | ||
name: "chunkResponse", | ||
value: ChunkResponse{ | ||
Chunk: testBytes, | ||
Proof: [][]byte{testBytes}, | ||
}, | ||
encodeValue: common.MustHexToBytes("0x0080677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c190480677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"), //nolint:lll | ||
}, | ||
{ | ||
name: "NoSuchChunk", | ||
value: NoSuchChunk{}, | ||
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() | ||
|
||
chunkFetchingResponse := NewChunkFetchingResponse() | ||
err := chunkFetchingResponse.Set(c.value) | ||
require.NoError(t, err) | ||
|
||
actualEncode, err := chunkFetchingResponse.Encode() | ||
require.NoError(t, err) | ||
|
||
require.Equal(t, c.encodeValue, actualEncode) | ||
}) | ||
|
||
t.Run("decode", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
chunkFetchingResponse := NewChunkFetchingResponse() | ||
err := chunkFetchingResponse.Decode(c.encodeValue) | ||
require.NoError(t, err) | ||
|
||
actualData, err := chunkFetchingResponse.Value() | ||
require.NoError(t, err) | ||
|
||
require.EqualValues(t, c.value, actualData) | ||
}) | ||
|
||
}) | ||
} | ||
} |