/ synthesizer / process / src / authorize.rs
authorize.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the deltavm library.
  3  
  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  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use super::*;
 17  
 18  impl<N: Network> Process<N> {
 19      /// Authorizes a call to the program function for the given inputs.
 20      #[inline]
 21      pub fn authorize<A: circuit::Alpha<Network = N>, R: Rng + CryptoRng>(
 22          &self,
 23          private_key: &PrivateKey<N>,
 24          program_id: impl TryInto<ProgramID<N>>,
 25          function_name: impl TryInto<Identifier<N>>,
 26          inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
 27          rng: &mut R,
 28      ) -> Result<Authorization<N>> {
 29          // Authorize the call.
 30          self.get_stack(program_id)?.authorize::<A, R>(private_key, function_name, inputs, rng)
 31      }
 32  
 33      /// Authorizes a call to the program function for the given inputs.
 34      /// Compared to `authorize`, this method does not check for circuit satisfiability of the request.
 35      #[inline]
 36      pub fn authorize_unchecked<A: circuit::Alpha<Network = N>, R: Rng + CryptoRng>(
 37          &self,
 38          private_key: &PrivateKey<N>,
 39          program_id: impl TryInto<ProgramID<N>>,
 40          function_name: impl TryInto<Identifier<N>>,
 41          inputs: impl ExactSizeIterator<Item = impl TryInto<Value<N>>>,
 42          rng: &mut R,
 43      ) -> Result<Authorization<N>> {
 44          // Authorize the call.
 45          self.get_stack(program_id)?.authorize_unchecked::<A, R>(private_key, function_name, inputs, rng)
 46      }
 47  
 48      /// Authorizes a call to the program function for the given inputs.
 49      /// Compared to `authorize`, no private key is needed, but this only works for single public requests.
 50      #[inline]
 51      pub fn authorize_request<A: circuit::Alpha<Network = N>, R: Rng + CryptoRng>(
 52          &self,
 53          request: Request<N>,
 54          rng: &mut R,
 55      ) -> Result<Authorization<N>> {
 56          // Initialize the program id.
 57          let program_id = request.program_id();
 58          // Authorize the call.
 59          self.get_stack(program_id)?.authorize_request::<A, R>(request, rng)
 60      }
 61  
 62      /// Authorizes the fee given the credits record, the fee amount (in microcredits),
 63      /// and the deployment or execution ID.
 64      #[inline]
 65      pub fn authorize_fee_private<A: circuit::Alpha<Network = N>, R: Rng + CryptoRng>(
 66          &self,
 67          private_key: &PrivateKey<N>,
 68          credits: Record<N, Plaintext<N>>,
 69          base_fee_in_microcredits: u64,
 70          priority_fee_in_microcredits: u64,
 71          deployment_or_execution_id: Field<N>,
 72          rng: &mut R,
 73      ) -> Result<Authorization<N>> {
 74          let timer = timer!("Process::authorize_fee_private");
 75  
 76          // Ensure the fee has the correct program ID.
 77          let program_id = ProgramID::from_str("credits.delta")?;
 78          // Ensure the fee has the correct function.
 79          let function_name = Identifier::from_str("fee_private")?;
 80  
 81          // Ensure the record contains a sufficient balance to pay the fee.
 82          ensure_record_microcredits_is_sufficient(
 83              &credits,
 84              base_fee_in_microcredits.saturating_add(priority_fee_in_microcredits),
 85          )?;
 86  
 87          // Construct the inputs.
 88          let inputs = [
 89              Value::Record(credits),
 90              Value::from(Literal::U64(U64::<N>::new(base_fee_in_microcredits))),
 91              Value::from(Literal::U64(U64::<N>::new(priority_fee_in_microcredits))),
 92              Value::from(Literal::Field(deployment_or_execution_id)),
 93          ]
 94          .into_iter();
 95          lap!(timer, "Construct the inputs");
 96  
 97          // Authorize the call.
 98          let authorization = self.get_stack(program_id)?.authorize::<A, R>(private_key, function_name, inputs, rng)?;
 99          finish!(timer, "Compute the authorization");
100  
101          // Return the authorization.
102          Ok(authorization)
103      }
104  
105      /// Authorizes the fee given the the fee amount (in microcredits) and the deployment or execution ID.
106      #[inline]
107      pub fn authorize_fee_public<A: circuit::Alpha<Network = N>, R: Rng + CryptoRng>(
108          &self,
109          private_key: &PrivateKey<N>,
110          base_fee_in_microcredits: u64,
111          priority_fee_in_microcredits: u64,
112          deployment_or_execution_id: Field<N>,
113          rng: &mut R,
114      ) -> Result<Authorization<N>> {
115          let timer = timer!("Process::authorize_fee_public");
116  
117          // Ensure the fee has the correct program ID.
118          let program_id = ProgramID::from_str("credits.delta")?;
119          // Ensure the fee has the correct function.
120          let function_name = Identifier::from_str("fee_public")?;
121  
122          // Construct the inputs.
123          let inputs = [
124              Value::from(Literal::U64(U64::<N>::new(base_fee_in_microcredits))),
125              Value::from(Literal::U64(U64::<N>::new(priority_fee_in_microcredits))),
126              Value::from(Literal::Field(deployment_or_execution_id)),
127          ]
128          .into_iter();
129          lap!(timer, "Construct the inputs");
130  
131          // Authorize the call.
132          let authorization = self.get_stack(program_id)?.authorize::<A, R>(private_key, function_name, inputs, rng)?;
133          finish!(timer, "Compute the authorization");
134  
135          // Return the authorization.
136          Ok(authorization)
137      }
138  }
139  
140  /// Ensures the record contains a sufficient balance to pay the fee.
141  fn ensure_record_microcredits_is_sufficient<N: Network>(
142      record: &Record<N, Plaintext<N>>,
143      fee_in_microcredits: u64,
144  ) -> Result<()> {
145      // Retrieve the balance from the record.
146      let balance = match record.find(&[Identifier::from_str("microcredits")?]) {
147          Ok(console::program::Entry::Private(Plaintext::Literal(Literal::U64(amount), _))) => *amount,
148          _ => bail!("The fee record does not contain a 'microcredits' entry"),
149      };
150      // Ensure the balance is sufficient to pay the fee.
151      ensure!(balance >= fee_in_microcredits, "Credits record balance is insufficient to pay the fee");
152      Ok(())
153  }