No, Casper FFG is a finality gadget that can work with any block proposal mechanism. Casper CBC is a full PoS proposal. Read the FAQs and papers for more details. Casper Proof of Stake compendium · ethereum/wiki Wiki · GitHub. Block proposers will do the block proposing, and they will collate transactions into blocks.
Some snippets from the spec, although you should read the whole thing before asking questions like this:
Block production is significantly different because of the proof of stake mechanism. A client simply checks what it thinks is the canonical chain when it should create a block, and looks up what its slot number is; when the slot arrives, it either proposes or attests to a block as required.
Read the “Per-block processing” section; note my emphasis in bold in the last sentence. Also note that the best way to understand specifications (and maybe improve on them) is by implementing them yourself.
Per-block processing
First, set recent_block_hashes
to the output of the following:
def get_new_recent_block_hashes(old_block_hashes, parent_slot,
current_slot, parent_hash):
d = current_slot - parent_slot
return old_block_hashes[d:] + [parent_hash] * min(d, len(old_block_hashes))
The output of get_block_hash
should not change, except that it will no longer throw for current_slot - 1
, and will now throw for current_slot - CYCLE_LENGTH * 2 - 1
A block can have 0 or more AttestationRecord
objects, where each AttestationRecord
object has the following fields:
fields = {
# Slot number
'slot': 'int64',
# Shard ID
'shard_id': 'int16',
# List of block hashes that this signature is signing over that
# are NOT part of the current chain, in order of oldest to newest
'oblique_parent_hashes': ['hash32'],
# Block hash in the shard that we are attesting to
'shard_block_hash': 'hash32',
# Who is participating
'attester_bitfield': 'bytes',
# Last justified block
'justified_slot': 'int256',
'justified_block_hash': 'hash32',
# The actual signature
'aggregate_sig': ['int256']
}
For each one of these attestations [TODO]:
- Verify that
slot < block.slot_number
and slot >= max(block.slot_number - CYCLE_LENGTH, 0)
- Verify that the
justified_slot
and justified_block_hash
given are in the chain and are equal to or earlier than the last_justified_slot
in the crystallized state.
- Compute
parent_hashes
= [get_block_hash(active_state, block, slot - CYCLE_LENGTH + i) for i in range(CYCLE_LENGTH - len(oblique_parent_hashes))] + oblique_parent_hashes
- Let
attestation_indices
be get_indices_for_slot(crystallized_state, slot)[x]
, choosing x
so that attestation_indices.shard_id
equals the shard_id
value provided to find the set of validators that is creating this attestation record.
- Verify that
len(attester_bitfield) == ceil_div8(len(attestation_indices))
, where ceil_div8 = (x + 7) // 8
. Verify that bits len(attestation_indices)....
and higher, if present (i.e. len(attestation_indices)
is not a multiple of 8), are all zero
- Derive a group public key by adding the public keys of all of the attesters in
attestation_indices
for whom the corresponding bit in attester_bitfield
(the ith bit is (attester_bitfield[i // 8] >> (7 - (i %8))) % 2
) equals 1
- Verify that
aggregate_sig
verifies using the group pubkey generated and hash(slot.to_bytes(8, 'big') + parent_hashes + shard_id + shard_block_hash)
as the message.
Extend the list of AttestationRecord
objects in the active_state
, ordering the new additions in the same order as they came in the block.
Verify that the slot % len(get_indices_for_slot(crystallized_state, slot)[0])
'th attester in get_indices_for_slot(crystallized_state, slot)[0]
is part of at least one of the AttestationRecord
objects; this attester can be considered to be the proposer of the block