mirror of
https://github.com/0glabs/0g-storage-node.git
synced 2024-11-10 10:05:17 +00:00
Update with the most recent storage contract (#142)
* Update with the most recent storage contract * fix nits
This commit is contained in:
parent
533bacb234
commit
7d73ccd1e1
@ -9,6 +9,7 @@ mod loader;
|
|||||||
mod metrics;
|
mod metrics;
|
||||||
mod mine;
|
mod mine;
|
||||||
mod miner_id;
|
mod miner_id;
|
||||||
|
mod monitor;
|
||||||
pub mod pora;
|
pub mod pora;
|
||||||
mod recall_range;
|
mod recall_range;
|
||||||
mod sealer;
|
mod sealer;
|
||||||
|
@ -9,7 +9,6 @@ use tokio::time::{sleep, Duration, Instant};
|
|||||||
use storage::config::ShardConfig;
|
use storage::config::ShardConfig;
|
||||||
use zgs_spec::{SECTORS_PER_LOAD, SECTORS_PER_MAX_MINING_RANGE, SECTORS_PER_PRICING};
|
use zgs_spec::{SECTORS_PER_LOAD, SECTORS_PER_MAX_MINING_RANGE, SECTORS_PER_PRICING};
|
||||||
|
|
||||||
use super::metrics;
|
|
||||||
use crate::recall_range::RecallRange;
|
use crate::recall_range::RecallRange;
|
||||||
use crate::{
|
use crate::{
|
||||||
pora::{AnswerWithoutProof, Miner},
|
pora::{AnswerWithoutProof, Miner},
|
||||||
@ -20,7 +19,7 @@ use crate::{
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct PoraService {
|
pub struct PoraService {
|
||||||
mine_context_receiver: mpsc::UnboundedReceiver<MineContextMessage>,
|
mine_context_receiver: broadcast::Receiver<MineContextMessage>,
|
||||||
mine_answer_sender: mpsc::UnboundedSender<AnswerWithoutProof>,
|
mine_answer_sender: mpsc::UnboundedSender<AnswerWithoutProof>,
|
||||||
msg_recv: broadcast::Receiver<MinerMessage>,
|
msg_recv: broadcast::Receiver<MinerMessage>,
|
||||||
loader: Arc<dyn PoraLoader>,
|
loader: Arc<dyn PoraLoader>,
|
||||||
@ -33,9 +32,29 @@ pub struct PoraService {
|
|||||||
iter_batch: usize,
|
iter_batch: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PoraPuzzle {
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub(super) struct PoraPuzzle {
|
||||||
context: MineContext,
|
context: MineContext,
|
||||||
target_quality: U256,
|
target_quality: U256,
|
||||||
|
max_shards: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PoraPuzzle {
|
||||||
|
pub fn new(context: MineContext, target_quality: U256, max_shards: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
context,
|
||||||
|
target_quality,
|
||||||
|
max_shards,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn max_shards(&self) -> u64 {
|
||||||
|
self.max_shards
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn context_digest(&self) -> H256 {
|
||||||
|
H256(self.context.digest)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct MineRangeConfig {
|
pub struct MineRangeConfig {
|
||||||
@ -89,7 +108,7 @@ impl PoraService {
|
|||||||
pub fn spawn(
|
pub fn spawn(
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
msg_recv: broadcast::Receiver<MinerMessage>,
|
msg_recv: broadcast::Receiver<MinerMessage>,
|
||||||
mine_context_receiver: mpsc::UnboundedReceiver<MineContextMessage>,
|
mine_context_receiver: broadcast::Receiver<MineContextMessage>,
|
||||||
loader: Arc<dyn PoraLoader>,
|
loader: Arc<dyn PoraLoader>,
|
||||||
config: &MinerConfig,
|
config: &MinerConfig,
|
||||||
miner_id: H256,
|
miner_id: H256,
|
||||||
@ -138,15 +157,19 @@ impl PoraService {
|
|||||||
Ok(MinerMessage::SetStartPosition(pos)) => {
|
Ok(MinerMessage::SetStartPosition(pos)) => {
|
||||||
info!("Change start position to: {:?}", pos);
|
info!("Change start position to: {:?}", pos);
|
||||||
self.mine_range.start_position = pos;
|
self.mine_range.start_position = pos;
|
||||||
|
self.report_reason_if_mine_stop("update mine range");
|
||||||
|
|
||||||
}
|
}
|
||||||
Ok(MinerMessage::SetEndPosition(pos)) => {
|
Ok(MinerMessage::SetEndPosition(pos)) => {
|
||||||
info!("Change end position to: {:?}", pos);
|
info!("Change end position to: {:?}", pos);
|
||||||
self.mine_range.end_position = pos;
|
self.mine_range.end_position = pos;
|
||||||
|
self.report_reason_if_mine_stop("update mine range");
|
||||||
}
|
}
|
||||||
Ok(MinerMessage::SetShardConfig(shard_config)) => {
|
Ok(MinerMessage::SetShardConfig(shard_config)) => {
|
||||||
self.mine_range.shard_config = shard_config;
|
self.mine_range.shard_config = shard_config;
|
||||||
|
self.report_reason_if_mine_stop("update shard");
|
||||||
}
|
}
|
||||||
Err(broadcast::error::RecvError::Closed)=>{
|
Err(broadcast::error::RecvError::Closed) => {
|
||||||
warn!("Unexpected: Mine service config channel closed.");
|
warn!("Unexpected: Mine service config channel closed.");
|
||||||
channel_opened = false;
|
channel_opened = false;
|
||||||
}
|
}
|
||||||
@ -157,21 +180,26 @@ impl PoraService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maybe_msg = self.mine_context_receiver.recv() => {
|
maybe_msg = self.mine_context_receiver.recv() => {
|
||||||
if let Some(msg) = maybe_msg {
|
match maybe_msg {
|
||||||
|
Ok(msg) => {
|
||||||
info!("Update mine service: {:?}", msg);
|
info!("Update mine service: {:?}", msg);
|
||||||
info!("Mine iterations statistics: {}", metrics::report());
|
self.puzzle = msg;
|
||||||
self.puzzle = msg.map(|(context, target_quality)| PoraPuzzle {
|
self.report_reason_if_mine_stop("update mine context");
|
||||||
context, target_quality
|
},
|
||||||
});
|
Err(broadcast::error::RecvError::Closed) => {
|
||||||
} else {
|
|
||||||
warn!("Mine context channel closed.");
|
warn!("Mine context channel closed.");
|
||||||
|
},
|
||||||
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
() = &mut diastole, if !diastole.is_elapsed() => {
|
() = &mut diastole, if !diastole.is_elapsed() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = async {}, if mining_enabled && cpu_percent > 0 && self.as_miner().map_or(false, |miner| miner.range.mining_length > 0) && diastole.is_elapsed() => {
|
_ = async {}, if mining_enabled
|
||||||
|
&& cpu_percent > 0
|
||||||
|
&& self.as_miner().is_ok()
|
||||||
|
&& diastole.is_elapsed() => {
|
||||||
let nonce = H256(rand::thread_rng().gen());
|
let nonce = H256(rand::thread_rng().gen());
|
||||||
let miner = self.as_miner().unwrap();
|
let miner = self.as_miner().unwrap();
|
||||||
|
|
||||||
@ -194,13 +222,27 @@ impl PoraService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_miner(&self) -> Option<Miner> {
|
fn as_miner(&self) -> Result<Miner, &'static str> {
|
||||||
let puzzle = self.puzzle.as_ref()?;
|
let puzzle = self.puzzle.as_ref().ok_or("no mine context")?;
|
||||||
|
|
||||||
let range = self.mine_range.to_valid_range(&puzzle.context)?;
|
let range = self
|
||||||
(range.mining_length > 0).then_some(())?;
|
.mine_range
|
||||||
|
.to_valid_range(&puzzle.context)
|
||||||
|
.ok_or("no mine range")?;
|
||||||
|
|
||||||
Some(Miner {
|
if range.mining_length == 0 {
|
||||||
|
return Err("mine range is zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
if puzzle.max_shards() < self.mine_range.shard_config.num_shard as u64 {
|
||||||
|
return Err("too many mine shards");
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.mine_range.shard_config.num_shard as u64 > puzzle.context.flow_length.as_u64() {
|
||||||
|
return Err("Not enough flow length to shard");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Miner {
|
||||||
range,
|
range,
|
||||||
miner_id: &self.miner_id,
|
miner_id: &self.miner_id,
|
||||||
mine_range_config: &self.mine_range,
|
mine_range_config: &self.mine_range,
|
||||||
@ -209,4 +251,10 @@ impl PoraService {
|
|||||||
loader: &*self.loader,
|
loader: &*self.loader,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn report_reason_if_mine_stop(&self, event: &'static str) {
|
||||||
|
if let Err(reason) = self.as_miner() {
|
||||||
|
info!(reason, "Mine stopped on {}", event);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
27
node/miner/src/monitor.rs
Normal file
27
node/miner/src/monitor.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use task_executor::TaskExecutor;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
use super::metrics;
|
||||||
|
|
||||||
|
pub struct Monitor {
|
||||||
|
period: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Monitor {
|
||||||
|
pub fn spawn(executor: TaskExecutor, period: Duration) {
|
||||||
|
let monitor = Monitor { period };
|
||||||
|
executor.spawn(
|
||||||
|
async move { Box::pin(monitor.start()).await },
|
||||||
|
"pora_master",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start(&self) {
|
||||||
|
loop {
|
||||||
|
info!("Mine iterations statistics: {}", metrics::report());
|
||||||
|
let _ = sleep(self.period).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -102,15 +102,16 @@ impl<'a> Miner<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let quality = self.pora(idx, &sealed_data, pad_seed);
|
let quality = self.pora(idx, &sealed_data, pad_seed);
|
||||||
let quality_scale = self.range.shard_mask.count_zeros();
|
let difficulty_scale_x64 = self
|
||||||
if quality <= U256::MAX >> quality_scale
|
.range
|
||||||
&& quality << quality_scale <= *self.target_quality
|
.difficulty_scale_x64(self.context.flow_length.as_u64());
|
||||||
{
|
|
||||||
|
if quality <= (self.target_quality / difficulty_scale_x64) << 64 {
|
||||||
debug!(
|
debug!(
|
||||||
"Find a PoRA valid answer, quality: {}, target_quality {}, scale {}",
|
"Find a PoRA valid answer, quality: {}, target_quality {}, scale {:.3}",
|
||||||
U256::MAX / quality,
|
U256::MAX / quality,
|
||||||
U256::MAX / self.target_quality,
|
U256::MAX / self.target_quality,
|
||||||
quality_scale
|
difficulty_scale_x64.as_u128() as f64 / (u64::MAX as f64 + 1.0)
|
||||||
);
|
);
|
||||||
inc_counter(&HIT_COUNT);
|
inc_counter(&HIT_COUNT);
|
||||||
// Undo mix data when find a valid solition
|
// Undo mix data when find a valid solition
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use ethereum_types::U256;
|
use ethereum_types::U256;
|
||||||
use tiny_keccak::{Hasher, Keccak};
|
use tiny_keccak::{Hasher, Keccak};
|
||||||
use zgs_spec::SECTORS_PER_LOAD;
|
use zgs_spec::{SECTORS_PER_LOAD, SECTORS_PER_MAX_MINING_RANGE};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
pub struct RecallRange {
|
pub struct RecallRange {
|
||||||
@ -38,6 +38,16 @@ impl RecallRange {
|
|||||||
|
|
||||||
Some(self.start_position + recall_offset * SECTORS_PER_LOAD as u64)
|
Some(self.start_position + recall_offset * SECTORS_PER_LOAD as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn difficulty_scale_x64(&self, flow_length: u64) -> U256 {
|
||||||
|
let no_shard_mine_length = std::cmp::min(flow_length, SECTORS_PER_MAX_MINING_RANGE as u64);
|
||||||
|
let sharded_mine_length = std::cmp::min(
|
||||||
|
flow_length >> self.shard_mask.count_zeros(),
|
||||||
|
SECTORS_PER_MAX_MINING_RANGE as u64,
|
||||||
|
);
|
||||||
|
|
||||||
|
(U256::from(no_shard_mine_length) << 64) / sharded_mine_length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<RecallRange> for contract_interface::RecallRange {
|
impl From<RecallRange> for contract_interface::RecallRange {
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
use crate::miner_id::check_and_request_miner_id;
|
use crate::miner_id::check_and_request_miner_id;
|
||||||
|
use crate::monitor::Monitor;
|
||||||
use crate::sealer::Sealer;
|
use crate::sealer::Sealer;
|
||||||
use crate::submitter::Submitter;
|
use crate::submitter::Submitter;
|
||||||
use crate::{config::MinerConfig, mine::PoraService, watcher::MineContextWatcher};
|
use crate::{config::MinerConfig, mine::PoraService, watcher::MineContextWatcher};
|
||||||
use network::NetworkMessage;
|
use network::NetworkMessage;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
use storage::config::ShardConfig;
|
use storage::config::ShardConfig;
|
||||||
use storage_async::Store;
|
use storage_async::Store;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
@ -48,7 +50,7 @@ impl MineService {
|
|||||||
let mine_answer_receiver = PoraService::spawn(
|
let mine_answer_receiver = PoraService::spawn(
|
||||||
executor.clone(),
|
executor.clone(),
|
||||||
msg_recv.resubscribe(),
|
msg_recv.resubscribe(),
|
||||||
mine_context_receiver,
|
mine_context_receiver.resubscribe(),
|
||||||
store.clone(),
|
store.clone(),
|
||||||
&config,
|
&config,
|
||||||
miner_id,
|
miner_id,
|
||||||
@ -57,12 +59,15 @@ impl MineService {
|
|||||||
Submitter::spawn(
|
Submitter::spawn(
|
||||||
executor.clone(),
|
executor.clone(),
|
||||||
mine_answer_receiver,
|
mine_answer_receiver,
|
||||||
|
mine_context_receiver,
|
||||||
provider.clone(),
|
provider.clone(),
|
||||||
store.clone(),
|
store.clone(),
|
||||||
&config,
|
&config,
|
||||||
);
|
);
|
||||||
|
|
||||||
Sealer::spawn(executor, provider, store, &config, miner_id);
|
Sealer::spawn(executor.clone(), provider, store, &config, miner_id);
|
||||||
|
|
||||||
|
Monitor::spawn(executor, Duration::from_secs(5));
|
||||||
|
|
||||||
debug!("Starting miner service");
|
debug!("Starting miner service");
|
||||||
|
|
||||||
|
@ -6,19 +6,23 @@ use ethers::providers::PendingTransaction;
|
|||||||
use hex::ToHex;
|
use hex::ToHex;
|
||||||
use shared_types::FlowRangeProof;
|
use shared_types::FlowRangeProof;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use storage::H256;
|
||||||
use storage_async::Store;
|
use storage_async::Store;
|
||||||
use task_executor::TaskExecutor;
|
use task_executor::TaskExecutor;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
|
|
||||||
use crate::config::{MineServiceMiddleware, MinerConfig};
|
use crate::config::{MineServiceMiddleware, MinerConfig};
|
||||||
use crate::pora::AnswerWithoutProof;
|
use crate::pora::AnswerWithoutProof;
|
||||||
|
use crate::watcher::MineContextMessage;
|
||||||
|
|
||||||
use zgs_spec::{BYTES_PER_SEAL, SECTORS_PER_SEAL};
|
use zgs_spec::{BYTES_PER_SEAL, SECTORS_PER_SEAL};
|
||||||
|
|
||||||
const SUBMISSION_RETIES: usize = 3;
|
const SUBMISSION_RETIES: usize = 15;
|
||||||
|
|
||||||
pub struct Submitter {
|
pub struct Submitter {
|
||||||
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
||||||
|
mine_context_receiver: broadcast::Receiver<MineContextMessage>,
|
||||||
mine_contract: PoraMine<MineServiceMiddleware>,
|
mine_contract: PoraMine<MineServiceMiddleware>,
|
||||||
flow_contract: ZgsFlow<MineServiceMiddleware>,
|
flow_contract: ZgsFlow<MineServiceMiddleware>,
|
||||||
default_gas_limit: Option<U256>,
|
default_gas_limit: Option<U256>,
|
||||||
@ -29,6 +33,7 @@ impl Submitter {
|
|||||||
pub fn spawn(
|
pub fn spawn(
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
mine_answer_receiver: mpsc::UnboundedReceiver<AnswerWithoutProof>,
|
||||||
|
mine_context_receiver: broadcast::Receiver<MineContextMessage>,
|
||||||
provider: Arc<MineServiceMiddleware>,
|
provider: Arc<MineServiceMiddleware>,
|
||||||
store: Arc<Store>,
|
store: Arc<Store>,
|
||||||
config: &MinerConfig,
|
config: &MinerConfig,
|
||||||
@ -39,6 +44,7 @@ impl Submitter {
|
|||||||
|
|
||||||
let submitter = Submitter {
|
let submitter = Submitter {
|
||||||
mine_answer_receiver,
|
mine_answer_receiver,
|
||||||
|
mine_context_receiver,
|
||||||
mine_contract,
|
mine_contract,
|
||||||
flow_contract,
|
flow_contract,
|
||||||
store,
|
store,
|
||||||
@ -51,18 +57,39 @@ impl Submitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn start(mut self) {
|
async fn start(mut self) {
|
||||||
|
let mut current_context_digest: Option<H256> = None;
|
||||||
loop {
|
loop {
|
||||||
match self.mine_answer_receiver.recv().await {
|
tokio::select! {
|
||||||
|
answer_msg = self.mine_answer_receiver.recv() => {
|
||||||
|
match answer_msg {
|
||||||
Some(answer) => {
|
Some(answer) => {
|
||||||
|
if Some(answer.context_digest) != current_context_digest {
|
||||||
|
info!("Skip submission because of inconsistent context digest");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if let Err(e) = self.submit_answer(answer).await {
|
if let Err(e) = self.submit_answer(answer).await {
|
||||||
warn!(e)
|
warn!(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
warn!("Mine submitter stopped because mine answer channel is closed.");
|
warn!("Mine submitter stopped because mine answer channel is closed.");
|
||||||
break;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context_msg = self.mine_context_receiver.recv() => {
|
||||||
|
match context_msg {
|
||||||
|
Ok(puzzle) => {
|
||||||
|
current_context_digest = puzzle.map(|p| p.context_digest());
|
||||||
|
}
|
||||||
|
Err(broadcast::error::RecvError::Closed) => {
|
||||||
|
warn!("Mine context channel closed.");
|
||||||
|
},
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +163,7 @@ impl Submitter {
|
|||||||
|
|
||||||
let receipt = pending_transaction
|
let receipt = pending_transaction
|
||||||
.retries(SUBMISSION_RETIES)
|
.retries(SUBMISSION_RETIES)
|
||||||
|
.interval(Duration::from_secs(2))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("Fail to execute mine answer transaction: {:?}", e))?
|
.map_err(|e| format!("Fail to execute mine answer transaction: {:?}", e))?
|
||||||
.ok_or(format!(
|
.ok_or(format!(
|
||||||
|
@ -19,9 +19,9 @@ use std::sync::Arc;
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{ops::DerefMut, str::FromStr};
|
use std::{ops::DerefMut, str::FromStr};
|
||||||
|
|
||||||
use crate::{config::MineServiceMiddleware, MinerConfig, MinerMessage};
|
use crate::{config::MineServiceMiddleware, mine::PoraPuzzle, MinerConfig, MinerMessage};
|
||||||
|
|
||||||
pub type MineContextMessage = Option<(MineContext, U256)>;
|
pub type MineContextMessage = Option<PoraPuzzle>;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref EMPTY_HASH: H256 =
|
pub static ref EMPTY_HASH: H256 =
|
||||||
@ -33,7 +33,7 @@ pub struct MineContextWatcher {
|
|||||||
flow_contract: ZgsFlow<MineServiceMiddleware>,
|
flow_contract: ZgsFlow<MineServiceMiddleware>,
|
||||||
mine_contract: PoraMine<MineServiceMiddleware>,
|
mine_contract: PoraMine<MineServiceMiddleware>,
|
||||||
|
|
||||||
mine_context_sender: mpsc::UnboundedSender<MineContextMessage>,
|
mine_context_sender: broadcast::Sender<MineContextMessage>,
|
||||||
last_report: MineContextMessage,
|
last_report: MineContextMessage,
|
||||||
|
|
||||||
msg_recv: broadcast::Receiver<MinerMessage>,
|
msg_recv: broadcast::Receiver<MinerMessage>,
|
||||||
@ -45,14 +45,14 @@ impl MineContextWatcher {
|
|||||||
msg_recv: broadcast::Receiver<MinerMessage>,
|
msg_recv: broadcast::Receiver<MinerMessage>,
|
||||||
provider: Arc<MineServiceMiddleware>,
|
provider: Arc<MineServiceMiddleware>,
|
||||||
config: &MinerConfig,
|
config: &MinerConfig,
|
||||||
) -> mpsc::UnboundedReceiver<MineContextMessage> {
|
) -> broadcast::Receiver<MineContextMessage> {
|
||||||
let provider = provider;
|
let provider = provider;
|
||||||
|
|
||||||
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());
|
||||||
|
|
||||||
let (mine_context_sender, mine_context_receiver) =
|
let (mine_context_sender, mine_context_receiver) =
|
||||||
mpsc::unbounded_channel::<MineContextMessage>();
|
broadcast::channel::<MineContextMessage>(4096);
|
||||||
let watcher = MineContextWatcher {
|
let watcher = MineContextWatcher {
|
||||||
provider,
|
provider,
|
||||||
flow_contract,
|
flow_contract,
|
||||||
@ -108,12 +108,17 @@ impl MineContextWatcher {
|
|||||||
let context_call = self.flow_contract.make_context_with_result();
|
let context_call = self.flow_contract.make_context_with_result();
|
||||||
let valid_call = self.mine_contract.can_submit();
|
let valid_call = self.mine_contract.can_submit();
|
||||||
let quality_call = self.mine_contract.pora_target();
|
let quality_call = self.mine_contract.pora_target();
|
||||||
|
let shards_call = self.mine_contract.max_shards();
|
||||||
|
|
||||||
let (context, can_submit, quality) =
|
let (context, can_submit, quality, max_shards) = try_join!(
|
||||||
try_join!(context_call.call(), valid_call.call(), quality_call.call())
|
context_call.call(),
|
||||||
|
valid_call.call(),
|
||||||
|
quality_call.call(),
|
||||||
|
shards_call.call()
|
||||||
|
)
|
||||||
.map_err(|e| format!("Failed to query mining context: {:?}", e))?;
|
.map_err(|e| format!("Failed to query mining context: {:?}", e))?;
|
||||||
let report = if can_submit && context.digest != EMPTY_HASH.0 {
|
let report = if can_submit && context.digest != EMPTY_HASH.0 {
|
||||||
Some((context, quality))
|
Some(PoraPuzzle::new(context, quality, max_shards))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -8,5 +8,5 @@ check_abis() {
|
|||||||
diff $(./scripts/search_abi.sh "$artifacts_path" "$contract_name.json") "storage-contracts-abis/$contract_name.json"
|
diff $(./scripts/search_abi.sh "$artifacts_path" "$contract_name.json") "storage-contracts-abis/$contract_name.json"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
check_abis DummyMarket DummyReward Flow PoraMine PoraMineTest FixedPrice OnePoolReward FixedPriceFlow
|
check_abis DummyMarket DummyReward Flow PoraMine PoraMineTest FixedPrice ChunkLinearReward FixedPriceFlow
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ copy_abis() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_abis DummyMarket DummyReward Flow PoraMine PoraMineTest FixedPrice OnePoolReward FixedPriceFlow
|
copy_abis DummyMarket DummyReward Flow PoraMine PoraMineTest FixedPrice ChunkLinearReward FixedPriceFlow
|
||||||
|
|
||||||
|
|
||||||
# Step 4: Get the current Git revision and write it to a specified file
|
# Step 4: Get the current Git revision and write it to a specified file
|
||||||
|
@ -1 +1 @@
|
|||||||
6ec57942cba3068d3373bcb2c88f8fd51d2322b1
|
dbeff538b949599c203e43be6ecc05e9e997d09d
|
||||||
|
619
storage-contracts-abis/ChunkLinearReward.json
Normal file
619
storage-contracts-abis/ChunkLinearReward.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -45,14 +45,14 @@ class MineTest(TestFramework):
|
|||||||
self.log.info("Submission done, current epoch is %d", start_epoch)
|
self.log.info("Submission done, current epoch is %d", start_epoch)
|
||||||
|
|
||||||
self.log.info("Wait for the first mine context release")
|
self.log.info("Wait for the first mine context release")
|
||||||
wait_until(lambda: int(blockchain.eth_blockNumber(), 16) >= start_epoch + 1, timeout=180)
|
wait_until(lambda: self.contract.epoch() >= start_epoch + 1, timeout=180)
|
||||||
self.contract.update_context()
|
self.contract.update_context()
|
||||||
|
|
||||||
self.log.info("Wait for the first mine answer")
|
self.log.info("Wait for the first mine answer")
|
||||||
wait_until(lambda: self.mine_contract.last_mined_epoch() == start_epoch + 1 and not self.mine_contract.can_submit(), timeout=180)
|
wait_until(lambda: self.mine_contract.last_mined_epoch() == start_epoch + 1 and not self.mine_contract.can_submit(), timeout=180)
|
||||||
|
|
||||||
self.log.info("Wait for the second mine context release")
|
self.log.info("Wait for the second mine context release")
|
||||||
wait_until(lambda: int(blockchain.eth_blockNumber(), 16) >= start_epoch + 2, timeout=180)
|
wait_until(lambda: self.contract.epoch() >= start_epoch + 2, timeout=180)
|
||||||
self.contract.update_context()
|
self.contract.update_context()
|
||||||
|
|
||||||
self.log.info("Wait for the second mine answer")
|
self.log.info("Wait for the second mine answer")
|
||||||
@ -60,7 +60,7 @@ class MineTest(TestFramework):
|
|||||||
|
|
||||||
self.nodes[0].miner_stop()
|
self.nodes[0].miner_stop()
|
||||||
self.log.info("Wait for the third mine context release")
|
self.log.info("Wait for the third mine context release")
|
||||||
wait_until(lambda: int(blockchain.eth_blockNumber(), 16) >= start_epoch + 3, timeout=180)
|
wait_until(lambda: self.contract.epoch() >= start_epoch + 3, timeout=180)
|
||||||
self.contract.update_context()
|
self.contract.update_context()
|
||||||
|
|
||||||
self.log.info("Submit the second data chunk")
|
self.log.info("Submit the second data chunk")
|
||||||
|
@ -50,6 +50,7 @@ class MineTest(TestFramework):
|
|||||||
|
|
||||||
SECTORS_PER_PRICING = int(8 * ( 2 ** 30 ) / 256)
|
SECTORS_PER_PRICING = int(8 * ( 2 ** 30 ) / 256)
|
||||||
|
|
||||||
|
|
||||||
self.log.info("Submit the actual data chunk (256 MB)")
|
self.log.info("Submit the actual data chunk (256 MB)")
|
||||||
self.submit_data(b"\x11", int(SECTORS_PER_PRICING / 32))
|
self.submit_data(b"\x11", int(SECTORS_PER_PRICING / 32))
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ class MineTest(TestFramework):
|
|||||||
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))
|
||||||
|
|
||||||
self.reward_contract.transfer(10000 * 10 ** 18)
|
self.reward_contract.donate(10000 * 10 ** 18)
|
||||||
self.log.info("Donation Done")
|
self.log.info("Donation Done")
|
||||||
self.log.info("Submit the data hash only (8 GB)")
|
self.log.info("Submit the data hash only (8 GB)")
|
||||||
self.submit_data(b"\x11", int(SECTORS_PER_PRICING), no_submit=True)
|
self.submit_data(b"\x11", int(SECTORS_PER_PRICING), no_submit=True)
|
||||||
|
@ -303,7 +303,7 @@ class BlockchainNode(TestNode):
|
|||||||
mine_contract.functions.setTargetSubmissions(2).transact(TX_PARAMS)
|
mine_contract.functions.setTargetSubmissions(2).transact(TX_PARAMS)
|
||||||
self.log.debug("Mine Initialized")
|
self.log.debug("Mine Initialized")
|
||||||
|
|
||||||
flow_initialize_hash = (flow_contract.get_function_by_signature('initialize(address)'))(dummy_market_contract.address).transact(TX_PARAMS)
|
flow_initialize_hash = flow_contract.functions.initialize(dummy_market_contract.address).transact(TX_PARAMS)
|
||||||
self.log.debug("Flow Initialized")
|
self.log.debug("Flow Initialized")
|
||||||
|
|
||||||
self.wait_for_transaction_receipt(w3, flow_initialize_hash)
|
self.wait_for_transaction_receipt(w3, flow_initialize_hash)
|
||||||
@ -325,7 +325,7 @@ class BlockchainNode(TestNode):
|
|||||||
market_contract, _ = deploy_contract("FixedPrice", [])
|
market_contract, _ = deploy_contract("FixedPrice", [])
|
||||||
self.log.debug("Market deployed")
|
self.log.debug("Market deployed")
|
||||||
|
|
||||||
reward_contract, _ =deploy_contract("OnePoolReward", [LIFETIME_MONTH])
|
reward_contract, _ =deploy_contract("ChunkLinearReward", [LIFETIME_MONTH * 31 * 86400])
|
||||||
self.log.debug("Reward deployed")
|
self.log.debug("Reward deployed")
|
||||||
|
|
||||||
flow_contract, _ = deploy_contract("FixedPriceFlow", [mine_period, 0])
|
flow_contract, _ = deploy_contract("FixedPriceFlow", [mine_period, 0])
|
||||||
@ -336,13 +336,15 @@ class BlockchainNode(TestNode):
|
|||||||
mine_contract.functions.setTargetSubmissions(2).transact(TX_PARAMS)
|
mine_contract.functions.setTargetSubmissions(2).transact(TX_PARAMS)
|
||||||
self.log.debug("Mine Initialized")
|
self.log.debug("Mine Initialized")
|
||||||
|
|
||||||
market_contract.functions.initialize(LIFETIME_MONTH, flow_contract.address, reward_contract.address).transact(TX_PARAMS)
|
price_per_sector = int(LIFETIME_MONTH * 256 * 10 * 1_000_000_000_000_000_000 / 1024 / 1024 / 1024 / 12)
|
||||||
|
market_contract.functions.initialize(price_per_sector, flow_contract.address, reward_contract.address).transact(TX_PARAMS)
|
||||||
self.log.debug("Market Initialized")
|
self.log.debug("Market Initialized")
|
||||||
|
|
||||||
reward_contract.functions.initialize(market_contract.address, mine_contract.address).transact(TX_PARAMS)
|
reward_contract.functions.initialize(market_contract.address, mine_contract.address).transact(TX_PARAMS)
|
||||||
|
reward_contract.functions.setBaseReward(10 ** 18).transact(TX_PARAMS)
|
||||||
self.log.debug("Reward Initialized")
|
self.log.debug("Reward Initialized")
|
||||||
|
|
||||||
flow_initialize_hash = (flow_contract.get_function_by_signature('initialize(address)'))(market_contract.address).transact(TX_PARAMS)
|
flow_initialize_hash = flow_contract.functions.initialize(market_contract.address).transact(TX_PARAMS)
|
||||||
self.log.debug("Flow Initialized")
|
self.log.debug("Flow Initialized")
|
||||||
|
|
||||||
self.wait_for_transaction_receipt(w3, flow_initialize_hash)
|
self.wait_for_transaction_receipt(w3, flow_initialize_hash)
|
||||||
|
@ -29,6 +29,14 @@ class ContractProxy:
|
|||||||
contract = self._get_contract(node_idx)
|
contract = self._get_contract(node_idx)
|
||||||
return getattr(contract.functions, fn_name)(**args).transact(copy(TX_PARAMS))
|
return getattr(contract.functions, fn_name)(**args).transact(copy(TX_PARAMS))
|
||||||
|
|
||||||
|
def _send_payable(self, fn_name, node_idx, value, **args):
|
||||||
|
assert node_idx < len(self.blockchain_nodes)
|
||||||
|
|
||||||
|
contract = self._get_contract(node_idx)
|
||||||
|
tx_params = copy(TX_PARAMS)
|
||||||
|
tx_params["value"] = value
|
||||||
|
return getattr(contract.functions, fn_name)(**args).transact(tx_params)
|
||||||
|
|
||||||
def _logs(self, event_name, node_idx, **args):
|
def _logs(self, event_name, node_idx, **args):
|
||||||
assert node_idx < len(self.blockchain_nodes)
|
assert node_idx < len(self.blockchain_nodes)
|
||||||
|
|
||||||
@ -66,7 +74,6 @@ class FlowContractProxy(ContractProxy):
|
|||||||
contract.w3, tx_hash, parent_hash=parent_hash
|
contract.w3, tx_hash, parent_hash=parent_hash
|
||||||
)
|
)
|
||||||
if receipt["status"] != 1:
|
if receipt["status"] != 1:
|
||||||
print(receipt)
|
|
||||||
assert_equal(receipt["status"], 1)
|
assert_equal(receipt["status"], 1)
|
||||||
return tx_hash
|
return tx_hash
|
||||||
|
|
||||||
@ -98,6 +105,12 @@ class MineContractProxy(ContractProxy):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IRewardContractProxy(ContractProxy):
|
class RewardContractProxy(ContractProxy):
|
||||||
def reward_distributes(self, node_idx=0):
|
def reward_distributes(self, node_idx=0):
|
||||||
return self._logs("DistributeReward", node_idx)
|
return self._logs("DistributeReward", node_idx)
|
||||||
|
|
||||||
|
def donate(self, value, node_idx = 0):
|
||||||
|
return self._send_payable("donate", node_idx, value)
|
||||||
|
|
||||||
|
def base_reward(self, node_idx = 0):
|
||||||
|
return self._call("baseReward", node_idx)
|
@ -15,7 +15,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from eth_utils import encode_hex
|
from eth_utils import encode_hex
|
||||||
from test_framework.bsc_node import BSCNode
|
from test_framework.bsc_node import BSCNode
|
||||||
from test_framework.contract_proxy import FlowContractProxy, MineContractProxy, IRewardContractProxy
|
from test_framework.contract_proxy import FlowContractProxy, MineContractProxy, RewardContractProxy
|
||||||
from test_framework.zgs_node import ZgsNode
|
from test_framework.zgs_node import ZgsNode
|
||||||
from test_framework.blockchain_node import BlockChainNodeType
|
from test_framework.blockchain_node import BlockChainNodeType
|
||||||
from test_framework.conflux_node import ConfluxNode, connect_sample_nodes
|
from test_framework.conflux_node import ConfluxNode, connect_sample_nodes
|
||||||
@ -174,7 +174,7 @@ class TestFramework:
|
|||||||
contract, tx_hash, mine_contract, reward_contract = self.blockchain_nodes[0].setup_contract(self.enable_market, self.mine_period)
|
contract, tx_hash, mine_contract, reward_contract = self.blockchain_nodes[0].setup_contract(self.enable_market, self.mine_period)
|
||||||
self.contract = FlowContractProxy(contract, self.blockchain_nodes)
|
self.contract = FlowContractProxy(contract, self.blockchain_nodes)
|
||||||
self.mine_contract = MineContractProxy(mine_contract, self.blockchain_nodes)
|
self.mine_contract = MineContractProxy(mine_contract, self.blockchain_nodes)
|
||||||
self.reward_contract = IRewardContractProxy(reward_contract, self.blockchain_nodes)
|
self.reward_contract = RewardContractProxy(reward_contract, self.blockchain_nodes)
|
||||||
|
|
||||||
|
|
||||||
for node in self.blockchain_nodes[1:]:
|
for node in self.blockchain_nodes[1:]:
|
||||||
|
Loading…
Reference in New Issue
Block a user