Skip to main content

midnight_circuits/instructions/
base64.rs

1// This file is part of MIDNIGHT-ZK.
2// Copyright (C) 2025 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 ff::PrimeField;
16use midnight_proofs::{
17    circuit::{Layouter, Value},
18    plonk::Error,
19};
20
21use crate::types::{AssignedByte, AssignedVector};
22
23/// This trait defines methods for converting data encoded in standard Base64 or
24/// Base64URL (URL-safe) format into its raw byte representation.
25pub trait Base64Instructions<F: PrimeField> {
26    /// Receives a base64 url-safe encoded string as [AssignedByte]s and returns
27    /// the decoded ASCII string as a vector of [AssignedByte].
28    /// If `padded` is selected, the input length must be a multiple of 4.
29    ///
30    /// The length of the output is always 3/4 of the padded input's length.
31    /// In order to reach this length, the output will be completed with one or
32    /// two ASCII_ZERO chars if necessary.
33    ///
34    /// # Panics
35    ///
36    /// If `padded` = true and the input length is not a multiple of 4.
37    fn decode_base64url(
38        &self,
39        layouter: &mut impl Layouter<F>,
40        b64url_input: &[AssignedByte<F>],
41        padded: bool,
42    ) -> Result<Vec<AssignedByte<F>>, Error>;
43
44    /// Receives a base64 encoded string as [AssignedByte]s and returns
45    /// the decoded ASCII string as a vector of [AssignedByte].
46    /// If `padded` is selected, the input length must be a multiple of 4.
47    ///
48    /// The length of the output is always 3/4 of the padded input's length.
49    /// In order to reach this length, the output will be completed with one or
50    /// two ASCII_ZERO chars if necessary.
51    ///
52    /// # Panics
53    ///
54    /// If `padded` = true and the input length is not a multiple of 4.
55    fn decode_base64(
56        &self,
57        layouter: &mut impl Layouter<F>,
58        b64_input: &[AssignedByte<F>],
59        padded: bool,
60    ) -> Result<Vec<AssignedByte<F>>, Error>;
61}
62
63/// An AssignedVector with additional assumptions:
64///  1. The filler elements in the vector are present in the Base64 table, and
65///     therefore, we can decode the whole buffer.
66///  2. The length of the vector is a multiple of 4. This is guaranteed for
67///     every padded base64 string.
68///
69/// Note:
70///  These extra assumptions guarantee completeness.
71///  Soundness is always guaranteed.
72#[derive(Debug, Clone)]
73pub struct Base64Vec<F: PrimeField, const M: usize, const A: usize>(
74    pub(crate) AssignedVector<F, AssignedByte<F>, M, A>,
75);
76
77impl<F: PrimeField, const M: usize, const A: usize> From<Base64Vec<F, M, A>>
78    for AssignedVector<F, AssignedByte<F>, M, A>
79{
80    fn from(value: Base64Vec<F, M, A>) -> Self {
81        value.0
82    }
83}
84
85/// Equivalent to Base64Instructions for variable-length inputs.
86pub trait Base64VarInstructions<F: PrimeField, const M: usize, const A: usize>:
87    Base64Instructions<F>
88{
89    /// Assigns a vector of bytes into Base64Vec.
90    ///
91    /// # Panics
92    ///
93    /// If |value| > M or 4 does not divide |value|.
94    fn assign_var_base64(
95        &self,
96        layouter: &mut impl Layouter<F>,
97        value: Value<Vec<u8>>,
98    ) -> Result<Base64Vec<F, M, A>, Error>;
99
100    /// Returns a Base64Vec from an AssignedVector.
101    fn base64_from_vec(
102        &self,
103        layouter: &mut impl Layouter<F>,
104        vec: &AssignedVector<F, AssignedByte<F>, M, A>,
105    ) -> Result<Base64Vec<F, M, A>, Error>;
106
107    /// Variable length equivalent of `decode_base64_url` in
108    /// `Base64Instructions`. Inputs must always be padded apropriately
109    /// according to the base64 format.
110    fn var_decode_base64url<const M_OUT: usize, const A_OUT: usize>(
111        &self,
112        layouter: &mut impl Layouter<F>,
113        b64url_input: &Base64Vec<F, M, A>,
114    ) -> Result<AssignedVector<F, AssignedByte<F>, M_OUT, A_OUT>, Error>;
115
116    /// Equivalent of `decode_base64` in `Base64Instructions`.
117    /// Inputs must always be padded apropriately according to the base64
118    /// format.
119    fn var_decode_base64<const M_OUT: usize, const A_OUT: usize>(
120        &self,
121        layouter: &mut impl Layouter<F>,
122        b64_input: &Base64Vec<F, M, A>,
123    ) -> Result<AssignedVector<F, AssignedByte<F>, M_OUT, A_OUT>, Error>;
124}