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 }