Signed Mining

This article discusses the idea of signed mining, which tries to provide a safe construct with a high degree of delibration, in a Proof of Work blockchain system.

A good mining algorithm for a blockchain must ensure delibration. That is, it must enforce that partcipants on the network are carrying out the action of mining as a deliberate action. Put it simply, the owner of miners must be aware that they are mining, and miners must be aware that they are actively spending their resources. Deliberation makes it more likely that the fundamental assumption of honest majority holds, and thus less likely to be the subject of 51% attacks.

Absence of delibration leads to botnets and malicious browser-based mining. In all those cases, the owners of the hardwares are not aware that they are participating in the mining process. If a mining algorithm cannot prevent those types of issues, controllers of botnets may be able to obtain a large share of the network hashrate, and carry out attacks such as double spending.

Signed mining adds an additional requirement for mining hardware to hold the private key of coinbase of mining rewards. In this way, botnets and browser-based mining become much less efficient to carry out.

Basic

Signed mining can be applied to any nonce-based mining algorithms. Those mining algorithms can be generalized to expose the following function:

fn verify(pre_hash: Hash, nonce: Nonce, seal: Seal) -> bool;

pre_hash is the hash of the header without PoW portion. nonce is a random number. The function verify checks that pre_hash and nonce evaluates to seal, and the resulting seal is above a given difficulty.

The mining process can then be expressed as follows:

loop {
  let nonce = Nonce::random();
  let seal = Seal::generate_from(pre_hash, nonce);
  if verify(pre_hash, nonce, seal) {
    return nonce
  }
}

Signed mining proposes to add an additional signing together with the nonce:

fn verify_signed(
  pre_hash: Hash,
  nonce: Nonce,
  signature: Signature,
  seal: Seal
) -> bool {
  signature.verify_with_message(pre_hash, nonce) &&
    seal.verify_with_pre(signature)
}

pre_hash and nonce are first signed by coinbase key producing signature. The signature is then fed into a normal nonce-based mining algorithm to produce the seal. The signing process happens once per nonce, and for mining, practically a large number of nonces are always tried before a block is produced. As a result, this enforces that mining hardwares must keep the private key together with the miner. Transmitting large amount of signatures through the network is impractical and inefficient.

Ethereum

This section describes a specification, with identifier 52-ESIGNED. (Discuss)

Specification

Replace the coinbase field of block header by r. Add two new fields into the block header, v and s. Together, v, r, s hold an secp256k1 signature, whose public key is interpreted as the new coinbase address for a block.

When verifying the Ethash PoW for a block, change the logic to be the following:

  • Given a header, get the hash \(H_1\) where v equals CHAIN_ID. r, s and mixHash equals 0.

  • Check that \(H_1\) is the valid preimage of the signature consisting of v, r and s, with v equal to CHAIN_ID * 2
    35
    or CHAIN_ID * 2 + 36.

  • Calculate hash \(H_2\), with mixHash set to 0 in the original header.

  • Check that \(H_2\) is the valid preimage for Ethash of mixHash and nonce.

Kulupu

This section describes a specification, with identifier 53-KSIGNED. (Discuss)

Specification

Change the header seal to be of the following SCALE encoded structure:

struct Seal {
  difficulty: Difficulty,
  nonce: H256,
  signature: Signature,
  work: H256,
}

Change the verification process to be as follows:

  • Check that difficulty is the valid difficulty.

  • Check that (difficulty, nonce) is the valid preimage of sr25519 signature, against public key provided in the pre-runtime digest.

  • Check that (difficulty, nonce, signature) is the valid preimage of RandomX work.