How Does the Proof of Scan Consensus Mechanism Work in 3DPass?

The Proof of Scan (PoScan) consensus mechanism in 3DPass combines Proof-of-Work mining with scan-based 3D object validation, requiring miners to compute valid object hashes using the PoscanAlgorithm, seal blocks with cryptographic proofs meeting network difficulty targets, and submit them through the PowBlockImport for runtime verification and finalization.

The 3DPass blockchain utilizes the Proof of Scan consensus mechanism to secure its ledger while incentivizing the creation and validation of unique 3D digital assets. Implemented as a Substrate-based consensus module, this mechanism ties block production to the computational verification of 3D objects stored on-chain. Unlike traditional Proof of Work, PoScan requires miners to demonstrate both computational work and successful object scanning to produce valid blocks.

Core Architecture of Proof of Scan

The PoScan engine orchestrates several specialized components that bridge the node service layer with the runtime.

POSCAN Primitives define the consensus engine identifiers and data structures in primitives/consensus/poscan/src/lib.rs. This module declares constants like POSCAN_ENGINE_ID, algorithm versions including POSCAN_ALGO_GRID2D_V3A and POSCAN_ALGO_GRID2D_V3_1, and the PoscanApi trait for runtime communication.

The PoScan Algorithm (consensus/poscan_algo/src/lib.rs) implements get_obj_hashes, which transforms 3D object data into deterministic hash sets using the Grid2D algorithm. It manages RandomX rotation for newer consensus versions and provides the DoubleHash struct for combining parent hashes with object hashes.

Mining Worker logic resides in nodes/poscan-consensus/src/service.rs, where start_mining_worker spawns the asynchronous thread responsible for fetching metadata, computing seals, and submitting valid blocks.

PowBlockImport bridges PoScan seals with Substrate's block import pipeline, verifying difficulty and signatures before forwarding to Grandpa finality.

Pallet Poscan (pallets/poscan/src/lib.rs) maintains the on-chain object state machine, quality control transitions, and reward distribution.

The Mining Loop and Block Production

The mining process begins when the service layer initializes the worker thread in nodes/poscan-consensus/src/service.rs.

Service Initialization

The node bootstraps the consensus engine by creating a PoscanAlgorithm instance and passing it to start_mining_worker:

let (worker, worker_task) = sc_consensus_poscan::start_mining_worker(
    Box::new(pow_block_import),
    client.clone(),
    select_chain,
    PoscanAlgorithm::new(client.clone()),
    proposer,
    network.clone(),
    network.clone(),
    Some(author.encode()),
    CreateInherentDataProviders { author: Some(author.encode()) },
    Duration::from_secs(10),
    Duration::from_secs(10),
    can_author_with,
);

This returns a worker handle for block submission and a task handle for the mining thread.

Hash Computation and Sealing

Inside the mining loop, the worker retrieves pending objects from the mining pool or deque, then computes hashes based on the current chain specification version. When the block number exceeds REJECT_OLD_ALGO_SINCE, the system uses POSCAN_ALGO_GRID2D_V3A with RandomX rotation; otherwise it uses POSCAN_ALGO_GRID2D_V3_1.

For consensus version 2 (CONS_V2_SPEC_VER), the algorithm generates a rotation hash using RandomX and recomputes object hashes:

let rotation_hash = randomx(&buf)?;
let hashes = get_obj_hashes(mining_algo, &mp.pre_obj, &rotation_hash, patch_rot);

The miner constructs a DoubleHash from the pre-hash and first object hash, then calculates the PoScan hash using either calc_hash (legacy) or calc_hash_randomx (current). This feeds into ComputeV2 (or ComputeV1 for older blocks), which is signed with the miner's key pair to create the seal.

Difficulty Verification and Submission

Before submission, the worker verifies that hash_meets_difficulty(&seal.work, seal.difficulty) returns true. Valid seals are encoded and submitted via worker.submit:

if hash_meets_difficulty(&seal.work, seal.difficulty) {
    futures::executor::block_on(
        worker.submit(seal.encode(), &psdata)
    );
}

Runtime Validation and Block Import

Once submitted, the sealed block enters the PowBlockImport queue. The import process performs cryptographic verification before accepting the block into the chain.

The validation sequence in the runtime:

  1. Decodes the seal and verifies the signature against the author's public key
  2. Recomputes the PoScan hash using DoubleHash to confirm it matches the sealed value
  3. Validates difficulty via hash_meets_difficulty
  4. Calls PoscanApi::check_object to verify object existence and state
  5. Forwards the block to Grandpa for finality

The runtime implementation in runtime/src/lib.rs fulfills the PoscanApi and DifficultyApi traits, querying pallet-poscan for object metadata and current difficulty targets.

