trie -> kv store
* simplify data storage to key-value, tries are not relevant for NBC * locked-down version of lmdb dependency * easier to build / maintain on various platforms
This commit is contained in:
parent
3dcdce137a
commit
2a67ac3c05
|
@ -136,3 +136,6 @@
|
|||
url = https://github.com/status-im/nim-bearssl.git
|
||||
ignore = dirty
|
||||
branch = master
|
||||
[submodule "vendor/lmdb"]
|
||||
path = vendor/lmdb
|
||||
url = https://github.com/status-im/lmdb.git
|
||||
|
|
|
@ -7,7 +7,6 @@ cache:
|
|||
directories:
|
||||
- vendor/nimbus-build-system/vendor/Nim/bin
|
||||
- vendor/go/bin
|
||||
- rocksdbCache
|
||||
- jsonTestsCache
|
||||
|
||||
git:
|
||||
|
@ -27,7 +26,6 @@ matrix:
|
|||
before_install:
|
||||
- export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
|
||||
- sudo apt-get -q update
|
||||
- sudo apt-get install -y librocksdb-dev
|
||||
- os: linux
|
||||
arch: arm64
|
||||
sudo: required
|
||||
|
@ -37,14 +35,10 @@ matrix:
|
|||
before_install:
|
||||
- export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
|
||||
- sudo apt-get -q update
|
||||
- sudo apt-get install -y libpcre3-dev librocksdb-dev
|
||||
- sudo apt-get install -y libpcre3-dev
|
||||
- os: osx
|
||||
env:
|
||||
- NPROC=2
|
||||
before_install:
|
||||
- launchctl setenv LIBRARY_PATH /usr/local/lib # for RocksDB
|
||||
# build our own rocksdb to test with a fixed version that we think works
|
||||
- vendor/nimbus-build-system/scripts/build_rocksdb.sh rocksdbCache
|
||||
|
||||
|
||||
install:
|
||||
|
|
26
README.md
26
README.md
|
@ -52,7 +52,6 @@ Nimbus has 4 external dependencies:
|
|||
|
||||
* Go 1.12 (for compiling libp2p daemon - being phased out)
|
||||
* Developer tools (C compiler, Make, Bash, Git)
|
||||
* [RocksDB](https://github.com/facebook/rocksdb/)
|
||||
* PCRE
|
||||
|
||||
Nim is not an external dependency, Nimbus will build its own local copy.
|
||||
|
@ -62,13 +61,13 @@ Nim is not an external dependency, Nimbus will build its own local copy.
|
|||
On common Linux distributions the dependencies can be installed with:
|
||||
```sh
|
||||
# Debian and Ubuntu
|
||||
sudo apt-get install build-essential git golang-go librocksdb-dev libpcre3-dev
|
||||
sudo apt-get install build-essential git golang-go libpcre3-dev
|
||||
|
||||
# Fedora
|
||||
dnf install @development-tools go rocksdb-devel pcre
|
||||
dnf install @development-tools go pcre
|
||||
|
||||
# Archlinux, using an AUR manager for pcre-static
|
||||
yourAURmanager -S base-devel go rocksdb pcre-static
|
||||
yourAURmanager -S base-devel go pcre-static
|
||||
```
|
||||
|
||||
### MacOS
|
||||
|
@ -76,14 +75,14 @@ yourAURmanager -S base-devel go rocksdb pcre-static
|
|||
Assuming you use [Homebrew](https://brew.sh/) to manage packages
|
||||
|
||||
```sh
|
||||
brew install go rocksdb pcre
|
||||
brew install go pcre
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
* install [Go](https://golang.org/doc/install#windows)
|
||||
You can install the developer tools by following the instruction in our [Windows dev environment section](#windows-dev-environment).
|
||||
It also provides a downloading script for prebuilt PCRE and RocksDB.
|
||||
It also provides a downloading script for prebuilt PCRE.
|
||||
|
||||
If you choose to install Go from source, both Go and Nimbus requires the same initial steps of installing Mingw.
|
||||
|
||||
|
@ -220,7 +219,7 @@ Variables -> Path -> Edit -> New -> C:\mingw-w64\mingw64\bin (it's "C:\mingw-w64
|
|||
|
||||
Install [Git for Windows](https://gitforwindows.org/) and use a "Git Bash" shell to clone and build nim-beacon-chain.
|
||||
|
||||
If you don't want to compile RocksDB and SQLite separately, you can fetch pre-compiled DLLs with:
|
||||
If you don't want to compile PCRE separately, you can fetch pre-compiled DLLs with:
|
||||
```bash
|
||||
mingw32-make # this first invocation will update the Git submodules
|
||||
mingw32-make fetch-dlls # this will place the right DLLs for your architecture in the "build/" directory
|
||||
|
@ -286,19 +285,6 @@ sudo apt-get install git libgflags-dev libsnappy-dev libpcre3-dev
|
|||
mkdir status
|
||||
cd status
|
||||
|
||||
# Install rocksdb
|
||||
git clone https://github.com/facebook/rocksdb.git
|
||||
cd rocksdb
|
||||
make shared_lib
|
||||
sudo make install-shared
|
||||
cd ..
|
||||
|
||||
# Raspberry pi doesn't include /usr/local/lib in library search path
|
||||
# Add it to your profile
|
||||
echo '# Local compiles (nimbus - rocksdb)' >> ~/.profile
|
||||
echo 'export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH' >> ~/.profile
|
||||
echo '' >> ~/.profile
|
||||
|
||||
# Install Go at least 1.12 (Buster only includes up to 1.11)
|
||||
# Raspbian is 32-bit, so the package is go1.XX.X.linux-armv6l.tar.gz (and not arm64)
|
||||
curl -O https://storage.googleapis.com/golang/go1.13.3.linux-armv6l.tar.gz
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import
|
||||
json, tables, options,
|
||||
chronicles, serialization, json_serialization, eth/common/eth_types_json_serialization,
|
||||
options,
|
||||
serialization,
|
||||
spec/[datatypes, digest, crypto],
|
||||
eth/trie/db, ssz
|
||||
kvstore, ssz
|
||||
|
||||
type
|
||||
BeaconChainDB* = ref object
|
||||
## Database storing resolved blocks and states - resolved blocks are such
|
||||
## blocks that form a chain back to the tail block.
|
||||
backend: TrieDatabaseRef
|
||||
backend: KVStoreRef
|
||||
|
||||
DbKeyKind = enum
|
||||
kHashToState
|
||||
|
@ -61,7 +61,7 @@ func subkey(root: Eth2Digest, slot: Slot): auto =
|
|||
|
||||
ret
|
||||
|
||||
proc init*(T: type BeaconChainDB, backend: TrieDatabaseRef): BeaconChainDB =
|
||||
proc init*(T: type BeaconChainDB, backend: KVStoreRef): BeaconChainDB =
|
||||
T(backend: backend)
|
||||
|
||||
proc putBlock*(db: BeaconChainDB, key: Eth2Digest, value: SignedBeaconBlock) =
|
||||
|
@ -99,22 +99,18 @@ proc putTailBlock*(db: BeaconChainDB, key: Eth2Digest) =
|
|||
db.backend.put(subkey(kTailBlock), key.data)
|
||||
|
||||
proc get(db: BeaconChainDB, key: auto, T: typedesc): Option[T] =
|
||||
let res = db.backend.get(key)
|
||||
if res.len != 0:
|
||||
var res: Option[T]
|
||||
discard db.backend.get(key, proc (data: openArray[byte]) =
|
||||
try:
|
||||
some(SSZ.decode(res, T))
|
||||
res = some(SSZ.decode(data, T))
|
||||
except SerializationError:
|
||||
none(T)
|
||||
else:
|
||||
none(T)
|
||||
discard
|
||||
)
|
||||
res
|
||||
|
||||
proc getBlock*(db: BeaconChainDB, key: Eth2Digest): Option[SignedBeaconBlock] =
|
||||
db.get(subkey(SignedBeaconBlock, key), SignedBeaconBlock)
|
||||
|
||||
proc getBlock*(db: BeaconChainDB, slot: Slot): Option[SignedBeaconBlock] =
|
||||
# TODO implement this
|
||||
discard
|
||||
|
||||
proc getState*(db: BeaconChainDB, key: Eth2Digest): Option[BeaconState] =
|
||||
db.get(subkey(BeaconState, key), BeaconState)
|
||||
|
||||
|
|
|
@ -3,10 +3,10 @@ import
|
|||
os, net, tables, random, strutils, times, sequtils,
|
||||
|
||||
# Nimble packages
|
||||
stew/[objects, bitseqs, byteutils], stew/ranges/ptr_arith,
|
||||
stew/[objects, bitseqs, byteutils],
|
||||
chronos, chronicles, confutils, metrics,
|
||||
json_serialization/std/[options, sets], serialization/errors,
|
||||
eth/trie/db, eth/trie/backends/rocksdb_backend, eth/async_utils,
|
||||
kvstore, kvstore_lmdb, eth/async_utils,
|
||||
|
||||
# Local modules
|
||||
spec/[datatypes, digest, crypto, beaconstate, helpers, validator, network],
|
||||
|
@ -135,7 +135,7 @@ proc init*(T: type BeaconNode, conf: BeaconNodeConf): Future[BeaconNode] {.async
|
|||
networkId = getPersistentNetIdentity(conf)
|
||||
nickname = if conf.nodeName == "auto": shortForm(networkId)
|
||||
else: conf.nodeName
|
||||
db = BeaconChainDB.init(trieDB newChainDb(conf.databaseDir))
|
||||
db = BeaconChainDB.init(kvStore LmdbStoreRef.init(conf.databaseDir))
|
||||
|
||||
var mainchainMonitor: MainchainMonitor
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
# Simple Key-Value store database interface
|
||||
|
||||
import
|
||||
tables, hashes, sets
|
||||
|
||||
type
|
||||
MemoryStoreRef* = ref object of RootObj
|
||||
records: Table[seq[byte], seq[byte]]
|
||||
|
||||
DataProc* = proc(val: openArray[byte])
|
||||
PutProc = proc (db: RootRef, key, val: openArray[byte]) {.gcsafe.}
|
||||
GetProc = proc (db: RootRef, key: openArray[byte], onData: DataProc): bool {.gcsafe.}
|
||||
DelProc = proc (db: RootRef, key: openArray[byte]) {.gcsafe.}
|
||||
ContainsProc = proc (db: RootRef, key: openArray[byte]): bool {.gcsafe.}
|
||||
|
||||
KVStoreRef* = ref object
|
||||
## Key-Value store virtual interface
|
||||
obj: RootRef
|
||||
putProc: PutProc
|
||||
getProc: GetProc
|
||||
delProc: DelProc
|
||||
containsProc: ContainsProc
|
||||
|
||||
template put*(db: KVStoreRef, key, val: openArray[byte]) =
|
||||
## Store ``value`` at ``key`` - overwrites existing value if already present
|
||||
db.putProc(db.obj, key, val)
|
||||
|
||||
template get*(db: KVStoreRef, key: openArray[byte], onData: untyped): bool =
|
||||
## Retrive value at ``key`` and call ``onData`` with the value. The data is
|
||||
## valid for the duration of the callback.
|
||||
## ``onData``: ``proc(data: openArray[byte])``
|
||||
## returns true if found and false otherwise.
|
||||
db.getProc(db.obj, key, onData)
|
||||
|
||||
template del*(db: KVStoreRef, key: openArray[byte]) =
|
||||
## Remove value at ``key`` from store - do nothing if the value is not present
|
||||
db.delProc(db.obj, key)
|
||||
|
||||
template contains*(db: KVStoreRef, key: openArray[byte]): bool =
|
||||
## Return true iff ``key`` has a value in store
|
||||
db.containsProc(db.obj, key)
|
||||
|
||||
proc get*(db: MemoryStoreRef, key: openArray[byte], onData: DataProc): bool =
|
||||
let key = @key
|
||||
db.records.withValue(key, v):
|
||||
onData(v[])
|
||||
return true
|
||||
|
||||
proc del*(db: MemoryStoreRef, key: openArray[byte]) =
|
||||
# TODO: This is quite inefficient and it won't be necessary once
|
||||
# https://github.com/nim-lang/Nim/issues/7457 is developed.
|
||||
let key = @key
|
||||
db.records.del(key)
|
||||
|
||||
proc contains*(db: MemoryStoreRef, key: openArray[byte]): bool =
|
||||
db.records.contains(@key)
|
||||
|
||||
proc put*(db: MemoryStoreRef, key, val: openArray[byte]) =
|
||||
# TODO: This is quite inefficient and it won't be necessary once
|
||||
# https://github.com/nim-lang/Nim/issues/7457 is developed.
|
||||
let key = @key
|
||||
db.records[key] = @val
|
||||
|
||||
proc init*(T: type MemoryStoreRef): T =
|
||||
T(
|
||||
records: initTable[seq[byte], seq[byte]]()
|
||||
)
|
||||
|
||||
proc putImpl[T](db: RootRef, key, val: openArray[byte]) =
|
||||
mixin put
|
||||
put(T(db), key, val)
|
||||
|
||||
proc getImpl[T](db: RootRef, key: openArray[byte], onData: DataProc): bool =
|
||||
mixin get
|
||||
get(T(db), key, onData)
|
||||
|
||||
proc delImpl[T](db: RootRef, key: openArray[byte]) =
|
||||
mixin del
|
||||
del(T(db), key)
|
||||
|
||||
proc containsImpl[T](db: RootRef, key: openArray[byte]): bool =
|
||||
mixin contains
|
||||
contains(T(db), key)
|
||||
|
||||
func kvStore*[T: RootRef](x: T): KVStoreRef =
|
||||
mixin del, get, put, contains
|
||||
|
||||
KVStoreRef(
|
||||
obj: x,
|
||||
putProc: putImpl[T],
|
||||
getProc: getImpl[T],
|
||||
delProc: delImpl[T],
|
||||
containsProc: containsImpl[T]
|
||||
)
|
|
@ -0,0 +1,159 @@
|
|||
## Implementation of KVStore based on LMDB
|
||||
## TODO: crashes on win32, investigate
|
||||
|
||||
import os
|
||||
|
||||
import ./kvstore
|
||||
|
||||
{.compile: "../vendor/lmdb/libraries/liblmdb/mdb.c".}
|
||||
{.compile: "../vendor/lmdb/libraries/liblmdb/midl.c".}
|
||||
|
||||
const
|
||||
MDB_NOSUBDIR = 0x4000
|
||||
MDB_RDONLY = 0x20000
|
||||
MDB_NOTFOUND = -30798
|
||||
|
||||
when defined(cpu64):
|
||||
const LMDB_MAP_SIZE = 1024'u64 * 1024'u64 * 1024'u64 * 10'u64 # 10TB enough?
|
||||
else:
|
||||
const LMDB_MAP_SIZE = 1024'u64 * 1024'u64 * 1024'u64 # 32bit limitation
|
||||
|
||||
type
|
||||
MDB_Env = distinct pointer
|
||||
MDB_Txn = distinct pointer
|
||||
MDB_Dbi = distinct cuint
|
||||
|
||||
MDB_val = object
|
||||
mv_size: csize
|
||||
mv_data: pointer
|
||||
|
||||
LmdbError* = object of CatchableError
|
||||
|
||||
# Used subset of the full LMDB API
|
||||
proc mdb_env_create(env: var MDB_Env): cint {.importc.}
|
||||
proc mdb_env_open(env: MDB_Env, path: cstring, flags: cuint, mode: cint): cint {.importc.}
|
||||
proc mdb_txn_begin(env: MDB_Env, parent: MDB_Txn, flags: cuint, txn: var MDB_Txn): cint {.importc.}
|
||||
proc mdb_txn_commit(txn: MDB_Txn): cint {.importc.}
|
||||
proc mdb_txn_abort(txn: MDB_Txn) {.importc.}
|
||||
proc mdb_dbi_open(txn: MDB_Txn, name: cstring, flags: cuint, dbi: var MDB_Dbi): cint {.importc.}
|
||||
proc mdb_env_close(env: MDB_Env) {.importc.}
|
||||
proc mdb_strerror(err: cint): cstring {.importc.}
|
||||
|
||||
proc mdb_get(txn: MDB_Txn, dbi: MDB_Dbi, key: var MDB_val, data: var MDB_val): cint {.importc.}
|
||||
proc mdb_del(txn: MDB_Txn, dbi: MDB_Dbi, key: var MDB_val, data: ptr MDB_val): cint {.importc.}
|
||||
proc mdb_put(txn: MDB_Txn, dbi: MDB_Dbi, key: var MDB_val, data: var MDB_val, flags: cuint): cint {.importc.}
|
||||
|
||||
proc mdb_env_set_mapsize(env: MDB_Env, size: uint64): cint {.importc.}
|
||||
|
||||
func raiseLmdbError(err: cint) {.noreturn.} =
|
||||
let tmp = mdb_strerror(err)
|
||||
raise (ref LmdbError)(msg: $tmp)
|
||||
|
||||
type
|
||||
LmdbStoreRef* = ref object of RootObj
|
||||
env: MDB_Env
|
||||
|
||||
template init(T: type MDB_Val, val: openArray[byte]): T =
|
||||
T(
|
||||
mv_size: val.len,
|
||||
mv_data: unsafeAddr val[0]
|
||||
)
|
||||
|
||||
proc begin(db: LmdbStoreRef, flags: cuint): tuple[txn: MDB_Txn, dbi: MDB_Dbi] =
|
||||
var
|
||||
txn: MDB_Txn
|
||||
dbi: MDB_Dbi
|
||||
|
||||
if (let x = mdb_txn_begin(db.env, nil, flags, txn); x != 0):
|
||||
raiseLmdbError(x)
|
||||
|
||||
if (let x = mdb_dbi_open(txn, nil, 0, dbi); x != 0):
|
||||
mdb_txn_abort(txn)
|
||||
raiseLmdbError(x)
|
||||
|
||||
(txn, dbi)
|
||||
|
||||
proc get*(db: LmdbStoreRef, key: openarray[byte], onData: DataProc): bool =
|
||||
if key.len == 0:
|
||||
return
|
||||
|
||||
var
|
||||
(txn, dbi) = db.begin(MDB_RDONLY)
|
||||
dbKey = MDB_Val.init(key)
|
||||
dbVal: MDB_val
|
||||
|
||||
# abort ok for read-only and easier for exception safety
|
||||
defer: mdb_txn_abort(txn)
|
||||
|
||||
if (let x = mdb_get(txn, dbi, dbKey, dbVal); x != 0):
|
||||
if x == MDB_NOTFOUND:
|
||||
return false
|
||||
|
||||
raiseLmdbError(x)
|
||||
|
||||
if not onData.isNil:
|
||||
onData(toOpenArrayByte(cast[cstring](dbVal.mv_data), 0, dbVal.mv_size.int - 1))
|
||||
|
||||
true
|
||||
|
||||
proc put*(db: LmdbStoreRef, key, value: openarray[byte]) =
|
||||
if key.len == 0: return
|
||||
|
||||
var
|
||||
(txn, dbi) = db.begin(0)
|
||||
dbKey = MDB_Val.init(key)
|
||||
dbVal = MDB_Val.init(value)
|
||||
|
||||
if (let x = mdb_put(txn, dbi, dbKey, dbVal, 0); x != 0):
|
||||
mdb_txn_abort(txn)
|
||||
raiseLmdbError(x)
|
||||
|
||||
if (let x = mdb_txn_commit(txn); x != 0):
|
||||
raiseLmdbError(x)
|
||||
|
||||
proc contains*(db: LmdbStoreRef, key: openarray[byte]): bool =
|
||||
db.get(key, nil)
|
||||
|
||||
proc del*(db: LmdbStoreRef, key: openarray[byte]) =
|
||||
if key.len == 0: return
|
||||
|
||||
var
|
||||
(txn, dbi) = db.begin(0)
|
||||
dbKey = MDB_Val.init(key)
|
||||
|
||||
if (let x = mdb_del(txn, dbi, dbKey, nil); x != 0):
|
||||
mdb_txn_abort(txn)
|
||||
|
||||
if x != MDB_NOTFOUND:
|
||||
raiseLmdbError(x)
|
||||
|
||||
return
|
||||
|
||||
if (let x = mdb_txn_commit(txn); x != 0):
|
||||
raiseLmdbError(x)
|
||||
|
||||
proc close*(db: LmdbStoreRef) =
|
||||
mdb_env_close(db.env)
|
||||
|
||||
proc init*(T: type LmdbStoreRef, basePath: string, readOnly = false): T =
|
||||
var
|
||||
env: MDB_Env
|
||||
|
||||
if (let x = mdb_env_create(env); x != 0):
|
||||
raiseLmdbError(x)
|
||||
|
||||
let dataDir = basePath / "nimbus.lmdb"
|
||||
|
||||
if (let x = mdb_env_set_mapsize(env, LMDB_MAP_SIZE); x != 0):
|
||||
mdb_env_close(env)
|
||||
raiseLmdbError(x)
|
||||
|
||||
var openFlags = MDB_NOSUBDIR
|
||||
if readOnly: openFlags = openFlags or MDB_RDONLY
|
||||
|
||||
# file mode ignored on windows
|
||||
if (let x = mdb_env_open(env, dataDir, openFlags.cuint, 0o664.cint); x != 0):
|
||||
mdb_env_close(env)
|
||||
raiseLmdbError(x)
|
||||
|
||||
T(env: env)
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import
|
||||
macros, hashes, json, strutils, tables,
|
||||
stew/[byteutils, bitseqs], chronicles, eth/common,
|
||||
stew/[byteutils, bitseqs], chronicles,
|
||||
../version, ../ssz/types, ./crypto, ./digest
|
||||
|
||||
# TODO Data types:
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
|
||||
import
|
||||
chronicles,
|
||||
nimcrypto/[sha2, hash, utils], eth/common/eth_types_json_serialization,
|
||||
nimcrypto/[sha2, hash, utils],
|
||||
hashes
|
||||
|
||||
export
|
||||
eth_types_json_serialization, hash.`$`
|
||||
hash.`$`
|
||||
|
||||
type
|
||||
Eth2Digest* = MDigest[32 * 8] ## `hash32` from spec
|
||||
|
|
|
@ -12,7 +12,7 @@ import
|
|||
endians, stew/shims/macros, options, algorithm, options,
|
||||
stew/[bitops2, bitseqs, objects, varints, ptrops, ranges/ptr_arith], stint,
|
||||
faststreams/input_stream, serialization, serialization/testing/tracing,
|
||||
nimcrypto/sha2, blscurve, eth/common,
|
||||
nimcrypto/sha2, blscurve,
|
||||
./spec/[crypto, datatypes, digest],
|
||||
./ssz/[types, bytes_reader]
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ FROM debian:bullseye-slim AS build
|
|||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq -y install build-essential make wget librocksdb-dev libpcre3-dev golang-go git &>/dev/null \
|
||||
&& apt-get -qq -y install build-essential make wget libpcre3-dev golang-go git &>/dev/null \
|
||||
&& apt-get -qq clean
|
||||
|
||||
# let Docker cache this between Git revision and testnet version changes
|
||||
|
@ -36,7 +36,7 @@ FROM debian:bullseye-slim
|
|||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
RUN apt-get -qq update \
|
||||
&& apt-get -qq -y install librocksdb-dev libpcre3 psmisc &>/dev/null \
|
||||
&& apt-get -qq -y install libpcre3 psmisc &>/dev/null \
|
||||
&& apt-get -qq clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ import # Unit test
|
|||
./test_block_pool,
|
||||
./test_helpers,
|
||||
./test_interop,
|
||||
./test_kvstore,
|
||||
./test_kvstore_lmdb,
|
||||
./test_ssz,
|
||||
./test_state_transition,
|
||||
./test_sync_protocol,
|
||||
|
|
|
@ -7,17 +7,16 @@
|
|||
|
||||
{.used.}
|
||||
|
||||
import options, unittest, sequtils, eth/trie/[db],
|
||||
../beacon_chain/[beacon_chain_db, extras, interop, ssz],
|
||||
import options, unittest, sequtils,
|
||||
../beacon_chain/[beacon_chain_db, extras, interop, ssz, kvstore],
|
||||
../beacon_chain/spec/[beaconstate, datatypes, digest, crypto],
|
||||
# test utilies
|
||||
./testutil, ./testblockutil
|
||||
|
||||
suite "Beacon chain DB" & preset():
|
||||
|
||||
timedTest "empty database" & preset():
|
||||
var
|
||||
db = init(BeaconChainDB, newMemoryDB())
|
||||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
|
||||
check:
|
||||
when const_preset=="minimal":
|
||||
|
@ -28,7 +27,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
timedTest "sanity check blocks" & preset():
|
||||
var
|
||||
db = init(BeaconChainDB, newMemoryDB())
|
||||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
|
||||
let
|
||||
blck = SignedBeaconBlock()
|
||||
|
@ -46,7 +45,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
timedTest "sanity check states" & preset():
|
||||
var
|
||||
db = init(BeaconChainDB, newMemoryDB())
|
||||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
|
||||
let
|
||||
state = BeaconState()
|
||||
|
@ -60,7 +59,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
timedTest "find ancestors" & preset():
|
||||
var
|
||||
db = init(BeaconChainDB, newMemoryDB())
|
||||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
x: ValidatorSig
|
||||
y = init(ValidatorSig, x.getBytes())
|
||||
|
||||
|
@ -101,7 +100,7 @@ suite "Beacon chain DB" & preset():
|
|||
# serialization where an all-zero default-initialized bls signature could
|
||||
# not be deserialized because the deserialization was too strict.
|
||||
var
|
||||
db = init(BeaconChainDB, newMemoryDB())
|
||||
db = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
|
||||
let
|
||||
state = initialize_beacon_state_from_eth1(
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
{.used.}
|
||||
|
||||
import
|
||||
unittest,
|
||||
../beacon_chain/kvstore
|
||||
|
||||
proc testKVStore*(db: KVStoreRef) =
|
||||
let
|
||||
key = [0'u8, 1, 2, 3]
|
||||
value = [3'u8, 2, 1, 0]
|
||||
value2 = [5'u8, 2, 1, 0]
|
||||
|
||||
check:
|
||||
db != nil
|
||||
|
||||
not db.get(key, proc(data: openArray[byte]) = discard)
|
||||
not db.contains(key)
|
||||
|
||||
db.del(key) # does nothing
|
||||
|
||||
db.put(key, value)
|
||||
|
||||
check:
|
||||
db.contains(key)
|
||||
db.get(key, proc(data: openArray[byte]) =
|
||||
check data == value
|
||||
)
|
||||
|
||||
db.put(key, value2) # overwrite old value
|
||||
check:
|
||||
db.contains(key)
|
||||
db.get(key, proc(data: openArray[byte]) =
|
||||
check data == value2
|
||||
)
|
||||
|
||||
db.del(key)
|
||||
check:
|
||||
not db.get(key, proc(data: openArray[byte]) = discard)
|
||||
not db.contains(key)
|
||||
|
||||
db.del(key) # does nothing
|
||||
|
||||
suite "MemoryStoreRef":
|
||||
test "KVStore interface":
|
||||
testKVStore(kvStore MemoryStoreRef.init())
|
|
@ -0,0 +1,24 @@
|
|||
{.used.}
|
||||
|
||||
import
|
||||
os,
|
||||
unittest,
|
||||
../beacon_chain/[kvstore, kvstore_lmdb],
|
||||
./test_kvstore
|
||||
|
||||
suite "LMDB":
|
||||
setup:
|
||||
let
|
||||
path = os.getTempDir() / "test_kvstore_lmdb"
|
||||
|
||||
os.removeDir(path)
|
||||
os.createDir(path)
|
||||
|
||||
teardown:
|
||||
os.removeDir(path)
|
||||
|
||||
test "KVStore interface":
|
||||
let db = LmdbStoreRef.init(path)
|
||||
defer: db.close()
|
||||
|
||||
testKVStore(kvStore db)
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
import
|
||||
algorithm, strformat, stats, times, std/monotimes, stew/endians2,
|
||||
chronicles, eth/trie/[db],
|
||||
../beacon_chain/[beacon_chain_db, block_pool, extras, ssz, beacon_node_types],
|
||||
chronicles,
|
||||
../beacon_chain/[beacon_chain_db, block_pool, extras, ssz, kvstore, beacon_node_types],
|
||||
../beacon_chain/spec/[digest, beaconstate, datatypes],
|
||||
testblockutil
|
||||
|
||||
|
@ -73,7 +73,7 @@ template timedTest*(name, body) =
|
|||
testTimes.add (f, name)
|
||||
|
||||
proc makeTestDB*(tailState: BeaconState, tailBlock: SignedBeaconBlock): BeaconChainDB =
|
||||
result = init(BeaconChainDB, newMemoryDB())
|
||||
result = init(BeaconChainDB, kvStore MemoryStoreRef.init())
|
||||
BlockPool.preInit(result, tailState, tailBlock)
|
||||
|
||||
proc makeTestDB*(validators: int): BeaconChainDB =
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit c8ecc17b38e164e6a728d66a9b1d05bc18dd3ace
|
Loading…
Reference in New Issue