Added json tags to beacon block (#8162)

This commit is contained in:
Giulio rebuffo 2023-09-08 22:26:02 +02:00 committed by GitHub
parent 97255efdb4
commit 4733f7fb52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 319 additions and 74 deletions

View File

@ -57,8 +57,8 @@ func (a *SignedAggregateAndProof) EncodingSizeSSZ() int {
* and signature is the aggregate BLS signature of the committee.
*/
type SyncAggregate struct {
SyncCommiteeBits [64]byte
SyncCommiteeSignature [96]byte
SyncCommiteeBits [64]byte `json:"sync_commitee_bits"`
SyncCommiteeSignature libcommon.Bytes96 `json:"signature"`
}
// return sum of the committee bits

View File

@ -23,46 +23,46 @@ const (
)
type SignedBeaconBlock struct {
Signature libcommon.Bytes96
Block *BeaconBlock
Signature libcommon.Bytes96 `json:"signature"`
Block *BeaconBlock `json:"message"`
}
type BeaconBlock struct {
Slot uint64
ProposerIndex uint64
ParentRoot libcommon.Hash
StateRoot libcommon.Hash
Body *BeaconBody
Slot uint64 `json:"slot"`
ProposerIndex uint64 `json:"proposer_index"`
ParentRoot libcommon.Hash `json:"parent_root"`
StateRoot libcommon.Hash `json:"state_root"`
Body *BeaconBody `json:"body"`
}
type BeaconBody struct {
// A byte array used for randomness in the beacon chain
RandaoReveal libcommon.Bytes96
RandaoReveal libcommon.Bytes96 `json:"randao_reveal"`
// Data related to the Ethereum 1.0 chain
Eth1Data *Eth1Data
Eth1Data *Eth1Data `json:"eth1_data"`
// A byte array used to customize validators' behavior
Graffiti libcommon.Hash
Graffiti libcommon.Hash `json:"graffit"`
// A list of slashing events for validators who included invalid blocks in the chain
ProposerSlashings *solid.ListSSZ[*ProposerSlashing]
ProposerSlashings *solid.ListSSZ[*ProposerSlashing] `json:"proposer_slashings"`
// A list of slashing events for validators who included invalid attestations in the chain
AttesterSlashings *solid.ListSSZ[*AttesterSlashing]
AttesterSlashings *solid.ListSSZ[*AttesterSlashing] `json:"attester_slashings"`
// A list of attestations included in the block
Attestations *solid.ListSSZ[*solid.Attestation]
Attestations *solid.ListSSZ[*solid.Attestation] `json:"attestations"`
// A list of deposits made to the Ethereum 1.0 chain
Deposits *solid.ListSSZ[*Deposit]
Deposits *solid.ListSSZ[*Deposit] `json:"deposits"`
// A list of validators who have voluntarily exited the beacon chain
VoluntaryExits *solid.ListSSZ[*SignedVoluntaryExit]
VoluntaryExits *solid.ListSSZ[*SignedVoluntaryExit] `json:"voluntary_exits"`
// A summary of the current state of the beacon chain
SyncAggregate *SyncAggregate
SyncAggregate *SyncAggregate `json:"sync_aggregate,omitempty"`
// Data related to crosslink records and executing operations on the Ethereum 2.0 chain
ExecutionPayload *Eth1Block
ExecutionPayload *Eth1Block `json:"execution_payload,omitempty"`
// Withdrawals Diffs for Execution Layer
ExecutionChanges *solid.ListSSZ[*SignedBLSToExecutionChange]
ExecutionChanges *solid.ListSSZ[*SignedBLSToExecutionChange] `json:"execution_changes,omitempty"`
// The commitments for beacon chain blobs
// With a max of 4 per block
BlobKzgCommitments *solid.ListSSZ[*KZGCommitment]
BlobKzgCommitments *solid.ListSSZ[*KZGCommitment] `json:"blob_kzg_commitments,omitempty"`
// The version of the beacon chain
Version clparams.StateVersion
Version clparams.StateVersion `json:"-"`
beaconCfg *clparams.BeaconChainConfig
}

View File

@ -1,7 +1,10 @@
package cltypes
import (
"encoding/json"
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
ssz2 "github.com/ledgerwatch/erigon/cl/ssz"
)
@ -16,6 +19,14 @@ const BYTES_PER_BLOB = uint64(BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB)
type KZGCommitment gokzg4844.KZGCommitment
func (b KZGCommitment) MarshalJSON() ([]byte, error) {
return json.Marshal(libcommon.Bytes48(b))
}
func (b *KZGCommitment) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, (*libcommon.Bytes48)(b))
}
func (b *KZGCommitment) Copy() *KZGCommitment {
copy := *b
return &copy

View File

@ -11,9 +11,9 @@ import (
// Change to EL engine
type BLSToExecutionChange struct {
ValidatorIndex uint64
From libcommon.Bytes48
To libcommon.Address
ValidatorIndex uint64 `json:"validator_index"`
From libcommon.Bytes48 `json:"from"`
To libcommon.Address `json:"to"`
}
func (b *BLSToExecutionChange) EncodeSSZ(buf []byte) ([]byte, error) {
@ -43,8 +43,8 @@ func (*BLSToExecutionChange) Static() bool {
}
type SignedBLSToExecutionChange struct {
Message *BLSToExecutionChange
Signature libcommon.Bytes96
Message *BLSToExecutionChange `json:"message"`
Signature libcommon.Bytes96 `json:"signature"`
}
func (s *SignedBLSToExecutionChange) EncodeSSZ(buf []byte) ([]byte, error) {

View File

@ -16,24 +16,24 @@ import (
// ETH1Block represents a block structure CL-side.
type Eth1Block struct {
ParentHash libcommon.Hash
FeeRecipient libcommon.Address
StateRoot libcommon.Hash
ReceiptsRoot libcommon.Hash
LogsBloom types.Bloom
PrevRandao libcommon.Hash
BlockNumber uint64
GasLimit uint64
GasUsed uint64
Time uint64
Extra *solid.ExtraData
BaseFeePerGas libcommon.Hash
ParentHash libcommon.Hash `json:"parent_hash"`
FeeRecipient libcommon.Address `json:"fee_recipient"`
StateRoot libcommon.Hash `json:"state_root"`
ReceiptsRoot libcommon.Hash `json:"receipts_root"`
LogsBloom types.Bloom `json:"logs_bloom"`
PrevRandao libcommon.Hash `json:"prev_randao"`
BlockNumber uint64 `json:"block_number"`
GasLimit uint64 `json:"gas_limit"`
GasUsed uint64 `json:"gas_used"`
Time uint64 `json:"timestamp"`
Extra *solid.ExtraData `json:"extra_data"`
BaseFeePerGas libcommon.Hash `json:"base_fee_per_gas"`
// Extra fields
BlockHash libcommon.Hash
Transactions *solid.TransactionsSSZ
Withdrawals *solid.ListSSZ[*types.Withdrawal]
BlobGasUsed uint64
ExcessBlobGas uint64
BlockHash libcommon.Hash `json:"block_hash"`
Transactions *solid.TransactionsSSZ `json:"transactions"`
Withdrawals *solid.ListSSZ[*types.Withdrawal] `json:"withdrawals,omitempty"`
BlobGasUsed uint64 `json:"blob_gas_used,omitempty"`
ExcessBlobGas uint64 `json:"excess_blob_gas,omitempty"`
// internals
version clparams.StateVersion
beaconCfg *clparams.BeaconChainConfig

View File

@ -10,9 +10,9 @@ import (
)
type Eth1Data struct {
Root libcommon.Hash
DepositCount uint64
BlockHash libcommon.Hash
Root libcommon.Hash `json:"deposit_root"`
DepositCount uint64 `json:"deposit_count"`
BlockHash libcommon.Hash `json:"block_hash"`
}
func (e *Eth1Data) Copy() *Eth1Data {

View File

@ -11,9 +11,9 @@ import (
* IndexedAttestation are attestantions sets to prove that someone misbehaved.
*/
type IndexedAttestation struct {
AttestingIndices solid.Uint64ListSSZ
Data solid.AttestationData
Signature libcommon.Bytes96
AttestingIndices solid.Uint64ListSSZ `json:"attesting_indicies"`
Data solid.AttestationData `json:"data"`
Signature libcommon.Bytes96 `json:"signature"`
}
func (i *IndexedAttestation) Static() bool {

View File

@ -6,8 +6,8 @@ import (
)
type ProposerSlashing struct {
Header1 *SignedBeaconBlockHeader
Header2 *SignedBeaconBlockHeader
Header1 *SignedBeaconBlockHeader `json:"signed_header_1"`
Header2 *SignedBeaconBlockHeader `json:"signed_header_2"`
}
func (p *ProposerSlashing) EncodeSSZ(dst []byte) ([]byte, error) {
@ -29,8 +29,8 @@ func (p *ProposerSlashing) HashSSZ() ([32]byte, error) {
}
type AttesterSlashing struct {
Attestation_1 *IndexedAttestation
Attestation_2 *IndexedAttestation
Attestation_1 *IndexedAttestation `json:"attestation_1"`
Attestation_2 *IndexedAttestation `json:"attestation_2"`
}
func (a *AttesterSlashing) EncodeSSZ(dst []byte) ([]byte, error) {

View File

@ -1,6 +1,10 @@
package solid
import (
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
"github.com/ledgerwatch/erigon-lib/common/length"
"github.com/ledgerwatch/erigon-lib/types/clonable"
"github.com/ledgerwatch/erigon-lib/types/ssz"
@ -44,6 +48,33 @@ func NewAttestionFromParameters(
return a
}
func (a Attestation) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
AggregationBits hexutility.Bytes
Signature libcommon.Bytes96
Data AttestationData
}{
AggregationBits: a.aggregationBitsBuffer,
Signature: a.Signature(),
Data: a.AttestantionData(),
})
}
func (a *Attestation) UnmarshalJSON(buf []byte) error {
var tmp struct {
AggregationBits hexutility.Bytes
Signature libcommon.Bytes96
Data AttestationData
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
a.SetAggregationBits(tmp.AggregationBits)
a.SetSignature(tmp.Signature)
a.SetAttestationData(tmp.Data)
return nil
}
// AggregationBits returns the aggregation bits buffer of the Attestation instance.
func (a *Attestation) AggregationBits() []byte {
return a.aggregationBitsBuffer

View File

@ -3,6 +3,7 @@ package solid
import (
"bytes"
"encoding/binary"
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
@ -37,6 +38,41 @@ func NewAttestionDataFromParameters(
return a
}
func (a AttestationData) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Slot uint64
Index uint64
BeaconBlockRoot libcommon.Hash
Source Checkpoint
Target Checkpoint
}{
Slot: a.Slot(),
BeaconBlockRoot: a.BeaconBlockRoot(),
Index: a.ValidatorIndex(),
Source: a.Source(),
Target: a.Target(),
})
}
func (a AttestationData) UnmarshalJSON(buf []byte) error {
var tmp struct {
Slot uint64
Index uint64
BeaconBlockRoot libcommon.Hash
Source Checkpoint
Target Checkpoint
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
a.SetSlot(tmp.Slot)
a.SetValidatorIndex(tmp.Index)
a.SetBeaconBlockRoot(tmp.BeaconBlockRoot)
a.SetSource(tmp.Source)
a.SetTarget(tmp.Target)
return nil
}
func NewAttestationData() AttestationData {
return make([]byte, attestationDataBufferSize)
}

View File

@ -3,6 +3,7 @@ package solid
import (
"bytes"
"encoding/binary"
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
@ -32,6 +33,26 @@ func NewCheckpoint() Checkpoint {
return make([]byte, checkpointSize)
}
func (c Checkpoint) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Epoch uint64
Root libcommon.Hash
}{Epoch: c.Epoch(), Root: c.BlockRoot()})
}
func (c Checkpoint) UnmarshalJSON(buf []byte) error {
var tmp struct {
Epoch uint64
Root libcommon.Hash
}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
c.SetEpoch(tmp.Epoch)
c.SetBlockRoot(tmp.Root)
return nil
}
// SetBlockRoot copies the given blockRoot into the correct location within the Checkpoint
func (c Checkpoint) SetBlockRoot(blockRoot libcommon.Hash) {
copy(c[8:], blockRoot[:]) // copy the blockRoot into the Checkpoint starting at index 8

View File

@ -2,8 +2,10 @@ package solid
import (
"encoding/binary"
"encoding/json"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
"github.com/ledgerwatch/erigon-lib/common/length"
"github.com/ledgerwatch/erigon-lib/types/clonable"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
@ -22,6 +24,18 @@ func NewExtraData() *ExtraData {
}
}
func (e *ExtraData) UnmarshalJSON(buf []byte) error {
if err := json.Unmarshal(buf, (*hexutility.Bytes)(&e.data)); err != nil {
return err
}
e.l = len(e.data)
return nil
}
func (e ExtraData) MarshalJSON() ([]byte, error) {
return json.Marshal(hexutility.Bytes(e.data[:e.l]))
}
// Clone creates a new instance of ExtraData.
func (*ExtraData) Clone() clonable.Clonable {
return NewExtraData()

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
"github.com/ledgerwatch/erigon-lib/common"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
@ -23,6 +25,28 @@ func NewHashList(c int) HashListSSZ {
}
}
func (arr *hashList) MarshalJSON() ([]byte, error) {
list := make([]libcommon.Hash, arr.l)
for i := 0; i < arr.l; i++ {
list[0] = arr.Get(i)
}
return json.Marshal(list)
}
func (arr *hashList) UnmarshalJSON(buf []byte) error {
var list []libcommon.Hash
if err := json.Unmarshal(buf, &list); err != nil {
return err
}
arr.Clear()
arr.l = len(list)
for _, elem := range list {
arr.Append(elem)
}
return nil
}
func (h *hashList) Append(val libcommon.Hash) {
offset := h.l * length.Hash
if offset == len(h.u) {

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
"github.com/ledgerwatch/erigon-lib/types/clonable"
@ -26,6 +28,14 @@ func (h *hashVector) Append(val libcommon.Hash) {
panic("not implmented")
}
func (h hashVector) MarshalJSON() ([]byte, error) {
return json.Marshal(h.u)
}
func (h *hashVector) UnmarshalJSON(buf []byte) error {
return json.Unmarshal(buf, h.u)
}
func (h *hashVector) Cap() int {
return h.u.l
}

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/types/ssz"
ssz2 "github.com/ledgerwatch/erigon/cl/ssz"
@ -23,7 +25,26 @@ type IterableSSZ[T any] interface {
ssz.HashableSSZ
}
type Uint64VectorSSZ IterableSSZ[uint64]
type Uint64ListSSZ IterableSSZ[uint64]
type HashListSSZ IterableSSZ[common.Hash]
type HashVectorSSZ IterableSSZ[common.Hash]
type Uint64ListSSZ interface {
IterableSSZ[uint64]
json.Marshaler
json.Unmarshaler
}
type Uint64VectorSSZ interface {
IterableSSZ[uint64]
json.Marshaler
json.Unmarshaler
}
type HashListSSZ interface {
IterableSSZ[common.Hash]
json.Marshaler
json.Unmarshaler
}
type HashVectorSSZ interface {
IterableSSZ[common.Hash]
json.Marshaler
json.Unmarshaler
}

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/types/clonable"
"github.com/ledgerwatch/erigon-lib/types/ssz"
@ -43,6 +45,14 @@ func NewStaticListSSZ[T encodableHashableSSZ](limit int, bytesPerElement int) *L
}
}
func (l ListSSZ[T]) MarshalJSON() ([]byte, error) {
return json.Marshal(l.list)
}
func (l *ListSSZ[T]) UnmarshalJSON(data []byte) error {
return json.Unmarshal(data, &l.list)
}
func NewDynamicListSSZFromList[T encodableHashableSSZ](list []T, limit int) *ListSSZ[T] {
return &ListSSZ[T]{
list: list,

View File

@ -1,7 +1,10 @@
package solid
import (
"encoding/json"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/hexutility"
"github.com/ledgerwatch/erigon-lib/types/clonable"
"github.com/ledgerwatch/erigon-lib/types/ssz"
"github.com/ledgerwatch/erigon/cl/merkle_tree"
@ -12,6 +15,27 @@ type TransactionsSSZ struct {
root libcommon.Hash // root
}
func (t *TransactionsSSZ) UnmarshalJSON(buf []byte) error {
tmp := []hexutility.Bytes{}
t.root = libcommon.Hash{}
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
t.underlying = nil
for _, tx := range tmp {
t.underlying = append(t.underlying, tx)
}
return nil
}
func (t TransactionsSSZ) MarshalJSON() ([]byte, error) {
tmp := []hexutility.Bytes{}
for _, tx := range t.underlying {
tmp = append(tmp, tx)
}
return json.Marshal(tmp)
}
func (*TransactionsSSZ) Clone() clonable.Clonable {
return &TransactionsSSZ{}
}

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
"github.com/ledgerwatch/erigon-lib/types/clonable"
)
@ -14,6 +16,14 @@ func NewUint64ListSSZ(limit int) Uint64ListSSZ {
}
}
func (h uint64ListSSZ) MarshalJSON() ([]byte, error) {
return json.Marshal(h.u)
}
func (h uint64ListSSZ) UnmarshalJSON(buf []byte) error {
return json.Unmarshal(buf, h.u)
}
func (h *uint64ListSSZ) Static() bool {
return false
}

View File

@ -1,6 +1,8 @@
package solid
import (
"encoding/json"
"github.com/ledgerwatch/erigon-lib/types/clonable"
)
@ -19,6 +21,14 @@ func NewUint64VectorSSZ(size int) Uint64VectorSSZ {
}
}
func (h uint64VectorSSZ) MarshalJSON() ([]byte, error) {
return json.Marshal(h.u)
}
func (h *uint64VectorSSZ) UnmarshalJSON(buf []byte) error {
return json.Unmarshal(buf, h.u)
}
func (arr *uint64VectorSSZ) Clear() {
arr.u.Clear()
}

View File

@ -2,6 +2,7 @@ package solid
import (
"encoding/binary"
"encoding/json"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/common/length"
@ -56,9 +57,26 @@ func (arr *byteBasedUint64Slice) CopyTo(target *byteBasedUint64Slice) {
copy(target.u, arr.u)
}
// depth returns the depth of the Merkle tree representing the slice.
func (arr *byteBasedUint64Slice) depth() int {
return int(GetDepth(uint64(arr.c) / 4))
func (arr *byteBasedUint64Slice) MarshalJSON() ([]byte, error) {
list := make([]uint64, arr.l)
for i := 0; i < arr.l; i++ {
list[0] = arr.Get(i)
}
return json.Marshal(list)
}
func (arr *byteBasedUint64Slice) UnmarshalJSON(buf []byte) error {
var list []uint64
if err := json.Unmarshal(buf, &list); err != nil {
return err
}
arr.Clear()
arr.l = len(list)
for _, elem := range list {
arr.Append(elem)
}
return nil
}
// Range iterates over the slice and applies a provided function to each element.

View File

@ -16,11 +16,10 @@ const (
)
type DepositData struct {
PubKey [48]byte
WithdrawalCredentials libcommon.Hash
Amount uint64
Signature libcommon.Bytes96
Root libcommon.Hash // Ignored if not for hashing
PubKey libcommon.Bytes48 `json:"pubkey"`
WithdrawalCredentials libcommon.Hash `json:"withdrawal_credentials"`
Amount uint64 `json:"amount"`
Signature libcommon.Bytes96 `json:"signature"`
}
func (d *DepositData) EncodeSSZ(dst []byte) ([]byte, error) {
@ -49,8 +48,8 @@ func (*DepositData) Static() bool {
type Deposit struct {
// Merkle proof is used for deposits
Proof solid.HashVectorSSZ // 33 X 32 size.
Data *DepositData
Proof solid.HashVectorSSZ `json:"proof"` // 33 X 32 size.
Data *DepositData `json:"data"`
}
func (d *Deposit) EncodeSSZ(dst []byte) ([]byte, error) {
@ -73,8 +72,8 @@ func (d *Deposit) HashSSZ() ([32]byte, error) {
}
type VoluntaryExit struct {
Epoch uint64
ValidatorIndex uint64
Epoch uint64 `json:"epoch"`
ValidatorIndex uint64 `json:"validator_index"`
}
func (e *VoluntaryExit) EncodeSSZ(buf []byte) ([]byte, error) {
@ -102,8 +101,8 @@ func (*VoluntaryExit) EncodingSizeSSZ() int {
}
type SignedVoluntaryExit struct {
VolunaryExit *VoluntaryExit
Signature libcommon.Bytes96
VolunaryExit *VoluntaryExit `json:"message"`
Signature libcommon.Bytes96 `json:"signature"`
}
func (e *SignedVoluntaryExit) EncodeSSZ(dst []byte) ([]byte, error) {

View File

@ -47,7 +47,6 @@ func TestDepositData(t *testing.T) {
WithdrawalCredentials: [32]byte{4, 5, 6},
Amount: 100,
Signature: [96]byte{7, 8, 9},
Root: [32]byte{10, 11, 12},
}
// Encode DepositData to SSZ

View File

@ -3,6 +3,7 @@ package stages
import (
"context"
"fmt"
"sync/atomic"
"time"
libcommon "github.com/ledgerwatch/erigon-lib/common"
@ -96,8 +97,13 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co
foundLatestEth1ValidHash = true // skip this if we are not using an engine supporting direct insertion
}
var currEth1Progress atomic.Int64
// Set up onNewBlock callback
cfg.downloader.SetOnNewBlock(func(blk *cltypes.SignedBeaconBlock) (finished bool, err error) {
if blk.Version() >= clparams.BellatrixVersion {
currEth1Progress.Store(int64(blk.Block.Body.ExecutionPayload.BlockNumber))
}
if !foundLatestEth1ValidHash {
payload := blk.Block.Body.ExecutionPayload
encodedPayload, err := payload.EncodeSSZ(nil)
@ -136,7 +142,8 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co
return
}
logArgs = append(logArgs,
"progress", currProgress,
"slot", currProgress,
"blockNumber", currEth1Progress.Load(),
"blk/sec", fmt.Sprintf("%.1f", speed),
"peers", peerCount)
logger.Info("Downloading History", logArgs...)