Difficulty Adjustment and Object Lifecycle

Retargeting Algorithm

PoScan implements a timestamp-based difficulty adjustment using parameters defined in the primitives:

  • Window: DIFFICULTY_ADJUST_WINDOW (approximately 1 hour)
  • Dampening: DIFFICULTY_DAMP_FACTOR and CLAMP_FACTOR prevent extreme fluctuations
  • Bounds: MIN_DIFFICULTY and MAX_DIFFICULTY enforce network security limits

The runtime calculates the next target difficulty via DifficultyApi::difficulty(), which the mining worker queries through the metadata at each loop iteration.

Object State Machine and Rewards

The pallet-poscan manages objects through a strict state machine: Created → QCInspecting → QCPassed/QCRejected → Estimated → Approved → SelfProved. State transitions trigger reward distributions (author_rewards, est_rewards) and fee processing.

Miners can participate individually or through pools using the MiningPoolApi, which provides pool-specific difficulty calculations and membership verification.

Practical Implementation Examples

Running a PoScan Node

Start a validator node with the consensus service:

cargo build --release -p poscan-consensus
./target/release/poscan-consensus \
    --chain poscan-dev \
    --author //Alice \
    --pruning archive \
    --validator

The --author flag specifies the miner's key for block signing.

Submitting 3D Objects via RPC

Clients submit objects for scanning through the poscan_putObject RPC method defined in nodes/poscan-consensus/src/rpc.rs:

let obj_data: Vec<u8> = std::fs::read("model.obj.lzss").unwrap();
let _: () = client.request(
    "poscan_putObject",
    (AccountId32::from([0u8; 32]), obj_data, 0u8, false)
).await.unwrap();

This creates a MiningProposal that enters the worker's pending object deque.

Runtime Seal Verification

The pallet validates seals using the same cryptographic primitives as the node:

fn validate_seal(seal: PoscanSeal, pre_hash: H256, difficulty: U256) -> DispatchResult {
    let compute = Compute::decode(&mut &seal[..])?;
    let dh = DoubleHash { pre_hash, obj_hash: compute.obj_hash };
    let expected = dh.calc_hash();
    ensure!(expected == compute.poscan_hash, Error::<T>::InvalidPoscanHash);
    ensure!(hash_meets_difficulty(&compute.work, difficulty), Error::<T>::DifficultyNotMet);
    Ok(())
}

Summary

  • The Proof of Scan consensus mechanism merges Proof-of-Work with 3D object validation, requiring miners to compute valid object hashes alongside cryptographic seals.
  • Mining occurs in nodes/poscan-consensus/src/service.rs through the start_mining_worker thread, which uses PoscanAlgorithm to generate hashes via get_obj_hashes in consensus/poscan_algo/src/lib.rs.
  • The system supports algorithm versioning (POSCAN_ALGO_GRID2D_V3A vs POSCAN_ALGO_GRID2D_V3_1) and consensus upgrades (CONS_V2_SPEC_VER) with RandomX rotation for enhanced security.
  • Block validation relies on PowBlockImport and runtime APIs (PoscanApi, DifficultyApi) to verify seals, difficulty, and object integrity before Grandpa finalization.
  • Difficulty retargets every DIFFICULTY_ADJUST_WINDOW using clamped dampening factors, while pallets/poscan/src/lib.rs manages object states and miner rewards.

Frequently Asked Questions

What is Proof of Scan in 3DPass?

Proof of Scan (PoScan) is a hybrid consensus mechanism that requires miners to perform computational work while simultaneously validating unique 3D objects. It functions as a Substrate PoW module where block production depends on successfully scanning and hashing 3D geometric data according to the PoscanAlgorithm specifications.

How does PoScan differ from traditional Proof of Work?

Traditional Proof of Work relies solely on hash rate to secure the network, whereas PoScan adds a scan-based validation layer where miners must possess valid 3D objects to create block seals. The DoubleHash structure combines block headers with object hashes, ensuring consensus participation requires both computational resources and digital asset ownership.

What role do 3D objects play in the consensus process?

3D objects serve as the "work payload" for mining. Miners retrieve pending objects from the mining pool or deque, process them through get_obj_hashes to generate deterministic hash sets, and incorporate these into the ComputeV1 or ComputeV2 structures. The runtime verifies object integrity via PoscanApi::check_object before accepting blocks.

How does the network adjust mining difficulty?

The runtime calculates difficulty using a timestamp-based retargeting algorithm with a DIFFICULTY_ADJUST_WINDOW of approximately one hour. The system applies DIFFICULTY_DAMP_FACTOR and CLAMP_FACTOR to smooth adjustments while respecting MIN_DIFFICULTY and MAX_DIFFICULTY bounds, ensuring consistent block times regardless of total network hash rate.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →