/ console / account / src / compute_key / from_bits.rs
from_bits.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> FromBits for ComputeKey<N> {
 19      /// Initializes a new compute key from a list of **little-endian** bits.
 20      fn from_bits_le(bits_le: &[bool]) -> Result<Self> {
 21          let group_size_in_bits = Group::<N>::size_in_bits();
 22  
 23          let (pk_sig_start, pk_sig_end) = (0, group_size_in_bits);
 24          let (pr_sig_start, pr_sig_end) = (pk_sig_end, pk_sig_end + group_size_in_bits);
 25  
 26          let Some(pk_sig_bits) = bits_le.get(pk_sig_start..pk_sig_end) else {
 27              bail!("Unable to recover the 'pk_sig' (LE) bits for the compute key");
 28          };
 29          let Some(pr_sig_bits) = bits_le.get(pr_sig_start..pr_sig_end) else {
 30              bail!("Unable to recover the 'pr_sig' (LE) bits for the compute key");
 31          };
 32  
 33          Self::try_from((Group::from_bits_le(pk_sig_bits)?, Group::from_bits_le(pr_sig_bits)?))
 34      }
 35  
 36      /// Initializes a new compute key from a list of **big-endian** bits.
 37      fn from_bits_be(bits_be: &[bool]) -> Result<Self> {
 38          let group_size_in_bits = Group::<N>::size_in_bits();
 39  
 40          let (pk_sig_start, pk_sig_end) = (0, group_size_in_bits);
 41          let (pr_sig_start, pr_sig_end) = (pk_sig_end, pk_sig_end + group_size_in_bits);
 42  
 43          let Some(pk_sig_bits) = bits_be.get(pk_sig_start..pk_sig_end) else {
 44              bail!("Unable to recover the 'pk_sig' (BE) bits for the compute key");
 45          };
 46          let Some(pr_sig_bits) = bits_be.get(pr_sig_start..pr_sig_end) else {
 47              bail!("Unable to recover the 'pr_sig' (BE) bits for the compute key");
 48          };
 49  
 50          Self::try_from((Group::from_bits_be(pk_sig_bits)?, Group::from_bits_be(pr_sig_bits)?))
 51      }
 52  }
 53  
 54  #[cfg(test)]
 55  mod tests {
 56      use super::*;
 57      use deltavm_console_network::MainnetV0;
 58  
 59      type CurrentNetwork = MainnetV0;
 60  
 61      const ITERATIONS: usize = 100;
 62  
 63      fn check_from_bits_le() -> Result<()> {
 64          let rng = &mut TestRng::default();
 65  
 66          for i in 0..ITERATIONS {
 67              // Sample a random compute_key.
 68              let expected = ComputeKey::<CurrentNetwork>::try_from(PrivateKey::new(rng).unwrap()).unwrap();
 69  
 70              let given_bits = expected.to_bits_le();
 71              assert_eq!(ComputeKey::<CurrentNetwork>::size_in_bits(), given_bits.len());
 72  
 73              let candidate = ComputeKey::<CurrentNetwork>::from_bits_le(&given_bits)?;
 74              assert_eq!(expected, candidate);
 75  
 76              // Add excess zero bits.
 77              let candidate = [given_bits, vec![false; i]].concat();
 78  
 79              let candidate = ComputeKey::<CurrentNetwork>::from_bits_le(&candidate)?;
 80              assert_eq!(expected, candidate);
 81              assert_eq!(ComputeKey::<CurrentNetwork>::size_in_bits(), candidate.to_bits_le().len());
 82          }
 83          Ok(())
 84      }
 85  
 86      fn check_from_bits_be() -> Result<()> {
 87          let rng = &mut TestRng::default();
 88  
 89          for i in 0..ITERATIONS {
 90              // Sample a random compute_key.
 91              let expected = ComputeKey::<CurrentNetwork>::try_from(PrivateKey::new(rng).unwrap()).unwrap();
 92  
 93              let given_bits = expected.to_bits_be();
 94              assert_eq!(ComputeKey::<CurrentNetwork>::size_in_bits(), given_bits.len());
 95  
 96              let candidate = ComputeKey::<CurrentNetwork>::from_bits_be(&given_bits)?;
 97              assert_eq!(expected, candidate);
 98  
 99              // Add excess zero bits.
100              let candidate = [given_bits, vec![false; i]].concat();
101  
102              let candidate = ComputeKey::<CurrentNetwork>::from_bits_be(&candidate)?;
103              assert_eq!(expected, candidate);
104              assert_eq!(ComputeKey::<CurrentNetwork>::size_in_bits(), candidate.to_bits_be().len());
105          }
106          Ok(())
107      }
108  
109      #[test]
110      fn test_from_bits_le() -> Result<()> {
111          check_from_bits_le()
112      }
113  
114      #[test]
115      fn test_from_bits_be() -> Result<()> {
116          check_from_bits_be()
117      }
118  }