Merge branch 'mine_subtask' into next_mine_spec

This commit is contained in:
Bruno Valente 2024-12-27 13:35:14 +08:00
commit ab6a4e8120
10 changed files with 383 additions and 34 deletions

View File

@ -1,4 +1,4 @@
use contract_interface::zgs_flow::MineContext; use contract_interface::pora_mine::MineContext;
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use rand::{self, Rng}; use rand::{self, Rng};
use std::time; use std::time;
@ -35,16 +35,23 @@ pub struct PoraService {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct PoraPuzzle { pub(super) struct PoraPuzzle {
context: MineContext, context: MineContext,
target_quality: U256, pora_target: U256,
max_shards: u64, max_shards: u64,
subtask_digest: H256,
} }
impl PoraPuzzle { impl PoraPuzzle {
pub fn new(context: MineContext, target_quality: U256, max_shards: u64) -> Self { pub fn new(
context: MineContext,
pora_target: U256,
max_shards: u64,
subtask_digest: H256,
) -> Self {
Self { Self {
context, context,
target_quality, pora_target,
max_shards, max_shards,
subtask_digest,
} }
} }
@ -255,7 +262,8 @@ impl PoraService {
miner_id: &self.miner_id, miner_id: &self.miner_id,
mine_range_config: &self.mine_range, mine_range_config: &self.mine_range,
context: &puzzle.context, context: &puzzle.context,
target_quality: &puzzle.target_quality, subtask_digest: &puzzle.subtask_digest,
pora_target: &puzzle.pora_target,
loader: &*self.loader, loader: &*self.loader,
}) })
} }

View File

