Skip to content

Implement FIPs #993 SealerID #1683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 22 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ fil_actor_power = { workspace = true, features = ["fil-actor"] }
fil_actor_reward = { workspace = true, features = ["fil-actor"] }
fil_actor_system = { workspace = true, features = ["fil-actor"] }
fil_actor_verifreg = { workspace = true, features = ["fil-actor"] }
fil_actor_sealer = { workspace = true, features = ["fil-actor"] }

[build-dependencies]
fil_actor_bundler = "8.0.0"
Expand Down Expand Up @@ -156,6 +157,7 @@ fil_actor_power = { path = "actors/power" }
fil_actor_reward = { path = "actors/reward" }
fil_actor_system = { path = "actors/system" }
fil_actor_verifreg = { path = "actors/verifreg" }
fil_actor_sealer = { path = "actors/sealer" }
fil_actors_evm_shared = { path = "actors/evm/shared" }
fil_actors_runtime = { path = "runtime" }
fil_builtin_actors_state = { path = "state" }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type ManifestPayload struct {
evm &ActorBytecode
eam &ActorBytecode
ethaccount &ActorBytecode
sealer &ActorBytecode
} representation listpairs

# RAW block
Expand Down
14 changes: 14 additions & 0 deletions actors/miner/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,17 @@ pub mod verifreg {
pub sector_claims: Vec<SectorClaimSummary>,
}
}

pub mod sealer {
use super::*;
use fvm_ipld_bitfield::BitField;

pub const ACTIVATE_SECTORS_METHOD: u64 =
frc42_dispatch::method_hash!("ActivateSectors");

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
pub struct ActivateSectorParams {
pub sector_numbers: BitField,
pub verifier_signature: Vec<u8>,
}
}
100 changes: 86 additions & 14 deletions actors/miner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2033,11 +2033,12 @@ impl Actor {
return Err(actor_error!(illegal_argument, "aggregate proof type must be SnarkPackV2"));
}

