Digital Signature Scheme
Digital signatures secure different parts of consensus by providing a means of authentication. Currently, we use Schnorr of two flavors (with schnorrkel library).
Non-canonical Schnorr:
Sign(secret_key, message)
Verify(public_key, message, signature)
Canonical Schnorr verifiable random function (VRF):
VRF_Sign(secret_key, message)
VRF_Verify(public_key, message, signature)
Canonical (deterministic) scheme is necessary for these cases to prevent attackers from repeated signing until they produce a local challenge they can win (as part of block grinding).
Hash function
Provides succinct commitments to arbitrary data.
Hash(message)
denotes SHA256 hash.
HASH_OUTPUT_BYTES
= 32 is the length of the hash output in bytes.™
Substrate primitives (i.e. block signing) use BLAKE2-256.
Hash-Based Message Authentication Code (HMAC)
Provides succinct commitments (tags) to piece encodings and salt. Full encodings are required to compute the tags using HMAC, preventing attackers from compressing or discarding their plots.
HMAC(key, message)
.
HMAC_OUTPUT_BYTES
= 32 since the HMAC uses SHA256.
Pseudorandom Permutation (PRP) Provides a means to make arbitrary useful data (i.e., blockchain history) look like random data through encoding while still being able to retrieve the useful data through decoding.
Encode(piece, IV, ENCODE_ROUNDS)
Decode(encoding, IV, ENCODE_ROUNDS)
Farmer’s public_key_hash
and piece_index
are combined into initialization vector (IV
) for the codec. This way the encoding of every piece is tied uniquely to the farmers identity and the same piece of useful data will be encoded differently for different farmers.
We use the modular square root permutation underlying SLOTH (slow-timed hash function) because it provides efficient decoding while having slow encoding, which protects from On-Demand Encoding attacks. We also use the CBC mode to prevent parallelization that could lead to efficient space-time trade-offs. The prime choice is SLOTH-256-189, and the number of rounds is equal to ENCODE_ROUNDS
.
Merkle tree Provides succinct commitments (Merkle roots) to arbitrary-sized data sets with efficient proofs (witnesses) of inclusion. Current usages include trees for:
These parameters are fixed at the beginning of the protocol and used by all clients.
salt
: initial value currently set to 0global_randomness
: initial value currently set to 0SLOT_DURATION
: duration of a slot, or the interval at which new challenges are sent to the blockchain, currently 1 sSLOT_PROBABILITY
: the probability of successful block in a slot (active slots coefficient), currently 1/6. This defines the expected block production rate of 1 block every 6 seconds.INITIAL_SOLUTION_RANGE
: solution range for proof-of-replication challenge for the first eraERA_DURATION_IN_BLOCKS
: solution range is adjusted after this many blocks, currently 2016 (as in Bitcoin).EON_DURATION_IN_SLOTS
: salt for deriving the tag is updated after this many 1s slots, currently 604800 slots, equal to 7 days.EON_NEXT_SALT_REVEAL
: salt for the next eon is revealed before the next eon starts to allow farmers to recommit to their plots in advance, currently happens 1 day before next eon startsGLOBAL_RANDOMNESS_UPDATE_INTERVAL
: global randomness used for global proof-of-replication challenge is updated after this many blocks, currently 100 blocks, roughly equal to 10 minutes at expected block production rateRECORD_SIZE
is 3840 bytes: the size of data in one piece (RECORD_SIZE = PIECE_SIZE - WITNESS_SIZE
)RECORDED_HISTORY_SEGMENT_SIZE
(RHSS) is 480 KiB: recorded history is encoded and plotted in segments of this size (RECORD_SIZE * MERKLE_NUM_LEAVES / 2
)