SignedBeaconBlock in state_transition (#773)
* using SignedBeaconBlock in state_transition
This commit is contained in:
parent
ab1a08084b
commit
91f87b55b4
|
@ -61,7 +61,7 @@ type
|
|||
mainchainMonitor: MainchainMonitor
|
||||
beaconClock: BeaconClock
|
||||
|
||||
proc onBeaconBlock*(node: BeaconNode, blck: SignedBeaconBlock) {.gcsafe.}
|
||||
proc onBeaconBlock*(node: BeaconNode, signedBlock: SignedBeaconBlock) {.gcsafe.}
|
||||
proc updateHead(node: BeaconNode): BlockRef
|
||||
|
||||
proc saveValidatorKey(keyName, key: string, conf: BeaconNodeConf) =
|
||||
|
@ -412,7 +412,7 @@ proc proposeBlock(node: BeaconNode,
|
|||
parent_root: head.root,
|
||||
body: blockBody))
|
||||
tmpState = hashedState
|
||||
discard state_transition(tmpState, newBlock.message, {skipValidation})
|
||||
discard state_transition(tmpState, newBlock, {skipValidation})
|
||||
# TODO only enable in fast-fail debugging situations
|
||||
# otherwise, bad attestations can bring down network
|
||||
# doAssert ok # TODO: err, could this fail somehow?
|
||||
|
@ -492,19 +492,19 @@ proc onAttestation(node: BeaconNode, attestation: Attestation) =
|
|||
|
||||
node.attestationPool.add(attestation)
|
||||
|
||||
proc onBeaconBlock(node: BeaconNode, blck: SignedBeaconBlock) =
|
||||
proc onBeaconBlock(node: BeaconNode, signedBlock: SignedBeaconBlock) =
|
||||
# We received a block but don't know much about it yet - in particular, we
|
||||
# don't know if it's part of the chain we're currently building.
|
||||
let blockRoot = hash_tree_root(blck.message)
|
||||
let blockRoot = hash_tree_root(signedBlock.message)
|
||||
debug "Block received",
|
||||
blck = shortLog(blck.message),
|
||||
signedBlock = shortLog(signedBlock.message),
|
||||
blockRoot = shortLog(blockRoot),
|
||||
cat = "block_listener",
|
||||
pcs = "receive_block"
|
||||
|
||||
beacon_blocks_received.inc()
|
||||
|
||||
if node.blockPool.add(blockRoot, blck).isNil:
|
||||
if node.blockPool.add(blockRoot, signedBlock).isNil:
|
||||
return
|
||||
|
||||
# The block we received contains attestations, and we might not yet know about
|
||||
|
@ -514,8 +514,8 @@ proc onBeaconBlock(node: BeaconNode, blck: SignedBeaconBlock) =
|
|||
# TODO shouldn't add attestations if the block turns out to be invalid..
|
||||
let currentSlot = node.beaconClock.now.toSlot
|
||||
if currentSlot.afterGenesis and
|
||||
blck.message.slot.epoch + 1 >= currentSlot.slot.epoch:
|
||||
for attestation in blck.message.body.attestations:
|
||||
signedBlock.message.slot.epoch + 1 >= currentSlot.slot.epoch:
|
||||
for attestation in signedBlock.message.body.attestations:
|
||||
node.onAttestation(attestation)
|
||||
|
||||
proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) =
|
||||
|
|
|
@ -374,7 +374,7 @@ proc add*(
|
|||
# but maybe we should use it as a hint that our clock is wrong?
|
||||
updateStateData(pool, pool.tmpState, BlockSlot(blck: parent, slot: blck.slot - 1))
|
||||
|
||||
if not state_transition(pool.tmpState.data, blck, {}):
|
||||
if not state_transition(pool.tmpState.data, signedBlock, {}):
|
||||
# TODO find a better way to log all this block data
|
||||
notice "Invalid block",
|
||||
blck = shortLog(blck),
|
||||
|
@ -570,12 +570,12 @@ proc skipAndUpdateState(
|
|||
afterUpdate(state)
|
||||
|
||||
proc skipAndUpdateState(
|
||||
state: var HashedBeaconState, blck: BeaconBlock, flags: UpdateFlags,
|
||||
state: var HashedBeaconState, signedBlock: SignedBeaconBlock, flags: UpdateFlags,
|
||||
afterUpdate: proc (state: HashedBeaconState)): bool =
|
||||
|
||||
skipAndUpdateState(state, blck.slot - 1, afterUpdate)
|
||||
skipAndUpdateState(state, signedBlock.message.slot - 1, afterUpdate)
|
||||
|
||||
let ok = state_transition(state, blck, flags)
|
||||
let ok = state_transition(state, signedBlock, flags)
|
||||
|
||||
afterUpdate(state)
|
||||
|
||||
|
@ -713,7 +713,7 @@ proc updateStateData*(pool: BlockPool, state: var StateData, bs: BlockSlot) =
|
|||
for i in countdown(ancestors.len - 1, 0):
|
||||
let ok =
|
||||
skipAndUpdateState(state.data,
|
||||
ancestors[i].data.message,
|
||||
ancestors[i].data,
|
||||
{skipValidation}) do (state: HashedBeaconState):
|
||||
pool.maybePutState(state, ancestors[i].refs)
|
||||
doAssert ok, "Blocks in database should never fail to apply.."
|
||||
|
|
|
@ -113,7 +113,7 @@ proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =
|
|||
true
|
||||
|
||||
proc state_transition*(
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags): bool {.nbench.}=
|
||||
state: var BeaconState, signedBlock: SignedBeaconBlock, flags: UpdateFlags): bool {.nbench.}=
|
||||
## Time in the beacon chain moves by slots. Every time (haha.) that happens,
|
||||
## we will update the beacon state. Normally, the state updates will be driven
|
||||
## by the contents of a new block, but it may happen that the block goes
|
||||
|
@ -147,7 +147,7 @@ proc state_transition*(
|
|||
var old_state = state
|
||||
|
||||
# These should never fail.
|
||||
process_slots(state, blck.slot)
|
||||
process_slots(state, signedBlock.message.slot)
|
||||
|
||||
# Block updates - these happen when there's a new block being suggested
|
||||
# by the block proposer. Every actor in the network will update its state
|
||||
|
@ -157,11 +157,11 @@ proc state_transition*(
|
|||
# https://github.com/ethereum/eth2.0-specs/issues/293
|
||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
||||
|
||||
if processBlock(state, blck, flags, per_epoch_cache):
|
||||
if processBlock(state, signedBlock.message, flags, per_epoch_cache):
|
||||
# This is a bit awkward - at the end of processing we verify that the
|
||||
# state we arrive at is what the block producer thought it would be -
|
||||
# meaning that potentially, it could fail verification
|
||||
if skipValidation in flags or verifyStateRoot(state, blck):
|
||||
if skipValidation in flags or verifyStateRoot(state, signedBlock.message):
|
||||
# TODO: allow skipping just verifyStateRoot for mocking
|
||||
# instead of both processBlock and verifyStateRoot
|
||||
# https://github.com/status-im/nim-beacon-chain/issues/407
|
||||
|
@ -220,23 +220,23 @@ proc process_slots*(state: var HashedBeaconState, slot: Slot) =
|
|||
state.root = hash_tree_root(state.data)
|
||||
|
||||
proc state_transition*(
|
||||
state: var HashedBeaconState, blck: BeaconBlock, flags: UpdateFlags): bool =
|
||||
state: var HashedBeaconState, signedBlock: SignedBeaconBlock, flags: UpdateFlags): bool =
|
||||
# Save for rollback
|
||||
var old_state = state
|
||||
|
||||
process_slots(state, blck.slot)
|
||||
process_slots(state, signedBlock.message.slot)
|
||||
var per_epoch_cache = get_empty_per_epoch_cache()
|
||||
|
||||
if processBlock(state.data, blck, flags, per_epoch_cache):
|
||||
if skipValidation in flags or verifyStateRoot(state.data, blck):
|
||||
if processBlock(state.data, signedBlock.message, flags, per_epoch_cache):
|
||||
if skipValidation in flags or verifyStateRoot(state.data, signedBlock.message):
|
||||
# State root is what it should be - we're done!
|
||||
|
||||
# TODO when creating a new block, state_root is not yet set.. comparing
|
||||
# with zero hash here is a bit fragile however, but this whole thing
|
||||
# should go away with proper hash caching
|
||||
state.root =
|
||||
if blck.state_root == Eth2Digest(): hash_tree_root(state.data)
|
||||
else: blck.state_root
|
||||
if signedBlock.message.state_root == Eth2Digest(): hash_tree_root(state.data)
|
||||
else: signedBlock.message.state_root
|
||||
|
||||
return true
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ type
|
|||
else:
|
||||
index: uint32
|
||||
|
||||
BeaconBlockCallback* = proc(blck: SignedBeaconBlock) {.gcsafe.}
|
||||
BeaconBlockCallback* = proc(signedBlock: SignedBeaconBlock) {.gcsafe.}
|
||||
BeaconSyncNetworkState* = ref object
|
||||
blockPool*: BlockPool
|
||||
forkVersion*: array[4, byte]
|
||||
|
|
|
@ -148,10 +148,10 @@ proc runFullTransition*(dir, preState, blocksPrefix: string, blocksQty: int, ski
|
|||
let blockPath = dir / blocksPrefix & $i & ".ssz"
|
||||
echo "Processing: ", blockPath
|
||||
|
||||
let blck = parseSSZ(blockPath, SignedBeaconBlock)
|
||||
let signedBlock = parseSSZ(blockPath, SignedBeaconBlock)
|
||||
let flags = if skipBLS: {skipValidation} # TODO: this also skips state root verification
|
||||
else: {}
|
||||
let success = state_transition(state[], blck.message, flags)
|
||||
let success = state_transition(state[], signedBlock.message, flags)
|
||||
echo "State transition status: ", if success: "SUCCESS ✓" else: "FAILURE ⚠️"
|
||||
|
||||
proc runProcessSlots*(dir, preState: string, numSlots: uint64) =
|
||||
|
|
|
@ -6,7 +6,7 @@ import
|
|||
cli do(pre: string, blck: string, post: string, verifyStateRoot = false):
|
||||
let
|
||||
stateX = SSZ.loadFile(pre, BeaconState)
|
||||
blckX = SSZ.loadFile(blck, BeaconBlock)
|
||||
blckX = SSZ.loadFile(blck, SignedBeaconBlock)
|
||||
flags = if verifyStateRoot: {skipValidation} else: {}
|
||||
|
||||
var stateY = HashedBeaconState(data: stateX, root: hash_tree_root(stateX))
|
||||
|
|
|
@ -91,7 +91,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
timers: array[Timers, RunningStat]
|
||||
attesters: RunningStat
|
||||
r: Rand
|
||||
blck: SignedBeaconBlock
|
||||
signedBlock: SignedBeaconBlock
|
||||
cache = get_empty_per_epoch_cache()
|
||||
|
||||
proc maybeWrite(last: bool) =
|
||||
|
@ -133,9 +133,9 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
else: tBlock
|
||||
|
||||
withTimer(timers[t]):
|
||||
blck = addBlock(state, latest_block_root, body, flags)
|
||||
signedBlock = addBlock(state, latest_block_root, body, flags)
|
||||
latest_block_root = withTimerRet(timers[tHashBlock]):
|
||||
hash_tree_root(blck.message)
|
||||
hash_tree_root(signedBlock.message)
|
||||
|
||||
if attesterRatio > 0.0:
|
||||
# attesterRatio is the fraction of attesters that actually do their
|
||||
|
|
|
@ -148,4 +148,4 @@ proc add*(state: var BeaconState, attestation: Attestation, slot: Slot) =
|
|||
|
||||
# TODO: we can skip just VerifyStateRoot
|
||||
doAssert state_transition(
|
||||
state, signedBlock.message, flags = {skipValidation})
|
||||
state, signedBlock, flags = {skipValidation})
|
||||
|
|
|
@ -99,4 +99,4 @@ proc applyEmptyBlock*(state: var BeaconState) =
|
|||
let signedBlock = mockBlock(state, state.slot, flags = {})
|
||||
# TODO: we only need to skip verifyStateRoot validation
|
||||
# processBlock validation should work
|
||||
doAssert state_transition(state, signedBlock.message, {skipValidation})
|
||||
doAssert state_transition(state, signedBlock, {skipValidation})
|
||||
|
|
|
@ -49,11 +49,11 @@ proc runTest(identifier: string) =
|
|||
let blck = parseTest(testDir/"blocks_" & $i & ".ssz", SSZ, SignedBeaconBlock)
|
||||
|
||||
if postRef.isNil:
|
||||
let success = state_transition(stateRef[], blck.message, flags = {})
|
||||
let success = state_transition(stateRef[], blck, flags = {})
|
||||
doAssert not success, "We didn't expect this invalid block to be processed"
|
||||
else:
|
||||
# TODO: The EF is using invalid BLS keys so we can't verify them
|
||||
let success = state_transition(stateRef[], blck.message, flags = {skipValidation})
|
||||
let success = state_transition(stateRef[], blck, flags = {skipValidation})
|
||||
doAssert success, "Failure when applying block " & $i
|
||||
|
||||
# check: stateRef.hash_tree_root() == postRef.hash_tree_root()
|
||||
|
|
|
@ -30,18 +30,18 @@ suite "Beacon chain DB" & preset():
|
|||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
|
||||
let
|
||||
blck = SignedBeaconBlock()
|
||||
root = hash_tree_root(blck.message)
|
||||
signedBlock = SignedBeaconBlock()
|
||||
root = hash_tree_root(signedBlock.message)
|
||||
|
||||
db.putBlock(blck)
|
||||
db.putBlock(signedBlock)
|
||||
|
||||
check:
|
||||
db.containsBlock(root)
|
||||
db.getBlock(root).get() == blck
|
||||
db.getBlock(root).get() == signedBlock
|
||||
|
||||
db.putStateRoot(root, blck.message.slot, root)
|
||||
db.putStateRoot(root, signedBlock.message.slot, root)
|
||||
check:
|
||||
db.getStateRoot(root, blck.message.slot).get() == root
|
||||
db.getStateRoot(root, signedBlock.message.slot).get() == root
|
||||
|
||||
timedTest "sanity check states" & preset():
|
||||
var
|
||||
|
|
|
@ -40,7 +40,7 @@ suite "Block processing" & preset():
|
|||
previous_block_root = hash_tree_root(genesisBlock.message)
|
||||
new_block = makeBlock(state, previous_block_root, BeaconBlockBody())
|
||||
|
||||
let block_ok = state_transition(state, new_block.message, {})
|
||||
let block_ok = state_transition(state, new_block, {})
|
||||
|
||||
check:
|
||||
block_ok
|
||||
|
@ -64,7 +64,7 @@ suite "Block processing" & preset():
|
|||
for i in 1..SLOTS_PER_EPOCH.int:
|
||||
var new_block = makeBlock(state, previous_block_root, BeaconBlockBody())
|
||||
|
||||
let block_ok = state_transition(state, new_block.message, {})
|
||||
let block_ok = state_transition(state, new_block, {})
|
||||
|
||||
check:
|
||||
block_ok
|
||||
|
@ -98,7 +98,7 @@ suite "Block processing" & preset():
|
|||
new_block = makeBlock(state, previous_block_root, BeaconBlockBody(
|
||||
attestations: @[attestation]
|
||||
))
|
||||
discard state_transition(state, new_block.message, {})
|
||||
discard state_transition(state, new_block, {})
|
||||
|
||||
check:
|
||||
# TODO epoch attestations can get multiplied now; clean up paths to
|
||||
|
|
|
@ -111,7 +111,7 @@ proc addBlock*(
|
|||
)
|
||||
)
|
||||
|
||||
let block_ok = state_transition(state, new_block.message, {skipValidation})
|
||||
let block_ok = state_transition(state, new_block, {skipValidation})
|
||||
doAssert block_ok
|
||||
|
||||
# Ok, we have the new state as it would look with the block applied - now we
|
||||
|
|
Loading…
Reference in New Issue