Skip to content

Commit

Permalink
handle validation errors InvalidOutputs and BadParent
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardmack committed Sep 10, 2024
1 parent 9b0f2e6 commit 31b83f1
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 16 deletions.
37 changes: 36 additions & 1 deletion dot/parachain/candidate-validation/candidate_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func (cv *CandidateValidation) validateFromChainState(msg ValidateFromChainState

persistedValidationData, validationCode, err := getValidationData(runtimeInstance,
msg.CandidateReceipt.Descriptor.ParaID)

if err != nil {
logger.Errorf("getting validation data: %w", err)
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Expand All @@ -173,6 +174,16 @@ func (cv *CandidateValidation) validateFromChainState(msg ValidateFromChainState
return
}

if persistedValidationData == nil {
badParent := BadParent
reason := ValidationResult{
InvalidResult: &badParent,
}
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Data: reason,
}
return
}
validationTask := &ValidationTask{
PersistedValidationData: *persistedValidationData,
ValidationCode: validationCode,
Expand All @@ -188,9 +199,33 @@ func (cv *CandidateValidation) validateFromChainState(msg ValidateFromChainState
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Err: err,
}
} else {
return
}
if !result.IsValid() {
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Data: *result,
}
return
}
valid, err := runtimeInstance.ParachainHostCheckValidationOutputs(parachaintypes.ParaID(msg.CandidateReceipt.
Descriptor.ParaID), result.ValidResult.CandidateCommitments)
if err != nil {
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Err: fmt.Errorf("check validation outputs: Bad request: %w", err),
}
return
}
if !valid {
invalidOutput := InvalidOutputs
reason := &ValidationResult{
InvalidResult: &invalidOutput,
}
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Data: *reason,
}
return
}
msg.Ch <- parachaintypes.OverseerFuncRes[ValidationResult]{
Data: *result,
}
}
73 changes: 60 additions & 13 deletions dot/parachain/candidate-validation/candidate_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ var (
paramsTooLarge = ParamsTooLarge
codeHashMismatch = CodeHashMismatch
badSignature = BadSignature
invalidOutputs = InvalidOutputs
badParent = BadParent
)