let (validation_batch, proof_inputs, sector_numbers) = validate_ni_sectors(
let (validation_batch, proof_inputs, sector_numbers, sealer_numbers) = validate_ni_sectors(
rt,
&params.sectors,
params.seal_proof_type,
params.require_activation_success,
params.sealer_id_actor,
)?;

if validation_batch.success_count == 0 {
Expand All @@ -2056,6 +2057,17 @@ impl Actor {
&params.aggregate_proof,
)?;

if let Some(sealer_id_actor) = params.sealer_id_actor {
let Some(sig) = params.sealer_id_verifier_signature else {
return Err(actor_error!(illegal_argument, "sealer id verifier signature is required when using Sealer ID"));
};
let Some(sealer_numbers) = sealer_numbers else {
return Err(actor_error!(illegal_argument, "sealer numbers are required when using Sealer ID"));
};

validate_sealer_id_numbers(rt, sealer_id_actor, sig, &sealer_numbers)?;
}

// With no data, QA power = raw power
let qa_sector_power = raw_power_for_sector(info.sector_size);

Expand Down Expand Up @@ -4952,22 +4964,29 @@ fn validate_ni_sectors(
sectors: &[SectorNIActivationInfo],
seal_proof_type: RegisteredSealProof,
all_or_nothing: bool,
) -> Result<(BatchReturn, Vec<SectorSealProofInput>, BitField), ActorError> {
sealer_id_actor: Option<ActorID>,
) -> Result<(BatchReturn, Vec<SectorSealProofInput>, BitField, Option<BitField>), ActorError> {
let receiver = rt.message().receiver();
let miner_id = receiver.id().unwrap();
let curr_epoch = rt.curr_epoch();
let activation_epoch = curr_epoch;
let challenge_earliest = curr_epoch - rt.policy().max_prove_commit_ni_randomness_lookback;
let unsealed_cid = CompactCommD::empty().get_cid(seal_proof_type).unwrap();
let entropy = serialize(&receiver, "address for get verify info")?;

let expected_sealer_id = match sealer_id_actor {
Some(sealer_id) => sealer_id,
None => receiver.id().unwrap(),
};

if sectors.is_empty() {
return Ok((BatchReturn::empty(), vec![], BitField::new()));
return Ok((BatchReturn::empty(), vec![], BitField::new(), None));
}
let mut batch = BatchReturnGen::new(sectors.len());

let mut verify_infos = vec![];
let mut sector_numbers = BitField::new();
let mut sealing_numbers = BitField::new();

for (i, sector) in sectors.iter().enumerate() {
let mut fail_validation = false;

Expand All @@ -4986,6 +5005,28 @@ fn validate_ni_sectors(

sector_numbers.set(sector.sector_number);

if sealer_id_actor.is_none() && sector.sector_number != sector.sealing_number {
warn!("sealing number must be same as sector number for all sectors");
fail_validation = true;
}

if sealer_id_actor.is_some() {
if sealing_numbers.get(sector.sealing_number) {
return Err(actor_error!(
illegal_argument,
"duplicate sealing number {}",
sector.sealing_number
));
}

if sector.sealing_number > MAX_SECTOR_NUMBER {
warn!("sealing number {} out of range 0..(2^63-1)", sector.sealing_number);
fail_validation = true;
}

sealing_numbers.set(sector.sealing_number);
}

if let Err(err) = validate_expiration(
rt.policy(),
curr_epoch,
Expand All @@ -4997,13 +5038,8 @@ fn validate_ni_sectors(
fail_validation = true;
}

if sector.sealer_id != miner_id {
warn!("sealer must be the same as the receiver actor for all sectors");
fail_validation = true;
}

if sector.sector_number != sector.sealing_number {
warn!("sealing number must be same as sector number for all sectors");
if sector.sealer_id != expected_sealer_id {
warn!("sealer must be the same as the expected sealer ID for all sectors");
fail_validation = true;
}

Expand Down Expand Up @@ -5061,7 +5097,12 @@ fn validate_ni_sectors(
}
}

Ok((batch.generate(), verify_infos, sector_numbers))
let out_sealing_numbers = match sealer_id_actor {
Some(_) => Some(sealing_numbers),
None => None,
};

Ok((batch.generate(), verify_infos, sector_numbers, out_sealing_numbers))
}

// Validates a batch of sector sealing proofs.
Expand Down Expand Up @@ -5126,7 +5167,7 @@ fn validate_seal_aggregate_proof(
fn verify_aggregate_seal(
rt: &impl Runtime,
proof_inputs: &[SectorSealProofInput],
miner_actor_id: ActorID,
sealer_id: ActorID,
seal_proof: RegisteredSealProof,
aggregate_proof: RegisteredAggregateProof,
proof_bytes: &RawBytes,
Expand All @@ -5135,7 +5176,7 @@ fn verify_aggregate_seal(
proof_inputs.iter().map(|pi| pi.to_aggregate_seal_verify_info()).collect();

rt.verify_aggregate_seals(&AggregateSealVerifyProofAndInfos {
miner: miner_actor_id,
miner: sealer_id,
seal_proof,
aggregate_proof,
proof: proof_bytes.clone().into(),
Expand All @@ -5144,6 +5185,37 @@ fn verify_aggregate_seal(
.context_code(ExitCode::USR_ILLEGAL_ARGUMENT, "aggregate seal verify failed")
}

fn validate_sealer_id_numbers(
rt: &impl Runtime,
sealer_id_actor: ActorID,
sealer_id_verifier_signature: Vec<u8>,
sealer_numbers: &BitField,
) -> Result<(), ActorError> {
let params = ext::sealer::ActivateSectorParams {
sector_numbers: sealer_numbers.clone(),
verifier_signature: sealer_id_verifier_signature,
};

assert_eq(rt.get_code_cid_for_type(Type::Sealer), rt.get_actor_code_cid(sealer_id_actor)).

let result = rt.send_simple(
&Address::new_id(sealer_id_actor),
ext::sealer::ACTIVATE_SECTORS_METHOD,
IpldBlock::serialize_cbor(&params)?,
TokenAmount::zero(),
)?;

if !result.exit_code.is_success() {
return Err(ActorError::checked(
result.exit_code,
"failed to verify Sealer ID sector numbers".to_string(),
None,
));
}

Ok(())
}

fn verify_deals(
rt: &impl Runtime,
sectors: &[ext::market::SectorDeals],
Expand Down
3 changes: 3 additions & 0 deletions actors/miner/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ pub struct ProveCommitSectorsNIParams {
pub aggregate_proof_type: RegisteredAggregateProof, // Proof type for aggregation
pub proving_deadline: u64, // The Window PoST deadline index at which to schedule the new sectors
pub require_activation_success: bool, // Whether to abort if any sector activation fails

pub sealer_id_actor: Option<ActorID>, // Optional sealer ID actor from which the sector numbers are derived from
pub sealer_id_verifier_signature: Option<Vec<u8>>, // Verifier signature
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize_tuple, Deserialize_tuple)]
Expand Down
24 changes: 18 additions & 6 deletions actors/miner/tests/types_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ mod serialization {
aggregate_proof_type: RegisteredAggregateProof::SnarkPackV2,
proving_deadline: 2,
require_activation_success: false,

sealer_id_actor: None,
sealer_id_verifier_signature: None,
final_sector_numbers: None,
},
// [[],byte[],8,1,2,false]
&hex!("868040080102f4")[..],
// [[],byte[],8,1,2,false,null,null,null]
&hex!("898040080102f4f6f6f6")[..],
),
(
ProveCommitSectorsNIParams {
Expand All @@ -49,9 +53,13 @@ mod serialization {
aggregate_proof_type: RegisteredAggregateProof::SnarkPackV2,
proving_deadline: 6,
require_activation_success: true,

sealer_id_actor: None,
sealer_id_verifier_signature: None,
final_sector_numbers: None,
},
// [[[1,2,bagboea4seaaqa,3,4,5]],byte[deadbeef],18,1,6,true]
&hex!("8681860102d82a49000182e2039220010003040544deadbeef120106f5"),
// [[[1,2,bagboea4seaaqa,3,4,5]],byte[deadbeef],18,1,6,true,null,null,null]
&hex!("8981860102d82a49000182e2039220010003040544deadbeef120106f5f6f6f6"),
),
(
ProveCommitSectorsNIParams {
Expand All @@ -78,10 +86,14 @@ mod serialization {
aggregate_proof_type: RegisteredAggregateProof::SnarkPackV2,
proving_deadline: 11,
require_activation_success: false,

sealer_id_actor: None,
sealer_id_verifier_signature: None,
final_sector_numbers: None,
},
// [[[1,2,bagboea4seaaqa,3,4,5],[6,7,bagboea4seaaqc,8,9,10]],byte[deadbeef],18,1,11,false]
// [[[1,2,bagboea4seaaqa,3,4,5],[6,7,bagboea4seaaqc,8,9,10]],byte[deadbeef],18,1,11,false,null,null,null]
&hex!(
"8682860102d82a49000182e20392200100030405860607d82a49000182e2039220010108090a44deadbeef12010bf4"
"8982860102d82a49000182e20392200100030405860607d82a49000182e2039220010108090a44deadbeef12010bf4f6f6f6"
),
),
];
Expand Down
4 changes: 4 additions & 0 deletions actors/miner/tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,10 @@ impl ActorHarness {
aggregate_proof_type: RegisteredAggregateProof::SnarkPackV2,
proving_deadline,
require_activation_success: true,

sealer_id_actor: None,
sealer_id_verifier_signature: None,
final_sector_numbers: None,
}
}

Expand Down
38 changes: 38 additions & 0 deletions actors/sealer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[package]
name = "fil_actor_sealer"
description = "Builtin sealer actor for Filecoin"
version.workspace = true
license.workspace = true
edition.workspace = true
repository.workspace = true
authors = ["Curio Storage Inc. <[email protected]>"]
keywords = ["filecoin", "web3", "wasm"]

[lib]
## lib is necessary for integration tests
## cdylib is necessary for Wasm build
crate-type = ["cdylib", "lib"]

[dependencies]
fil_actors_runtime = { workspace = true }
fvm_shared = { workspace = true }
num-traits = { workspace = true }
num-derive = { workspace = true }
log = { workspace = true }
lazy_static = { workspace = true }
serde = { workspace = true }
fvm_ipld_blockstore = { workspace = true }
fvm_ipld_encoding = { workspace = true }
cid = { workspace = true }
fvm_ipld_bitfield = { workspace = true }
multihash-codetable = { workspace = true }
anyhow = { workspace = true }
frc42_dispatch = { workspace = true }


[dev-dependencies]
fil_actors_runtime = { workspace = true, features = ["test_utils", "sector-default"] }
num = { workspace = true }

[features]
fil-actor = ["fil_actors_runtime/fil-actor"]
17 changes: 17 additions & 0 deletions actors/sealer/src/ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use fvm_ipld_encoding::strict_bytes;
use fvm_ipld_encoding::tuple::*;

pub mod account {
use super::*;

pub const AUTHENTICATE_MESSAGE_METHOD: u64 =
frc42_dispatch::method_hash!("AuthenticateMessage");

#[derive(Serialize_tuple, Deserialize_tuple)]
pub struct AuthenticateMessageParams {
#[serde(with = "strict_bytes")]
pub signature: Vec<u8>,
#[serde(with = "strict_bytes")]
pub message: Vec<u8>,
}
}
Loading
Loading