-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
44 changed files
with
1,146 additions
and
663 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,88 @@ | ||
use crate::{ByteConversion, Field, FieldConversion}; | ||
use mina_signer::CompressedPubKey; | ||
|
||
use crate::{Field, FromBytes, ToBytes, ToFields}; | ||
|
||
/// Byte representation of base 58 encoded public keys. | ||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
pub struct Address([u8; 55]); | ||
|
||
impl Address { | ||
// Example: B62qoTFrus93Ryi1VzbFakzErBBmcikHEq27vhMkU4FfjGfCovv41fb | ||
// Regexp: /^B62q[1-9A-HJ-NP-Za-km-z]{51}$/ | ||
pub fn is_valid(addr: &str) -> Result<(), ()> { | ||
if addr.len() != 55 { | ||
return Err(()); | ||
} | ||
impl FieldConversion<2> for Address { | ||
fn to_fields(&self) -> [Field; 2] { | ||
let pubkey = CompressedPubKey::from_address(std::str::from_utf8(&self.0).unwrap()).unwrap(); | ||
|
||
if addr[0..4].as_bytes() != [66, 54, 50, 113] { | ||
return Err(()); | ||
} | ||
let [field_0] = pubkey.x.to_fields(); | ||
let [field_1] = pubkey.is_odd.to_fields(); | ||
|
||
for c in addr.bytes() { | ||
match c { | ||
b'1'..=b'9' | ||
| b'A'..=b'H' | ||
| b'J'..=b'N' | ||
| b'P'..=b'Z' | ||
| b'a'..=b'k' | ||
| b'm'..=b'z' => (), | ||
_ => return Err(()), | ||
} | ||
} | ||
|
||
Ok(()) | ||
[field_0, field_1] | ||
} | ||
} | ||
|
||
impl FromBytes for Address { | ||
type Bytes = [u8; 55]; | ||
|
||
fn from_bytes(bytes: Self::Bytes) -> Self { | ||
Address(bytes) | ||
impl ByteConversion<55> for Address { | ||
fn to_bytes(&self) -> [u8; 55] { | ||
self.0 | ||
} | ||
} | ||
|
||
impl ToBytes for Address { | ||
type Bytes = [u8; 55]; | ||
|
||
fn to_bytes(&self) -> Self::Bytes { | ||
self.0 | ||
fn from_bytes(bytes: &[u8; 55]) -> Self { | ||
Address(bytes.to_owned()) | ||
} | ||
} | ||
|
||
impl ToFields for Address { | ||
type Fields = [Field; 2]; | ||
/// Checks the given address to be valid. | ||
/// | ||
/// Returns `true` if it is a valid address, otherwise returns `false`. | ||
/// | ||
/// Example valid address: `B62qoTFrus93Ryi1VzbFakzErBBmcikHEq27vhMkU4FfjGfCovv41fb` | ||
/// | ||
/// Regular expression: `/^B62q[1-9A-HJ-NP-Za-km-z]{51}$/` | ||
/// | ||
/// # Examples | ||
/// | ||
/// Check an address: | ||
/// | ||
/// ```rs | ||
/// let is_valid = check_address("B62qoTFrus93Ryi1VzbFakzErBBmcikHEq27vhMkU4FfjGfCovv41fb"); | ||
/// assert_eq!(is_valid, true); | ||
/// ``` | ||
/// | ||
pub fn check_address(addr: &str) -> bool { | ||
if addr.len() != 55 { | ||
return false; | ||
} | ||
|
||
fn to_fields(&self) -> Self::Fields { | ||
let pubkey = CompressedPubKey::from_address(std::str::from_utf8(&self.0).unwrap()).unwrap(); | ||
if addr[0..4].as_bytes() != [66, 54, 50, 113] { | ||
return false; | ||
} | ||
|
||
[pubkey.x, pubkey.is_odd.into()] | ||
for c in addr.bytes() { | ||
match c { | ||
b'1'..=b'9' | b'A'..=b'H' | b'J'..=b'N' | b'P'..=b'Z' | b'a'..=b'k' | b'm'..=b'z' => (), | ||
_ => return false, | ||
} | ||
} | ||
|
||
true | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
|
||
fn checks_if_address_is_valid() { | ||
// /^B62q[1-9A-HJ-NP-Za-km-z]{51}$/ | ||
|
||
let addr = "B62qoTFrus93Ryi1VzbFakzErBBmcikHEq27vhMkU4FfjGfCovv41fb"; | ||
assert_eq!(Address::is_valid(addr), Ok(())); | ||
assert_eq!(check_address(addr), true); | ||
|
||
let addr = "B63qoTFrus93Ryi1VzbFakzErBBmcikHEq27vhMkU4FfjGfCovv41fb"; | ||
assert_eq!(Address::is_valid(addr), Err(())); | ||
assert_eq!(check_address(addr), false); | ||
|
||
let addr = "B63qoTFrus93Ryi1VzbFakzErBBmcikHEq2ivhMkU4FfjGfCovv41fb"; | ||
assert_eq!(Address::is_valid(addr), Err(())); | ||
assert_eq!(check_address(addr), false); | ||
|
||
let addr = "B63qoTFrus93Ryi1VzbFakzErBBmcikHEq2fjGfCovv41fb"; | ||
assert_eq!(Address::is_valid(addr), Err(())); | ||
assert_eq!(check_address(addr), false); | ||
|
||
let addr = "B63qoTFrus93Ryi1VzbFakzErBBmcikHEq2ivhMkU4FfvhMkU4FfjGfCovv41fb"; | ||
assert_eq!(Address::is_valid(addr), Err(())); | ||
assert_eq!(check_address(addr), false); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/// The trait that is used to convert statically sized data structures back and forth into bytes. | ||
/// | ||
/// The constant generic parameter `L` represents the length of the byte representation of the data structures. | ||
pub trait ByteConversion<const L: usize> { | ||
/// Converts the data structure to bytes. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Convert to bytes: | ||
/// | ||
/// ```rs | ||
/// let bytes = data.to_bytes(); | ||
/// ``` | ||
/// | ||
fn to_bytes(&self) -> [u8; L]; | ||
|
||
/// Creates a data structure from the given bytes. | ||
/// | ||
/// # Examples | ||
/// | ||
/// Create a data structure: | ||
/// | ||
/// ```rs | ||
/// let data = ByteConversion.from_bytes(bytes); | ||
/// ``` | ||
/// | ||
fn from_bytes(bytes: &[u8; L]) -> Self; | ||
} | ||
|
||
impl ByteConversion<8> for u64 { | ||
fn to_bytes(&self) -> [u8; 8] { | ||
self.to_le_bytes() | ||
} | ||
|
||
fn from_bytes(bytes: &[u8; 8]) -> Self { | ||
u64::from_le_bytes(bytes.to_owned()) | ||
} | ||
} | ||
|
||
impl ByteConversion<1> for bool { | ||
fn to_bytes(&self) -> [u8; 1] { | ||
(self.to_owned() as u8).to_le_bytes() | ||
} | ||
|
||
fn from_bytes(bytes: &[u8; 1]) -> Self { | ||
bytes[0] != 0 | ||
} | ||
} |
Oops, something went wrong.