138 lines
4.7 KiB
Plaintext
138 lines
4.7 KiB
Plaintext
pub fn sha3_384_hash(data: Bytes) -> Hash {
|
|
return Hash::sha3_384(data);
|
|
}
|
|
|
|
pub fn sha3_384_hash_string(data: String) -> Hash {
|
|
return Hash::sha3_384(data.as_bytes());
|
|
}
|
|
|
|
pub fn sha3_384_hash_multiple(data_list: Vec<Bytes>) -> Hash {
|
|
let mut combined = Bytes::new();
|
|
for data in data_list {
|
|
combined.extend(data);
|
|
}
|
|
return Hash::sha3_384(combined);
|
|
}
|
|
|
|
pub fn address_from_public_key(public_key: Bytes) -> Address {
|
|
require(public_key.len() == 33 || public_key.len() == 65, "Invalid public key length");
|
|
let hash = sha3_384_hash(public_key);
|
|
return Address::from_hash(hash);
|
|
}
|
|
|
|
pub fn is_valid_address(address: Address) -> bool {
|
|
return !address.is_zero();
|
|
}
|
|
|
|
pub fn verify_ed25519_signature(message: Bytes, signature: Bytes, public_key: Bytes) -> bool {
|
|
require(signature.len() == 64, "Invalid signature length");
|
|
require(public_key.len() == 32, "Invalid public key length");
|
|
return crypto::ed25519_verify(message, signature, public_key);
|
|
}
|
|
|
|
pub fn verify_ecdsa_signature(message_hash: Hash, signature: Bytes, public_key: Bytes) -> bool {
|
|
require(signature.len() == 65, "Invalid signature length");
|
|
require(public_key.len() == 33 || public_key.len() == 65, "Invalid public key length");
|
|
return crypto::ecdsa_verify(message_hash.as_bytes(), signature, public_key);
|
|
}
|
|
|
|
pub fn recover_ecdsa_public_key(message_hash: Hash, signature: Bytes) -> Bytes {
|
|
require(signature.len() == 65, "Invalid signature length");
|
|
return crypto::ecdsa_recover(message_hash.as_bytes(), signature);
|
|
}
|
|
|
|
pub fn create_message_hash(message: String) -> Hash {
|
|
let prefix = "\x19NAC Signed Message:\n";
|
|
let len_str = message.len().to_string();
|
|
let mut full_message = Bytes::from(prefix);
|
|
full_message.extend(Bytes::from(len_str));
|
|
full_message.extend(Bytes::from(message));
|
|
return sha3_384_hash(full_message);
|
|
}
|
|
|
|
pub fn verify_signed_message(message: String, signature: Bytes, signer: Address) -> bool {
|
|
require(signature.len() == 65, "Invalid signature length");
|
|
let message_hash = create_message_hash(message);
|
|
let recovered_pubkey = recover_ecdsa_public_key(message_hash, signature);
|
|
let recovered_address = address_from_public_key(recovered_pubkey);
|
|
return recovered_address == signer;
|
|
}
|
|
|
|
pub fn compute_merkle_root(leaves: Vec<Hash>) -> Hash {
|
|
require(leaves.len() > 0, "Leaves cannot be empty");
|
|
if leaves.len() == 1 {
|
|
return leaves[0];
|
|
}
|
|
let mut current_level = leaves;
|
|
while current_level.len() > 1 {
|
|
let mut next_level = Vec::new();
|
|
let mut i = 0;
|
|
while i < current_level.len() {
|
|
if i + 1 < current_level.len() {
|
|
let combined = Bytes::new();
|
|
combined.extend(current_level[i].as_bytes());
|
|
combined.extend(current_level[i + 1].as_bytes());
|
|
next_level.push(sha3_384_hash(combined));
|
|
i += 2;
|
|
} else {
|
|
let combined = Bytes::new();
|
|
combined.extend(current_level[i].as_bytes());
|
|
combined.extend(current_level[i].as_bytes());
|
|
next_level.push(sha3_384_hash(combined));
|
|
i += 1;
|
|
}
|
|
}
|
|
current_level = next_level;
|
|
}
|
|
return current_level[0];
|
|
}
|
|
|
|
pub fn verify_merkle_proof(leaf: Hash, proof: Vec<Hash>, root: Hash, index: u256) -> bool {
|
|
let mut computed_hash = leaf;
|
|
let mut current_index = index;
|
|
for proof_element in proof {
|
|
let combined = Bytes::new();
|
|
if current_index % 2 == 0 {
|
|
combined.extend(computed_hash.as_bytes());
|
|
combined.extend(proof_element.as_bytes());
|
|
} else {
|
|
combined.extend(proof_element.as_bytes());
|
|
combined.extend(computed_hash.as_bytes());
|
|
}
|
|
computed_hash = sha3_384_hash(combined);
|
|
current_index = current_index / 2;
|
|
}
|
|
return computed_hash == root;
|
|
}
|
|
|
|
pub fn pseudo_random(seed: Bytes) -> u256 {
|
|
let hash = sha3_384_hash(seed);
|
|
return u256::from_bytes(hash.as_bytes());
|
|
}
|
|
|
|
pub fn pseudo_random_from_block() -> u256 {
|
|
let mut seed = Bytes::new();
|
|
seed.extend(block.hash.as_bytes());
|
|
seed.extend(block.timestamp.to_bytes());
|
|
seed.extend(tx.hash.as_bytes());
|
|
return pseudo_random(seed);
|
|
}
|
|
|
|
pub fn base58_encode(data: Bytes) -> String {
|
|
const ALPHABET: &str = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
return crypto::base58_encode(data);
|
|
}
|
|
|
|
pub fn base58_decode(encoded: String) -> Bytes {
|
|
return crypto::base58_decode(encoded);
|
|
}
|
|
|
|
pub fn hex_encode(data: Bytes) -> String {
|
|
return "0x" + data.to_hex();
|
|
}
|
|
|
|
pub fn hex_decode(hex_string: String) -> Bytes {
|
|
let hex = hex_string.trim_start_matches("0x");
|
|
return Bytes::from_hex(hex);
|
|
}
|