More persistance

This commit is contained in:
Yuriy Glukhov 2019-01-25 16:17:35 +02:00 committed by zah
parent dda24619e8
commit 917c48d9a5
5 changed files with 77 additions and 28 deletions

View File

@ -4,12 +4,12 @@ import
spec/[datatypes, digest, crypto],
eth_trie/db, ssz
const STATE_STORAGE_PERIOD = 1000 # Save states once per this number of slots. TODO: Find a good number.
type
BeaconChainDB* = ref object
backend: TrieDatabaseRef
BeaconStateRef* = ref BeaconState
DbKey = object
data: array[33, byte]
dataEndPos: uint8
@ -17,6 +17,9 @@ type
DbKeyKind = enum
kLastFinalizedState
kHashToBlock
kSlotToBlockHash
kSlotToState
kHashToValidatorRegistryChangeLog
template toOpenArray*(k: DbKey): openarray[byte] =
@ -31,23 +34,67 @@ proc hashToBlockKey(h: Eth2Digest): DbKey =
result.data[1 .. ^1] = h.data
result.dataEndPos = 32
proc slotToBlockHashKey(s: uint64): DbKey =
result.data[0] = byte ord(kSlotToBlockHash)
copyMem(addr result.data[1], unsafeAddr(s), sizeof(s))
result.dataEndPos = uint8 sizeof(s)
proc slotToStateKey(s: uint64): DbKey =
result.data[0] = byte ord(kSlotToState)
copyMem(addr result.data[1], unsafeAddr(s), sizeof(s))
result.dataEndPos = uint8 sizeof(s)
proc hashToValidatorRegistryChangeLogKey(deltaChainTip: Eth2Digest): DbKey =
result.data[0] = byte ord(kHashToValidatorRegistryChangeLog)
result.data[1 .. ^1] = deltaChainTip.data
result.dataEndPos = 32
proc init*(T: type BeaconChainDB, backend: TrieDatabaseRef): BeaconChainDB =
new result
result.backend = backend
proc lastFinalizedState*(db: BeaconChainDB): BeaconStateRef =
try:
let res = db.backend.get(lastFinalizedStateKey().toOpenArray)
if res.len != 0:
result.new
result[] = ssz.deserialize(res, BeaconState).get
except:
error "Failed to load the latest finalized state",
err = getCurrentExceptionMsg()
return nil
proc lastFinalizedState*(db: BeaconChainDB): BeaconState =
let res = db.backend.get(lastFinalizedStateKey().toOpenArray)
if res.len == 0:
raise newException(Exception, "Internal error: Database has no finalized state")
ssz.deserialize(res, BeaconState).get
proc isInitialized*(db: BeaconChainDB): bool =
db.backend.get(lastFinalizedStateKey().toOpenArray).len != 0
proc persistState*(db: BeaconChainDB, s: BeaconState) =
if s.slot != GENESIS_SLOT:
# TODO: Verify incoming state slot is higher than lastFinalizedState one
discard
else:
# Make sure we have no states
assert(not db.isInitialized)
var prevState: BeaconState
if s.slot != GENESIS_SLOT:
prevState = db.lastFinalizedState()
if prevState.validator_registry_delta_chain_tip != s.validator_registry_delta_chain_tip:
# Validator registry has changed in the incoming state.
# TODO: Save the changelog.
discard
let serializedState = ssz.serialize(s)
db.backend.put(lastFinalizedStateKey().toOpenArray, serializedState)
if s.slot mod STATE_STORAGE_PERIOD == 0:
# Save slot to state mapping
db.backend.put(slotToStateKey(s.slot).toOpenArray, serializedState)
proc persistBlock*(db: BeaconChainDB, s: BeaconState, b: BeaconBlock) =
db.backend.put(lastFinalizedStateKey().toOpenArray, ssz.serialize(s))
var prevState = db.lastFinalizedState()
db.persistState(s)
let blockHash = b.hash_tree_root_final
db.backend.put(hashToBlockKey(blockHash).toOpenArray, ssz.serialize(b))
db.backend.put(slotToBlockHashKey(b.slot).toOpenArray, blockHash.data)
# proc getValidatorChangeLog*(deltaChainTip: Eth2Digest)
proc getBlock*(db: BeaconChainDB, hash: Eth2Digest, output: var BeaconBlock): bool =
let res = db.backend.get(hashToBlockKey(hash).toOpenArray)

View File

@ -49,6 +49,12 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): T =
let trieDB = trieDB newChainDb(string conf.dataDir)
result.db = BeaconChainDB.init(trieDB)
if not result.db.isInitialized:
# Use stateSnapshot as genesis
info "Initializing DB"
result.db.persistState(result.config.stateSnapshot.get)
result.keys = ensureNetworkKeys(string conf.dataDir)
var address: Address
@ -81,14 +87,10 @@ proc connectToNetwork(node: BeaconNode) {.async.} =
proc sync*(node: BeaconNode): Future[bool] {.async.} =
let persistedState = node.db.lastFinalizedState()
if persistedState.isNil or
persistedState[].slotDistanceFromNow() > WEAK_SUBJECTVITY_PERIOD.int64:
if node.config.stateSnapshot.isSome:
node.beaconState = node.config.stateSnapshot.get
else:
node.beaconState = await obtainTrustedStateSnapshot(node.db)
if persistedState.slotDistanceFromNow() > WEAK_SUBJECTVITY_PERIOD.int64:
node.beaconState = await obtainTrustedStateSnapshot(node.db)
else:
node.beaconState = persistedState[]
node.beaconState = persistedState
var targetSlot = toSlot timeSinceGenesis(node.beaconState)
let t = now()
@ -354,6 +356,7 @@ proc processBlocks*(node: BeaconNode) =
node.headBlock = newBlock
node.headBlockRoot = newBlockRoot
node.beaconState = state
node.db.persistBlock(node.beaconState, newBlock)
# TODO:
#

View File

@ -13,7 +13,7 @@ proc initRandao*(bytes: openarray[byte]): Randao =
raise newException(Exception, "Wrong randao size")
var s: Eth2Digest
s.data[0 .. ^1] = bytes
initRandao(bytes)
initRandao(s)
proc initialCommitment*(r: Randao): Eth2Digest =
repeatHash(r.seed, MaxRandaoLevels)

View File

@ -16,7 +16,11 @@ type
p2pProtocol BeaconSync(version = 1,
shortName = "bcs"):
requestResponse:
proc getValidatorChangeLog(peer: Peer, changeLogHead: Eth2Digest)
proc getValidatorChangeLog(peer: Peer, changeLogHead: Eth2Digest) =
var bb: BeaconBlock
var bs: BeaconState
# TODO: get the changelog from the DB.
await peer.validatorChangeLog(reqId, bb, bs, [], [], @[])
proc validatorChangeLog(peer: Peer,
signedBlock: BeaconBlock,
@ -25,11 +29,6 @@ p2pProtocol BeaconSync(version = 1,
removed: openarray[uint32],
order: seq[byte])
template `++`(x: var int): int =
let y = x
inc x
y
type
# A bit shorter names for convenience
ChangeLog = BeaconSync.validatorChangeLog

View File

@ -27,7 +27,7 @@ proc obtainTrustedStateSnapshot*(db: BeaconChainDB): Future[BeaconState] {.async
#
# 5. Check that the state snapshot hash is correct and save it in the DB.
discard
assert(false, "Not implemented")
proc createStateSnapshot*(startup: ChainStartupData, outFile: string) =
let initialState = get_initial_beacon_state(startup.validatorDeposits,