/ console / program / src / owner / mod.rs
mod.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm 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  mod bytes;
 17  mod serialize;
 18  mod string;
 19  
 20  use alphavm_console_account::{Address, PrivateKey, Signature};
 21  use alphavm_console_network::Network;
 22  use alphavm_console_types::prelude::*;
 23  
 24  #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 25  pub struct ProgramOwner<N: Network> {
 26      /// The address of the program owner.
 27      address: Address<N>,
 28      /// The signature of the program owner, over the deployment transaction ID.
 29      signature: Signature<N>,
 30  }
 31  
 32  impl<N: Network> ProgramOwner<N> {
 33      /// Initializes a new program owner.
 34      pub fn new<R: Rng + CryptoRng>(private_key: &PrivateKey<N>, deployment_id: Field<N>, rng: &mut R) -> Result<Self> {
 35          // Derive the address.
 36          let address = Address::try_from(private_key)?;
 37          // Sign the transaction ID.
 38          let signature = private_key.sign(&[deployment_id], rng)?;
 39          // Return the program owner.
 40          Ok(Self { address, signature })
 41      }
 42  
 43      /// Initializes a new program owner from an address and signature.
 44      pub fn from(address: Address<N>, signature: Signature<N>) -> Self {
 45          Self { address, signature }
 46      }
 47  
 48      /// Returns the address of the program owner.
 49      pub const fn address(&self) -> Address<N> {
 50          self.address
 51      }
 52  
 53      /// Returns the signature of the program owner.
 54      pub const fn signature(&self) -> &Signature<N> {
 55          &self.signature
 56      }
 57  
 58      /// Verify that the signature is valid for the given deployment ID.
 59      pub fn verify(&self, deployment_id: Field<N>) -> bool {
 60          self.signature.verify(&self.address, &[deployment_id])
 61      }
 62  }
 63  
 64  #[cfg(test)]
 65  pub(crate) mod test_helpers {
 66      use super::*;
 67      use alphavm_console_network::MainnetV0;
 68  
 69      use std::sync::OnceLock;
 70  
 71      type CurrentNetwork = MainnetV0;
 72  
 73      pub(crate) fn sample_program_owner() -> ProgramOwner<CurrentNetwork> {
 74          static INSTANCE: OnceLock<ProgramOwner<CurrentNetwork>> = OnceLock::new();
 75          *INSTANCE.get_or_init(|| {
 76              // Initialize the RNG.
 77              let rng = &mut TestRng::default();
 78  
 79              // Initialize a private key.
 80              let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
 81  
 82              // Initialize a deployment ID.
 83              let deployment_id: Field<CurrentNetwork> = rng.r#gen();
 84  
 85              // Return the program owner.
 86              ProgramOwner::new(&private_key, deployment_id, rng).unwrap()
 87          })
 88      }
 89  
 90      #[test]
 91      fn test_verify_program_owner() {
 92          // Initialize the RNG.
 93          let rng = &mut TestRng::default();
 94  
 95          // Initialize a private key.
 96          let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
 97  
 98          // Initialize a deployment ID.
 99          let deployment_id: Field<CurrentNetwork> = rng.r#gen();
100  
101          // Construct the program owner.
102          let owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap();
103          // Ensure that the program owner is verified for the given deployment ID.
104          assert!(owner.verify(deployment_id));
105  
106          // Ensure that the program owner is not verified for a different deployment ID.
107          let incorrect_deployment_id: Field<CurrentNetwork> = rng.r#gen();
108          assert!(!owner.verify(incorrect_deployment_id));
109      }
110  }