@ -2,7 +2,7 @@ use super::metrics::*;
use crate::recall_range::RecallRange; use crate::recall_range::RecallRange;
use crate::{MineRangeConfig, PoraLoader}; use crate::{MineRangeConfig, PoraLoader};
use blake2::{Blake2b512, Digest}; use blake2::{Blake2b512, Digest};
use contract_interface::zgs_flow::MineContext; use contract_interface::pora_mine::MineContext;
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use ethers::utils::keccak256; use ethers::utils::keccak256;
use lighthouse_metrics::inc_counter; use lighthouse_metrics::inc_counter;
@ -25,7 +25,8 @@ pub(crate) struct Miner<'a> {
pub range: RecallRange, pub range: RecallRange,
pub miner_id: &'a H256, pub miner_id: &'a H256,
pub context: &'a MineContext, pub context: &'a MineContext,
pub target_quality: &'a U256, pub subtask_digest: &'a H256,
pub pora_target: &'a U256,
pub loader: &'a dyn PoraLoader, pub loader: &'a dyn PoraLoader,
pub mine_range_config: &'a MineRangeConfig, pub mine_range_config: &'a MineRangeConfig,
} }
@ -107,11 +108,11 @@ impl<'a> Miner<'a> {
.range .range
.difficulty_scale_x64(self.context.flow_length.as_u64()); .difficulty_scale_x64(self.context.flow_length.as_u64());
if quality <= (self.target_quality / difficulty_scale_x64) << 64 { if quality <= (self.pora_target / difficulty_scale_x64) << 64 {
debug!( debug!(
"Find a PoRA valid answer, quality: {}, target_quality {}, scale {:.3}", "Find a PoRA valid answer, quality: {}, pora_target {}, scale {:.3}",
U256::MAX / quality, U256::MAX / quality,
U256::MAX / self.target_quality, U256::MAX / self.pora_target,
difficulty_scale_x64.as_u128() as f64 / u64::MAX as f64 difficulty_scale_x64.as_u128() as f64 / u64::MAX as f64
); );
inc_counter(&HIT_COUNT); inc_counter(&HIT_COUNT);
@ -139,7 +140,7 @@ impl<'a> Miner<'a> {
let mut hasher = Blake2b512::new(); let mut hasher = Blake2b512::new();
hasher.update(self.miner_id); hasher.update(self.miner_id);
hasher.update(nonce); hasher.update(nonce);
hasher.update(self.context.digest); hasher.update(self.subtask_digest);
hasher.update(self.range.digest()); hasher.update(self.range.digest());
hasher.finalize().into() hasher.finalize().into()
}; };

View File

@ -87,7 +87,7 @@ impl Sealer {
async fn update_flow_length(&mut self) -> Result<()> { async fn update_flow_length(&mut self) -> Result<()> {
let recent_context = self.flow_contract.make_context_with_result().call().await?; let recent_context = self.flow_contract.make_context_with_result().call().await?;
debug!(target: "seal", "Recent context is {:?}", recent_context); debug!("Recent context is {:?}", recent_context);
let recent_flow_length = recent_context.flow_length.as_u64(); let recent_flow_length = recent_context.flow_length.as_u64();
if self.last_context_flow_length < recent_flow_length { if self.last_context_flow_length < recent_flow_length {

View File

@ -46,6 +46,7 @@ impl MineService {
msg_recv.resubscribe(), msg_recv.resubscribe(),
provider.clone(), provider.clone(),
&config, &config,
miner_id,
); );
let mine_answer_receiver = PoraService::spawn( let mine_answer_receiver = PoraService::spawn(

View File

@ -1,6 +1,6 @@
#![allow(unused)] #![allow(unused)]
use contract_interface::{zgs_flow::MineContext, PoraMine, ZgsFlow}; use contract_interface::{zgs_flow::MineContext, PoraMine, WorkerContext, ZgsFlow};
use ethereum_types::{Address, H256, U256}; use ethereum_types::{Address, H256, U256};
use ethers::{ use ethers::{
contract::Contract, contract::Contract,
@ -36,6 +36,7 @@ pub struct MineContextWatcher {
mine_context_sender: broadcast::Sender<MineContextMessage>, mine_context_sender: broadcast::Sender<MineContextMessage>,
last_report: MineContextMessage, last_report: MineContextMessage,
query_interval: Duration, query_interval: Duration,
miner_id: H256,
msg_recv: broadcast::Receiver<MinerMessage>, msg_recv: broadcast::Receiver<MinerMessage>,
} }
@ -46,6 +47,7 @@ impl MineContextWatcher {
msg_recv: broadcast::Receiver<MinerMessage>, msg_recv: broadcast::Receiver<MinerMessage>,
provider: Arc<Provider<RetryClient<Http>>>, provider: Arc<Provider<RetryClient<Http>>>,
config: &MinerConfig, config: &MinerConfig,
miner_id: H256,
) -> broadcast::Receiver<MineContextMessage> { ) -> broadcast::Receiver<MineContextMessage> {
let mine_contract = PoraMine::new(config.mine_address, provider.clone()); let mine_contract = PoraMine::new(config.mine_address, provider.clone());
let flow_contract = ZgsFlow::new(config.flow_address, provider.clone()); let flow_contract = ZgsFlow::new(config.flow_address, provider.clone());
@ -60,6 +62,7 @@ impl MineContextWatcher {
msg_recv, msg_recv,
last_report: None, last_report: None,
query_interval: config.context_query_interval, query_interval: config.context_query_interval,
miner_id,
}; };
executor.spawn( executor.spawn(
async move { Box::pin(watcher.start()).await }, async move { Box::pin(watcher.start()).await },
@ -105,20 +108,26 @@ impl MineContextWatcher {
} }
async fn query_recent_context(&mut self) -> Result<(), String> { async fn query_recent_context(&mut self) -> Result<(), String> {
let context_call = self.flow_contract.make_context_with_result(); let miner_id = self.miner_id.0;
let valid_call = self.mine_contract.can_submit(); let WorkerContext {
let quality_call = self.mine_contract.pora_target(); context,
let shards_call = self.mine_contract.max_shards(); pora_target,
subtask_digest,
max_shards,
} = self
.mine_contract
.compute_worker_context(miner_id)
.call()
.await
.map_err(|e| format!("Failed to query mining context: {:?}", e))?;
let (context, can_submit, quality, max_shards) = try_join!( let report = if pora_target > U256::zero() && context.digest != EMPTY_HASH.0 {
context_call.call(), Some(PoraPuzzle::new(
valid_call.call(), context,
quality_call.call(), pora_target,
shards_call.call() max_shards,
) H256(subtask_digest),
.map_err(|e| format!("Failed to query mining context: {:?}", e))?; ))
let report = if can_submit && context.digest != EMPTY_HASH.0 {
Some(PoraPuzzle::new(context, quality, max_shards))
} else { } else {
None None
}; };
@ -127,6 +136,8 @@ impl MineContextWatcher {
return Ok(()); return Ok(());
} }
debug!("Update pora puzzle: {:?}", report);
self.mine_context_sender self.mine_context_sender
.send(report.clone()) .send(report.clone())
.map_err(|e| format!("Failed to send out the most recent mine context: {:?}", e))?; .map_err(|e| format!("Failed to send out the most recent mine context: {:?}", e))?;

View File

@ -1 +1 @@
bc826a18642023401040cf6dd4f2b10b0748075f 1e931c7b168f9bc2b55f7b8fd96946e35b373048

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -75,7 +75,7 @@ class MineTest(TestFramework):
wait_until(lambda: self.mine_contract.last_mined_epoch() == start_epoch + 1 and not self.mine_contract.can_submit(), timeout=120) wait_until(lambda: self.mine_contract.last_mined_epoch() == start_epoch + 1 and not self.mine_contract.can_submit(), timeout=120)
rewards = self.reward_contract.reward_distributes() rewards = self.reward_contract.reward_distributes()
assert_equal(len(rewards), 2) assert_equal(len(rewards), 4)
firstReward = rewards[0].args.amount firstReward = rewards[0].args.amount
self.log.info("Received reward %d Gwei", firstReward / (10**9)) self.log.info("Received reward %d Gwei", firstReward / (10**9))
@ -96,8 +96,8 @@ class MineTest(TestFramework):
assert_equal(self.contract.epoch(), start_epoch + 2) assert_equal(self.contract.epoch(), start_epoch + 2)
rewards = self.reward_contract.reward_distributes() rewards = self.reward_contract.reward_distributes()
assert_equal(len(rewards), 4) assert_equal(len(rewards), 8)
secondReward = rewards[2].args.amount secondReward = rewards[4].args.amount
self.log.info("Received reward %d Gwei", secondReward / (10**9)) self.log.info("Received reward %d Gwei", secondReward / (10**9))
assert_greater_than(secondReward, 100 * firstReward / (start_epoch + 1)) assert_greater_than(secondReward, 100 * firstReward / (start_epoch + 1))

View File

@ -105,6 +105,9 @@ class MineContractProxy(ContractProxy):
def can_submit(self, node_idx=0): def can_submit(self, node_idx=0):
return self._call("canSubmit", node_idx) return self._call("canSubmit", node_idx)
def current_submissions(self, node_idx=0):
return self._call("currentSubmissions", node_idx)
def set_quality(self, quality, node_idx=0): def set_quality(self, quality, node_idx=0):
return self._send("setQuality", node_idx, _targetQuality=quality) return self._send("setQuality", node_idx, _targetQuality=quality)