func createTestCandidateReceiptAndValidationCode(t *testing.T) (
func createTestCandidateReceiptAndValidationCodeWParaId(t *testing.T, id uint32) (
parachaintypes.CandidateReceipt, parachaintypes.ValidationCode) {
// this wasm was achieved by building polkadot's adder test parachain
runtimeFilePath := "./testdata/test_parachain_adder.wasm"
Expand All @@ -38,7 +40,7 @@ func createTestCandidateReceiptAndValidationCode(t *testing.T) (
collatorKeypair, err := sr25519.GenerateKeypair()
require.NoError(t, err)

descriptor := makeValidCandidateDescriptor(t, 1000,
descriptor := makeValidCandidateDescriptor(t, id,
common.MustHexToHash("0xded542bacb3ca6c033a57676f94ae7c8f36834511deb44e3164256fd3b1c0de0"),
common.MustHexToHash("0x690d8f252ef66ab0f969c3f518f90012b849aa5ac94e1752c5e5ae5a8996de37"),
common.MustHexToHash("0xb608991ffc48dd405fd4b10e92eaebe2b5a2eedf44d0c3efb8997fdee8bebed9"),
Expand Down Expand Up @@ -107,7 +109,7 @@ func TestCandidateValidation_wasm_invalid_magic_number(t *testing.T) {
func TestCandidateValidation_processMessageValidateFromExhaustive(t *testing.T) {
t.Parallel()

candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCode(t)
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCodeWParaId(t, 1000)
candidateReceipt2 := candidateReceipt
candidateReceipt2.Descriptor.PovHash = common.MustHexToHash(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
Expand Down Expand Up @@ -261,7 +263,7 @@ func TestCandidateValidation_processMessageValidateFromExhaustive(t *testing.T)
func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T) {
t.Parallel()

candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCode(t)
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCodeWParaId(t, 1000)
candidateReceipt2 := candidateReceipt
candidateReceipt2.Descriptor.PovHash = common.MustHexToHash(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
Expand All @@ -278,6 +280,11 @@ func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T)
candidateReceipt5 := candidateReceipt
candidateReceipt5.Descriptor.ParaID = 5

candidateReceipt6, _ := createTestCandidateReceiptAndValidationCodeWParaId(t, 6)

candidateReceipt7 := candidateReceipt
candidateReceipt7.Descriptor.ParaID = 7

ctrl := gomock.NewController(t)
t.Cleanup(ctrl.Finish)

Expand Down Expand Up @@ -318,6 +325,16 @@ func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T)
mockInstance.EXPECT().
ParachainHostValidationCode(uint32(1000), gomock.AssignableToTypeOf(parachaintypes.OccupiedCoreAssumption{})).
Return(&validationCode, nil)
validCandidateCommitments := parachaintypes.CandidateCommitments{
HeadData: parachaintypes.HeadData{Data: []byte{2, 0, 0, 0, 0, 0, 0, 0, 123, 207, 206, 8, 219, 227,
136, 82, 236, 169, 14, 100, 45, 100, 31, 177, 154, 160, 220, 245, 59, 106, 76, 168, 122, 109,
164, 169, 22, 46, 144, 39, 103, 92, 31, 78, 66, 72, 252, 64, 24, 194, 129, 162, 128, 1, 77, 147,
200, 229, 189, 242, 111, 198, 236, 139, 16, 143, 19, 245, 113, 233, 138, 210}},
ProcessedDownwardMessages: 0,
HrmpWatermark: 1,
}
mockInstance.EXPECT().ParachainHostCheckValidationOutputs(parachaintypes.ParaID(1000),
validCandidateCommitments).Return(true, nil)

mockInstance.EXPECT().
ParachainHostPersistedValidationData(
Expand Down Expand Up @@ -355,9 +372,26 @@ func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T)
ParachainHostValidationCode(uint32(5), gomock.AssignableToTypeOf(parachaintypes.OccupiedCoreAssumption{})).
Return(&validationCode, nil)

mockInstance.EXPECT().
ParachainHostPersistedValidationData(uint32(6), gomock.AssignableToTypeOf(parachaintypes.OccupiedCoreAssumption{})).
Return(&expectedPersistedValidationData, nil)
mockInstance.EXPECT().
ParachainHostValidationCode(uint32(6), gomock.AssignableToTypeOf(parachaintypes.OccupiedCoreAssumption{})).
Return(&validationCode, nil)
mockInstance.EXPECT().ParachainHostCheckValidationOutputs(parachaintypes.ParaID(6),
validCandidateCommitments).Return(false, nil)

mockInstance.EXPECT().
ParachainHostPersistedValidationData(uint32(7), gomock.AssignableToTypeOf(parachaintypes.
OccupiedCoreAssumption{})).
Return(nil, nil)
mockInstance.EXPECT().
ParachainHostValidationCode(uint32(7), gomock.AssignableToTypeOf(parachaintypes.OccupiedCoreAssumption{})).
Return(&validationCode, nil)

mockBlockState := NewMockBlockState(ctrl)
mockBlockState.EXPECT().GetRuntime(common.MustHexToHash(
"0xded542bacb3ca6c033a57676f94ae7c8f36834511deb44e3164256fd3b1c0de0")).Return(mockInstance, nil).Times(5)
"0xded542bacb3ca6c033a57676f94ae7c8f36834511deb44e3164256fd3b1c0de0")).Return(mockInstance, nil).Times(7)

bd, err := scale.Marshal(BlockDataInAdderParachain{
State: uint64(1),
Expand Down Expand Up @@ -423,6 +457,26 @@ func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T)
InvalidResult: &badSignature,
},
},
"invalid_outputs": {
msg: ValidateFromChainState{
CandidateReceipt: candidateReceipt6,
Pov: pov,
Ch: sender,
},
want: &ValidationResult{
InvalidResult: &invalidOutputs,
},
},
"bad_parent": {
msg: ValidateFromChainState{
CandidateReceipt: candidateReceipt7,
Pov: pov,
Ch: sender,
},
want: &ValidationResult{
InvalidResult: &badParent,
},
},
"happy_path": {
msg: ValidateFromChainState{
CandidateReceipt: candidateReceipt,
Expand All @@ -431,14 +485,7 @@ func TestCandidateValidation_processMessageValidateFromChainState(t *testing.T)
},
want: &ValidationResult{
ValidResult: &Valid{
CandidateCommitments: parachaintypes.CandidateCommitments{
HeadData: parachaintypes.HeadData{Data: []byte{2, 0, 0, 0, 0, 0, 0, 0, 123, 207, 206, 8, 219, 227,
136, 82, 236, 169, 14, 100, 45, 100, 31, 177, 154, 160, 220, 245, 59, 106, 76, 168, 122, 109,
164, 169, 22, 46, 144, 39, 103, 92, 31, 78, 66, 72, 252, 64, 24, 194, 129, 162, 128, 1, 77, 147,
200, 229, 189, 242, 111, 198, 236, 139, 16, 143, 19, 245, 113, 233, 138, 210}},
ProcessedDownwardMessages: 0,
HrmpWatermark: 1,
},
CandidateCommitments: validCandidateCommitments,
PersistedValidationData: parachaintypes.PersistedValidationData{
ParentHead: parachaintypes.HeadData{Data: []byte{1, 0, 0, 0, 0, 0, 0, 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
Expand Down
2 changes: 1 addition & 1 deletion dot/parachain/candidate-validation/host_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

func TestHost_validate(t *testing.T) {
t.Parallel()
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCode(t)
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCodeWParaId(t, 1000)
candidateReceipt2 := candidateReceipt
candidateReceipt2.Descriptor.PovHash = common.MustHexToHash(
"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef")
Expand Down
2 changes: 1 addition & 1 deletion dot/parachain/candidate-validation/worker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

func Test_worker_executeRequest(t *testing.T) {
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCode(t)
candidateReceipt, validationCode := createTestCandidateReceiptAndValidationCodeWParaId(t, 1000)

validationRuntime, err := parachain.SetupVM(validationCode)
require.NoError(t, err)
Expand Down

0 comments on commit 31b83f1

Please sign in to comment.