1use crate::proto_serde::ProtoSerde;
2use crate::structs::{Hash, PoWProof, PoWProofType, Transaction};
3use crate::{bytes_data, RgResult, SafeOption};
4use sha3::Digest;
5use std::time::Instant;
6
7
8fn check_difficulty_bytes(vec: &Vec<u8>, leading_zeros_bytes: usize) -> bool {
9 vec.len() >= leading_zeros_bytes &&
10 vec.iter().take(leading_zeros_bytes).all(|&b| b == 0)
11}
12
13fn check_difficulty_bits(vec: &Vec<u8>, leading_zero_bits: usize) -> bool {
14 let mut count = 0;
15 for &byte in vec.iter() {
16 if byte == 0 {
17 count += 8; } else {
20 count += byte.leading_zeros() as usize; break;
23 }
24 }
25 count > leading_zero_bits
26}
27
28
29
30impl PoWProof {
31 pub fn from_hash_sha3_256(hash: &Hash, difficulty: usize) -> RgResult<PoWProof> {
32 let mut proof = PoWProof::default();
33 proof.proof_type = PoWProofType::Sha3256Nonce as i32;
34 let mut nonce: i64 = 0;
35 loop {
36 proof.index_counter = bytes_data(nonce.to_be_bytes().to_vec());
37 if proof.verify(hash, difficulty)? {
38 break
39 }
40 nonce += 1;
41 }
42 Ok(proof)
45 }
46
47 pub fn merged_bytes(&self, hash: &Hash) -> RgResult<Vec<u8>> {
48 let hash_bytes = hash.proto_serialize();
49 let nonce = self.index_counter.safe_get()?.value.clone();
50 let mut merged = hash_bytes.clone();
51 merged.extend_from_slice(&*nonce);
52 Ok(merged)
53 }
54
55 pub fn merged_digest_hash(&self, hash: &Hash) -> RgResult<Hash> {
56 let merged = self.merged_bytes(hash)?;
57 Ok(Hash::digest(merged))
58 }
59
60 pub fn verify(&self, hash: &Hash, difficulty: usize) -> RgResult<bool> {
61 Ok(check_difficulty_bytes(&self.merged_digest_hash(&hash)?.raw_bytes()?, difficulty))
62 }
63
64 pub fn merged_hex(&self, hash: &Hash) -> RgResult<String> {
65 Ok(hex::encode(self.merged_digest_hash(hash)?.raw_bytes()?))
66 }
67
68 pub fn nonce_int(&self) -> RgResult<i64> {
69 Ok(i64::from_be_bytes(self.index_counter.safe_get()?.value.clone().as_slice().try_into().expect("nonce")))
70 }
71}
72
73
74#[test]
75fn test_pow() {
76 let difficulty = 1;
78
79 let mut elapsed_all = vec![];
80
81 for i in 0..30 {
82 let now = Instant::now();
83 let string = format!("hello{}", i);
84 let hash = Hash::from_string_calculate(&*string);
85 let proof = PoWProof::from_hash_sha3_256(&hash, difficulty).expect("proof");
86 proof.verify(&hash, difficulty).expect("verify");
87 println!("hash: {:?}", hash.hex());
88 println!("merged hex bytes: {:?}", hex::encode(proof.merged_bytes(&hash).expect("")));
89 println!("Proof merged hash: {:?}", proof.merged_hex(&hash).expect("merged_hex"));
90 println!("Proof merged bytes: {:?}", proof.merged_digest_hash(&hash).expect("merged_hex").vec());
91 println!("Proof nonce: {:?}", proof.nonce_int().expect("nonce_int"));
92 let elapsed = now.elapsed();
93 elapsed_all.push(elapsed.as_millis());
94 println!("Elapsed: {:?}", elapsed);
95 }
96 let avg = elapsed_all.iter().sum::<u128>() / elapsed_all.len() as u128;
97 println!("Average: {:?}", avg);
98
99}
100
101pub trait TransactionPowValidate {
102 fn pow_validate(&self) -> RgResult<bool>;
103}
104
105impl TransactionPowValidate for Transaction {
106 fn pow_validate(&self) -> RgResult<bool> {
107 let options = self.options.safe_get_msg("Missing tx options in pow validate")?;
108 let proof = options
109 .pow_proof.safe_get_msg("Missing pow proof")?;
110 proof.verify(&self.signable_hash(), 1)
111 }
112}