Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
676838a
Setting up logs
BHouwens Jun 26, 2024
04e0ba9
initial implementation of SHA3-256 in an OpenGL compute shader
DaMatrix Jun 26, 2024
d8c2ac9
working SHA3-256 on the GPU
DaMatrix Jun 27, 2024
12be98e
gpu miner can mine when no difficulty function is set!
DaMatrix Jun 27, 2024
2b8484d
initial attempt at implementing the difficulty function on the GPU
DaMatrix Jun 27, 2024
f0136b3
difficulty function on the GPU works!
DaMatrix Jun 27, 2024
03ce2ab
clean up opengl api a bit
DaMatrix Jun 28, 2024
3876ed4
clean up opengl api even more
DaMatrix Jun 28, 2024
86e0306
integrate the opengl miner into the existing mining function
DaMatrix Jun 28, 2024
41d226d
make the opengl miner safe to be created and destroyed from multiple …
DaMatrix Jun 28, 2024
3673764
try to improve miner thread-safety
DaMatrix Jun 28, 2024
b161f06
split up miner-related code into separate modules
DaMatrix Jul 1, 2024
ad2089b
add a constant for SHA3-256 digest size
DaMatrix Jul 1, 2024
e17a8ba
initial implementation of a miner in vulkan
DaMatrix Jul 1, 2024
d705ac7
miner_pow: add a more general-purpose user interface as a trait for a…
DaMatrix Jul 2, 2024
18a2d79
move opengl miner into miner_pow directory and add separate miner ben…
DaMatrix Jul 2, 2024
08d2199
Merge branch 'refs/heads/difficulty_function_opengl' into difficulty_…
DaMatrix Jul 2, 2024
007e8d1
miner_pow::vulkan: implement PoWBlockMiner
DaMatrix Jul 2, 2024
5bb8f5f
miner_pow::vulkan: use specialization constants instead of uniforms f…
DaMatrix Jul 2, 2024
29f1898
miner_pow::vulkan: specialize hash code for SHA3-256
DaMatrix Jul 3, 2024
0f4714b
miner_pow: add a flag to indicate if a miner is hardware-accelerated
DaMatrix Jul 3, 2024
bf8b21c
miner_pow: improved handling for nonces
DaMatrix Jul 3, 2024
dcbe669
Allow blocks to have nonces up to 32 bytes in length
DaMatrix Jul 3, 2024
79ad899
Drastically reduce minimum block PoW difficulty
DaMatrix Jul 3, 2024
ff4ae3c
Merge branch 'refs/heads/difficulty_function_opengl' into difficulty_…
DaMatrix Jul 3, 2024
f7d2399
miner_pow: abstract away object type so that we can use the same mine…
DaMatrix Jul 3, 2024
983f091
miner_pow: implement required traits to use miner for addresses as well
DaMatrix Jul 3, 2024
5fb9ce4
miner_pow: dynamically select the best miner implementation
DaMatrix Jul 3, 2024
dba8319
Merge branch 'refs/heads/difficulty_function_opengl' into difficulty_…
DaMatrix Jul 3, 2024
5d4ae75
miner_pow::vulkan: fix build after merge
DaMatrix Jul 3, 2024
568034d
miner_pow::vulkan: pre-digest leading bytes on the CPU
DaMatrix Jul 3, 2024
7aaa999
miner_pow::vulkan: Add optimized functions for digesting more than 1 …
DaMatrix Jul 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
413 changes: 412 additions & 1 deletion Cargo.lock

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ readme = "README.md"
description = "The AIBlock Network"

[dependencies]
ahash = "0.8.11"
async-std = "1.7.0"
async-trait = "0.1.58"
async-stream = "0.3.2"
Expand All @@ -15,8 +16,11 @@ bytes = { version = "1.0.1", features = ["serde"] }
chrono = "0.4.10"
clap = "2.33.0"
config = { version = "0.10.1", features = ["toml"] }
crevice = "0.16.0"
futures = "0.3"
futures-util = "0.3.15"
gl = "0.14.0"
glfw = "0.57.0"
hex = "0.4.2"
merkletree = "0.23.0"
merkle-log = "0.0.3"
Expand All @@ -41,9 +45,12 @@ tracing-subscriber = "0.2.3"
tracing-futures = "0.2.3"
warp = { version = "0.3.1", features = ["tls"] }
url = "2.4.1"
vulkano = "0.34.0"
vulkano-shaders = "0.34.0"
trust-dns-resolver = "0.23.2"
rustls-pemfile = "2.0.0"

[features]
mock = []
config_override = []
benchmark_miners = []
4 changes: 3 additions & 1 deletion src/api/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ async fn get_db_with_block_no_mutex() -> SimpleDb {
block.header = apply_mining_tx(block.header, nonce, "test".to_string());

if !validate_pow_block(&block.header) {
block.header = generate_pow_for_block(block.header);
block.header.nonce_and_mining_tx_hash.0 = generate_pow_for_block(&block.header)
.expect("error occurred while mining block")
.expect("couldn't find a valid nonce");
let new_nonce = hex::encode(&block.header.nonce_and_mining_tx_hash.0);
panic!(
"get_db_with_block_no_mutex: Out of date nonce: {} -> new({})",
Expand Down
21 changes: 18 additions & 3 deletions src/asert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fn map_asert_inputs(
const TARGET_BLOCK_TIME_D: Duration = Duration::from_secs(ASERT_TARGET_HASHES_PER_BLOCK);
const HALF_LIFE_D: Duration = Duration::from_secs(ASERT_HALF_LIFE);

let anchor_target = "0x1f00ffff".parse().unwrap();
let anchor_target = "0xc800ffff".parse().unwrap();

let context = Asert::with_parameters(TARGET_BLOCK_TIME_D, HALF_LIFE_D)
.with_anchor(anchor_block_height, anchor_target)
Expand Down Expand Up @@ -290,8 +290,9 @@ impl Sub for Timestamp {
pub struct CompactTarget(u32);

impl CompactTarget {
/// This is defined ... somewhere.
pub const MAX: CompactTarget = CompactTarget(u32::from_be_bytes([0x1d, 0x00, 0xff, 0xff]));
/// This is the easiest difficulty possible. It's roughly equivalent to requiring a single
/// leading zero byte.
pub const MAX: CompactTarget = CompactTarget(u32::from_be_bytes([0x22, 0x00, 0x00, 0x01]));

pub fn expand(&self) -> Target {
let byte_len = self.0 >> 24;
Expand All @@ -308,6 +309,10 @@ impl CompactTarget {
Target(target)
}

pub fn expand_integer(&self) -> Integer {
self.expand().0
}

pub fn into_array(self) -> [u8; 4] {
self.0.to_be_bytes()
}
Expand Down Expand Up @@ -385,11 +390,15 @@ impl HeaderHash {

pub fn is_below_target(&self, target: &Target) -> bool {
let h_int = Integer::from_digits(self.0.as_slice(), rug::integer::Order::MsfBe);
println!("h_int: {:?}", h_int);
println!("target: {:?}", target.0);
println!("h_int <= target.0: {:?}", h_int <= target.0);
h_int <= target.0
}

pub fn is_below_compact_target(&self, target: &CompactTarget) -> bool {
let target = target.expand();
println!("target: {:?}", target);
self.is_below_target(&target)
}

Expand All @@ -398,6 +407,12 @@ impl HeaderHash {
}
}

impl From<sha3_256::Output<sha3::Sha3_256>> for HeaderHash {
fn from(value: sha3_256::Output<sha3::Sha3_256>) -> Self {
Self(value)
}
}

/// The expanded integer from of a `CompactTarget` that represents the target
/// a block hash must be lower than in order to meet PoW requirements.
///
Expand Down
2 changes: 1 addition & 1 deletion src/bin/node_settings_local_raft_1.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jurisdiction = "US"
backup_block_modulo = 4
peer_limit = 5
sub_peer_limit = 1
mempool_mining_event_timeout= 3000
mempool_mining_event_timeout= 30000
storage_block_timeout = 30000
#backup_restore = true
enable_trigger_messages_pipeline_reset = true
Expand Down
11 changes: 10 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ pub const SANC_LIST_TEST: &str = "src/db/sanc_list_test.json";

/*------- LIMIT CONSTANTS -------*/

/// Length of address PoW nonce
pub const ADDRESS_POW_NONCE_LEN: usize = 4;

/// Maximum length of PoW nonce
pub const POW_NONCE_MAX_LEN: usize = 32; // The size of a SHA3-256 digest

/// Length of random number generation for miner subselection
pub const POW_RNUM_SELECT: usize = 10;

/// Default limit on number of internal transactions for a miner node
pub const INTERNAL_TX_LIMIT: usize = 999;

Expand Down Expand Up @@ -106,7 +115,7 @@ pub const COINBASE_MATURITY: u64 = if cfg!(test) { 0 } else { 100 };
// note that this can be overriden through configuration,
// which is handy for running locally or for low-difficulty test networks.
/// Block height at which ASERT DAA is activated
pub const ACTIVATION_HEIGHT_ASERT: u64 = u64::MAX;
pub const ACTIVATION_HEIGHT_ASERT: u64 = 3;
/// Number of desired hashes submitted per block interval by miners
pub const ASERT_TARGET_HASHES_PER_BLOCK: u64 = 11;

Expand Down
23 changes: 0 additions & 23 deletions src/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,29 +220,6 @@ pub struct ProofOfWork {
pub nonce: Vec<u8>,
}

/// PoW structure for blocks
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProofOfWorkBlock {
pub nonce: Vec<u8>,
pub block: Block,
}

impl Default for ProofOfWorkBlock {
fn default() -> Self {
Self::new()
}
}

impl ProofOfWorkBlock {
///Proof of work block constructor
pub fn new() -> Self {
ProofOfWorkBlock {
nonce: Vec::new(),
block: Block::new(),
}
}
}

/// Winning PoW structure
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct WinningPoWInfo {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod key_creation;
mod mempool;
mod mempool_raft;
mod miner;
mod miner_pow;
mod pre_launch;
mod raft;
mod raft_store;
Expand Down
2 changes: 1 addition & 1 deletion src/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::threaded_call::{ThreadedCallChannel, ThreadedCallSender};
use crate::tracked_utxo::TrackedUtxoSet;
use crate::utils::{
apply_mining_tx, check_druid_participants, create_item_asset_tx_from_sig, create_socket_addr,
format_parition_pow_address, generate_pow_random_num, get_timestamp_now,
format_parition_pow_address, get_timestamp_now, generate_pow_random_num,
is_timestamp_difference_greater, to_api_keys, to_route_pow_infos, validate_pow_block,
validate_pow_for_address, ApiKeys, LocalEvent, LocalEventChannel, LocalEventSender,
ResponseResult, RoutesPoWInfo, StringError,
Expand Down
5 changes: 4 additions & 1 deletion src/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1536,7 +1536,10 @@ impl MinerNode {
/// * `info` - Block Proof of work info
fn generate_pow_for_block(mut info: BlockPoWInfo) -> task::JoinHandle<BlockPoWInfo> {
task::spawn_blocking(move || {
info.header = generate_pow_for_block(info.header);
info.header.nonce_and_mining_tx_hash.0 = generate_pow_for_block(&info.header)
.expect("error occurred while mining block")
// TODO: We should make BlockPoWInfo actually indicate if no PoW could be found
.expect("couldn't find a valid nonce");
info
})
}
Expand Down
92 changes: 92 additions & 0 deletions src/miner_pow/cpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use tw_chain::crypto::sha3_256;
use crate::constants::MINING_DIFFICULTY;
use crate::miner_pow::{MinerStatistics, SHA3_256PoWMiner, PoWDifficulty, MineError};

/// A miner which runs on the CPU.
#[derive(Copy, Clone, Debug)]
pub struct CpuMiner(); // this is stateless

impl CpuMiner {
/// Creates a new CPU miner instance.
pub fn new() -> Self {
Self()
}
}

impl SHA3_256PoWMiner for CpuMiner {
fn is_hw_accelerated(&self) -> bool {
false
}

fn min_nonce_count(&self) -> u32 {
1
}

fn nonce_peel_amount(&self) -> u32 {
// TODO: We'd probably want to choose a better metric for this
1 << 10
}

fn generate_pow_internal(
&mut self,
leading_bytes: &[u8],
trailing_bytes: &[u8],
difficulty: &PoWDifficulty,
first_nonce: u32,
nonce_count: u32,
statistics: &mut MinerStatistics,
) -> Result<Option<u32>, MineError> {
if nonce_count == 0 {
return Ok(None);
}

let mut stats_updater = statistics.update_safe();

let difficulty_target = match difficulty {
// The target value is higher than the largest possible SHA3-256 hash. Therefore,
// every hash will meet the required difficulty threshold, so we can just return
// an arbitrary nonce.
PoWDifficulty::TargetHashAlwaysPass => return Ok(Some(first_nonce)),

PoWDifficulty::LeadingZeroBytes { leading_zeroes } => {
assert_eq!(*leading_zeroes, MINING_DIFFICULTY);
None
},
PoWDifficulty::TargetHash { target_hash } => Some(target_hash),
};

let block_header_nonce_offset = leading_bytes.len();
let mut block_header_bytes =
[ leading_bytes, &0u32.to_le_bytes(), trailing_bytes ].concat();

for i in 0..nonce_count {
let nonce = first_nonce.wrapping_add(i);

block_header_bytes
[block_header_nonce_offset..block_header_nonce_offset + 4]
.copy_from_slice(&nonce.to_ne_bytes());

let hash = sha3_256::digest(&block_header_bytes);

stats_updater.computed_hashes(1);

match difficulty_target {
None => {
// There isn't a difficulty function, check if the first MINING_DIFFICULTY bytes
// of the hash are 0
let hash_prefix = hash.first_chunk::<MINING_DIFFICULTY>().unwrap();
if hash_prefix == &[0u8; MINING_DIFFICULTY] {
return Ok(Some(nonce));
}
}
Some(target) => {
if hash.as_slice() <= target.as_slice() {
return Ok(Some(nonce));
}
}
}
}

Ok(None)
}
}
Loading