Skip to main content

midnight_circuits/instructions/
base64.rs

1// This file is part of MIDNIGHT-ZK.
2// Copyright (C) Midnight Foundation
3// SPDX-License-Identifier: Apache-2.0
4// Licensed under the Apache License, Version 2.0 (the "License");
5// You may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7// http://www.apache.org/licenses/LICENSE-2.0
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//! Set of Base64 instructions.
15use midnight_proofs::{
16    circuit::{Layouter, Value},
17    plonk::Error,
18};
19
20use crate::{
21    types::{AssignedByte, AssignedVector},
22    CircuitField,
23};
24
25/// This trait defines methods for converting data encoded in standard Base64 or
26/// Base64URL (URL-safe) format into its raw byte representation.
27pub trait Base64Instructions<F: CircuitField> {
28    /// Receives a base64 url-safe encoded string as [AssignedByte]s and returns
29    /// the decoded ASCII string as a vector of [AssignedByte].
30    /// If `padded` is selected, the input length must be a multiple of 4.
31    ///
32    /// The length of the output is always 3/4 of the padded input's length.
33    /// In order to reach this length, the output will be completed with one or
34    /// two ASCII_ZERO chars if necessary.
35    ///
36    /// # Panics
37    ///
38    /// If `padded` = true and the input length is not a multiple of 4.
39    fn decode_base64url(
40        &self,
41        layouter: &mut impl Layouter<F>,
42        b64url_input: &[AssignedByte<F>],
43        padded: bool,
44    ) -> Result<Vec<AssignedByte<F>>, Error>;
45
46    /// Receives a base64 encoded string as [AssignedByte]s and returns
47    /// the decoded ASCII string as a vector of [AssignedByte].
48    /// If `padded` is selected, the input length must be a multiple of 4.
49    ///
50    /// The length of the output is always 3/4 of the padded input's length.
51    /// In order to reach this length, the output will be completed with one or
52    /// two ASCII_ZERO chars if necessary.
53    ///
54    /// # Panics
55    ///
56    /// If `padded` = true and the input length is not a multiple of 4.
57    fn decode_base64(
58        &self,
59        layouter: &mut impl Layouter<F>,
60        b64_input: &[AssignedByte<F>],
61        padded: bool,
62    ) -> Result<Vec<AssignedByte<F>>, Error>;
63}
64
65/// An AssignedVector with additional assumptions:
66///  1. The filler elements in the vector are present in the Base64 table, and
67///     therefore, we can decode the whole buffer.
68///  2. The length of the vector is a multiple of 4. This is guaranteed for
69///     every padded base64 string.
70///
71/// Note:
72///  These extra assumptions guarantee completeness.
73///  Soundness is always guaranteed.
74#[derive(Debug, Clone)]
75pub struct Base64Vec<F: CircuitField, const M: usize, const A: usize>(
76    pub(crate) AssignedVector<F, AssignedByte<F>, M, A>,
77);
78
79impl<F: CircuitField, const M: usize, const A: usize> From<Base64Vec<F, M, A>>
80    for AssignedVector<F, AssignedByte<F>, M, A>
81{
82    fn from(value: Base64Vec<F, M, A>) -> Self {
83        value.0
84    }
85}
86
87/// Equivalent to Base64Instructions for variable-length inputs.
88pub trait Base64VarInstructions<F: CircuitField, const M: usize, const A: usize>:
89    Base64Instructions<F>
90{
91    /// Assigns a vector of bytes into Base64Vec.
92    ///
93    /// # Panics
94    ///
95    /// If |value| > M or 4 does not divide |value|.
96    fn assign_var_base64(
97        &self,
98        layouter: &mut impl Layouter<F>,
99        value: Value<Vec<u8>>,
100    ) -> Result<Base64Vec<F, M, A>, Error>;
101
102    /// Returns a Base64Vec from an AssignedVector.
103    fn base64_from_vec(
104        &self,
105        layouter: &mut impl Layouter<F>,
106        vec: &AssignedVector<F, AssignedByte<F>, M, A>,
107    ) -> Result<Base64Vec<F, M, A>, Error>;
108
109    /// Variable length equivalent of `decode_base64_url` in
110    /// `Base64Instructions`. Inputs must always be padded apropriately
111    /// according to the base64 format.
112    fn var_decode_base64url<const M_OUT: usize, const A_OUT: usize>(
113        &self,
114        layouter: &mut impl Layouter<F>,
115        b64url_input: &Base64Vec<F, M, A>,
116    ) -> Result<AssignedVector<F, AssignedByte<F>, M_OUT, A_OUT>, Error>;
117
118    /// Equivalent of `decode_base64` in `Base64Instructions`.
119    /// Inputs must always be padded apropriately according to the base64
120    /// format.
121    fn var_decode_base64<const M_OUT: usize, const A_OUT: usize>(
122        &self,
123        layouter: &mut impl Layouter<F>,
124        b64_input: &Base64Vec<F, M, A>,
125    ) -> Result<AssignedVector<F, AssignedByte<F>, M_OUT, A_OUT>, Error>;
126}