2018-11-23 23:58:49 +00:00
|
|
|
import
|
2019-01-14 12:19:44 +00:00
|
|
|
os, json, tables, options,
|
2018-11-23 23:58:49 +00:00
|
|
|
chronicles, json_serialization, eth_common/eth_types_json_serialization,
|
2019-01-14 12:19:44 +00:00
|
|
|
spec/[datatypes, digest, crypto],
|
|
|
|
eth_trie/db, ssz
|
2018-11-23 23:58:49 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
BeaconChainDB* = ref object
|
2019-01-14 12:19:44 +00:00
|
|
|
backend: TrieDatabaseRef
|
2018-11-23 23:58:49 +00:00
|
|
|
|
|
|
|
BeaconStateRef* = ref BeaconState
|
|
|
|
|
2019-01-14 12:19:44 +00:00
|
|
|
DbKey = object
|
|
|
|
data: array[33, byte]
|
|
|
|
dataEndPos: uint8
|
|
|
|
|
|
|
|
DbKeyKind = enum
|
|
|
|
kLastFinalizedState
|
|
|
|
kHashToBlock
|
|
|
|
|
|
|
|
|
|
|
|
template toOpenArray*(k: DbKey): openarray[byte] =
|
|
|
|
k.data.toOpenArray(0, int(k.dataEndPos))
|
|
|
|
|
|
|
|
proc lastFinalizedStateKey(): DbKey =
|
|
|
|
result.data[0] = byte ord(kLastFinalizedState)
|
|
|
|
result.dataEndPos = 0
|
|
|
|
|
|
|
|
proc hashToBlockKey(h: Eth2Digest): DbKey =
|
|
|
|
result.data[0] = byte ord(kHashToBlock)
|
|
|
|
result.data[1 .. ^1] = h.data
|
|
|
|
result.dataEndPos = 32
|
|
|
|
|
|
|
|
proc init*(T: type BeaconChainDB, backend: TrieDatabaseRef): BeaconChainDB =
|
2018-11-23 23:58:49 +00:00
|
|
|
new result
|
2019-01-14 12:19:44 +00:00
|
|
|
result.backend = backend
|
2018-11-23 23:58:49 +00:00
|
|
|
|
|
|
|
proc lastFinalizedState*(db: BeaconChainDB): BeaconStateRef =
|
|
|
|
try:
|
2019-01-14 12:19:44 +00:00
|
|
|
let res = db.backend.get(lastFinalizedStateKey().toOpenArray)
|
|
|
|
if res.len != 0:
|
|
|
|
result.new
|
|
|
|
result[] = ssz.deserialize(res, BeaconState).get
|
2018-11-23 23:58:49 +00:00
|
|
|
except:
|
2018-12-19 12:58:53 +00:00
|
|
|
error "Failed to load the latest finalized state",
|
|
|
|
err = getCurrentExceptionMsg()
|
2018-11-23 23:58:49 +00:00
|
|
|
return nil
|
|
|
|
|
|
|
|
proc persistBlock*(db: BeaconChainDB, s: BeaconState, b: BeaconBlock) =
|
2019-01-14 12:19:44 +00:00
|
|
|
db.backend.put(lastFinalizedStateKey().toOpenArray, ssz.serialize(s))
|
|
|
|
|
|
|
|
proc getBlock*(db: BeaconChainDB, hash: Eth2Digest, output: var BeaconBlock): bool =
|
|
|
|
let res = db.backend.get(hashToBlockKey(hash).toOpenArray)
|
|
|
|
if res.len != 0:
|
|
|
|
output = ssz.deserialize(res, BeaconBlock).get
|
|
|
|
true
|
|
|
|
else:
|
|
|
|
false
|
|
|
|
|
|
|
|
proc getBlock*(db: BeaconChainDB, hash: Eth2Digest): BeaconBlock =
|
|
|
|
if not db.getBlock(hash, result):
|
|
|
|
raise newException(Exception, "Block not found")
|
2018-11-23 23:58:49 +00:00
|
|
|
|