diff --git a/lib/parachain/collation_fetching.go b/lib/parachain/collation_fetching.go new file mode 100644 index 0000000000..44270456a2 --- /dev/null +++ b/lib/parachain/collation_fetching.go @@ -0,0 +1,85 @@ +package parachain + +import ( + "fmt" + + "github.com/ChainSafe/gossamer/lib/common" + "github.com/ChainSafe/gossamer/pkg/scale" +) + +// CollationFetchingRequest represents a request to retrieve +// the advertised collation at the specified relay chain block. +type CollationFetchingRequest struct { + // Relay parent we want a collation for + RelayParent common.Hash `scale:"1"` + + // Parachain id of the collation + ParaID ParaID `scale:"2"` +} + +// Encode returns the SCALE encoding of the CollationFetchingRequest +func (c *CollationFetchingRequest) Encode() ([]byte, error) { + return scale.Marshal(*c) +} + +// CollationFetchingResponse represents a response sent by collator +type CollationFetchingResponse scale.VaryingDataType + +// Collation represents a requested collation to be delivered +type Collation struct { + CandidateReceipt CandidateReceipt `scale:"1"` + PoV PoV `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 []byte + +// Index returns the index of varying data type +func (Collation) Index() uint { + return 0 +} + +// NewCollationFetchingResponse returns a new collation fetching response varying data type +func NewCollationFetchingResponse() CollationFetchingResponse { + vdt := scale.MustNewVaryingDataType(Collation{}) + return CollationFetchingResponse(vdt) +} + +// Set will set a value using the underlying varying data type +func (c *CollationFetchingResponse) Set(val scale.VaryingDataTypeValue) (err error) { + vdt := scale.VaryingDataType(*c) + err = vdt.Set(val) + if err != nil { + return + } + *c = CollationFetchingResponse(vdt) + return +} + +// Value returns the value from the underlying varying data type +func (c *CollationFetchingResponse) Value() (val scale.VaryingDataTypeValue, err error) { + vdt := scale.VaryingDataType(*c) + return vdt.Value() +} + +// Encode returns the SCALE encoding of the CollationFetchingResponse +func (c *CollationFetchingResponse) Encode() ([]byte, error) { + return scale.Marshal(*c) +} + +// Decode returns the SCALE decoding of the CollationFetchingResponse. +func (c *CollationFetchingResponse) Decode(in []byte) (err error) { + return scale.Unmarshal(in, c) +} + +// String formats a CollationFetchingResponse as a string +func (c *CollationFetchingResponse) String() string { + if c == nil { + return "CollationFetchingResponse=nil" + } + + v, _ := c.Value() + collation := v.(Collation) + return fmt.Sprintf("CollationFetchingResponse Collation=%+v", collation) +} diff --git a/lib/parachain/collation_fetching_test.go b/lib/parachain/collation_fetching_test.go new file mode 100644 index 0000000000..83671f79dd --- /dev/null +++ b/lib/parachain/collation_fetching_test.go @@ -0,0 +1,128 @@ +package parachain + +import ( + "testing" + + "github.com/ChainSafe/gossamer/lib/common" + "github.com/stretchr/testify/require" +) + +func TestEncodeCollationFetchingRequest(t *testing.T) { + collationFetchingRequest := CollationFetchingRequest{ + RelayParent: common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19"), + ParaID: 5, + } + + actualEncode, err := collationFetchingRequest.Encode() + require.NoError(t, err) + + expextedEncode := common.MustHexToBytes("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1905000000") + require.Equal(t, expextedEncode, actualEncode) +} + +func TestCollationFetchingResponse(t *testing.T) { + t.Parallel() + + testHash := common.MustHexToHash("0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19") + + var collatorID CollatorID + tempCollatID := common.MustHexToBytes("0x48215b9d322601e5b1a95164cea0dc4626f545f98343d07f1551eb9543c4b147") + copy(collatorID[:], tempCollatID) + + var collatorSignature CollatorSignature + tempSignature := common.MustHexToBytes(testDataStatement["collatorSignature"]) + copy(collatorSignature[:], tempSignature) + + collation := Collation{ + CandidateReceipt: CandidateReceipt{ + Descriptor: CandidateDescriptor{ + ParaID: uint32(1), + RelayParent: testHash, + Collator: collatorID, + PersistedValidationDataHash: testHash, + PovHash: testHash, + ErasureRoot: testHash, + Signature: collatorSignature, + ParaHead: testHash, + ValidationCodeHash: ValidationCodeHash(testHash), + }, + CommitmentsHash: testHash, + }, + PoV: PoV{1, 2, 3}, + } + + // expected encoding is generated by running rust test code: + // fn collation_fetching_response() { + // let test_hash: H256 = H256::from_str( + // "0x677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19" + // ).unwrap(); + // let collator_result = sr25519::Public::from_string( + // "0x48215b9d322601e5b1a95164cea0dc4626f545f98343d07f1551eb9543c4b147", + // ); + // if collator_result.is_err() { + // println!( + // "collator_result.unwrap_err()=> {:?}", + // collator_result.unwrap_err() + // ); + // } + // let collator = CollatorId::from(collator_result.unwrap()); + // let collsign = CollatorSignature::from(sr25519::Signature([ + // 198, 124, 185, 59, 240, 163, 111, 206, 227, 210, 157, 232, 166, 166, 154, 117, 150, 89, + // 104, 10, 207, 72, 100, 117, 224, 162, 85, 42, 95, 190, 216, 126, 69, 173, 206, 95, 41, 6, + // 152, 216, 89, 96, 149, 114, 43, 51, 89, 146, 39, 247, 70, 31, 81, 175, 134, 23, 200, 190, + // 116, 184, 148, 207, 27, 134, + // ])); + // let candidate_descriptor = CandidateDescriptor { + // para_id: 1.into(), + // relay_parent: test_hash, + // collator: collator.clone(), + // persisted_validation_data_hash: test_hash, + // pov_hash: test_hash, + // erasure_root: test_hash, + // signature: collsign.clone(), + // para_head: test_hash, + // validation_code_hash: ValidationCodeHash::from(test_hash), + // }; + // let candidate_receipt = CandidateReceipt{ + // descriptor: candidate_descriptor, + // commitments_hash: test_hash + // }; + // let pov = PoV{ + // block_data: vec![1, 2, 3].into() + // }; + // let collation_fetching_response = CollationFetchingResponse::Collation( + // candidate_receipt, pov + // ); + // println!( + // "CollationFetchingResponse encode => {:?}\n\n", + // collation_fetching_response.encode() + // ); + // } + encodedValue := common.MustHexToBytes(testDataCollationProtocol["collationFetchigResponse"]) + + t.Run("encode_collation_fetching_response", func(t *testing.T) { + t.Parallel() + + responseVDT := NewCollationFetchingResponse() + err := responseVDT.Set(collation) + require.NoError(t, err) + + actualEncode, err := responseVDT.Encode() + require.NoError(t, err) + + require.Equal(t, encodedValue, actualEncode) + }) + + t.Run("Decode_collation_fetching_response", func(t *testing.T) { + t.Parallel() + + responseVDT := NewCollationFetchingResponse() + err := responseVDT.Decode(encodedValue) + require.NoError(t, err) + + actualData, err := responseVDT.Value() + require.NoError(t, err) + + require.EqualValues(t, collation, actualData) + }) +} diff --git a/lib/parachain/testdata/collation_protocol.yaml b/lib/parachain/testdata/collation_protocol.yaml index f312759fc2..f5acb9fc2c 100644 --- a/lib/parachain/testdata/collation_protocol.yaml +++ b/lib/parachain/testdata/collation_protocol.yaml @@ -2,3 +2,5 @@ declare: "0x000048215b9d322601e5b1a95164cea0dc4626f545f98343d07f1551eb9543c4b14705000000c67cb93bf0a36fcee3d29de8a6a69a759659680acf486475e0a2552a5fbed87e45adce5f290698d8596095722b33599227f7461f51af8617c8be74b894cf1b86" collationSeconded: "0x000405050505050505050505050505050505050505050505050505050505050505050101000000050505050505050505050505050505050505050505050505050505050505050548215b9d322601e5b1a95164cea0dc4626f545f98343d07f1551eb9543c4b147050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505c67cb93bf0a36fcee3d29de8a6a69a759659680acf486475e0a2552a5fbed87e45adce5f290698d8596095722b33599227f7461f51af8617c8be74b894cf1b8605050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505040c01020300010c0102030c010203050000000000000005000000c67cb93bf0a36fcee3d29de8a6a69a759659680acf486475e0a2552a5fbed87e45adce5f290698d8596095722b33599227f7461f51af8617c8be74b894cf1b86" + +collationFetchigResponse: "0x0001000000677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c1948215b9d322601e5b1a95164cea0dc4626f545f98343d07f1551eb9543c4b147677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19c67cb93bf0a36fcee3d29de8a6a69a759659680acf486475e0a2552a5fbed87e45adce5f290698d8596095722b33599227f7461f51af8617c8be74b894cf1b86677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c19677811d2f3ded2489685468dbdb2e4fa280a249fba9356acceb2e823820e2c190c010203"