lib.rs 35.3 KB
Newer Older
		.unwrap();
		assert_matches!(v, ValidationResult::Invalid(InvalidCandidate::ExecutionError(_)));
	}

	#[test]
	fn candidate_validation_timeout_is_internal_error() {
		let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() };

		let pov = PoV { block_data: BlockData(vec![1; 32]) };
		let validation_code = ValidationCode(vec![2; 16]);

		let mut descriptor = CandidateDescriptor::default();
		descriptor.pov_hash = pov.hash();
		descriptor.validation_code_hash = validation_code.hash();
		collator_sign(&mut descriptor, Sr25519Keyring::Alice);

		let check = perform_basic_checks(
			&descriptor,
			validation_data.max_pov_size,
			&pov,
			&validation_code,
		);
		assert!(check.is_ok());
		let v = executor::block_on(validate_candidate_exhaustive(
			MockValidatorBackend::with_hardcoded_result(
				Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::HardTimeout)),
			),
			validation_code,
			descriptor,
			Arc::new(pov),
		assert_matches!(v, Ok(ValidationResult::Invalid(InvalidCandidate::Timeout)));

	#[test]
	fn candidate_validation_code_mismatch_is_invalid() {
		let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() };

		let pov = PoV { block_data: BlockData(vec![1; 32]) };
		let validation_code = ValidationCode(vec![2; 16]);

		let mut descriptor = CandidateDescriptor::default();
		descriptor.pov_hash = pov.hash();
		descriptor.validation_code_hash = ValidationCode(vec![1; 16]).hash();
		collator_sign(&mut descriptor, Sr25519Keyring::Alice);

		let check = perform_basic_checks(
			&descriptor,
			validation_data.max_pov_size,
			&pov,
			&validation_code,
		);
		assert_matches!(check, Err(InvalidCandidate::CodeHashMismatch));

		let v = executor::block_on(validate_candidate_exhaustive(
			MockValidatorBackend::with_hardcoded_result(
				Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::HardTimeout)),
			),
			validation_data,
			validation_code,
			descriptor,
			Arc::new(pov),
			&Default::default(),
		))
		.unwrap()
		.unwrap();

		assert_matches!(v, ValidationResult::Invalid(InvalidCandidate::CodeHashMismatch));
	}

	#[test]
	fn compressed_code_works() {
		let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() };
		let pov = PoV { block_data: BlockData(vec![1; 32]) };
		let head_data = HeadData(vec![1, 1, 1]);

		let raw_code = vec![2u8; 16];
		let validation_code = sp_maybe_compressed_blob::compress(
			&raw_code,
			VALIDATION_CODE_BOMB_LIMIT,
		)
			.map(ValidationCode)
			.unwrap();

		let mut descriptor = CandidateDescriptor::default();
		descriptor.pov_hash = pov.hash();
		descriptor.para_head = head_data.hash();
		descriptor.validation_code_hash = validation_code.hash();
		collator_sign(&mut descriptor, Sr25519Keyring::Alice);

		let validation_result = WasmValidationResult {
			head_data,
			new_validation_code: None,
			upward_messages: Vec::new(),
			horizontal_messages: Vec::new(),
			processed_downward_messages: 0,
			hrmp_watermark: 0,
		};

		let v = executor::block_on(validate_candidate_exhaustive(
			MockValidatorBackend::with_hardcoded_result(Ok(validation_result)),
			validation_data,
			validation_code,
			descriptor,
			Arc::new(pov),
			&Default::default(),

		assert_matches!(v, Ok(ValidationResult::Valid(_, _)));
	}

	#[test]
	fn code_decompression_failure_is_invalid() {
		let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() };
		let pov = PoV { block_data: BlockData(vec![1; 32]) };
		let head_data = HeadData(vec![1, 1, 1]);

		let raw_code = vec![2u8; VALIDATION_CODE_BOMB_LIMIT + 1];
		let validation_code = sp_maybe_compressed_blob::compress(
			&raw_code,
			VALIDATION_CODE_BOMB_LIMIT + 1,
		)
			.map(ValidationCode)
			.unwrap();

		let mut descriptor = CandidateDescriptor::default();
		descriptor.pov_hash = pov.hash();
		descriptor.para_head = head_data.hash();
		descriptor.validation_code_hash = validation_code.hash();
		collator_sign(&mut descriptor, Sr25519Keyring::Alice);

		let validation_result = WasmValidationResult {
			head_data,
			new_validation_code: None,
			upward_messages: Vec::new(),
			horizontal_messages: Vec::new(),
			processed_downward_messages: 0,
			hrmp_watermark: 0,
		};

		let v = executor::block_on(validate_candidate_exhaustive(
			MockValidatorBackend::with_hardcoded_result(Ok(validation_result)),
			validation_data,
			validation_code,
			descriptor,
			Arc::new(pov),
			&Default::default(),

		assert_matches!(
			v,
			Ok(ValidationResult::Invalid(InvalidCandidate::CodeDecompressionFailure))
		);
	}

	#[test]
	fn pov_decompression_failure_is_invalid() {
		let validation_data = PersistedValidationData {
			max_pov_size: POV_BOMB_LIMIT as u32,
			..Default::default()
		 };
		let head_data = HeadData(vec![1, 1, 1]);

		let raw_block_data = vec![2u8; POV_BOMB_LIMIT + 1];
		let pov = sp_maybe_compressed_blob::compress(
			&raw_block_data,
			POV_BOMB_LIMIT + 1,
		)
			.map(|raw| PoV { block_data: BlockData(raw) })
			.unwrap();

		let validation_code = ValidationCode(vec![2; 16]);

		let mut descriptor = CandidateDescriptor::default();
		descriptor.pov_hash = pov.hash();
		descriptor.para_head = head_data.hash();
		descriptor.validation_code_hash = validation_code.hash();
		collator_sign(&mut descriptor, Sr25519Keyring::Alice);

		let validation_result = WasmValidationResult {
			head_data,
			new_validation_code: None,
			upward_messages: Vec::new(),
			horizontal_messages: Vec::new(),
			processed_downward_messages: 0,
			hrmp_watermark: 0,
		};

		let v = executor::block_on(validate_candidate_exhaustive(
			MockValidatorBackend::with_hardcoded_result(Ok(validation_result)),
			validation_data,
			validation_code,
			descriptor,
			Arc::new(pov),
			&Default::default(),

		assert_matches!(
			v,
			Ok(ValidationResult::Invalid(InvalidCandidate::PoVDecompressionFailure))
		);
	}