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}