Skip to content

Commit

Permalink
fix: daser-network err
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkingLee committed Dec 16, 2023
1 parent c82f4b6 commit 1a2a7c2
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 96 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 26 additions & 24 deletions crates/daser/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,27 +290,26 @@ impl DasNetworkServiceWrapper {
let extension = header.extension();

let mut keys = Vec::new();
for &idx in index {
if idx < row_count {

for &y in index {
if y < row_count {
for x in 0..EXTENDED_SEGMENTS_PER_BLOB {
let position = Position { x: x as u32, y: idx };
let at = idx * EXTENDED_SEGMENTS_PER_BLOB as u32 + x as u32;
let position = Position { x: x as u32, y };

if let Some((app_lookup, _)) = extension.get_lookup(at) {
if let Some((app_lookup, _)) = extension.get_lookup(y) {
let key = sample_key(app_lookup.app_id, app_lookup.nonce, &position);
keys.push(KademliaKey::new(&key));
} else {
return Err(anyhow!("prepare_rows_keys: get_lookup failed"))
return Err(anyhow!("prepare_cols_keys: get_lookup failed"))
}
}
} else {
if idx >= row_count * 2 {
return Err(anyhow!("prepare_rows_keys: idx is too large"))
if y >= row_count * 2 {
return Err(anyhow!("prepare_cols_keys: idx is too large"))
}
let block_hash = HeaderWithCommitment::hash(header);
for x in 0..EXTENDED_SEGMENTS_PER_BLOB {
let position = Position { x: x as u32, y: idx };
let key = sample_key_from_block(&block_hash.encode(), &position);
let position = Position { x: x as u32, y };
let key = sample_key_from_block(&header.hash().encode(), &position);
keys.push(KademliaKey::new(&key));
}
}
Expand All @@ -332,27 +331,30 @@ impl DasNetworkServiceWrapper {
return Ok(vec![])
}

let block_hash = HeaderWithCommitment::hash(header);
let extension = header.extension();
let mut keys = Vec::new();

for &idx in index {
for &x in index {
for y in 0..row_count {
let position = Position { x: idx, y };
let at = idx * row_count * 2 + y;
let app_lookup = extension
.get_lookup(at)
.ok_or_else(|| anyhow!("prepare_cols_keys: get_lookup failed for sample_key"))?
.0;
let key = sample_key(app_lookup.app_id, app_lookup.nonce, &position);
keys.push(KademliaKey::new(&key));
let position = Position { x, y };

if let Some((app_lookup, _)) = extension.get_lookup(y) {
let key = sample_key(app_lookup.app_id, app_lookup.nonce, &position);
keys.push(KademliaKey::new(&key));
} else {
return Err(anyhow!("prepare_rows_keys: get_lookup failed"))
}
}

for y in row_count..(row_count * 2) {
let position = Position { x: idx, y };
let key = sample_key_from_block(&block_hash.encode(), &position);
for y in row_count..row_count * 2 {
let position = Position { x, y };
let key = sample_key_from_block(&header.hash().encode(), &position);
keys.push(KademliaKey::new(&key));
}

if x > EXTENDED_SEGMENTS_PER_BLOB as u32 {
return Err(anyhow!("prepare_rows_keys: idx is too large"))
}
}

Ok(keys)
Expand Down
4 changes: 3 additions & 1 deletion crates/proof-of-space/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
anyhow = "1.0.66"
chacha20 = { version = "0.9.1", default-features = false}
bit-vec = { version = "0.6.3", optional = true }

scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = [
Expand Down Expand Up @@ -45,5 +46,6 @@ std = [
"scale-info/std",
"melo-das-db/std",
"melo-core-primitives/std",
"sp-std/std"
"sp-std/std",
"bit-vec"
]
1 change: 1 addition & 0 deletions crates/proof-of-space/src/solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ where
/// # Returns
///
/// A vector of selected indices.
#[cfg(feature = "std")]
pub fn select_indices(
farmer_id: &FarmerId,
block_hash: &Hash,
Expand Down
150 changes: 84 additions & 66 deletions crates/proof-of-space/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::Vec;
#[cfg(feature = "std")]
use bit_vec::BitVec;

/// Folds a hash output to a 32-bit unsigned integer.
/// This function is useful for reducing a larger hash output to a smaller, manageable size.
Expand Down Expand Up @@ -61,42 +63,53 @@ pub fn hash_to_u16_xor(hash: &[u8]) -> u16 {
})
}

/// Selects indices from a hash where a specified number of consecutive bits are 1,
/// with the `end` parameter indicating the bit position in binary.
#[cfg(feature = "std")]
pub fn hash_to_bitvec(hash: &[u8; 32]) -> BitVec {
BitVec::from_bytes(hash)
}

/// Selects indices where a specified number of consecutive bits are 1.
///
/// Parameters:
/// This function scans a hash represented as a byte array and finds indices
/// where 'n' consecutive bits are set to 1. The search is performed within
/// the range specified by `start` and `end`. The function supports wrapping
/// around the end of the array to the start, enabling circular checks.
///
/// # Parameters
/// * `hash`: A reference to a 32-byte hash array.
/// * `start`: The starting index for the selection.
/// * `end`: The bit position in binary to check in each byte.
/// * `start`: The starting index for the selection within the bit array.
/// * `end`: The end index (exclusive) for the selection within the bit array.
/// * `n`: The number of consecutive 1 bits required.
///
/// Returns:
/// # Returns
/// A vector of indices where each index meets the specified bit criteria.
/// If `n` is 0, or if `start` or `end` are out of bounds, the function returns an empty vector.
#[cfg(feature = "std")]
pub fn select_indices(hash: &[u8; 32], start: usize, end: usize, n: usize) -> Vec<u32> {
assert!(end <= 7, "end must be a bit position within a byte (0-7)");

(start..32)
.filter_map(|i| {
// Check if `n` consecutive bits starting from the `end` bit are 1.
if (0..n).all(|offset| {
// Calculate the bit position and byte index for the offset.
let bit_position = (end + offset) % 8;
let byte_index = i + (end + offset) / 8;

// Prevent index out of bounds.
if byte_index >= 32 {
return false
}

// Check if the bit at the position is 1.
hash[byte_index] & (1 << bit_position) != 0
}) {
Some(i as u32)
} else {
None
let bits = hash_to_bitvec(hash);
let bit_len = bits.len();

if n == 0 || n > bit_len || start >= end || end > bit_len {
return Vec::new()
}

let mut indices = Vec::new();

for i in start..end {
let mut all_ones = true;
for j in 0..n {
if !bits[(i + j) % bit_len] {
all_ones = false;
break
}
})
.collect()
}

if all_ones {
indices.push(i as u32);
}
}

indices
}

/// Checks if a given index is valid based on the number of consecutive 1 bits in a hash.
Expand Down Expand Up @@ -181,6 +194,7 @@ pub fn xor_byte_slices(a: &[u8], b: &[u8]) -> Vec<u8> {

#[cfg(test)]
mod tests {

use super::*;
// use crate::BlakeTwo256;
// use sp_core::Hasher;
Expand Down Expand Up @@ -216,64 +230,68 @@ mod tests {
}

#[test]
fn test_select_indices() {
let hash = [0b1111_1111u8; 32];
// Check the 1st bit position in each byte
let indices = select_indices(&hash, 0, 1, 3);
// Every byte should match, since it's full of 1s
assert_eq!(indices.len(), 32);
fn test_select_indices_basic() {
let hash = [0b10101010; 32];
let indices = select_indices(&hash, 0, 256, 2);
assert!(indices.is_empty());

let indices = select_indices(&hash, 0, 256, 1);
let expected_indices: Vec<u32> = (0..255).step_by(2).collect();
assert_eq!(indices, expected_indices);
}

#[test]
fn test_select_indices_non_uniform() {
let hash = [0b1010_1010u8; 32];
// Check the 1st bit position in each byte
let indices = select_indices(&hash, 0, 1, 2);
// No match as there are no 2 consecutive 1s starting from 1st bit position
fn test_select_indices_n_too_large() {
let hash = [0b11111111; 32];
let indices = select_indices(&hash, 0, 258, 33);
assert!(indices.is_empty());
}

#[test]
fn test_select_indices_no_match() {
let hash = [0b0101_0101u8; 32];
// Check the 1st bit position in each byte
let indices = select_indices(&hash, 0, 1, 3);
// No match as there are no 3 consecutive 1s starting from 1st bit position
assert!(indices.is_empty());
fn test_select_indices_wraparound() {
let mut hash = [0; 32];
hash[0] = 0b10000000;
hash[31] = 0b00000001;
let indices = select_indices(&hash, 0, 256, 2);
assert_eq!(indices, vec![255]);
}

#[test]
fn test_select_indices_partial_bytes() {
let hash = [0b1111_0000u8; 32];
// Check the 1st bit position in bytes from 2 to 29
let indices = select_indices(&hash, 2, 1, 4);
// No matches should be found
assert!(indices.is_empty());
}
fn test_select_indices_boundary_conditions() {
let hash = [0b11110000; 32];
let indices = select_indices(&hash, 0, 32 * 8, 4);
let expected_indices = (0..32).map(|x| x * 8).collect::<Vec<u32>>();
assert_eq!(indices, expected_indices);
}

#[test]
fn test_is_index_valid_short_hash() {
let hash = [0b1111_1111u8; 16]; // Shorter than 32 bytes
assert!(!is_index_valid(&hash, 0, 16, 3));
fn test_select_indices_consecutive_ones() {
let mut hash = [0; 32];
hash[1] = 0b00001111;
hash[2] = 0b11110000;
let indices = select_indices(&hash, 8, 24, 8);
assert_eq!(indices, vec![12]);
}

#[test]
fn test_is_index_valid_boundary() {
let hash = [0b1111_1111u8; 32];
assert!(is_index_valid(&hash, 7 * 8, 32, 1)); // Edge case at the boundary
fn test_select_indices_empty() {
let hash = [0; 32];
let indices = select_indices(&hash, 0, 256, 1);
assert!(indices.is_empty());
}

#[test]
fn test_is_index_valid_max_values() {
let hash = [0b1111_1111u8; 32];
assert!(!is_index_valid(&hash, 32 * 8 - 1, 32, 3)); // Edge case with maximum values
fn test_select_indices_invalid_n() {
let hash = [0b10101010; 32];
let indices = select_indices(&hash, 0, 256, 0);
assert!(indices.is_empty());
}

#[test]
fn test_is_index_valid() {
let hash = [0b1111_1111u8; 32];
assert!(is_index_valid(&hash, 0, 32, 3));
assert!(!is_index_valid(&hash, 256, 32, 3));
fn test_select_indices_out_of_bounds() {
let hash = [0b10101010; 32];
let indices = select_indices(&hash, 256, 512, 2);
assert!(indices.is_empty());
}

#[test]
Expand Down
15 changes: 10 additions & 5 deletions farmer/src/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ pub async fn run<H: HeaderWithCommitment + Sync>(

let rows_count = header.col_num().unwrap_or_default();

info!(" Received best block header #{}", block_number.clone());
info!(" Received best block header #{}", block_number.clone());

if rows_count == 0 {
info!("⏭️ No data in block #{}", block_number.clone());
continue
}

info!("🚩 Data rows num: {}", rows_count);

let message = (header.clone(), received_at);
if let Err(error) = message_tx.send(message).await.context("Send failed") {
error!("❌ Fail to process best block header: {error}");
Expand Down Expand Up @@ -133,6 +135,8 @@ pub async fn run<H: HeaderWithCommitment + Sync>(
PiecePosition::from_column,
);

info!("💾 Data saved successfully");

let mut solutions: Vec<Solution<H256, u32>> = Vec::new();

pre_cells.iter().for_each(|pre_cell| {
Expand All @@ -147,7 +151,7 @@ pub async fn run<H: HeaderWithCommitment + Sync>(
});

for solution in &solutions {
info!(" Found solution: {:?}", solution);
info!(" Found solution: {:?}", solution);

let solution_tx = melodot::tx().farmers_fortune().claim(
pre_cell_to_runtime(&solution.pre_cell),
Expand All @@ -163,12 +167,13 @@ pub async fn run<H: HeaderWithCommitment + Sync>(

match res {
Ok(tx_status) => match tx_status.wait_for_finalized_success().await {
Ok(_) => info!("Transaction finalized successfully"),
Err(e) => error!("Error finalizing transaction: {:?}", e),
Ok(_) => info!("❤️‍ Solution submitted successfully"),
Err(e) => error!("Error submitted solution: {:?}", e),
},
Err(e) => error!("Error submitting transaction: {:?}", e),
Err(e) => error!("Error submitting solution: {:?}", e),
}
}

} else if let Err(e) = message {
error!("❌ Error receiving best header message: {:?}", e);
}
Expand Down

0 comments on commit 1a2a7c2

Please sign in to comment.