mirror of
https://github.com/codex-storage/nim-codex.git
synced 2025-01-10 13:05:48 +00:00
b3e57a37e2
* wire prover into node * stricter case object checks * return correct proof * misc renames * adding usefull traces * fix nodes and tolerance to match expected params * format challenges in logs * add circom compat to solidity groth16 convertion * update * bump time to give nodes time to load with all circom artifacts * misc * misc * use correct dataset geometry in erasure * make errors more searchable * use parens around `=? (await...)` calls * styling * styling * use push raises * fix to match constructor arguments * merge master * merge master * integration: fix proof parameters for a test Increased times due to ZK proof generation. Increased storage requirement because we're now hosting 5 slots instead of 1. * sales: calculate initial proof at start of period reason: this ensures that the period (and therefore the challenge) doesn't change while we're calculating the proof * integration: fix proof parameters for tests Increased times due to waiting on next period. Fixed data to be of right size. Updated expected payout due to hosting 5 slots. * sales: wait for stable proof challenge When the block pointer is nearing the wrap-around point, we wait another period before calculating a proof. * fix merge conflict --------- Co-authored-by: Dmitriy Ryajov <dryajov@gmail.com> Co-authored-by: Eric <5089238+emizzle@users.noreply.github.com>
244 lines
8.6 KiB
Nim
244 lines
8.6 KiB
Nim
## logutils is a module that has several goals:
|
|
## 1. Fix json logging output (run with `--log-format=json`) which was
|
|
## effectively broken for many types using default Chronicles json
|
|
## serialization.
|
|
## 2. Ability to specify log output for textlines and json sinks together or
|
|
## separately
|
|
## - This is useful if consuming json in some kind of log parser and need
|
|
## valid json with real values
|
|
## - eg a shortened Cid is nice to see in a text log in stdout, but won't
|
|
## provide a real Cid when parsed in json
|
|
## 4. Remove usages of `nim-json-serialization` from the codebase
|
|
## 5. Remove need to declare `writeValue` for new types
|
|
## 6. Remove need to [avoid importing or exporting `toJson`, `%`, `%*` to prevent
|
|
## conflicts](https://github.com/codex-storage/nim-codex/pull/645#issuecomment-1838834467)
|
|
##
|
|
## When declaring a new type, one should consider importing the `codex/logutils`
|
|
## module, and specifying `formatIt`. If textlines log output and json log output
|
|
## need to be different, overload `formatIt` and specify a `LogFormat`. If json
|
|
## serialization is needed, it can be declared with a `%` proc. `logutils`
|
|
## imports and exports `utils/json` which handles the de/serialization, examples
|
|
## below. **Only `codex/logutils` needs to be imported.**
|
|
##
|
|
## Using `logutils` in the Codex codebase:
|
|
## - Instead of importing `pkg/chronicles`, import `pkg/codex/logutils`
|
|
## - most of `chronicles` is exported by `logutils`
|
|
## - Instead of importing `std/json`, import `pkg/codex/utils/json`
|
|
## - `std/json` is exported by `utils/json` which is exported by `logutils`
|
|
## - Instead of importing `pkg/nim-json-serialization`, import
|
|
## `pkg/codex/utils/json`
|
|
## - one of the goals is to remove the use of `nim-json-serialization`
|
|
##
|
|
## ```nim
|
|
## import pkg/codex/logutils
|
|
##
|
|
## type
|
|
## BlockAddress* = object
|
|
## case leaf*: bool
|
|
## of true:
|
|
## treeCid* {.serialize.}: Cid
|
|
## index* {.serialize.}: Natural
|
|
## else:
|
|
## cid* {.serialize.}: Cid
|
|
##
|
|
## logutils.formatIt(LogFormat.textLines, BlockAddress):
|
|
## if it.leaf:
|
|
## "treeCid: " & shortLog($it.treeCid) & ", index: " & $it.index
|
|
## else:
|
|
## "cid: " & shortLog($it.cid)
|
|
##
|
|
## logutils.formatIt(LogFormat.json, BlockAddress): %it
|
|
##
|
|
## # chronicles textlines output
|
|
## TRC test tid=14397405 ba="treeCid: zb2*fndjU1, index: 0"
|
|
## # chronicles json output
|
|
## {"lvl":"TRC","msg":"test","tid":14397405,"ba":{"treeCid":"zb2rhgsDE16rLtbwTFeNKbdSobtKiWdjJPvKEuPgrQAfndjU1","index":0}}
|
|
## ```
|
|
## In this case, `BlockAddress` is just an object, so `utils/json` can handle
|
|
## serializing it without issue (only fields annotated with `{.serialize.}` will
|
|
## serialize (aka opt-in serialization)).
|
|
##
|
|
## If one so wished, another option for the textlines log output, would be to
|
|
## simply `toString` the serialised json:
|
|
## ```nim
|
|
## logutils.formatIt(LogFormat.textLines, BlockAddress): $ %it
|
|
## # or, more succinctly:
|
|
## logutils.formatIt(LogFormat.textLines, BlockAddress): it.toJson
|
|
## ```
|
|
## In that case, both the textlines and json sinks would have the same output,
|
|
## so we could reduce this even further by not specifying a `LogFormat`:
|
|
## ```nim
|
|
## type
|
|
## BlockAddress* = object
|
|
## case leaf*: bool
|
|
## of true:
|
|
## treeCid* {.serialize.}: Cid
|
|
## index* {.serialize.}: Natural
|
|
## else:
|
|
## cid* {.serialize.}: Cid
|
|
##
|
|
## logutils.formatIt(BlockAddress): %it
|
|
##
|
|
## # chronicles textlines output
|
|
## TRC test tid=14400673 ba="{\"treeCid\":\"zb2rhgsDE16rLtbwTFeNKbdSobtKiWdjJPvKEuPgrQAfndjU1\",\"index\":0}"
|
|
## # chronicles json output
|
|
## {"lvl":"TRC","msg":"test","tid":14400673,"ba":{"treeCid":"zb2rhgsDE16rLtbwTFeNKbdSobtKiWdjJPvKEuPgrQAfndjU1","index":0}}
|
|
## ```
|
|
|
|
import std/options
|
|
import std/sequtils
|
|
import std/strutils
|
|
import std/sugar
|
|
import std/typetraits
|
|
|
|
import pkg/chronicles except toJson, `%`
|
|
from pkg/libp2p import Cid, MultiAddress, `$`
|
|
import pkg/questionable
|
|
import pkg/questionable/results
|
|
import pkg/stew/byteutils
|
|
import pkg/stint
|
|
import pkg/upraises
|
|
|
|
import ./utils/json
|
|
|
|
export byteutils
|
|
export chronicles except toJson, formatIt, `%`
|
|
export questionable
|
|
export sequtils
|
|
export strutils
|
|
export sugar
|
|
export upraises
|
|
export json
|
|
export results
|
|
|
|
func shortLog*(long: string, ellipses = "*", start = 3, stop = 6): string =
|
|
## Returns compact string representation of ``long``.
|
|
var short = long
|
|
let minLen = start + ellipses.len + stop
|
|
if len(short) > minLen:
|
|
short.insert(ellipses, start)
|
|
|
|
when (NimMajor, NimMinor) > (1, 4):
|
|
short.delete(start + ellipses.len .. short.high - stop)
|
|
else:
|
|
short.delete(start + ellipses.len, short.high - stop)
|
|
|
|
short
|
|
|
|
func shortHexLog*(long: string): string =
|
|
if long[0..1] == "0x": result &= "0x"
|
|
result &= long[2..long.high].shortLog("..", 4, 4)
|
|
|
|
func short0xHexLog*[N: static[int], T: array[N, byte]](v: T): string =
|
|
v.to0xHex.shortHexLog
|
|
|
|
func short0xHexLog*[T: distinct](v: T): string =
|
|
type BaseType = T.distinctBase
|
|
BaseType(v).short0xHexLog
|
|
|
|
func short0xHexLog*[U: distinct, T: seq[U]](v: T): string =
|
|
type BaseType = U.distinctBase
|
|
"@[" & v.map(x => BaseType(x).short0xHexLog).join(",") & "]"
|
|
|
|
func to0xHexLog*[T: distinct](v: T): string =
|
|
type BaseType = T.distinctBase
|
|
BaseType(v).to0xHex
|
|
|
|
func to0xHexLog*[U: distinct, T: seq[U]](v: T): string =
|
|
type BaseType = U.distinctBase
|
|
"@[" & v.map(x => BaseType(x).to0xHex).join(",") & "]"
|
|
|
|
proc formatTextLineSeq*(val: seq[string]): string =
|
|
"@[" & val.join(", ") & "]"
|
|
|
|
template formatIt*(format: LogFormat, T: typedesc, body: untyped) =
|
|
# Provides formatters for logging with Chronicles for the given type and
|
|
# `LogFormat`.
|
|
# NOTE: `seq[T]`, `Option[T]`, and `seq[Option[T]]` are overriddden
|
|
# since the base `setProperty` is generic using `auto` and conflicts with
|
|
# providing a generic `seq` and `Option` override.
|
|
when format == LogFormat.json:
|
|
proc formatJsonOption(val: ?T): JsonNode =
|
|
if it =? val:
|
|
json.`%`(body)
|
|
else:
|
|
newJNull()
|
|
|
|
proc formatJsonResult*(val: ?!T): JsonNode =
|
|
without it =? val, error:
|
|
let jObj = newJObject()
|
|
jObj["error"] = newJString(error.msg)
|
|
return jObj
|
|
json.`%`(body)
|
|
|
|
proc setProperty*(r: var JsonRecord, key: string, res: ?!T) =
|
|
var it {.inject, used.}: T
|
|
setProperty(r, key, res.formatJsonResult)
|
|
|
|
proc setProperty*(r: var JsonRecord, key: string, opt: ?T) =
|
|
var it {.inject, used.}: T
|
|
let v = opt.formatJsonOption
|
|
setProperty(r, key, v)
|
|
|
|
proc setProperty*(r: var JsonRecord, key: string, opts: seq[?T]) =
|
|
var it {.inject, used.}: T
|
|
let v = opts.map(opt => opt.formatJsonOption)
|
|
setProperty(r, key, json.`%`(v))
|
|
|
|
proc setProperty*(r: var JsonRecord, key: string, val: seq[T]) =
|
|
var it {.inject, used.}: T
|
|
let v = val.map(it => body)
|
|
setProperty(r, key, json.`%`(v))
|
|
|
|
proc setProperty*(r: var JsonRecord, key: string, val: T) {.upraises:[ValueError, IOError].} =
|
|
var it {.inject, used.}: T = val
|
|
let v = body
|
|
setProperty(r, key, json.`%`(v))
|
|
|
|
elif format == LogFormat.textLines:
|
|
proc formatTextLineOption*(val: ?T): string =
|
|
var v = "none(" & $T & ")"
|
|
if it =? val:
|
|
v = "some(" & $(body) & ")" # that I used to know :)
|
|
v
|
|
|
|
proc formatTextLineResult*(val: ?!T): string =
|
|
without it =? val, error:
|
|
return "Error: " & error.msg
|
|
$(body)
|
|
|
|
proc setProperty*(r: var TextLineRecord, key: string, res: ?!T) =
|
|
var it {.inject, used.}: T
|
|
setProperty(r, key, res.formatTextLineResult)
|
|
|
|
proc setProperty*(r: var TextLineRecord, key: string, opt: ?T) =
|
|
var it {.inject, used.}: T
|
|
let v = opt.formatTextLineOption
|
|
setProperty(r, key, v)
|
|
|
|
proc setProperty*(r: var TextLineRecord, key: string, opts: seq[?T]) =
|
|
var it {.inject, used.}: T
|
|
let v = opts.map(opt => opt.formatTextLineOption)
|
|
setProperty(r, key, v.formatTextLineSeq)
|
|
|
|
proc setProperty*(r: var TextLineRecord, key: string, val: seq[T]) =
|
|
var it {.inject, used.}: T
|
|
let v = val.map(it => body)
|
|
setProperty(r, key, v.formatTextLineSeq)
|
|
|
|
proc setProperty*(r: var TextLineRecord, key: string, val: T) {.upraises:[ValueError, IOError].} =
|
|
var it {.inject, used.}: T = val
|
|
let v = body
|
|
setProperty(r, key, v)
|
|
|
|
template formatIt*(T: type, body: untyped) {.dirty.} =
|
|
formatIt(LogFormat.textLines, T): body
|
|
formatIt(LogFormat.json, T): body
|
|
|
|
formatIt(LogFormat.textLines, Cid): shortLog($it)
|
|
formatIt(LogFormat.json, Cid): $it
|
|
formatIt(UInt256): $it
|
|
formatIt(MultiAddress): $it
|
|
formatIt(LogFormat.textLines, array[32, byte]): it.short0xHexLog
|
|
formatIt(LogFormat.json, array[32, byte]): it.to0xHex
|