Skip to main content

corevm_host/
input_streams.rs

1use alloc::vec::Vec;
2use bytes::{Buf, Bytes};
3use codec::{Compact, Decode, Encode};
4use ed25519_consensus::{Signature, VerificationKey};
5
6const SIGNATURE_LEN: usize = 64;
7
8/// Input chunk.
9///
10/// Contains data for each stream.
11#[derive(Encode, Debug, Default, Clone)]
12pub struct InputChunk {
13	pub video: Bytes,
14	pub audio: Bytes,
15	// TODO @ivan Ideally console and host messages should be chunked and signed separately
16	// because they're consumed independently from video/audio.
17	pub console: Bytes,
18	/// Messages exchanged between the service and the host (builder/monitor etc.).
19	pub host_messages: Vec<Bytes>,
20}
21
22impl InputChunk {
23	/// Decode signed input chunk.
24	///
25	/// Checks the signature at the end of the input against the provided key before doing the usual
26	/// decoding.
27	pub fn decode_signed(mut input: Bytes, key: &VerificationKey) -> Result<Self, codec::Error> {
28		let signature_offset = input.len().checked_sub(SIGNATURE_LEN).ok_or("No signature")?;
29		let signature = input.split_off(signature_offset);
30		let signature: Signature = (&signature[..]).try_into().expect("Signature size is constant");
31		key.verify(&signature, &input[..]).map_err(|_| "Bad signature")?;
32		let mut input = BytesInput(input);
33		let video = input.decode_bytes()?;
34		let audio = input.decode_bytes()?;
35		let console = input.decode_bytes()?;
36		let Compact(len) = Compact::<u32>::decode(&mut input)?;
37		let mut host_messages = Vec::new();
38		for _ in 0..len {
39			host_messages.push(input.decode_bytes()?);
40		}
41		if !input.0.is_empty() {
42			return Err("Invalid InputChunk".into());
43		}
44		Ok(Self { video, audio, console, host_messages })
45	}
46
47	/// Decode multiple signed chunks from the extrinsic.
48	pub fn decode_multiple_signed(
49		extrinsic: Bytes,
50		key: &VerificationKey,
51	) -> Result<Vec<Self>, codec::Error> {
52		let mut chunks = Vec::new();
53		let mut input = BytesInput(extrinsic);
54		while !input.0.is_empty() {
55			let raw_chunk = input.decode_bytes()?;
56			let chunk = Self::decode_signed(raw_chunk, key)?;
57			chunks.push(chunk);
58		}
59		Ok(chunks)
60	}
61}
62
63struct BytesInput(Bytes);
64
65impl BytesInput {
66	/// Decode [`Bytes`] from the input without copying.
67	fn decode_bytes(&mut self) -> Result<Bytes, codec::Error> {
68		let Compact(len) = Compact::<u32>::decode(self)?;
69		if len > self.0.len() as u32 {
70			return Err("Invalid bytes".into());
71		}
72		let bytes = self.0.split_to(len as usize);
73		Ok(bytes)
74	}
75}
76
77impl codec::Input for BytesInput {
78	fn remaining_len(&mut self) -> Result<Option<usize>, codec::Error> {
79		Ok(Some(self.0.len()))
80	}
81
82	fn read(&mut self, buf: &mut [u8]) -> Result<(), codec::Error> {
83		let n = buf.len();
84		if n > self.0.len() {
85			return Err("Buffer overflow".into());
86		}
87		buf.copy_from_slice(&self.0[..n]);
88		self.0.advance(n);
89		Ok(())
90	}
91}