forked from ordinals/ord
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathteleburn.rs
94 lines (85 loc) Β· 2.79 KB
/
teleburn.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use {super::*, sha3::Digest, sha3::Keccak256};
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Ethereum(String);
impl From<InscriptionId> for Ethereum {
fn from(inscription_id: InscriptionId) -> Self {
let mut array = [0; 36];
let (txid, index) = array.split_at_mut(32);
txid.copy_from_slice(inscription_id.txid.as_ref());
index.copy_from_slice(&inscription_id.index.to_be_bytes());
let digest = bitcoin::hashes::sha256::Hash::hash(&array);
Self(create_address_with_checksum(&hex::encode(&digest[0..20])))
}
}
impl Display for Ethereum {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
/// Given the hex digits of an Ethereum address, return that address with a
/// checksum as per https://eips.ethereum.org/EIPS/eip-55
fn create_address_with_checksum(address: &str) -> String {
assert_eq!(address.len(), 40);
assert!(address
.chars()
.all(|c| c.is_ascii_hexdigit() && (!c.is_alphabetic() || c.is_lowercase())));
let hash = hex::encode(&Keccak256::digest(address.as_bytes())[..20]);
assert_eq!(hash.len(), 40);
"0x"
.chars()
.chain(address.chars().zip(hash.chars()).map(|(a, h)| match h {
'0'..='7' => a,
'8'..='9' | 'a'..='f' => a.to_ascii_uppercase(),
_ => unreachable!(),
}))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_eth_checksum_generation() {
// test addresses from https://eips.ethereum.org/EIPS/eip-55
for addr in &[
"0x27b1fdb04752bbc536007a920d24acb045561c26",
"0x52908400098527886E0F7030069857D2E4169EE7",
"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
"0x8617E340B3D01FA5F11F306F4090FD50E238070D",
"0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb",
"0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB",
"0xde709f2102306220921060314715629080e2fb77",
"0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359",
] {
let lowercased = String::from(&addr[2..]).to_ascii_lowercase();
assert_eq!(addr.to_string(), create_address_with_checksum(&lowercased));
}
}
#[test]
fn test_inscription_id_to_teleburn_address() {
for (inscription_id, addr) in &[
(
InscriptionId {
txid: Txid::all_zeros(),
index: 0,
},
"0x6db65fD59fd356F6729140571B5BCd6bB3b83492",
),
(
InscriptionId::from_str(
"6fb976ab49dcec017f1e201e84395983204ae1a7c2abf7ced0a85d692e442799i7",
)
.unwrap(),
"0xEb26fEFA572a25F0ED7B41C5249bCba2Ca976475",
),
(
InscriptionId::from_str(
"6fb976ab49dcec017f1e201e84395983204ae1a7c2abf7ced0a85d692e442799i0",
)
.unwrap(),
"0xe43A06530BdF8A4e067581f48Fae3b535559dA9e",
),
] {
assert_eq!(*addr, Ethereum::from(*inscription_id).0);
}
}
}